3 import types
.Types
.MalType
;
7 // Reader class implementation
8 var tokens
:Array
<String
>;
11 public function new(toks
:Array
<String
>) {
15 public function next() {
16 return tokens
[position
++];
19 public function peek() {
20 if (tokens
.length
> position
) {
21 return tokens
[position
];
28 // Static functions grouped with Reader class
29 static function tokenize(str
:String
) {
30 var re
= ~/[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/g;
31 var tokens
= new Array
<String
>();
33 while (re
.matchSub(str
, pos
)) {
34 var t
= re
.matched(1);
35 if (t
== "") { break; }
36 var pos_len
= re
.matchedPos();
37 pos
= pos_len
.pos
+ pos_len
.len
;
38 if (t
.charAt(0) == ";") { continue; }
45 static function read_atom(rdr
:Reader
) {
46 var re_int
= ~/^[0-9]*$/;
47 var re_str
= ~/^".*"$/;
48 var token
= rdr
.next();
49 return switch (token
) {
56 case _
if (token
.charAt(0) == ":"):
57 MalString("\x7f" + token
.substr(1));
58 case _
if (re_int
.match(token
)):
59 MalInt(Std
.parseInt(token
));
60 case _
if (re_str
.match(token
)):
64 s
= token
.substr(1, token
.length
-2);
65 MalString(re3
.replace(
75 static function read_seq(rdr
:Reader
, start
, end
) {
77 var token
= rdr
.next();
79 throw 'expected \'${start}\'';
81 while ((token
= rdr
.peek()) != end
) {
83 throw 'expected \'${end}\', got EOF';
85 lst
.push(read_form(rdr
));
91 static function read_form(rdr
:Reader
):MalType
{
92 var token
= rdr
.peek();
93 return switch (token
) {
94 // reader macros/transforms
96 MalList([MalSymbol("quote"), read_form(rdr
)]);
98 MalList([MalSymbol("quasiquote"), read_form(rdr
)]);
100 MalList([MalSymbol("unquote"), read_form(rdr
)]);
101 case "~@": rdr
.next();
102 MalList([MalSymbol("splice-unquote"), read_form(rdr
)]);
103 case "^": rdr
.next();
104 var meta
= read_form(rdr
);
105 MalList([MalSymbol("with-meta"), read_form(rdr
), meta
]);
106 case "@": rdr
.next();
107 MalList([MalSymbol("deref"), read_form(rdr
)]);
110 case ")": throw("unexpected ')'");
111 case "(": MalList(read_seq(rdr
, '(', ')'));
114 case "]": throw("unexpected ']'");
115 case "[": MalVector(read_seq(rdr
, '[', ']'));
118 case "}": throw("unexpected '}'");
119 case "{": hash_map(read_seq(rdr
, '{', '}'));
120 case _
: read_atom(rdr
);
124 public static function read_str(str
:String
):MalType
{
125 var tokens
= tokenize(str
);
126 if (tokens
.length
== 0) { throw(new BlankLine()); }
127 return read_form(new Reader(tokens
));