babel_bridge 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +6 -0
- data/lib/nodes.rb +1 -1
- data/lib/nodes/empty_node.rb +1 -20
- data/lib/nodes/node.rb +33 -32
- data/lib/nodes/non_terminal_node.rb +10 -13
- data/lib/nodes/root_node.rb +4 -0
- data/lib/nodes/rule_node.rb +97 -44
- data/lib/nodes/terminal_node.rb +3 -3
- data/lib/parser.rb +95 -61
- data/lib/pattern_element.rb +71 -43
- data/lib/rule.rb +12 -6
- data/lib/rule_variant.rb +39 -15
- data/lib/string.rb +2 -9
- data/lib/tools.rb +26 -6
- data/lib/version.rb +2 -1
- data/spec/advanced_parsers_spec.rb +49 -0
- data/spec/basic_parsing_spec.rb +94 -0
- data/spec/bb_spec.rb +7 -163
- data/spec/ignore_whitespace_spec.rb +227 -0
- data/spec/inspect_spec.rb +50 -0
- data/spec/many_spec.rb +60 -0
- data/spec/node_spec.rb +117 -0
- data/spec/pattern_generators_spec.rb +41 -0
- data/spec/rule_parsing_spec.rb +61 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/tools_spec.rb +21 -0
- metadata +13 -4
- data/lib/nodes/many_node.rb +0 -53
- data/test/test_bb.rb +0 -458
- data/test/test_helper.rb +0 -44
data/test/test_bb.rb
DELETED
@@ -1,458 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__),"..","lib","babel_bridge"))
|
2
|
-
require File.expand_path(File.join(File.dirname(__FILE__),"test_helper"))
|
3
|
-
|
4
|
-
class BBTests < TestHelper
|
5
|
-
|
6
|
-
def new_module
|
7
|
-
@module_counter||=0
|
8
|
-
@module_counter+=1
|
9
|
-
"TestModule#{@module_counter}"
|
10
|
-
end
|
11
|
-
|
12
|
-
def new_parser(&block)
|
13
|
-
@parser_counter||=0
|
14
|
-
@parser_counter+=1
|
15
|
-
Object.const_set(klass_name="TestParser#{@parser_counter}",Class.new(BabelBridge::Parser,&block))
|
16
|
-
Object.const_get(klass_name).new
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_foobar
|
20
|
-
parser=new_parser do #Class.new BabelBridge::Parser do
|
21
|
-
rule :foo, "foo", :bar
|
22
|
-
rule :bar, "bar"
|
23
|
-
end
|
24
|
-
|
25
|
-
assert_nil parser.parse("foo")
|
26
|
-
assert parser.parse("foobar")
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_as
|
30
|
-
parser=new_parser do
|
31
|
-
rule :foo, match("foo").as(:boo)
|
32
|
-
end
|
33
|
-
|
34
|
-
assert parser.parse("foo")
|
35
|
-
assert_equal "foo", parser.parse("foo").boo.text
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_many_as
|
39
|
-
parser=new_parser do
|
40
|
-
rule :foo, many("foo").as(:boo)
|
41
|
-
end
|
42
|
-
|
43
|
-
assert parser.parse("foo")
|
44
|
-
assert parser.parse("foofoo")
|
45
|
-
assert_equal "foofoo", parser.parse("foofoo").boo.text
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_negative
|
49
|
-
parser=new_parser do
|
50
|
-
rule :foo, match!("boo"), /[a-zA-Z]+/
|
51
|
-
end
|
52
|
-
|
53
|
-
assert_nil parser.parse("boo")
|
54
|
-
assert parser.parse("foo")
|
55
|
-
assert parser.parse("boO")
|
56
|
-
assert parser.parse("abc")
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_foo
|
60
|
-
parser=new_parser do
|
61
|
-
rule :foo, "foo"
|
62
|
-
end
|
63
|
-
|
64
|
-
assert p=parser.parse("foo")
|
65
|
-
assert_equal 0,p.offset
|
66
|
-
assert_equal 3,p.match_length
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_regex
|
70
|
-
parser=new_parser do
|
71
|
-
rule :foo, /[0-9]+/
|
72
|
-
end
|
73
|
-
|
74
|
-
%w{ 0 1 10 123 1001 }.each do |numstr|
|
75
|
-
assert_equal numstr,parser.parse(numstr).text
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_regex_offset
|
80
|
-
parser=new_parser do
|
81
|
-
rule :foo, /[0-9]+/
|
82
|
-
rule :foo, "hi", /[0-9]+/
|
83
|
-
end
|
84
|
-
|
85
|
-
assert_equal 1,parser.parse("123").matches.length
|
86
|
-
assert_equal 2,parser.parse("hi123").matches.length
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_optional
|
90
|
-
parser=new_parser do
|
91
|
-
rule :foo, "foo", :bar?
|
92
|
-
rule :bar, "bar"
|
93
|
-
end
|
94
|
-
|
95
|
-
assert parser.parse("foo")
|
96
|
-
assert parser.parse("foobar")
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_could
|
100
|
-
parser=new_parser do
|
101
|
-
rule :foo, could.match(/[a-z]/), /[a-zA-Z]+/
|
102
|
-
end
|
103
|
-
assert_nil parser.parse("FOO")
|
104
|
-
assert parser.parse("fOO")
|
105
|
-
assert parser.parse("foo")
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_optional_middle
|
109
|
-
parser=new_parser do
|
110
|
-
rule :foo, "foo", :bar?, "foo"
|
111
|
-
rule :bar, "bar"
|
112
|
-
end
|
113
|
-
|
114
|
-
assert parser.parse("foofoo")
|
115
|
-
assert parser.parse("foobarfoo")
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_greedy_optional_middle
|
119
|
-
parser=new_parser do
|
120
|
-
rule :foo, "foo", :bar?, "foo"
|
121
|
-
rule :bar, "foo"
|
122
|
-
end
|
123
|
-
|
124
|
-
assert_nil parser.parse("foofoo")
|
125
|
-
assert parser.parse("foofoofoo")
|
126
|
-
end
|
127
|
-
|
128
|
-
def test_not
|
129
|
-
parser=new_parser do
|
130
|
-
rule :foo, "foo", :bar!
|
131
|
-
rule :bar, "bar"
|
132
|
-
end
|
133
|
-
|
134
|
-
assert_nil parser.parse("foofud") # this should fail because it doesn't match the entire input
|
135
|
-
assert parser.parse("foofud",0,:foo)
|
136
|
-
assert parser.parse("foo")
|
137
|
-
assert_nil parser.parse("foobar")
|
138
|
-
end
|
139
|
-
|
140
|
-
def test_recursive
|
141
|
-
parser=new_parser do
|
142
|
-
rule :foo, "foo", :foo?
|
143
|
-
end
|
144
|
-
|
145
|
-
assert parser.parse("foo")
|
146
|
-
assert parser.parse("foofoo")
|
147
|
-
assert f=parser.parse("foofoofoo")
|
148
|
-
|
149
|
-
# assert_nil parser[:foo].parse("foobar")
|
150
|
-
end
|
151
|
-
|
152
|
-
def test_alternate
|
153
|
-
v1=nil
|
154
|
-
v2=nil
|
155
|
-
parser=new_parser do
|
156
|
-
v1=rule :foo, "foo"
|
157
|
-
v2=rule :foo, "bar"
|
158
|
-
end
|
159
|
-
|
160
|
-
assert r1=parser.parse("foo")
|
161
|
-
assert r2=parser.parse("bar")
|
162
|
-
assert_equal v1,r1.class
|
163
|
-
assert_equal v2,r2.class
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_add
|
167
|
-
parser=new_parser do
|
168
|
-
rule :add, :number, "+", :number
|
169
|
-
rule :number, /[0-9]+/
|
170
|
-
end
|
171
|
-
|
172
|
-
assert parser.parse("1+1")
|
173
|
-
assert parser.parse("987+123")
|
174
|
-
end
|
175
|
-
|
176
|
-
def test_method
|
177
|
-
parser=new_parser do
|
178
|
-
rule :number, /[0-9]+/ do
|
179
|
-
def number
|
180
|
-
text.to_i
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
assert p=parser.parse("123")
|
186
|
-
assert_equal 123,p.number
|
187
|
-
end
|
188
|
-
|
189
|
-
def test_adder
|
190
|
-
parser=new_parser do
|
191
|
-
rule :adder, :number, "+", :number do
|
192
|
-
def answer;
|
193
|
-
number[0].number + number[1].number
|
194
|
-
end
|
195
|
-
end
|
196
|
-
rule :number, /[0-9]+/ do
|
197
|
-
def number; text.to_i end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
|
202
|
-
assert p=parser.parse("123+654")
|
203
|
-
assert_equal 777,p.answer
|
204
|
-
end
|
205
|
-
|
206
|
-
def test_adder_multiplier
|
207
|
-
parser=new_parser do
|
208
|
-
|
209
|
-
rule :adder, :multiplier, "+", :adder do
|
210
|
-
def value
|
211
|
-
multiplier.value + adder.value
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
rule :adder, :multiplier do
|
216
|
-
def value
|
217
|
-
multiplier.value
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
rule :multiplier, :number, "*", :multiplier do
|
222
|
-
def value
|
223
|
-
number.value * multiplier.value
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
rule :multiplier, :number do
|
228
|
-
def value
|
229
|
-
number.value
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
rule :number, /[0-9]+/ do
|
234
|
-
def value; text.to_i end
|
235
|
-
end
|
236
|
-
|
237
|
-
end
|
238
|
-
|
239
|
-
assert_equal 123,parser.parse("123").value
|
240
|
-
assert_equal 369,parser.parse("123*3").value
|
241
|
-
assert_equal 370,parser.parse("123*3+1").value
|
242
|
-
assert_equal 129,parser.parse("123+3*2").value
|
243
|
-
assert_equal 777,parser.parse("123+654").value
|
244
|
-
assert_equal 281,parser.parse("20*4+1+100*2").value
|
245
|
-
end
|
246
|
-
|
247
|
-
def test_rule_class
|
248
|
-
parser=new_parser do
|
249
|
-
rule :foo, "foo"
|
250
|
-
rule :foo, "bar"
|
251
|
-
node_class :foo do
|
252
|
-
def value; text end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
assert_equal "foo",parser.parse("foo").value
|
257
|
-
assert_equal "bar",parser.parse("bar").value
|
258
|
-
end
|
259
|
-
|
260
|
-
def test_indexed_match_reference_with_optional
|
261
|
-
parser=new_parser do
|
262
|
-
rule :foo, :bar, :boo?, :bar do
|
263
|
-
def outter
|
264
|
-
bar[0].text + bar[1].text
|
265
|
-
end
|
266
|
-
end
|
267
|
-
rule :bar, /[0-9]+,?/
|
268
|
-
rule :boo, /[A-Z]+,?/
|
269
|
-
end
|
270
|
-
|
271
|
-
assert_equal "1,2", parser.parse("1,2").outter
|
272
|
-
assert_equal "1,3", parser.parse("1,A,3").outter
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
def test_verbose
|
277
|
-
parser=new_parser do
|
278
|
-
rule :foo, {:match=>"foo"}, {:match=>"bar",:optional=>true}
|
279
|
-
end
|
280
|
-
|
281
|
-
assert parser.parse("foo")
|
282
|
-
assert parser.parse("foobar")
|
283
|
-
end
|
284
|
-
|
285
|
-
def test_custom_parser
|
286
|
-
parser=new_parser do
|
287
|
-
rule :foo, {:parser=>lambda do |parent_node|
|
288
|
-
offset=parent_node.next
|
289
|
-
src=parent_node.src
|
290
|
-
|
291
|
-
# Note, the \A anchors the search at the beginning of the string
|
292
|
-
if src[offset..-1].index(/\A[A-Z]+/)==0
|
293
|
-
endpattern=$~.to_s
|
294
|
-
if i=src.index(endpattern,offset+endpattern.length)
|
295
|
-
range = offset..(i+endpattern.length)
|
296
|
-
BabelBridge::TerminalNode.new(parent_node,range,"endpattern")
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end}
|
300
|
-
end
|
301
|
-
|
302
|
-
assert parser.parse("END this is in the middle END")
|
303
|
-
assert_equal "END this is in END",parser.parse("END this is in END the middle END",0,:foo).text
|
304
|
-
assert_nil parser.parse("END this is in the middle EN")
|
305
|
-
assert_nil parser.parse(" END this is in the middle END")
|
306
|
-
end
|
307
|
-
|
308
|
-
def test_poly
|
309
|
-
parser=new_parser do
|
310
|
-
rule :foo, many("foo").as(:foo)
|
311
|
-
end
|
312
|
-
assert_equal ["foo"], parser.parse("foo").foo.collect {|f| f.text}
|
313
|
-
assert_equal ["foo","foo"], parser.parse("foofoo").foo.collect {|f| f.text}
|
314
|
-
assert_equal ["foo","foo","foo"], parser.parse("foofoofoo").foo.collect {|f| f.text}
|
315
|
-
end
|
316
|
-
|
317
|
-
def test_poly_delimiter
|
318
|
-
parser=new_parser do
|
319
|
-
rule :foo, many("foo",/ +/).as(:foo)
|
320
|
-
end
|
321
|
-
assert_equal ["foo"], parser.parse("foo").foo.collect {|f| f.text}
|
322
|
-
assert parser.parse("foo foo")
|
323
|
-
assert_equal ["foo","foo"], parser.parse("foo foo").foo.collect {|f| f.text}
|
324
|
-
end
|
325
|
-
|
326
|
-
def test_poly_optional_delimiter
|
327
|
-
parser=new_parser do
|
328
|
-
rule :foo, many(";",match?(/ +/))
|
329
|
-
end
|
330
|
-
assert parser.parse(";")
|
331
|
-
assert parser.parse_and_puts_errors(";;")
|
332
|
-
assert parser.parse("; ; ;")
|
333
|
-
end
|
334
|
-
|
335
|
-
def test_many
|
336
|
-
assert_equal({:many=>";",:match=>true}, BabelBridge::Parser.many(";"))
|
337
|
-
end
|
338
|
-
|
339
|
-
def test_many?
|
340
|
-
assert_equal({:many=>";", :optionally=>true, :match=>true}, BabelBridge::Parser.many?(";"))
|
341
|
-
end
|
342
|
-
|
343
|
-
def test_many!
|
344
|
-
assert_equal({:many=>";", :dont=>true, :match=>true}, BabelBridge::Parser.many!(";"))
|
345
|
-
end
|
346
|
-
|
347
|
-
def test_match
|
348
|
-
assert_equal({:match=>";"}, BabelBridge::Parser.match(";"))
|
349
|
-
end
|
350
|
-
|
351
|
-
def test_match?
|
352
|
-
assert_equal({:match=>";",:optionally=>true}, BabelBridge::Parser.match?(";"))
|
353
|
-
end
|
354
|
-
|
355
|
-
def test_match!
|
356
|
-
assert_equal({:match=>";",:dont=>true}, BabelBridge::Parser.match!(";"))
|
357
|
-
end
|
358
|
-
|
359
|
-
def test_dont
|
360
|
-
assert_equal({:match=>";",:dont=>true}, BabelBridge::Parser.dont.match(";"))
|
361
|
-
end
|
362
|
-
|
363
|
-
def test_optionally
|
364
|
-
assert_equal({:match=>";",:optionally=>true}, BabelBridge::Parser.optionally.match(";"))
|
365
|
-
end
|
366
|
-
|
367
|
-
def test_could
|
368
|
-
assert_equal({:match=>";",:could=>true}, BabelBridge::Parser.could.match(";"))
|
369
|
-
end
|
370
|
-
|
371
|
-
def test_ignore_whitespace
|
372
|
-
parser=new_parser do
|
373
|
-
ignore_whitespace
|
374
|
-
rule :pair, "foo", "bar"
|
375
|
-
end
|
376
|
-
assert parser.parse("foobar")
|
377
|
-
assert parser.parse("foo bar")
|
378
|
-
assert parser.parse("foobar ")
|
379
|
-
assert parser.parse("foo bar ")
|
380
|
-
end
|
381
|
-
|
382
|
-
def test_binary_operator_rule
|
383
|
-
parser=new_parser do
|
384
|
-
binary_operators_rule :bin_op, :int, ["**", [:/, :*], [:+, "-"]], :right_operators => ["**"] do
|
385
|
-
def evaluate
|
386
|
-
"(#{left.evaluate}#{operator}#{right.evaluate})"
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
rule :int, /[-]?[0-9]+/ do
|
391
|
-
def evaluate; to_s; end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
assert_equal "(1+2)", parser.parse("1+2").evaluate
|
395
|
-
assert_equal "((1+2)+3)", parser.parse("1+2+3").evaluate
|
396
|
-
assert_equal "(1+(2*3))", parser.parse("1+2*3").evaluate
|
397
|
-
assert_equal "((1*2)+3)", parser.parse("1*2+3").evaluate
|
398
|
-
assert_equal "(5**6)", parser.parse("5**6").evaluate
|
399
|
-
assert_equal "((1-2)+((3*4)/(5**6)))", parser.parse("1-2+3*4/5**6").evaluate
|
400
|
-
assert_equal "(5**(6**7))", parser.parse("5**6**7").evaluate
|
401
|
-
end
|
402
|
-
|
403
|
-
def test_dont_parser
|
404
|
-
parser = new_parser do
|
405
|
-
rule :option, dont.match(/msg.*/), /.*/
|
406
|
-
end
|
407
|
-
assert_nil parser.parse "msg test"
|
408
|
-
assert parser.parse "non test"
|
409
|
-
end
|
410
|
-
|
411
|
-
def test_line_col
|
412
|
-
assert_equal [1,1], "".line_col(0)
|
413
|
-
assert_equal [1,1], " ".line_col(0)
|
414
|
-
assert_equal [1,1], "a\nbb\nccc".line_col(0)
|
415
|
-
assert_equal [1,2], "a\nbb\nccc".line_col(1)
|
416
|
-
assert_equal [2,1], "a\nbb\nccc".line_col(2)
|
417
|
-
assert_equal [2,2], "a\nbb\nccc".line_col(3)
|
418
|
-
assert_equal [2,3], "a\nbb\nccc".line_col(4)
|
419
|
-
assert_equal [3,1], "a\nbb\nccc".line_col(5)
|
420
|
-
assert_equal [3,2], "a\nbb\nccc".line_col(6)
|
421
|
-
assert_equal [3,3], "a\nbb\nccc".line_col(7)
|
422
|
-
assert_equal [3,4], "a\nbb\nccc".line_col(8)
|
423
|
-
assert_equal [3,4], "a\nbb\nccc".line_col(9)
|
424
|
-
end
|
425
|
-
|
426
|
-
def disabled_test_recursive_block
|
427
|
-
# PEG does have this problem, so this isn't really an error
|
428
|
-
# But maybe in the future we'll handle it better.
|
429
|
-
# SBD: Disabled 2010-10-24
|
430
|
-
parser=new_parser do
|
431
|
-
rule :foo, :foo, ";"
|
432
|
-
rule :foo, "-"
|
433
|
-
|
434
|
-
end
|
435
|
-
parser.parse "-"
|
436
|
-
end
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
def regex_performance
|
441
|
-
parser=new_parser do
|
442
|
-
rule :foo, many(:element)
|
443
|
-
rule :element, /[0-9]+/
|
444
|
-
rule :element, "a"
|
445
|
-
end
|
446
|
-
|
447
|
-
str=("a"*10000)+"1"
|
448
|
-
start_time=Time.now
|
449
|
-
res=parser.parse(str)
|
450
|
-
end_time=Time.now
|
451
|
-
puts "time for matching string of length #{str.length}: #{((end_time-start_time)*1000).to_i}ms"
|
452
|
-
puts "parse tree size: #{res.element.length}"
|
453
|
-
assert res
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
tests=BBTests.new
|
458
|
-
tests.run_tests(ARGV.length>0 && ARGV)
|