From e91c55c2b65cf7628760433f1fcce84f40e645df Mon Sep 17 00:00:00 2001 From: Vasilij Schneidermann Date: Tue, 26 Sep 2017 22:07:49 +0200 Subject: [PATCH] Fix unescaping in chuck, common-lisp, gst, guile, python --- chuck/types/boxed/String.ck | 3 ++- common-lisp/src/reader.lisp | 16 ++++++++++++---- gst/util.st | 6 ++++-- guile/reader.scm | 15 ++++----------- python/reader.py | 4 ++-- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/chuck/types/boxed/String.ck b/chuck/types/boxed/String.ck index c0ec6f71e2..4c7390a8b3 100644 --- a/chuck/types/boxed/String.ck +++ b/chuck/types/boxed/String.ck @@ -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; } diff --git a/common-lisp/src/reader.lisp b/common-lisp/src/reader.lisp index 5391b4dd89..cfcb5ae8dd 100644 --- a/common-lisp/src/reader.lisp +++ b/common-lisp/src/reader.lisp @@ -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) diff --git a/gst/util.st b/gst/util.st index 5a73576e27..4a0009e6b0 100644 --- a/gst/util.st +++ b/gst/util.st @@ -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 ] diff --git a/guile/reader.scm b/guile/reader.scm index c734759e03..38cebbe066 100644 --- a/guile/reader.scm +++ b/guile/reader.scm @@ -78,21 +78,14 @@ (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) diff --git a/python/reader.py b/python/reader.py index 44c9d741cc..84c46c5d92 100644 --- a/python/reader.py +++ b/python/reader.py @@ -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]+$")