# New Ticket Created by Stuart Jansen
# Please include the string: [perl #50052]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=50052 >
* Test case for disappearing whitespace in string literals
* Fix for disappearing whitespace in string literals
* Support for basic escape sequences
---
MANIFEST | 1 +
languages/lolcode/config/makefiles/root.in | 1 +
languages/lolcode/lolcode.pir | 1 +
languages/lolcode/src/parser/actions.pm | 2 +-
languages/lolcode/src/parser/grammar.pg | 2 +-
languages/lolcode/src/parser/yarn_literal.pir | 71 +++++++++++++++++++++++++
languages/lolcode/t/00-sanity.t | 8 +++-
languages/lolcode/t/04-strings.t | 11 ++++
8 files changed, 94 insertions(+), 3 deletions(-)
create mode 100644 languages/lolcode/src/parser/yarn_literal.pir
create mode 100644 languages/lolcode/t/04-strings.t
diff --git a/MANIFEST b/MANIFEST
index d7d048a..bbcb64a 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1560,6 +1560,7 @@ languages/lolcode/src/builtins/math.pir [lolcode]
languages/lolcode/src/builtins/var_or_function.pir [lolcode]
languages/lolcode/src/parser/actions.pm [lolcode]
languages/lolcode/src/parser/grammar.pg [lolcode]
+languages/lolcode/src/parser/yarn_literal.pir [lolcode]
languages/lolcode/t/00-sanity.t [lolcode]
languages/lolcode/t/01-vars.t [lolcode]
languages/lolcode/t/02-functions.t [lolcode]
diff --git a/languages/lolcode/config/makefiles/root.in b/languages/lolcode/config/makefiles/root.in
index 4244135..9b4e1ae 100644
--- a/languages/lolcode/config/makefiles/root.in
+++ b/languages/lolcode/config/makefiles/root.in
@@ -36,6 +36,7 @@ SOURCES = lolcode.pir \
src/gen_grammar.pir \
src/gen_actions.pir \
src/gen_builtins.pir \
+ src/parser/yarn_literal.pir \
# $(LOLCODE_GROUP)
BUILTINS_PIR = \
diff --git a/languages/lolcode/lolcode.pir b/languages/lolcode/lolcode.pir
index 0d46096..576bccb 100644
--- a/languages/lolcode/lolcode.pir
+++ b/languages/lolcode/lolcode.pir
@@ -52,6 +52,7 @@ to the lolcode compiler.
.include 'src/gen_builtins.pir'
.include 'src/gen_grammar.pir'
+.include 'src/parser/yarn_literal.pir'
.include 'src/gen_actions.pir'
=back
diff --git a/languages/lolcode/src/parser/actions.pm b/languages/lolcode/src/parser/actions.pm
index 341bd9d..6c9b06c 100644
--- a/languages/lolcode/src/parser/actions.pm
+++ b/languages/lolcode/src/parser/actions.pm
@@ -173,7 +173,7 @@ method boolean($/) {
}
method quote($/) {
- make PAST::Val.new( :value( $($<string_literal>) ), :node($/) );
+ make PAST::Val.new( :value( $($<yarn_literal>) ), :node($/) );
}
method math($/) {
diff --git a/languages/lolcode/src/parser/grammar.pg b/languages/lolcode/src/parser/grammar.pg
index 3c96dee..7152f83 100644
--- a/languages/lolcode/src/parser/grammar.pg
+++ b/languages/lolcode/src/parser/grammar.pg
@@ -123,7 +123,7 @@ token float { '-'? \d+ '.' \d+ {*} }
rule boolean { [ 'WIN' | 'FAIL' ] {*} }
rule quote {
- [ \" <string_literal: "> \" ]
+ [ <.before '"'> <yarn_literal> ]
{*}
}
diff --git a/languages/lolcode/src/parser/yarn_literal.pir b/languages/lolcode/src/parser/yarn_literal.pir
new file mode 100644
index 0000000..d9bc1f0
--- /dev/null
+++ b/languages/lolcode/src/parser/yarn_literal.pir
@@ -0,0 +1,71 @@
+# $Id$
+
+.namespace ['lolcode::Grammar']
+
+.sub 'yarn_literal' :method
+ .param pmc adverbs :slurpy :named
+
+ .local string delim
+ delim = '"'
+
+ ## create a new match object, get the new match position
+ .local pmc mob
+ .local int pos, lastpos, delimlen
+ .local string target
+ (mob, pos, target) = self.'new'(self)
+ lastpos = length target
+
+ ## leave space for close delimiter
+ delimlen = length delim
+ lastpos -= delimlen
+
+ ## now initialize and loop through target
+ literal_init:
+ .local string literal, litchar, escaped
+ literal = ''
+ litchar = substr target, pos, 1
+ inc pos
+ if litchar == delim goto literal_loop
+ self.'panic'('Missing open delimiter for YARN literal.')
+
+ literal_loop:
+ ## if we're beyond the last possible position, fail
+ if pos > lastpos goto fail
+
+ ## get next character in literal
+ litchar = substr target, pos, 1
+ inc pos
+ if litchar == delim goto literal_end
+
+ ## add non-escape characters to literal
+ if litchar != ':' goto add_litchar
+
+ ## interpolate escaped
+ escaped = substr target, pos, 1
+ $I0 = index ':)>o"', escaped
+ if $I0 < 0 goto add_litchar
+ inc pos
+
+ litchar = substr ":\n\t\a\"", $I0, 1
+ goto add_litchar
+
+ add_litchar:
+ literal .= litchar
+ goto literal_loop
+
+ literal_end:
+ mob.'to'(pos)
+ mob.'result_object'(literal)
+ .return (mob)
+
+ fail:
+ mob.'to'(-1)
+ .return (mob)
+.end
+
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/languages/lolcode/t/00-sanity.t b/languages/lolcode/t/00-sanity.t
index e8525e4..e3bbeed 100644
--- a/languages/lolcode/t/00-sanity.t
+++ b/languages/lolcode/t/00-sanity.t
@@ -1,9 +1,10 @@
HAI 1.2
- VISIBLE "1..4"
+ VISIBLE "1..5"
BTW THIS IS COMMENT OK?
VISIBLE "ok 1"
+ BTW VISIBLE IS SLURPY
VISIBLE "ok " 2
OBTW this is a multi-line comment.
@@ -12,8 +13,13 @@ HAI 1.2
TLDR
VISIBLE "ok 3"
+ BTW VISIBLE WITHOUT CARRIAGE RETURN
VISIBLE "o" !
VISIBLE "k 4"
+ BTW SLURPY VISIBLE WITHOUT CARRIAGE RETURN
+ VISIBLE "o" "k" " " 5 !
+ VISIBLE ""
+
BTW vim: set filetype=lolcode :
KTHXBYE
diff --git a/languages/lolcode/t/04-strings.t b/languages/lolcode/t/04-strings.t
new file mode 100644
index 0000000..abddf50
--- /dev/null
+++ b/languages/lolcode/t/04-strings.t
@@ -0,0 +1,11 @@
+HAI 1.2
+ VISIBLE "1..3"
+
+ BTW SIMPLE ESCAPE
+ VISIBLE "ok 1 :)" !
+
+ BTW SIMPLE ESCAPE WITH MULTIPLE ARGS
+ VISIBLE "ok 2" ":)" "ok 3"
+
+ BTW vim: set filetype=lolcode :
+KTHXBYE