perl6, r, skew: detect unclosed strings.
authorJoel Martin <github@martintribe.org>
Wed, 31 Jul 2019 04:46:36 +0000 (23:46 -0500)
committerJoel Martin <github@martintribe.org>
Wed, 31 Jul 2019 04:47:06 +0000 (23:47 -0500)
Detect strings that are not properly terminated.

perl6/reader.pm
r/reader.r
skew/reader.sk

index c8f7ed3..70d83a3 100644 (file)
@@ -46,11 +46,13 @@ sub read_list ($rdr, $end) {
 sub read_atom ($rdr) {
   my $atom = $rdr.next;
   given $atom {
-    when /^\"/ {
-      die X::MalIncomplete.new(end => '"') if $atom !~~ /\"$/;
+    when /^'"' [ \\. || <-[\"\\]> ]* '"'$/ {
       s:g/^\"|\"$//;
       MalString(.trans(/\\\"/ => '"', /\\n/ => "\n", /\\\\/ => '\\'));
     }
+    when /^\"/ {
+      die X::MalIncomplete.new(end => '"');
+    }
     when /^\:(.*)/ { MalString("\x29E$0") }
     when /^'-'? <[0..9]>+$/ { MalNumber($_) }
     when 'nil' { $NIL }
index be163e6..dd78299 100644 (file)
@@ -42,15 +42,14 @@ read_atom <- function(rdr) {
         as.integer(token)
     } else if (re_match("^-?[0-9][0-9.]*$", token)) {
         as.double(token)
-    } else if (substr(token,1,1) == "\"") {
-        if (substr(token, nchar(token), nchar(token)) != "\"") {
-            throw("expected '\"', got EOF")
-        }
+    } else if (re_match("^\"(?:\\\\.|[^\\\\\"])*\"$", token)) {
         gsub("\x7f", "\\\\",
             gsub("\\\\n", "\n",
                  gsub("\\\\\"", "\"",
                       gsub("\\\\\\\\", "\x7f",
                            substr(token, 2, nchar(token)-1)))))
+    } else if (substr(token,1,1) == "\"") {
+        throw("expected '\"', got EOF")
     } else if (substr(token,1,1) == ":") {
         new.keyword(substring(token,2))
     } else if (token == "nil") {
index f383fdb..15bc83e 100644 (file)
@@ -34,6 +34,7 @@ def unescape(s string) string {
 }
 
 def read_atom(rdr Reader) MalVal {
+  var sre = RegExp.new("^\"(?:\\\\.|[^\\\\\"])*\"$")
   const token = rdr.peek
   if token == "nil" {
     rdr.next
@@ -58,7 +59,7 @@ def read_atom(rdr Reader) MalVal {
     }
     case '"' {
       const s = rdr.next
-      if s[s.count - 1] == '"' {
+      if sre.exec(s) {
         return MalString.new(unescape(s.slice(1, s.count - 1)))
       } else {
         throw MalError.new("expected '\"', got EOF")