tests: make throw of non-strings optional/soft.
[jackhill/mal.git] / guile / reader.scm
index 8dafa97..c734759 100644 (file)
   (cond
    ((null? lst) ht)
    (else
-    (let lp((k (car lst)))
+    (let lp((next lst))
       (cond
-       ((null? k) ht)
+       ((null? next) ht)
        (else
-        (when (null? (cdr lst))
-              (throw 'mal-error "read_hashmap: lack of value" k))
-        (let ((v (cadr lst)))
+        (when (null? (cdr next))
+          (throw 'mal-error
+                 (format #f "read_hashmap: '~a' lack of value" (car next))))
+        (let ((k (car next))
+              (v (cadr next)))
           (hash-set! ht k v)
-          (lp (cddr lst)))))))))
+          (lp (cddr next)))))))))
 
 (define (read_atom reader)
   (define (->str s)
     (string-sub
-     (string-sub s "\\\\\"" "\"")
-     "\\\\\n" "\n"))
+     (string-sub
+      (string-sub s "\\\\\"" "\"")
+      "\\\\n" "\n")
+     "\\\\\\\\" "\\"))
   (let ((token (reader 'next)))
     (cond
      ((string-match "^-?[0-9][0-9.]*$" token)
                (->str (match:substring m 1))
                (throw 'mal-error "expected '\"'"))))
      ((string-match "^:(.*)" token)
-      => (lambda (m) (_keyword (match:substring m 1))))
+      => (lambda (m) (string->keyword (match:substring m 1))))
      ((string=? "nil" token) nil)
      ((string=? "true" token) #t)
      ((string=? "false" token) #f)
      (else (string->symbol token)))))
 
 (define (read_form reader)
+  (define (clean x)
+    (if (string? x)
+        (string-trim-both
+         x
+         (lambda (c) (char-set-contains? char-set:whitespace c)))
+        x)) 
   (define (next) (reader 'next))
   (define (more) (read_form reader))
-  (match (reader 'peek)
+  (match (clean (reader 'peek)) 
     (() (throw 'mal-error "blank line")) ; FIXME: what should be returned?
     ("'" (next) (list 'quote (more)))
     ("`" (next) (list 'quasiquote (more)))
 (define (read_str str)
   (if (eof-object? str)
       str
-      (let ((tokens (tokenizer str)))
-        (read_form (make-Reader (if (null? tokens) (list str) tokens))))))
+      (let* ((tokens (tokenizer str))
+             (t (if (null? tokens)
+                    (if (char=? (string-ref str 0) #\;)
+                        '()
+                        (list str))
+                    tokens)))
+        (read_form (make-Reader t)))))