coffee, dart, elixir, elm: detect unclosed strings.
authorJoel Martin <github@martintribe.org>
Wed, 31 Jul 2019 03:25:17 +0000 (22:25 -0500)
committerJoel Martin <github@martintribe.org>
Wed, 31 Jul 2019 03:27:57 +0000 (22:27 -0500)
Detect more cases of strings being unterminated.

coffee/Makefile
coffee/reader.coffee
dart/reader.dart
elixir/lib/mal/reader.ex
elm/Reader.elm

index 74b3c96..4036473 100644 (file)
@@ -3,11 +3,18 @@ SOURCES_BASE = node_readline.coffee types.coffee \
 SOURCES_LISP = env.coffee core.coffee stepA_mal.coffee
 SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
 
+STEPS = step0_repl.coffee step1_read_print.coffee \
+       step2_eval.coffee step3_env.coffee step4_if_fn_do.coffee \
+       step5_tco.coffee step6_file.coffee step7_quote.coffee \
+       step8_macros.coffee step9_try.coffee stepA_mal.coffee
+
 all: node_modules dist
 
 node_modules:
        npm install
 
+$(STEPS): node_modules
+
 dist: mal.coffee mal
 
 mal.coffee: $(SOURCES)
index f0253eb..e551bec 100644 (file)
@@ -22,10 +22,11 @@ read_atom = (rdr) ->
   token = rdr.next()
   if token.match /^-?[0-9]+$/ then parseInt token,10
   else if token.match /^-?[0-9][0-9.]*$/ then parseFloat token,10
-  else if token[0] == '"'
-    throw new Error "expected '\"', got EOF" if token[-1..-1] != '"'
+  else if token.match /^"(?:\\.|[^\\"])*"$/
     token.slice(1, token.length-1)
       .replace(/\\(.)/g, (_, c) -> if c == 'n' then '\n' else c)
+  else if token[0] == '"'
+    throw new Error "expected '\"', got EOF"
   else if token[0] == ':' then types._keyword(token[1..])
   else if token == "nil" then null
   else if token == "true" then true
index fc6eb51..b746f70 100644 (file)
@@ -2,6 +2,8 @@ import 'types.dart';
 
 final malRegExp = new RegExp(
     r"""[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"?|;.*|[^\s\[\]{}('"`,;)]*)""");
+final strRegExp = new RegExp(
+    r"""^"(?:\\.|[^\\"])*"$""");
 
 class Reader {
   final List<String> tokens;
@@ -114,10 +116,7 @@ MalType read_atom(Reader reader) {
     return new MalInt(intAtom);
   }
 
-  if (token[0] == '"') {
-    if (token[token.length -1 ] != '"') {
-      throw new ParseException("expected '\"', got EOF");
-    }
+  if (strRegExp.matchAsPrefix(token) != null) {
     var sanitizedToken = token
         // remove surrounding quotes
         .substring(1, token.length - 1)
@@ -126,6 +125,10 @@ MalType read_atom(Reader reader) {
     return new MalString(sanitizedToken);
   }
 
+  if (token[0] == '"') {
+    throw new ParseException("expected '\"', got EOF");
+  }
+
   if (token[0] == ':') {
     return new MalKeyword(token.substring(1));
   }
index 8670429..07f3719 100644 (file)
@@ -83,7 +83,7 @@ defmodule Mal.Reader do
   defp read_atom(":" <> rest), do: String.to_atom(rest)
   defp read_atom(token) do
     cond do
-      String.starts_with?(token, "\"") and String.ends_with?(token, "\"") ->
+      String.match?(token, ~r/^"(?:\\.|[^\\"])*"$/) ->
         token
           |> Code.string_to_quoted
           |> elem(1)
index c770460..2016e8a 100644 (file)
@@ -198,4 +198,4 @@ that's why it's down below. :)
 -}
 strString : Parser s String
 strString =
-    regex "\"(\\\\\"|[^\"])*\"" <?> "string"
+    regex "\"(\\\\.|[^\\\\\"])*\"" <?> "string"