treetop 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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