1 types = require "./types.coffee"
2 _symbol = types._symbol
6 constructor: (@tokens) -> @position = 0
7 next: -> @tokens[@position++]
8 peek: -> @tokens[@position]
14 re = /[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/g
16 while (match = re.exec(str)[1]) != ""
17 continue if match[0] == ';'
23 if token.match /^-?[0-9]+$/ then parseInt token,10
24 else if token.match /^-?[0-9][0-9.]*$/ then parseFloat token,10
25 else if token[0] == '"'
26 token.slice(1, token.length-1)
28 .replace(/\\n/g, "\n")
29 .replace(/\\\\/g, "\\")
30 else if token[0] == ':' then types._keyword(token[1..])
31 else if token == "nil" then null
32 else if token == "true" then true
33 else if token == "false" then false
36 read_list = (rdr, start='(', end=')') ->
39 throw new Error "expected '" + start + "'" if token != start
40 while (token = rdr.peek()) != end
41 throw new Error "expected '" + end + "', got EOF" if !token
42 ast.push read_form rdr
46 read_vector = (rdr) ->
47 types._vector(read_list(rdr, '[', ']')...)
49 read_hash_map = (rdr) ->
50 types._hash_map(read_list(rdr, '{', '}')...)
55 when '\'' then [_symbol('quote'), read_form(rdr.skip())]
56 when '`' then [_symbol('quasiquote'), read_form(rdr.skip())]
57 when '~' then [_symbol('unquote'), read_form(rdr.skip())]
58 when '~@' then [_symbol('splice-unquote'), read_form(rdr.skip())]
60 meta = read_form(rdr.skip())
61 [_symbol('with-meta'), read_form(rdr), meta]
62 when '@' then [_symbol('deref'), read_form(rdr.skip())]
65 when ')' then throw new Error "unexpected ')'"
66 when '(' then read_list(rdr)
68 when ']' then throw new Error "unexpected ']'"
69 when '[' then read_vector(rdr)
71 when '}' then throw new Error "unexpected '}'"
72 when '{' then read_hash_map(rdr)
77 exports.BlankException = BlankException = (msg) -> null
79 exports.read_str = read_str = (str) ->
80 tokens = tokenize(str)
81 throw new BlankException() if tokens.length == 0
82 read_form(new Reader(tokens))
84 #console.log read_str "(1 \"two\" three)"
85 #console.log read_str "[1 2 3]"
86 #console.log read_str '{"abc" 123 "def" 456}'