treetop 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/Rakefile +3 -2
- data/doc/contributing_and_planned_features.markdown +1 -1
- data/doc/using_in_ruby.markdown +2 -2
- data/examples/lambda_calculus/arithmetic.rb +551 -0
- data/examples/lambda_calculus/arithmetic_test.rb +1 -1
- data/examples/lambda_calculus/lambda_calculus.rb +39 -72
- data/examples/lambda_calculus/lambda_calculus_test.rb +2 -2
- data/examples/lambda_calculus/test_helper.rb +3 -3
- data/lib/treetop.rb +3 -0
- data/lib/treetop/bootstrap_gen_1_metagrammar.rb +22 -14
- data/lib/treetop/compiler.rb +1 -2
- data/lib/treetop/compiler/grammar_compiler.rb +12 -5
- data/lib/treetop/compiler/metagrammar.rb +931 -558
- data/lib/treetop/compiler/metagrammar.treetop +26 -6
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -2
- data/lib/treetop/compiler/node_classes/atomic_expression.rb +4 -0
- data/lib/treetop/compiler/node_classes/character_class.rb +10 -1
- data/lib/treetop/compiler/node_classes/choice.rb +2 -4
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +8 -17
- data/lib/treetop/compiler/node_classes/parsing_rule.rb +3 -3
- data/lib/treetop/compiler/node_classes/predicate.rb +1 -1
- data/lib/treetop/compiler/node_classes/repetition.rb +3 -4
- data/lib/treetop/compiler/node_classes/sequence.rb +4 -4
- data/lib/treetop/compiler/node_classes/terminal.rb +11 -1
- data/lib/treetop/compiler/ruby_builder.rb +2 -2
- data/lib/treetop/ruby_extensions.rb +1 -1
- data/lib/treetop/runtime.rb +0 -3
- data/lib/treetop/runtime/compiled_parser.rb +42 -34
- data/lib/treetop/runtime/node_cache.rb +1 -1
- data/lib/treetop/runtime/syntax_node.rb +51 -32
- data/lib/treetop/runtime/terminal_parse_failure.rb +7 -24
- data/lib/treetop/runtime/terminal_syntax_node.rb +7 -2
- metadata +12 -7
- data/examples/TALK +0 -33
- data/lib/treetop/compiler/load_grammar.rb +0 -7
- data/lib/treetop/compiler/metagrammar. +0 -0
- data/lib/treetop/runtime/parse_failure.rb +0 -32
- data/lib/treetop/runtime/parse_result.rb +0 -30
@@ -2,7 +2,7 @@ dir = File.dirname(__FILE__)
|
|
2
2
|
require File.expand_path("#{dir}/test_helper")
|
3
3
|
|
4
4
|
require File.expand_path("#{dir}/arithmetic_node_classes")
|
5
|
-
|
5
|
+
Treetop.load File.expand_path("#{dir}/arithmetic")
|
6
6
|
|
7
7
|
class ArithmeticParserTest < Test::Unit::TestCase
|
8
8
|
include ParserTestHelper
|
@@ -2,12 +2,7 @@ module LambdaCalculus
|
|
2
2
|
include Treetop::Runtime
|
3
3
|
|
4
4
|
def root
|
5
|
-
|
6
|
-
if index == input.size
|
7
|
-
return result
|
8
|
-
else
|
9
|
-
return ParseFailure.new(input, index, result.nested_failures)
|
10
|
-
end
|
5
|
+
@root || :program
|
11
6
|
end
|
12
7
|
|
13
8
|
include Arithmetic
|
@@ -55,13 +50,13 @@ module LambdaCalculus
|
|
55
50
|
return cached
|
56
51
|
end
|
57
52
|
|
58
|
-
i0, s0
|
53
|
+
i0, s0 = index, []
|
59
54
|
r1 = _nt_expression
|
60
55
|
s0 << r1
|
61
56
|
if r1.success?
|
62
|
-
s2,
|
57
|
+
s2, i2 = [], index
|
63
58
|
loop do
|
64
|
-
i3, s3
|
59
|
+
i3, s3 = index, []
|
65
60
|
r4 = parse_terminal(';', SyntaxNode)
|
66
61
|
s3 << r4
|
67
62
|
if r4.success?
|
@@ -77,16 +72,15 @@ module LambdaCalculus
|
|
77
72
|
r3.extend(Program0)
|
78
73
|
else
|
79
74
|
self.index = i3
|
80
|
-
r3 = ParseFailure.new(input, i3
|
75
|
+
r3 = ParseFailure.new(input, i3)
|
81
76
|
end
|
82
|
-
nr2 << r3
|
83
77
|
if r3.success?
|
84
78
|
s2 << r3
|
85
79
|
else
|
86
80
|
break
|
87
81
|
end
|
88
82
|
end
|
89
|
-
r2 = SyntaxNode.new(input, i2...index, s2
|
83
|
+
r2 = SyntaxNode.new(input, i2...index, s2)
|
90
84
|
s0 << r2
|
91
85
|
end
|
92
86
|
if s0.last.success?
|
@@ -95,7 +89,7 @@ module LambdaCalculus
|
|
95
89
|
r0.extend(Program2)
|
96
90
|
else
|
97
91
|
self.index = i0
|
98
|
-
r0 = ParseFailure.new(input, i0
|
92
|
+
r0 = ParseFailure.new(input, i0)
|
99
93
|
end
|
100
94
|
|
101
95
|
node_cache[:program][start_index] = r0
|
@@ -111,39 +105,29 @@ module LambdaCalculus
|
|
111
105
|
return cached
|
112
106
|
end
|
113
107
|
|
114
|
-
i0
|
108
|
+
i0 = index
|
115
109
|
r1 = _nt_definition
|
116
|
-
nr0 << r1
|
117
110
|
if r1.success?
|
118
111
|
r0 = r1
|
119
|
-
r1.update_nested_results(nr0)
|
120
112
|
else
|
121
113
|
r2 = _nt_conditional
|
122
|
-
nr0 << r2
|
123
114
|
if r2.success?
|
124
115
|
r0 = r2
|
125
|
-
r2.update_nested_results(nr0)
|
126
116
|
else
|
127
117
|
r3 = _nt_application
|
128
|
-
nr0 << r3
|
129
118
|
if r3.success?
|
130
119
|
r0 = r3
|
131
|
-
r3.update_nested_results(nr0)
|
132
120
|
else
|
133
121
|
r4 = _nt_function
|
134
|
-
nr0 << r4
|
135
122
|
if r4.success?
|
136
123
|
r0 = r4
|
137
|
-
r4.update_nested_results(nr0)
|
138
124
|
else
|
139
125
|
r5 = super
|
140
|
-
nr0 << r5
|
141
126
|
if r5.success?
|
142
127
|
r0 = r5
|
143
|
-
r5.update_nested_results(nr0)
|
144
128
|
else
|
145
129
|
self.index = i0
|
146
|
-
r0 = ParseFailure.new(input, i0
|
130
|
+
r0 = ParseFailure.new(input, i0)
|
147
131
|
end
|
148
132
|
end
|
149
133
|
end
|
@@ -187,7 +171,7 @@ module LambdaCalculus
|
|
187
171
|
return cached
|
188
172
|
end
|
189
173
|
|
190
|
-
i0, s0
|
174
|
+
i0, s0 = index, []
|
191
175
|
r1 = parse_terminal('def', SyntaxNode)
|
192
176
|
s0 << r1
|
193
177
|
if r1.success?
|
@@ -212,7 +196,7 @@ module LambdaCalculus
|
|
212
196
|
r0.extend(Definition1)
|
213
197
|
else
|
214
198
|
self.index = i0
|
215
|
-
r0 = ParseFailure.new(input, i0
|
199
|
+
r0 = ParseFailure.new(input, i0)
|
216
200
|
end
|
217
201
|
|
218
202
|
node_cache[:definition][start_index] = r0
|
@@ -276,7 +260,7 @@ module LambdaCalculus
|
|
276
260
|
return cached
|
277
261
|
end
|
278
262
|
|
279
|
-
i0, s0
|
263
|
+
i0, s0 = index, []
|
280
264
|
r1 = parse_terminal('if', SyntaxNode)
|
281
265
|
s0 << r1
|
282
266
|
if r1.success?
|
@@ -333,7 +317,7 @@ module LambdaCalculus
|
|
333
317
|
r0.extend(Conditional1)
|
334
318
|
else
|
335
319
|
self.index = i0
|
336
|
-
r0 = ParseFailure.new(input, i0
|
320
|
+
r0 = ParseFailure.new(input, i0)
|
337
321
|
end
|
338
322
|
|
339
323
|
node_cache[:conditional][start_index] = r0
|
@@ -349,21 +333,17 @@ module LambdaCalculus
|
|
349
333
|
return cached
|
350
334
|
end
|
351
335
|
|
352
|
-
i0
|
336
|
+
i0 = index
|
353
337
|
r1 = _nt_application
|
354
|
-
nr0 << r1
|
355
338
|
if r1.success?
|
356
339
|
r0 = r1
|
357
|
-
r1.update_nested_results(nr0)
|
358
340
|
else
|
359
341
|
r2 = super
|
360
|
-
nr0 << r2
|
361
342
|
if r2.success?
|
362
343
|
r0 = r2
|
363
|
-
r2.update_nested_results(nr0)
|
364
344
|
else
|
365
345
|
self.index = i0
|
366
|
-
r0 = ParseFailure.new(input, i0
|
346
|
+
r0 = ParseFailure.new(input, i0)
|
367
347
|
end
|
368
348
|
end
|
369
349
|
|
@@ -412,7 +392,7 @@ module LambdaCalculus
|
|
412
392
|
return cached
|
413
393
|
end
|
414
394
|
|
415
|
-
i0, s0
|
395
|
+
i0, s0 = index, []
|
416
396
|
r1 = _nt_operator
|
417
397
|
s0 << r1
|
418
398
|
if r1.success?
|
@@ -429,7 +409,7 @@ module LambdaCalculus
|
|
429
409
|
r0.extend(Application1)
|
430
410
|
else
|
431
411
|
self.index = i0
|
432
|
-
r0 = ParseFailure.new(input, i0
|
412
|
+
r0 = ParseFailure.new(input, i0)
|
433
413
|
end
|
434
414
|
|
435
415
|
node_cache[:application][start_index] = r0
|
@@ -445,21 +425,17 @@ module LambdaCalculus
|
|
445
425
|
return cached
|
446
426
|
end
|
447
427
|
|
448
|
-
i0
|
428
|
+
i0 = index
|
449
429
|
r1 = _nt_function
|
450
|
-
nr0 << r1
|
451
430
|
if r1.success?
|
452
431
|
r0 = r1
|
453
|
-
r1.update_nested_results(nr0)
|
454
432
|
else
|
455
433
|
r2 = _nt_variable
|
456
|
-
nr0 << r2
|
457
434
|
if r2.success?
|
458
435
|
r0 = r2
|
459
|
-
r2.update_nested_results(nr0)
|
460
436
|
else
|
461
437
|
self.index = i0
|
462
|
-
r0 = ParseFailure.new(input, i0
|
438
|
+
r0 = ParseFailure.new(input, i0)
|
463
439
|
end
|
464
440
|
end
|
465
441
|
|
@@ -476,21 +452,17 @@ module LambdaCalculus
|
|
476
452
|
return cached
|
477
453
|
end
|
478
454
|
|
479
|
-
i0
|
455
|
+
i0 = index
|
480
456
|
r1 = _nt_function
|
481
|
-
nr0 << r1
|
482
457
|
if r1.success?
|
483
458
|
r0 = r1
|
484
|
-
r1.update_nested_results(nr0)
|
485
459
|
else
|
486
460
|
r2 = _nt_variable
|
487
|
-
nr0 << r2
|
488
461
|
if r2.success?
|
489
462
|
r0 = r2
|
490
|
-
r2.update_nested_results(nr0)
|
491
463
|
else
|
492
464
|
self.index = i0
|
493
|
-
r0 = ParseFailure.new(input, i0
|
465
|
+
r0 = ParseFailure.new(input, i0)
|
494
466
|
end
|
495
467
|
end
|
496
468
|
|
@@ -545,7 +517,7 @@ module LambdaCalculus
|
|
545
517
|
return cached
|
546
518
|
end
|
547
519
|
|
548
|
-
i0, s0
|
520
|
+
i0, s0 = index, []
|
549
521
|
r1 = parse_terminal('\\', SyntaxNode)
|
550
522
|
s0 << r1
|
551
523
|
if r1.success?
|
@@ -570,7 +542,7 @@ module LambdaCalculus
|
|
570
542
|
r0.extend(Function1)
|
571
543
|
else
|
572
544
|
self.index = i0
|
573
|
-
r0 = ParseFailure.new(input, i0
|
545
|
+
r0 = ParseFailure.new(input, i0)
|
574
546
|
end
|
575
547
|
|
576
548
|
node_cache[:function][start_index] = r0
|
@@ -599,14 +571,14 @@ module LambdaCalculus
|
|
599
571
|
return cached
|
600
572
|
end
|
601
573
|
|
602
|
-
i0, s0
|
574
|
+
i0, s0 = index, []
|
603
575
|
i1 = index
|
604
576
|
r2 = _nt_keyword
|
605
577
|
if r2.success?
|
606
|
-
r1 = ParseFailure.new(input, i1
|
578
|
+
r1 = ParseFailure.new(input, i1)
|
607
579
|
else
|
608
580
|
self.index = i1
|
609
|
-
r1 = SyntaxNode.new(input, index...index
|
581
|
+
r1 = SyntaxNode.new(input, index...index)
|
610
582
|
end
|
611
583
|
s0 << r1
|
612
584
|
if r1.success?
|
@@ -619,7 +591,7 @@ module LambdaCalculus
|
|
619
591
|
r0.extend(Variable1)
|
620
592
|
else
|
621
593
|
self.index = i0
|
622
|
-
r0 = ParseFailure.new(input, i0
|
594
|
+
r0 = ParseFailure.new(input, i0)
|
623
595
|
end
|
624
596
|
|
625
597
|
node_cache[:variable][start_index] = r0
|
@@ -638,22 +610,18 @@ module LambdaCalculus
|
|
638
610
|
return cached
|
639
611
|
end
|
640
612
|
|
641
|
-
i0, s0
|
642
|
-
i1
|
613
|
+
i0, s0 = index, []
|
614
|
+
i1 = index
|
643
615
|
r2 = parse_terminal('if', SyntaxNode)
|
644
|
-
nr1 << r2
|
645
616
|
if r2.success?
|
646
617
|
r1 = r2
|
647
|
-
r2.update_nested_results(nr1)
|
648
618
|
else
|
649
619
|
r3 = parse_terminal('else', SyntaxNode)
|
650
|
-
nr1 << r3
|
651
620
|
if r3.success?
|
652
621
|
r1 = r3
|
653
|
-
r3.update_nested_results(nr1)
|
654
622
|
else
|
655
623
|
self.index = i1
|
656
|
-
r1 = ParseFailure.new(input, i1
|
624
|
+
r1 = ParseFailure.new(input, i1)
|
657
625
|
end
|
658
626
|
end
|
659
627
|
s0 << r1
|
@@ -661,10 +629,10 @@ module LambdaCalculus
|
|
661
629
|
i4 = index
|
662
630
|
r5 = _nt_non_space_char
|
663
631
|
if r5.success?
|
664
|
-
r4 = ParseFailure.new(input, i4
|
632
|
+
r4 = ParseFailure.new(input, i4)
|
665
633
|
else
|
666
634
|
self.index = i4
|
667
|
-
r4 = SyntaxNode.new(input, index...index
|
635
|
+
r4 = SyntaxNode.new(input, index...index)
|
668
636
|
end
|
669
637
|
s0 << r4
|
670
638
|
end
|
@@ -673,7 +641,7 @@ module LambdaCalculus
|
|
673
641
|
r0.extend(Keyword0)
|
674
642
|
else
|
675
643
|
self.index = i0
|
676
|
-
r0 = ParseFailure.new(input, i0
|
644
|
+
r0 = ParseFailure.new(input, i0)
|
677
645
|
end
|
678
646
|
|
679
647
|
node_cache[:keyword][start_index] = r0
|
@@ -692,14 +660,14 @@ module LambdaCalculus
|
|
692
660
|
return cached
|
693
661
|
end
|
694
662
|
|
695
|
-
i0, s0
|
663
|
+
i0, s0 = index, []
|
696
664
|
i1 = index
|
697
665
|
r2 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
|
698
666
|
if r2.success?
|
699
|
-
r1 = ParseFailure.new(input, i1
|
667
|
+
r1 = ParseFailure.new(input, i1)
|
700
668
|
else
|
701
669
|
self.index = i1
|
702
|
-
r1 = SyntaxNode.new(input, index...index
|
670
|
+
r1 = SyntaxNode.new(input, index...index)
|
703
671
|
end
|
704
672
|
s0 << r1
|
705
673
|
if r1.success?
|
@@ -711,7 +679,7 @@ module LambdaCalculus
|
|
711
679
|
r0.extend(NonSpaceChar0)
|
712
680
|
else
|
713
681
|
self.index = i0
|
714
|
-
r0 = ParseFailure.new(input, i0
|
682
|
+
r0 = ParseFailure.new(input, i0)
|
715
683
|
end
|
716
684
|
|
717
685
|
node_cache[:non_space_char][start_index] = r0
|
@@ -727,17 +695,16 @@ module LambdaCalculus
|
|
727
695
|
return cached
|
728
696
|
end
|
729
697
|
|
730
|
-
s0,
|
698
|
+
s0, i0 = [], index
|
731
699
|
loop do
|
732
700
|
r1 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
|
733
|
-
nr0 << r1
|
734
701
|
if r1.success?
|
735
702
|
s0 << r1
|
736
703
|
else
|
737
704
|
break
|
738
705
|
end
|
739
706
|
end
|
740
|
-
r0 = SyntaxNode.new(input, i0...index, s0
|
707
|
+
r0 = SyntaxNode.new(input, i0...index, s0)
|
741
708
|
|
742
709
|
node_cache[:space][start_index] = r0
|
743
710
|
|
@@ -2,8 +2,8 @@ dir = File.dirname(__FILE__)
|
|
2
2
|
require File.expand_path("#{dir}/test_helper")
|
3
3
|
require File.expand_path("#{dir}/arithmetic_node_classes")
|
4
4
|
require File.expand_path("#{dir}/lambda_calculus_node_classes")
|
5
|
-
|
6
|
-
|
5
|
+
Treetop.load File.expand_path("#{dir}/arithmetic")
|
6
|
+
Treetop.load File.expand_path("#{dir}/lambda_calculus")
|
7
7
|
|
8
8
|
class Treetop::Runtime::SyntaxNode
|
9
9
|
def method_missing(method, *args)
|
@@ -9,10 +9,10 @@ module ParserTestHelper
|
|
9
9
|
|
10
10
|
def parse(input)
|
11
11
|
result = @parser.parse(input)
|
12
|
-
|
13
|
-
puts
|
12
|
+
unless result
|
13
|
+
puts @parser.terminal_failures.join("\n")
|
14
14
|
end
|
15
|
-
assert result.
|
15
|
+
assert !result.nil?
|
16
16
|
result
|
17
17
|
end
|
18
18
|
end
|
data/lib/treetop.rb
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
# This file's job is to load a Treetop::Compiler::Metagrammar and Treetop::Compiler::MetagrammarParser
|
2
|
+
# into the environment by compiling the current metagrammar.treetop using a trusted version of Treetop.
|
3
|
+
|
1
4
|
require 'rubygems'
|
2
5
|
dir = File.dirname(__FILE__)
|
3
6
|
|
7
|
+
TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP = '>= 1.1.5'
|
8
|
+
|
4
9
|
# Loading trusted version of Treetop to compile the compiler
|
5
|
-
|
10
|
+
gem_spec = Gem.source_index.find_name('treetop', TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP).last
|
11
|
+
raise "Install a Treetop Gem version #{TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP} to bootstrap." unless gem_spec
|
12
|
+
trusted_treetop_path = gem_spec.full_gem_path
|
6
13
|
require File.join(trusted_treetop_path, 'lib', 'treetop')
|
7
14
|
|
8
15
|
# Relocating trusted version of Treetop to Trusted::Treetop
|
@@ -12,10 +19,8 @@ Object.send(:remove_const, :Treetop)
|
|
12
19
|
Object.send(:remove_const, :TREETOP_ROOT)
|
13
20
|
|
14
21
|
# Requiring version of Treetop that is under test
|
22
|
+
$exclude_metagrammar = true
|
15
23
|
require File.expand_path(File.join(dir, '..', 'treetop'))
|
16
|
-
# Remove stale Metagrammar defined by the generated metagrammar.rb in system under test
|
17
|
-
Treetop::Compiler.send(:remove_const, :Metagrammar)
|
18
|
-
Treetop::Compiler.send(:remove_const, :MetagrammarParser)
|
19
24
|
|
20
25
|
# Compile and evaluate freshly generated metagrammar source
|
21
26
|
METAGRAMMAR_PATH = File.join(TREETOP_ROOT, 'compiler', 'metagrammar.treetop')
|
@@ -23,15 +28,18 @@ compiled_metagrammar_source = Trusted::Treetop::Compiler::GrammarCompiler.new.ru
|
|
23
28
|
Object.class_eval(compiled_metagrammar_source)
|
24
29
|
|
25
30
|
# The compiler under test was compiled with the trusted grammar and therefore depends on its runtime
|
26
|
-
# But the runtime in the global namespace is the new runtime. We therefore inject the
|
27
|
-
# into the compiler so its parser functions correctly
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
# But the runtime in the global namespace is the new runtime. We therefore inject the trusted runtime
|
32
|
+
# into the compiler so its parser functions correctly. It will still not work for custom classes that
|
33
|
+
# explicitly subclass the wrong runtime. For now I am working around this by keeping 1 generation of
|
34
|
+
# backward compatibility in these cases.
|
35
|
+
# Treetop::Compiler::Metagrammar.module_eval do
|
36
|
+
# include Trusted::Treetop::Runtime
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Treetop::Compiler.send(:remove_const, :MetagrammarParser)
|
40
|
+
# class Treetop::Compiler::MetagrammarParser < Trusted::Treetop::Runtime::CompiledParser
|
41
|
+
# include Treetop::Compiler::Metagrammar
|
42
|
+
# include Trusted::Treetop::Runtime
|
43
|
+
# end
|
36
44
|
|
37
45
|
$bootstrapped_gen_1_metagrammar = true
|