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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# File 'lib/muskox.rb', line 16
def parse input
r = nil
schema_stack = [schema]
stack = [[ROOT, ROOT]]
lexer = Pure::Lexer.new input, :quirks_mode => true
lexer.lex do |type, value|
case type
when :property
if schema_stack.last["properties"] && schema_stack.last["properties"].keys.include?(value)
stack.push [type, value]
else
raise ParserError, "Unexpected property: #{value}"
end
when :array_begin
case stack.last.first
when :property
last = stack.last
matching_type expected_type(schema_stack.last, last), "array" do
stack.push [:array, []]
schema_stack.push(schema["properties"][last.last])
end
when ROOT
stack.push [:array, []]
else
raise "unknown stack type #{stack.last}"
end
when :array_end
array_top = stack.pop
case stack.last.first
when :property
schema_stack.pop
last = stack.pop
matching_type expected_type(schema_stack.last, last), "array" do
stack.last.last[last.last] = array_top.last
end
when :array
matching_type expected_type(schema_stack.last, last), "array" do
stack.last.last << array_top.last
end
when ROOT
matching_type schema_stack.last["type"], "array" do
r = stack.last.last
end
else
raise "unknown stack type #{stack.last}"
end
when :object_begin
case stack.last.first
when :property
last = stack.last
matching_type expected_type(schema_stack.last, last), "object" do
stack.push [:object, {}]
schema_stack.push(schema["properties"][last.last])
end
when ROOT
stack.push [:object, {}]
end
when :object_end
object_top = stack.pop
if schema_stack.last["required"] && !(schema_stack.last["required"] - object_top.last.keys).empty?
raise ParserError
end
case stack.last.first
when :property
schema_stack.pop
last = stack.pop
matching_type expected_type(schema_stack.last, last), "object", stack.last.first == :object do
stack.last.last[last.last] = object_top.last
end
when ROOT
matching_type schema_stack.last["type"], "object" do
r = object_top.last
end
else
raise "unknown stack type #{stack.last.first}"
end
when :integer, :string, :float, :boolean, :null
case stack.last.first
when :property
last = stack.pop
matching_type expected_type(schema_stack.last, last), type, stack.last.first == :object do
stack.last.last[last.last] = value
end
when :array
case schema_stack.last["items"]
when Hash
matching_type schema_stack.last["items"]["type"], type do
stack.last.last << value
end
when Array
matching_type schema_stack.last["items"][stack.last.last.size]["type"], type do
stack.last.last << value
end
else
raise "Unexpected items type #{schema_stack.last["items"]}"
end
when ROOT
matching_type schema_stack.last["type"], type do
r = stack.last.last
end
else
raise "unknown stack type #{stack.last.inspect}"
end
else
raise "unhandled token type: #{type}: #{value}"
end
end
r
end
|