neg 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +168 -1
- data/TODO.txt +4 -5
- data/lib/neg.rb +1 -0
- data/lib/neg/errors.rb +66 -0
- data/lib/neg/input.rb +1 -1
- data/lib/neg/parser.rb +71 -49
- data/lib/neg/translator.rb +76 -0
- data/lib/neg/version.rb +2 -2
- data/spec/parser_alternative_spec.rb +8 -3
- data/spec/parser_character_spec.rb +2 -19
- data/spec/parser_lookahead_parser_spec.rb +18 -16
- data/spec/parser_non_terminal_spec.rb +9 -12
- data/spec/parser_repetition_spec.rb +5 -14
- data/spec/parser_sequence_spec.rb +2 -15
- data/spec/parser_spec.rb +15 -0
- data/spec/parser_string_spec.rb +3 -3
- data/spec/sample_arith_spec.rb +90 -0
- data/spec/sample_compact_spec.rb +50 -0
- data/spec/sample_json_parser_spec.rb +169 -50
- metadata +12 -2
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
|
5
|
+
describe 'sample compact arith parser' do
|
6
|
+
|
7
|
+
class CompactArithParser < Neg::Parser
|
8
|
+
|
9
|
+
parser do
|
10
|
+
|
11
|
+
expression == operation
|
12
|
+
|
13
|
+
operator == `+` | `-` | `*` | `/`
|
14
|
+
operation == value + (operator + value) * 0
|
15
|
+
value == parenthese | number
|
16
|
+
parenthese == `(` + expression + `)`
|
17
|
+
number == `-` * -1 + _('0-9') * 1
|
18
|
+
end
|
19
|
+
|
20
|
+
translator do
|
21
|
+
|
22
|
+
on(:number) { |n| n.result.to_i }
|
23
|
+
on(:operator) { |n| n.result }
|
24
|
+
on(:value) { |n| n.results.first }
|
25
|
+
|
26
|
+
on(:expression) { |n|
|
27
|
+
results = n.results.flatten(2)
|
28
|
+
results.size == 1 ? results.first : results
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'parses and translates' do
|
34
|
+
|
35
|
+
CompactArithParser.parse('0').should == 0
|
36
|
+
CompactArithParser.parse('101').should == 101
|
37
|
+
CompactArithParser.parse('(12)').should == 12
|
38
|
+
CompactArithParser.parse('1+2+3').should == [ 1, '+', 2, '+', 3 ]
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'does not translate if :translate => false' do
|
42
|
+
|
43
|
+
CompactArithParser.parse('0', :translate => false).should ==
|
44
|
+
[ :expression, [ 0, 1, 1 ], true, nil, [
|
45
|
+
[ :value, [ 0, 1, 1 ], true, nil, [
|
46
|
+
[ :number, [ 0, 1, 1 ], true, "0", [] ] ] ],
|
47
|
+
[ nil, [ 1, 1, 2 ], true, nil, [] ] ] ]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -6,81 +6,200 @@ describe 'sample JSON parser' do
|
|
6
6
|
|
7
7
|
class JsonParser < Neg::Parser
|
8
8
|
|
9
|
-
|
9
|
+
parser do
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#}
|
11
|
+
value ==
|
12
|
+
spaces? +
|
13
|
+
(object | array | string | number | btrue | bfalse | null) +
|
14
|
+
spaces?
|
16
15
|
|
17
|
-
|
18
|
-
# str('{') >> spaces? >>
|
19
|
-
# (entry >> (comma >> entry).repeat).maybe.as(:object) >>
|
20
|
-
# spaces? >> str('}')
|
21
|
-
#}
|
16
|
+
spaces? == _("\s\n\r") * 0
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
# string.as(:key) >> spaces? >>
|
26
|
-
# str(':') >> spaces? >>
|
27
|
-
# value.as(:val)
|
28
|
-
# ).as(:entry)
|
29
|
-
#}
|
18
|
+
object == `{` + (entry + (`,` + entry) * 0) * 0 + `}`
|
19
|
+
entry == spaces? + string + spaces? + `:` + value
|
30
20
|
|
31
|
-
|
21
|
+
array == `[` + (value + (`,` + value) * 0) * 0 + `]`
|
32
22
|
|
33
|
-
|
34
|
-
# str('"') >> (
|
35
|
-
# #str('\\') >> any | str('"').absent? >> any
|
36
|
-
# #(str('\\') | str('"').absent?) >> any
|
37
|
-
# (str('\\') >> any | match('[^"]')
|
38
|
-
# ).repeat.as(:string) >> str('"')
|
39
|
-
#}
|
23
|
+
string == `"` + ((`\\` + _) | _('^"')) * 0 + `"`
|
40
24
|
|
41
|
-
|
25
|
+
_digit == _("0-9")
|
42
26
|
|
43
|
-
|
27
|
+
number ==
|
28
|
+
`-` * -1 +
|
29
|
+
(`0` | (_("1-9") + _digit * 0)) +
|
30
|
+
(`.` + _digit * 1) * -1 +
|
31
|
+
(_("eE") + _("+-") * -1 + _digit * 1) * -1
|
44
32
|
|
45
|
-
|
46
|
-
|
33
|
+
btrue == `true`
|
34
|
+
bfalse == `false`
|
35
|
+
null == `null`
|
36
|
+
end
|
47
37
|
|
48
|
-
|
38
|
+
translator do
|
49
39
|
|
50
|
-
|
51
|
-
|
52
|
-
(`0` | (_("1-9") + digit * 0)) +
|
53
|
-
(`.` + digit * 1) * -1 +
|
54
|
-
(_("eE") + _("+-") * -1 + digit * 1) * -1
|
40
|
+
on(:value) { |n| n.results.first.first }
|
41
|
+
on(:spaces?) { throw nil }
|
55
42
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
43
|
+
on(:object) { |n|
|
44
|
+
f2 = n.results.flatten(2)
|
45
|
+
Hash[f2.any? ? [ f2.shift ] + f2.flatten(2) : []]
|
46
|
+
}
|
47
|
+
on(:array) { |n|
|
48
|
+
f2 = n.results.flatten(2)
|
49
|
+
f2.any? ? [ f2.shift ] + f2.flatten(2) : []
|
50
|
+
}
|
51
|
+
|
52
|
+
on(:string) { |n| eval(n.result) }
|
60
53
|
|
61
|
-
|
54
|
+
on(:number) { |n|
|
55
|
+
n.result.match(/[\.eE]/) ? n.result.to_f : n.result.to_i
|
56
|
+
}
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
58
|
+
on(:btrue) { true }
|
59
|
+
on(:bfalse) { false }
|
60
|
+
on(:null) { nil }
|
61
|
+
end
|
66
62
|
end
|
67
63
|
|
68
64
|
it 'parses "false"' do
|
69
65
|
|
70
|
-
|
71
|
-
|
66
|
+
JsonParser.parse("false", :translate => false).should ==
|
67
|
+
[ :value,
|
68
|
+
[ 0, 1, 1 ],
|
69
|
+
true,
|
70
|
+
nil,
|
71
|
+
[
|
72
|
+
[ :spaces?, [ 0, 1, 1 ], true, "", [] ],
|
73
|
+
[ nil, [ 0, 1, 1 ], true, nil, [
|
74
|
+
[:bfalse, [ 0, 1, 1 ], true, "false", [] ] ] ],
|
75
|
+
[ :spaces?, [ 5, 1, 6 ], true, "", [] ] ] ]
|
72
76
|
end
|
73
77
|
|
74
78
|
it 'parses "13"' do
|
75
79
|
|
76
|
-
|
77
|
-
|
80
|
+
JsonParser.parse("13", :translate => false).should ==
|
81
|
+
[ :value,
|
82
|
+
[ 0, 1, 1 ],
|
83
|
+
true,
|
84
|
+
nil,
|
85
|
+
[
|
86
|
+
[ :spaces?, [ 0, 1, 1 ], true, "", [] ],
|
87
|
+
[ nil, [ 0, 1, 1 ], true, nil, [
|
88
|
+
[:number, [ 0, 1, 1 ], true, "13", [] ] ] ],
|
89
|
+
[ :spaces?, [ 2, 1, 3 ], true, "", [] ] ] ]
|
78
90
|
end
|
79
91
|
|
80
92
|
it 'parses "-12"' do
|
81
93
|
|
82
|
-
|
83
|
-
|
94
|
+
JsonParser.parse("-12", :translate => false).should ==
|
95
|
+
[ :value,
|
96
|
+
[ 0, 1, 1 ],
|
97
|
+
true,
|
98
|
+
nil,
|
99
|
+
[
|
100
|
+
[ :spaces?, [ 0, 1, 1 ], true, "", [] ],
|
101
|
+
[ nil, [ 0, 1, 1 ], true, nil, [
|
102
|
+
[:number, [ 0, 1, 1 ], true, "-12", [] ] ] ],
|
103
|
+
[ :spaces?, [ 3, 1, 4 ], true, "", [] ] ] ]
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'translates "false"' do
|
107
|
+
|
108
|
+
JsonParser.parse("false").should == false
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'translates "13"' do
|
112
|
+
|
113
|
+
JsonParser.parse("13").should == 13
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'translates "-12"' do
|
117
|
+
|
118
|
+
JsonParser.parse("-12").should == -12
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'translates "-1.2"' do
|
122
|
+
|
123
|
+
JsonParser.parse("-1.2").should == -1.2
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'translates "-1.2e8"' do
|
127
|
+
|
128
|
+
JsonParser.parse("-1.2e8").should == -120000000.0
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'translates "-1e8"' do
|
132
|
+
|
133
|
+
JsonParser.parse("-1e8").should == -100000000.0
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'translates "null"' do
|
137
|
+
|
138
|
+
JsonParser.parse("null").should == nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'translates "[]"' do
|
142
|
+
|
143
|
+
JsonParser.parse("[]").should == []
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'translates "[ 1, 2, -3 ]"' do
|
147
|
+
|
148
|
+
JsonParser.parse("[ 1, 2, -3 ]").should == [ 1, 2, -3 ]
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'translates "[ 1, [ true, 2, false ], -3 ]"' do
|
152
|
+
|
153
|
+
JsonParser.parse("[ 1, [ true, 2, false ], -3 ]").should ==
|
154
|
+
[ 1, [ true, 2, false ], -3 ]
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'translates "" (empty string)' do
|
158
|
+
|
159
|
+
JsonParser.parse('""').should == ''
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'translates "a bc"' do
|
163
|
+
|
164
|
+
JsonParser.parse('"a bc"').should == 'a bc'
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'translates "a \"nada\" bc"' do
|
168
|
+
|
169
|
+
JsonParser.parse('"a \"nada\" bc"').should == 'a "nada" bc'
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'translates {} (empty object)' do
|
173
|
+
|
174
|
+
JsonParser.parse('{}').should == {}
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'translates { "a": 1, "b": "B" }' do
|
178
|
+
|
179
|
+
JsonParser.parse('{ "a": 1, "b": "B" }').should == { 'a' => 1, 'b' => 'B' }
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'translates { "a": [ 1, 2, "trois" ] }' do
|
183
|
+
|
184
|
+
JsonParser.parse('{ "a": [ 1, 2, "trois" ] }').should ==
|
185
|
+
{ 'a' => [ 1, 2, 'trois' ] }
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'tolerates newlines' do
|
189
|
+
|
190
|
+
JsonParser.parse(%{
|
191
|
+
[ 1,2
|
192
|
+
, 3
|
193
|
+
]
|
194
|
+
}).should ==
|
195
|
+
[ 1, 2, 3 ]
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'raises a ParseError on incorrect input' do
|
199
|
+
|
200
|
+
lambda do
|
201
|
+
JsonParser.parse("x")
|
202
|
+
end.should raise_error(Neg::ParseError, 'expected "{", got "x"')
|
84
203
|
end
|
85
204
|
end
|
86
205
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -51,8 +51,10 @@ extensions: []
|
|
51
51
|
extra_rdoc_files: []
|
52
52
|
files:
|
53
53
|
- Rakefile
|
54
|
+
- lib/neg/errors.rb
|
54
55
|
- lib/neg/input.rb
|
55
56
|
- lib/neg/parser.rb
|
57
|
+
- lib/neg/translator.rb
|
56
58
|
- lib/neg/version.rb
|
57
59
|
- lib/neg.rb
|
58
60
|
- spec/input_spec.rb
|
@@ -64,6 +66,8 @@ files:
|
|
64
66
|
- spec/parser_sequence_spec.rb
|
65
67
|
- spec/parser_spec.rb
|
66
68
|
- spec/parser_string_spec.rb
|
69
|
+
- spec/sample_arith_spec.rb
|
70
|
+
- spec/sample_compact_spec.rb
|
67
71
|
- spec/sample_json_parser_spec.rb
|
68
72
|
- spec/spec_helper.rb
|
69
73
|
- neg.gemspec
|
@@ -83,12 +87,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
87
|
- - ! '>='
|
84
88
|
- !ruby/object:Gem::Version
|
85
89
|
version: '0'
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
hash: -2623637621873378549
|
86
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
94
|
none: false
|
88
95
|
requirements:
|
89
96
|
- - ! '>='
|
90
97
|
- !ruby/object:Gem::Version
|
91
98
|
version: '0'
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
hash: -2623637621873378549
|
92
102
|
requirements: []
|
93
103
|
rubyforge_project: ruote
|
94
104
|
rubygems_version: 1.8.24
|