1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 01:57:09 +03:00
mal/pil/reader.l
Vasilij Schneidermann f5763ca16a Implement step 3
2016-10-03 00:31:43 +02:00

123 lines
4.3 KiB
Plaintext

(class +Reader)
# tokens
(dm T (Tokens)
(=: tokens Tokens) )
(dm next> ()
(pop (:: tokens)) )
(dm peek> ()
(car (: tokens)) )
(de read-str (String)
(let (Tokens (tokenizer String)
Reader (new '(+Reader) Tokens) )
(read-form Reader) ) )
(de tokenizer (String)
# [\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)
(let (Special " []{}()'\"`,;" )
(make
(for (Chars (chop String) Chars)
(let Char (pop 'Chars)
(cond
((member Char '(" " ","))
# do nothing, whitespace
)
((and (= Char "~") (= (car Chars) "@"))
(link "~@")
(pop 'Chars) ) # remove @ token
((index Char (chop "[]{}()'`~^\@"))
(link Char) )
((= Char "\"")
(link
(pack
(make
(link Char)
(let (Char (car Chars) Done NIL)
(while (and (not Done) Chars)
(link (pop 'Chars))
(cond
((= Char "\\")
(link (pop 'Chars)) # add char after \
(setq Char (car Chars)) )
((<> Char "\"")
(setq Char (car Chars)) )
((= Char "\"")
(setq Done T) ) ) ) ) ) ) ) )
((= Char ";")
(while (and Chars (<> Char "\n"))
(setq Char (pop 'Chars)) ) )
((not (index Char (chop Special)))
(link
(pack
(make
(link Char)
(let Char (car Chars)
(while (and Chars (not (index Char (chop Special))))
(link (pop 'Chars))
(setq Char (car Chars)) ) ) ) ) ) ) ) ) ) ) ) )
(de read-form (Reader)
(case (peek> Reader)
("'" (read-macro Reader 'quote))
("`" (read-macro Reader 'quasiquote))
("~" (read-macro Reader 'unquote))
("~@" (read-macro Reader 'splice-unquote))
("@" (read-macro Reader 'deref))
("\^" (read-meta Reader))
("(" (read-list Reader 'list ")"))
("[" (read-list Reader 'vector "]"))
("{" (read-list Reader 'map "}"))
(T (read-atom Reader)) ) )
(de read-macro (Reader symbol)
(next> Reader) # pop reader macro token
(MAL-list (list (MAL-symbol symbol) (read-form Reader))) )
(de read-meta (Reader)
(next> Reader) # pop reader macro token
(let Form (read-form Reader)
(MAL-list (list (MAL-symbol 'with-meta) (read-form Reader) Form) ) ) )
(de read-list (Reader Type Ender)
(next> Reader) # pop list start
(new (list (case Type
(list '+MALList)
(vector '+MALVector)
(map '+MALMap) ) )
(make
(use Done
(while (not Done)
(let Token (peek> Reader)
(cond
((= Token Ender)
(next> Reader) # pop list end
(setq Done T) )
((not Token)
(let Msg (pack "expected '" Ender "', got EOF")
(throw 'err (MAL-error Msg)) ) )
(T (link (read-form Reader))) ) ) ) ) ) ) )
(de read-atom (Reader)
(let (Token (next> Reader)
Chars (chop Token))
(cond
((= Token "true")
*MAL-true)
((= Token "false")
*MAL-false)
((= Token "nil")
*MAL-nil)
((format Token)
(MAL-number @) )
((= (car Chars) "\"")
(if (= (last Chars) "\"")
(MAL-string (any Token))
(throw 'err (MAL-error "expected '\"', got EOF")) ) )
((= (car Chars) ":")
(MAL-keyword (intern (pack (cdr Chars)))) )
((not Token)
(throw 'err (MAL-error "end of token stream")) )
(T (MAL-symbol (intern Token))) ) ) )