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;
}
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)
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
]
(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)
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
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]+$")