treetop 1.1.4 → 1.2.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/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
|