1 #include
"yeti_regex.i"
4 TOKENIZER_REGEXP
= regcomp
("[[:space:],]*(~@|[][{}()'`~@]|\"([\\
].|
[^\\\
"])*\"?|
;.
*|
[^
][[:space
:]{}()'\
"`~@,;]*)", newline
=1)
13 m
= regmatch
(TOKENIZER_REGEXP
, str
, match0
, match1
, start
=pos
, indices
=1)
21 token
= strpart
(str
, b
:e
)
23 if
(strpart
(token
, 1:1) == ";") continue
36 if
(rdr.pos
> numberof
(*rdr.tokens
)) return string
(0)
37 return
(*rdr.tokens
)(rdr.pos
)
42 token
= reader_peek
(rdr
)
47 NUMBER_REGEXP
= regcomp
("^-?[0-9]+$")
48 STR_REGEXP
= regcomp
("^\"([\\
].|
[^\\\
"])*\"$
")
49 STR_BAD_REGEXP = regcomp("^\
".*$")
53 s
= strpart
(s
, 2:-1) // remove surrounding quotes
54 s
= streplaceall
(s
, "\\\\", "\x01")
55 s
= streplaceall
(s
, "\\n", "\n")
56 s
= streplaceall
(s
, "\\\"", "\
"")
57 return streplaceall
(s
, "\x01", "\\")
62 token
= reader_next
(rdr
)
63 if
(token
== "nil") return MAL_NIL
64 else if
(token
== "true") return MAL_TRUE
65 else if
(token
== "false") return MAL_FALSE
66 else if
(regmatch
(NUMBER_REGEXP
, token
)) return MalNumber
(val
=tonum
(token
))
67 else if
(regmatch
(STR_REGEXP
, token
)) return MalString
(val
=unescape
(token
))
68 else if
(regmatch
(STR_BAD_REGEXP
, token
)) return MalError
(message
=("expected '\"'
, got EOF
"))
69 else if (strpart(token, 1:1) == ":") return MalKeyword(val=strpart(token, 2:))
70 else return MalSymbol(val=token)
73 func read_seq(rdr, start_char, end_char)
75 token = reader_next(rdr)
76 if (token != start_char) {
77 return MalError(message=("expected '
" + start_char + "'
, got EOF
"))
81 token = reader_peek(rdr)
82 while (token != end_char) {
83 if (token == string(0)) {
84 return MalError(message=("expected '
" + end_char + "'
, got EOF
"))
87 if (structof(e) == MalError) return e
89 token = reader_peek(rdr)
91 token = reader_next(rdr)
97 seq = read_seq(rdr, "(", ")")
98 if (structof(seq) == MalError) return seq
99 return MalList(val=&seq)
102 func read_vector(rdr)
104 seq = read_seq(rdr, "[", "]")
105 if (structof(seq) == MalError) return seq
106 return MalVector(val=&seq)
109 func read_hashmap(rdr)
111 seq = read_seq(rdr, "{", "}")
112 if (structof(seq) == MalError) return seq
113 return array_to_hashmap(seq)
116 func reader_macro(rdr, symbol_name)
118 shortcut = reader_next(rdr)
119 form = read_form(rdr)
120 if (structof(form) == MalError) return form
121 seq = [&MalSymbol(val=symbol_name), &form]
122 return MalList(val=&seq)
125 func reader_with_meta_macro(rdr)
127 shortcut = reader_next(rdr)
128 meta = read_form(rdr)
129 if (structof(meta) == MalError) return meta
130 form = read_form(rdr)
131 if (structof(form) == MalError) return form
132 seq = [&MalSymbol(val="with-meta
"), &form, &meta]
133 return MalList(val=&seq)
138 token = reader_peek(rdr)
139 if (token == "'
") return reader_macro(rdr, "quote
")
140 else if (token == "`
") return reader_macro(rdr, "quasiquote
")
141 else if (token == "~
") return reader_macro(rdr, "unquote
")
142 else if (token == "~@
") return reader_macro(rdr, "splice-unquote
")
143 else if (token == "@
") return reader_macro(rdr, "deref
")
144 else if (token == "^
") return reader_with_meta_macro(rdr)
145 else if (token == "(") return read_list(rdr)
146 else if (token == ")") return MalError(message="unexpected '
)'
")
147 else if (token == "[") return read_vector(rdr)
148 else if (token == "]") return MalError(message="unexpected '
]'
")
149 else if (token == "{") return read_hashmap(rdr)
150 else if (token == "}") return MalError(message="unexpected '
}'
")
151 else return read_atom(rdr)
156 tokens = tokenize(str)
157 rdr = Reader(tokens=&tokens, pos=1)
158 return read_form(rdr)