Fix unescaping in chuck, common-lisp, gst, guile, python
authorVasilij Schneidermann <mail@vasilij.de>
Tue, 26 Sep 2017 20:07:49 +0000 (22:07 +0200)
committerJoel Martin <github@martintribe.org>
Thu, 28 Sep 2017 12:40:47 +0000 (07:40 -0500)
chuck/types/boxed/String.ck
common-lisp/src/reader.lisp
gst/util.st
guile/reader.scm
python/reader.py

index c0ec6f7..4c7390a 100644 (file)
@@ -112,9 +112,10 @@ public class String
     fun static string parse(string input)
     {
         slice(input, 1, input.length() - 1) => string output;
+        replaceAll(output, "\\\\", "\177") => output;
         replaceAll(output, "\\\"", "\"") => output;
         replaceAll(output, "\\n", "\n") => output;
-        replaceAll(output, "\\\\", "\\") => output;
+        replaceAll(output, "\177", "\\") => output;
         return output;
     }
 
index 5391b4d..cfcb5ae 100644 (file)
@@ -90,12 +90,20 @@ raised"
   reader)
 
 (defun parse-string (token)
+  ;; read-from-string doesn't handle \n
   (if (and (> (length token) 1)
            (scan *string-re* token))
-      (read-from-string (utils:replace-all token
-                                             "\\n"
-                                             "
-"))
+      (let ((input (subseq token 1 (1- (length token)))))
+        (with-output-to-string (out)
+          (with-input-from-string (in input)
+            (loop while (peek-char nil in nil)
+                  do (let ((char (read-char in)))
+                       (if (eql char #\\ )
+                           (let ((char (read-char in)))
+                             (if (eql char #\n)
+                                 (terpri out)
+                               (princ char out)))
+                         (princ char out)))))))
       (error 'eof :context "string")))
 
 (defun expand-quote (reader)
index 5a73576..4a0009e 100644 (file)
@@ -10,12 +10,14 @@ SequenceableCollection extend [
 
 String extend [
     parse [
-        |text|
+        |text canary|
+        canary := 8r177 asCharacter asString.
         text := self copyFrom: 2 to: self size - 1.
+        text := text copyReplaceAll: '\\' with: canary.
         text := text copyReplaceAll: '\"' with: '"'.
         text := text copyReplaceAll: '\n' with: '
 '.
-        text := text copyReplaceAll: '\\' with: '\'.
+        text := text copyReplaceAll: canary with: '\'.
         ^text
     ]
 
index c734759..38cebbe 100644 (file)
           (lp (cddr next)))))))))
 
 (define (read_atom reader)
-  (define (->str s)
-    (string-sub
-     (string-sub
-      (string-sub s "\\\\\"" "\"")
-      "\\\\n" "\n")
-     "\\\\\\\\" "\\"))
   (let ((token (reader 'next)))
     (cond
      ((string-match "^-?[0-9][0-9.]*$" token)
       => (lambda (m) (string->number (match:substring m 0))))
-     ((string-match "^\"(.*)(.)$" token)
-      => (lambda (m)
-           (if (string=? "\"" (match:substring m 2))
-               (->str (match:substring m 1))
-               (throw 'mal-error "expected '\"'"))))
+     ((eqv? (string-ref token 0) #\")
+      (if (eqv? (string-ref token (- (string-length token) 1)) #\")
+          (with-input-from-string token read)
+          (throw 'mal-error "expected '\"'")))
      ((string-match "^:(.*)" token)
       => (lambda (m) (string->keyword (match:substring m 1))))
      ((string=? "nil" token) nil)
index 44c9d74..84c46c5 100644 (file)
@@ -1,5 +1,5 @@
 import re
-from mal_types import (_symbol, _keyword, _list, _vector, _hash_map, _s2u)
+from mal_types import (_symbol, _keyword, _list, _vector, _hash_map, _s2u, _u)
 
 class Blank(Exception): pass
 
@@ -23,7 +23,7 @@ def tokenize(str):
     return [t for t in re.findall(tre, str) if t[0] != ';']
 
 def _unescape(s):
-    return s.replace('\\"', '"').replace('\\n', '\n').replace('\\\\', '\\')
+    return s.replace('\\\\', _u('\u029e')).replace('\\"', '"').replace('\\n', '\n').replace(_u('\u029e'), '\\')
 
 def read_atom(reader):
     int_re = re.compile(r"-?[0-9]+$")