io, livescript: Detect more unterminated strings.
authorBen Harris <bjh21@bjh21.me.uk>
Fri, 17 May 2019 21:46:33 +0000 (22:46 +0100)
committerBen Harris <bjh21@bjh21.me.uk>
Fri, 17 May 2019 22:22:56 +0000 (23:22 +0100)
Rather than treating anything beginning and ending with '"' as a valid
string, we now use a regexp to detect a valid string and treat any other
token starting with '"' as an error.

io/MalReader.io
livescript/reader.ls

index 354ec30..16cc3bd 100644 (file)
@@ -26,9 +26,9 @@ MalReader := Object clone do (
     )
 
     numberRegex := Regex with("^-?[0-9]+$")
+    stringRegex := Regex with("^\"(?:[\\\\].|[^\\\\\"])*\"$")
 
     read_string := method(token,
-        (token endsWithSeq("\"")) ifFalse(Exception raise("expected '\"', got EOF"))
         placeholder := 127 asCharacter
         token exSlice(1, -1) replaceSeq("\\\\", placeholder) replaceSeq("\\\"", "\"") replaceSeq("\\n", "\n") replaceSeq(placeholder, "\\")
     )
@@ -40,7 +40,8 @@ MalReader := Object clone do (
         (token == "false") ifTrue(return(false))
         (token == "nil") ifTrue(return(nil))
         (token beginsWithSeq(":")) ifTrue(return(MalKeyword with(token exSlice(1))))
-        (token beginsWithSeq("\"")) ifTrue(return(read_string(token)))
+        (token hasMatchOfRegex(stringRegex)) ifTrue(return(read_string(token)))
+        (token beginsWithSeq("\"")) ifTrue(Exception raise("expected '\"', got EOF"))
         MalSymbol with(token)
     )
 
index 0eba293..119ab9f 100644 (file)
@@ -111,10 +111,10 @@ read_atom = (reader) ->
     token = reader.peek!
     if token in constants
         {type: \const, value: reader.next!}
-    else if token[0] == '"'
-        if not token.endsWith '"'
-            parse-error "expected '\"', got EOF"
+    else if token.match /^"(?:\\.|[^\\"])*"$/
         {type: \string, value: decode-string reader.next!}
+    else if token[0] == '"'
+        parse-error "expected '\"', got EOF"
     else if token.match /^-?\d+$/
         {type: \int, value: parseInt reader.next!}
     else if token != '~@' and token not in special_chars