2 from mal_types
import (_symbol
, _keyword
, _list
, _vector
, _hash_map
, _s2u
, _u
)
4 class Blank(Exception): pass
7 def __init__(self
, tokens
, position
=0):
9 self
.position
= position
13 return self
.tokens
[self
.position
-1]
16 if len(self
.tokens
) > self
.position
:
17 return self
.tokens
[self
.position
]
22 tre
= re
.compile(r
"""[\s,]*(~@|[\[\]{}()'`~^@]|"(?:[\\].|[^\\"])*"?|;.*|[^\s\[\]{}()'"`@,;]+)""");
23 return [t
for t
in re
.findall(tre
, str) if t
[0] != ';']
26 return s
.replace('\\\\', _u('\u029e')).replace('\\"', '"').replace('\\n', '\n').replace(_u('\u029e'), '\\')
28 def read_atom(reader
):
29 int_re
= re
.compile(r
"-?[0-9]+$")
30 float_re
= re
.compile(r
"-?[0-9][0-9.]*$")
31 string_re
= re
.compile(r
'"(?:[\\].|[^\\"])*"')
33 if re
.match(int_re
, token
): return int(token
)
34 elif re
.match(float_re
, token
): return int(token
)
35 elif re
.match(string_re
, token
):return _s2u(_unescape(token
[1:-1]))
36 elif token
[0] == '"': raise Exception("expected '\"', got EOF")
37 elif token
[0] == ':': return _keyword(token
[1:])
38 elif token
== "nil": return None
39 elif token
== "true": return True
40 elif token
== "false": return False
41 else: return _symbol(token
)
43 def read_sequence(reader
, typ
=list, start
='(', end
=')'):
46 if token
!= start
: raise Exception("expected '" + start
+ "'")
50 if not token
: raise Exception("expected '" + end
+ "', got EOF")
51 ast
.append(read_form(reader
))
56 def read_hash_map(reader
):
57 lst
= read_sequence(reader
, list, '{', '}')
58 return _hash_map(*lst
)
60 def read_list(reader
):
61 return read_sequence(reader
, _list
, '(', ')')
63 def read_vector(reader
):
64 return read_sequence(reader
, _vector
, '[', ']')
66 def read_form(reader
):
68 # reader macros/transforms
74 return _list(_symbol('quote'), read_form(reader
))
77 return _list(_symbol('quasiquote'), read_form(reader
))
80 return _list(_symbol('unquote'), read_form(reader
))
83 return _list(_symbol('splice-unquote'), read_form(reader
))
86 meta
= read_form(reader
)
87 return _list(_symbol('with-meta'), read_form(reader
), meta
)
90 return _list(_symbol('deref'), read_form(reader
))
93 elif token
== ')': raise Exception("unexpected ')'")
94 elif token
== '(': return read_list(reader
)
97 elif token
== ']': raise Exception("unexpected ']'");
98 elif token
== '[': return read_vector(reader
);
101 elif token
== '}': raise Exception("unexpected '}'");
102 elif token
== '{': return read_hash_map(reader
);
105 else: return read_atom(reader
);
108 tokens
= tokenize(str)
109 if len(tokens
) == 0: raise Blank("Blank Line")
110 return read_form(Reader(tokens
))