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.
Files changed (39) hide show
  1. data/README +1 -1
  2. data/Rakefile +3 -2
  3. data/doc/contributing_and_planned_features.markdown +1 -1
  4. data/doc/using_in_ruby.markdown +2 -2
  5. data/examples/lambda_calculus/arithmetic.rb +551 -0
  6. data/examples/lambda_calculus/arithmetic_test.rb +1 -1
  7. data/examples/lambda_calculus/lambda_calculus.rb +39 -72
  8. data/examples/lambda_calculus/lambda_calculus_test.rb +2 -2
  9. data/examples/lambda_calculus/test_helper.rb +3 -3
  10. data/lib/treetop.rb +3 -0
  11. data/lib/treetop/bootstrap_gen_1_metagrammar.rb +22 -14
  12. data/lib/treetop/compiler.rb +1 -2
  13. data/lib/treetop/compiler/grammar_compiler.rb +12 -5
  14. data/lib/treetop/compiler/metagrammar.rb +931 -558
  15. data/lib/treetop/compiler/metagrammar.treetop +26 -6
  16. data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -2
  17. data/lib/treetop/compiler/node_classes/atomic_expression.rb +4 -0
  18. data/lib/treetop/compiler/node_classes/character_class.rb +10 -1
  19. data/lib/treetop/compiler/node_classes/choice.rb +2 -4
  20. data/lib/treetop/compiler/node_classes/parsing_expression.rb +8 -17
  21. data/lib/treetop/compiler/node_classes/parsing_rule.rb +3 -3
  22. data/lib/treetop/compiler/node_classes/predicate.rb +1 -1
  23. data/lib/treetop/compiler/node_classes/repetition.rb +3 -4
  24. data/lib/treetop/compiler/node_classes/sequence.rb +4 -4
  25. data/lib/treetop/compiler/node_classes/terminal.rb +11 -1
  26. data/lib/treetop/compiler/ruby_builder.rb +2 -2
  27. data/lib/treetop/ruby_extensions.rb +1 -1
  28. data/lib/treetop/runtime.rb +0 -3
  29. data/lib/treetop/runtime/compiled_parser.rb +42 -34
  30. data/lib/treetop/runtime/node_cache.rb +1 -1
  31. data/lib/treetop/runtime/syntax_node.rb +51 -32
  32. data/lib/treetop/runtime/terminal_parse_failure.rb +7 -24
  33. data/lib/treetop/runtime/terminal_syntax_node.rb +7 -2
  34. metadata +12 -7
  35. data/examples/TALK +0 -33
  36. data/lib/treetop/compiler/load_grammar.rb +0 -7
  37. data/lib/treetop/compiler/metagrammar. +0 -0
  38. data/lib/treetop/runtime/parse_failure.rb +0 -32
  39. 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
- load_grammar File.expand_path("#{dir}/arithmetic")
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
- result = _nt_program
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, nr0 = index, [], []
53
+ i0, s0 = index, []
59
54
  r1 = _nt_expression
60
55
  s0 << r1
61
56
  if r1.success?
62
- s2, nr2, i2 = [], [], index
57
+ s2, i2 = [], index
63
58
  loop do
64
- i3, s3, nr3 = index, [], []
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, s3)
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, nr2)
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, s0)
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, nr0 = index, []
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, nr0)
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, nr0 = index, [], []
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, s0)
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, nr0 = index, [], []
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, s0)
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, nr0 = index, []
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, nr0)
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, nr0 = index, [], []
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, s0)
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, nr0 = index, []
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, nr0)
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, nr0 = index, []
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, nr0)
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, nr0 = index, [], []
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, s0)
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, nr0 = index, [], []
574
+ i0, s0 = index, []
603
575
  i1 = index
604
576
  r2 = _nt_keyword
605
577
  if r2.success?
606
- r1 = ParseFailure.new(input, i1, r2.nested_failures)
578
+ r1 = ParseFailure.new(input, i1)
607
579
  else
608
580
  self.index = i1
609
- r1 = SyntaxNode.new(input, index...index, r2.nested_failures)
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, s0)
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, nr0 = index, [], []
642
- i1, nr1 = index, []
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, nr1)
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, r5.nested_failures)
632
+ r4 = ParseFailure.new(input, i4)
665
633
  else
666
634
  self.index = i4
667
- r4 = SyntaxNode.new(input, index...index, r5.nested_failures)
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, s0)
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, nr0 = index, [], []
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, r2.nested_failures)
667
+ r1 = ParseFailure.new(input, i1)
700
668
  else
701
669
  self.index = i1
702
- r1 = SyntaxNode.new(input, index...index, r2.nested_failures)
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, s0)
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, nr0, i0 = [], [], index
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, nr0)
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
- load_grammar File.expand_path("#{dir}/arithmetic")
6
- load_grammar File.expand_path("#{dir}/lambda_calculus")
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
- if result.failure?
13
- puts result.nested_failures.join("\n")
12
+ unless result
13
+ puts @parser.terminal_failures.join("\n")
14
14
  end
15
- assert result.success?
15
+ assert !result.nil?
16
16
  result
17
17
  end
18
18
  end
data/lib/treetop.rb CHANGED
@@ -8,3 +8,6 @@ TREETOP_ROOT = File.join(dir, 'treetop')
8
8
  require File.join(TREETOP_ROOT, "ruby_extensions")
9
9
  require File.join(TREETOP_ROOT, "runtime")
10
10
  require File.join(TREETOP_ROOT, "compiler")
11
+
12
+ require 'polyglot'
13
+ Polyglot.register(["treetop", "tt"], Treetop)
@@ -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
- trusted_treetop_path = Gem.source_index.find_name('treetop').last.full_gem_path
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 tursted runtime
27
- # into the compiler so its parser functions correctly
28
- Treetop::Compiler::Metagrammar.module_eval do
29
- include Trusted::Treetop::Runtime
30
- end
31
-
32
- Treetop::Compiler.send(:remove_const, :MetagrammarParser)
33
- class Treetop::Compiler::MetagrammarParser < Trusted::Treetop::Runtime::CompiledParser
34
- include Treetop::Compiler::Metagrammar
35
- end
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