# 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

Reply via email to