1 MalReader
:= Object clone do (
3 Reader
:= Object clone do (
7 with
:= method(theTokens
,
8 self clone setTokens(theTokens
)
11 peek
:= method(tokens
at(pos
))
19 tokenizerRegex
:= Regex with("[\\s ,]*(~@|[\\[\\]{}()'`~@]|\"(?:[\\\\].|[^\\\\\"])*\"?|;.*|[^\\s \\[\\]{}()'\"`~@,;]*)")
21 tokenize
:= method(str
,
22 tokenizerRegex
matchesIn(str
) \
23 map(m
, m
at(1) asMutable strip
) \
24 select(t
, t size
> 0) \
25 select(t
, t
exSlice(0, 1) != ";")
28 numberRegex
:= Regex with("^-?[0-9]+$")
30 read_string
:= method(token
,
31 (token
endsWithSeq("\"")) ifFalse(Exception raise("expected '\"', got EOF"))
32 placeholder
:= 127 asCharacter
33 token
exSlice(1, -1) replaceSeq("\\\\", placeholder
) replaceSeq("\\\"", "\"") replaceSeq("\\n", "\n") replaceSeq(placeholder
, "\\")
36 read_atom
:= method(rdr
,
38 (token
hasMatchOfRegex(numberRegex
)) ifTrue(return(token asNumber
))
39 (token
== "true") ifTrue(return(true
))
40 (token
== "false") ifTrue(return(false
))
41 (token
== "nil") ifTrue(return(nil
))
42 (token
beginsWithSeq(":")) ifTrue(return(MalKeyword
with(token
exSlice(1))))
43 (token
beginsWithSeq("\"")) ifTrue(return(read_string(token
)))
47 read_list
:= method(rdr
, start
, end
,
49 if(token
!= start
, Exception raise("expected '" .. start
.. "'"))
53 if(token
isNil, Exception raise("expected '" .. end
.. "', got EOF"))
54 ast
push(read_form(rdr
))
61 reader_macro
:= method(symbol
, rdr
,
63 MalList
with(list(MalSymbol
with(symbol
), read_form(rdr
)))
66 read_form
:= method(rdr
,
68 (token
== "'") ifTrue(return(reader_macro("quote", rdr
)))
69 (token
== "`") ifTrue(return(reader_macro("quasiquote", rdr
)))
70 (token
== "~") ifTrue(return(reader_macro("unquote", rdr
)))
71 (token
== "~@") ifTrue(return(reader_macro("splice-unquote", rdr
)))
72 (token
== "^") ifTrue(
74 meta
:= read_form(rdr
)
75 return(MalList
with(list(MalSymbol
with("with-meta"), read_form(rdr
), meta
)))
77 (token
== "@") ifTrue(return(reader_macro("deref", rdr
)))
78 (token
== "(") ifTrue(return(MalList
with(read_list(rdr
, "(", ")"))))
79 (token
== ")") ifTrue(Exception raise("unexepcted ')'"))
80 (token
== "[") ifTrue(return(MalVector
with(read_list(rdr
, "[", "]"))))
81 (token
== "]") ifTrue(Exception raise("unexepcted ']'"))
82 (token
== "{") ifTrue(return(MalMap
withList(read_list(rdr
, "{", "}"))))
83 (token
== "}") ifTrue(Exception raise("unexepcted '}'"))
87 read_str
:= method(str
,
88 tokens
:= tokenize(str
)
89 if(tokens isEmpty
, nil
, read_form(Reader
with(tokens
)))