/
parser.cr
112 lines (89 loc) · 1.97 KB
/
parser.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
require "./lexer"
class JSON::Parser
def initialize(string_or_io : String | IO)
@lexer = JSON::Lexer.new(string_or_io)
next_token
end
def parse : Type
json = parse_value
check :EOF
json
end
private def parse_value
case token.type
when :INT
value_and_next_token token.int_value
when :FLOAT
value_and_next_token token.float_value
when :STRING
value_and_next_token token.string_value
when :null
value_and_next_token nil
when :true
value_and_next_token true
when :false
value_and_next_token false
when :"["
parse_array
when :"{"
parse_object
else
unexpected_token
end
end
private def parse_array
next_token
ary = [] of Type
if token.type != :"]"
while true
ary << parse_value
case token.type
when :","
next_token
unexpected_token if token.type == :"]"
when :"]"
break
end
end
end
next_token
ary
end
private def parse_object
next_token_expect_object_key
object = {} of String => Type
if token.type != :"}"
while true
check :STRING
key = token.string_value
next_token
check :":"
next_token
value = parse_value
object[key] = value
case token.type
when :","
next_token_expect_object_key
unexpected_token if token.type == :"}"
when :"}"
break
end
end
end
next_token
object
end
private delegate token, @lexer
private delegate next_token, @lexer
private delegate next_token_expect_object_key, @lexer
private def value_and_next_token(value)
next_token
value
end
private def check(token_type)
unexpected_token unless token.type == token_type
end
private def unexpected_token
raise ParseException.new("unexpected token '#{token}'", token.line_number, token.column_number)
end
end