treetop 1.5.3 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -13
  2. data/Rakefile +9 -3
  3. data/doc/pitfalls_and_advanced_techniques.markdown +1 -1
  4. data/doc/sitegen.rb +1 -1
  5. data/doc/syntactic_recognition.markdown +2 -0
  6. data/doc/tt.1 +1 -1
  7. data/lib/treetop/compiler/metagrammar.rb +81 -13
  8. data/lib/treetop/compiler/metagrammar.treetop +67 -13
  9. data/lib/treetop/compiler/node_classes/anything_symbol.rb +5 -1
  10. data/lib/treetop/compiler/node_classes/character_class.rb +6 -2
  11. data/lib/treetop/compiler/node_classes/choice.rb +9 -5
  12. data/lib/treetop/compiler/node_classes/nonterminal.rb +2 -2
  13. data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +5 -1
  14. data/lib/treetop/compiler/node_classes/parsing_expression.rb +12 -2
  15. data/lib/treetop/compiler/node_classes/predicate.rb +8 -1
  16. data/lib/treetop/compiler/node_classes/predicate_block.rb +7 -0
  17. data/lib/treetop/compiler/node_classes/repetition.rb +31 -11
  18. data/lib/treetop/compiler/node_classes/sequence.rb +5 -1
  19. data/lib/treetop/compiler/node_classes/terminal.rb +12 -2
  20. data/lib/treetop/runtime/compiled_parser.rb +12 -6
  21. data/lib/treetop/runtime/syntax_node.rb +24 -15
  22. data/lib/treetop/runtime/terminal_parse_failure.rb +4 -3
  23. data/lib/treetop/version.rb +2 -2
  24. data/spec/compiler/and_predicate_spec.rb +1 -1
  25. data/spec/compiler/anything_symbol_spec.rb +4 -1
  26. data/spec/compiler/character_class_spec.rb +4 -1
  27. data/spec/compiler/choice_spec.rb +20 -11
  28. data/spec/compiler/failure_propagation_functional_spec.rb +1 -1
  29. data/spec/compiler/grammar_spec.rb +4 -1
  30. data/spec/compiler/not_predicate_spec.rb +20 -6
  31. data/spec/compiler/occurrence_range_spec.rb +25 -28
  32. data/spec/compiler/one_or_more_spec.rb +2 -2
  33. data/spec/compiler/optional_spec.rb +2 -2
  34. data/spec/compiler/parenthesized_expression_spec.rb +15 -1
  35. data/spec/compiler/semantic_predicate_spec.rb +17 -16
  36. data/spec/compiler/sequence_spec.rb +1 -1
  37. data/spec/compiler/terminal_spec.rb +8 -1
  38. data/spec/compiler/terminal_symbol_spec.rb +4 -1
  39. data/spec/compiler/zero_or_more_spec.rb +4 -2
  40. data/spec/runtime/compiled_parser_spec.rb +33 -3
  41. metadata +20 -21
  42. data/examples/lambda_calculus/lambda_calculus +0 -0
@@ -1,8 +1,8 @@
1
1
  module Treetop #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 5
5
- TINY = 3
4
+ MINOR = 6
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -29,7 +29,7 @@ module AndPredicateSpec
29
29
  terminal_failures.size.should == 1
30
30
  failure = terminal_failures[0]
31
31
  failure.index.should == 3
32
- failure.expected_string.should == 'bar'
32
+ failure.expected_string.should == '"bar"'
33
33
  end
34
34
  end
35
35
  end
@@ -19,7 +19,10 @@ module AnythingSymbolSpec
19
19
  end
20
20
 
21
21
  it "fails to parse epsilon" do
22
- parse('').should be_nil
22
+ parse('') do |result|
23
+ result.should be_nil
24
+ parser.terminal_failures.size.should == 1
25
+ end
23
26
  end
24
27
  end
25
28
 
@@ -21,7 +21,10 @@ module CharacterClassSpec
21
21
  end
22
22
 
23
23
  it "does not match single characters outside of that range" do
24
- parse('8').should be_nil
24
+ parse('8') do |result|
25
+ result.should be_nil
26
+ parser.terminal_failures.size.should == 1
27
+ end
25
28
  parse('a').should be_nil
26
29
  end
27
30
 
@@ -2,42 +2,51 @@ require 'spec_helper'
2
2
 
3
3
  module ChoiceSpec
4
4
  describe "A choice between terminal symbols" do
5
- testing_expression '"foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }'
5
+ testing_expression '("foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }) {def bat_method; end}'
6
6
 
7
7
  it "successfully parses input matching any of the alternatives, returning a node that responds to methods defined in its respective inline module" do
8
8
  result = parse('foo')
9
9
  result.should_not be_nil
10
10
  result.should respond_to(:foo_method)
11
-
11
+ result.should_not respond_to(:bar_method)
12
+ result.should_not respond_to(:baz_method)
13
+ result.should respond_to(:bat_method)
14
+
12
15
  result = parse('bar')
13
16
  result.should_not be_nil
17
+ result.should_not respond_to(:foo_method)
14
18
  result.should respond_to(:bar_method)
15
-
19
+ result.should_not respond_to(:baz_method)
20
+ result.should respond_to(:bat_method)
21
+
16
22
  result = parse('baz')
17
23
  result.should_not be_nil
24
+ result.should_not respond_to(:foo_method)
25
+ result.should_not respond_to(:bar_method)
18
26
  result.should respond_to(:baz_method)
27
+ result.should respond_to(:bat_method)
19
28
  end
20
-
29
+
21
30
  it "upon parsing a string matching the second alternative, records the failure of the first terminal" do
22
31
  result = parse('bar')
23
32
  terminal_failures = parser.terminal_failures
24
33
  terminal_failures.size.should == 1
25
34
  failure = terminal_failures[0]
26
- failure.expected_string.should == 'foo'
35
+ failure.expected_string.should == '"foo"'
27
36
  failure.index.should == 0
28
37
  end
29
-
38
+
30
39
  it "upon parsing a string matching the third alternative, records the failure of the first two terminals" do
31
40
  result = parse('baz')
32
-
41
+
33
42
  terminal_failures = parser.terminal_failures
34
-
43
+
35
44
  terminal_failures.size.should == 2
36
45
 
37
46
  failure_1 = terminal_failures[0]
38
47
  failure_1.expected_string == 'foo'
39
48
  failure_1.index.should == 0
40
-
49
+
41
50
  failure_2 = terminal_failures[1]
42
51
  failure_2.expected_string == 'bar'
43
52
  failure_2.index.should == 0
@@ -53,7 +62,7 @@ module ChoiceSpec
53
62
  end
54
63
  end
55
64
 
56
- describe "A choice between terminals followed by a block" do
65
+ describe "A choice between terminals followed by a block" do
57
66
  testing_expression "('a'/ 'bb' / [c]) { def a_method; end }"
58
67
 
59
68
  it "extends a match of any of its subexpressions with a module created from the block" do
@@ -68,7 +77,7 @@ module ChoiceSpec
68
77
  end
69
78
  end
70
79
 
71
- describe "a choice followed by a declared module" do
80
+ describe "a choice followed by a declared module" do
72
81
  testing_expression "('a'/ 'bb' / [c]) <ChoiceSpec::TestModule>"
73
82
 
74
83
  it "extends a match of any of its subexpressions with a module created from the block" do
@@ -15,7 +15,7 @@ describe "An expression for braces surrounding zero or more letters followed by
15
15
  terminal_failures.size.should == 1
16
16
  failure = terminal_failures[0]
17
17
  failure.index.should == 6
18
- failure.expected_string.should == ';'
18
+ failure.expected_string.should == "';'"
19
19
  end
20
20
  end
21
21
  end
@@ -31,7 +31,10 @@ module GrammarSpec
31
31
  end
32
32
 
33
33
  it "fails if it does not parse all input" do
34
- parse('barbarbazbaz').should be_nil
34
+ parse('barbarbazbaz') do |result|
35
+ result.should be_nil
36
+ parser.terminal_failures.size.should == 1
37
+ end
35
38
  end
36
39
 
37
40
  it "mixes in included modules" do
@@ -5,7 +5,21 @@ module NotPredicateSpec
5
5
  testing_expression '!"foo"'
6
6
 
7
7
  it "fails to parse input matching the terminal symbol" do
8
- parse('foo').should be_nil
8
+ parse('foo') do |result|
9
+ result.should be_nil
10
+ parser.terminal_failures.size.should == 1
11
+ end
12
+ end
13
+ end
14
+
15
+ describe "A !-predicated character class symbol" do
16
+ testing_expression '![aeiou]'
17
+
18
+ it "fails to parse input matching the terminal symbol" do
19
+ parse('e') do |result|
20
+ result.should be_nil
21
+ parser.terminal_failures.size.should == 1
22
+ end
9
23
  end
10
24
  end
11
25
 
@@ -20,10 +34,7 @@ module NotPredicateSpec
20
34
  parse('foo') do |result|
21
35
  result.should_not be_nil
22
36
  terminal_failures = parser.terminal_failures
23
- terminal_failures.size.should == 1
24
- failure = terminal_failures.first
25
- failure.index.should == 3
26
- failure.expected_string.should == 'bar'
37
+ terminal_failures.size.should == 0
27
38
  end
28
39
  end
29
40
  end
@@ -32,7 +43,10 @@ module NotPredicateSpec
32
43
  testing_expression '!("a" "b" "cc")'
33
44
 
34
45
  it "fails to parse matching input" do
35
- parse('abcc').should be_nil
46
+ parse('abcc') do |result|
47
+ result.should be_nil
48
+ parser.terminal_failures.size.should == 1
49
+ end
36
50
  end
37
51
  end
38
52
  end
@@ -14,10 +14,7 @@ module OccurrenceRangeSpec
14
14
  result.should respond_to(:a_method)
15
15
 
16
16
  terminal_failures = parser.terminal_failures
17
- terminal_failures.size.should == 1
18
- failure = terminal_failures.first
19
- failure.index.should == 0
20
- failure.expected_string.should == 'foo'
17
+ terminal_failures.size.should == 0
21
18
  end
22
19
  end
23
20
 
@@ -28,10 +25,7 @@ module OccurrenceRangeSpec
28
25
  result.should respond_to(:a_method)
29
26
 
30
27
  terminal_failures = parser.terminal_failures
31
- terminal_failures.size.should == 1
32
- failure = terminal_failures.first
33
- failure.index.should == 0
34
- failure.expected_string.should == 'foo'
28
+ terminal_failures.size.should == 0
35
29
  end
36
30
  end
37
31
 
@@ -42,10 +36,7 @@ module OccurrenceRangeSpec
42
36
  result.should respond_to(:a_method)
43
37
 
44
38
  terminal_failures = parser.terminal_failures
45
- terminal_failures.size.should == 1
46
- failure = terminal_failures.first
47
- failure.index.should == 3
48
- failure.expected_string.should == 'foo'
39
+ terminal_failures.size.should == 0
49
40
  end
50
41
  end
51
42
 
@@ -60,14 +51,23 @@ module OccurrenceRangeSpec
60
51
  end
61
52
  end
62
53
 
63
- it "fails to parses three of that terminal, returning an instance of the declared node class and reporting no failure" do
54
+ it "fails to parses two of that terminal but fails because of an extra one" do
64
55
  parse("foofoofoo") do |result|
65
56
  result.should be_nil
66
57
 
67
- terminal_failures = parser.terminal_failures
68
- terminal_failures.size.should == 0
58
+ parser.terminal_failures.size.should == 1
69
59
  end
70
60
  end
61
+
62
+ it "parses two of three of that terminal, reporting no failure" do
63
+ parse("foofoofoo", :consume_all_input => false) do |result|
64
+ result.should_not be_nil
65
+ result.elements.size.should == 2
66
+
67
+ parser.terminal_failures.size.should == 0
68
+ end
69
+ end
70
+
71
71
  end
72
72
 
73
73
  describe "two to four of a terminal symbol followed by a node class declaration and a block" do
@@ -80,7 +80,7 @@ module OccurrenceRangeSpec
80
80
  terminal_failures.size.should == 1
81
81
  failure = terminal_failures.first
82
82
  failure.index.should == 0
83
- failure.expected_string.should == 'foo'
83
+ failure.expected_string.should == '"foo"'
84
84
  end
85
85
  end
86
86
 
@@ -92,7 +92,7 @@ module OccurrenceRangeSpec
92
92
  terminal_failures.size.should == 1
93
93
  failure = terminal_failures.first
94
94
  failure.index.should == 3
95
- failure.expected_string.should == 'foo'
95
+ failure.expected_string.should == '"foo"'
96
96
  end
97
97
  end
98
98
 
@@ -103,10 +103,7 @@ module OccurrenceRangeSpec
103
103
  result.should respond_to(:a_method)
104
104
 
105
105
  terminal_failures = parser.terminal_failures
106
- terminal_failures.size.should == 1
107
- failure = terminal_failures.first
108
- failure.index.should == 6
109
- failure.expected_string.should == 'foo'
106
+ terminal_failures.size.should == 0
110
107
  end
111
108
  end
112
109
 
@@ -117,16 +114,16 @@ module OccurrenceRangeSpec
117
114
  result.should respond_to(:a_method)
118
115
 
119
116
  terminal_failures = parser.terminal_failures
120
- terminal_failures.size.should == 0
117
+ terminal_failures.size.should == 0
121
118
  end
122
119
  end
123
120
 
124
- it "fails to parses five of that terminal, returning an instance of the declared node class and reporting no failure" do
121
+ it "fails to parses four of that terminal because there's an extra unconsumed one" do
125
122
  parse("foofoofoofoofoo") do |result|
126
123
  result.should be_nil
127
124
 
128
125
  terminal_failures = parser.terminal_failures
129
- terminal_failures.size.should == 0
126
+ terminal_failures.size.should == 1
130
127
  end
131
128
  end
132
129
  end
@@ -141,7 +138,7 @@ module OccurrenceRangeSpec
141
138
  terminal_failures.size.should == 1
142
139
  failure = terminal_failures.first
143
140
  failure.index.should == 0
144
- failure.expected_string.should == 'foo'
141
+ failure.expected_string.should == '"foo"'
145
142
  end
146
143
  end
147
144
 
@@ -153,7 +150,7 @@ module OccurrenceRangeSpec
153
150
  terminal_failures.size.should == 1
154
151
  failure = terminal_failures.first
155
152
  failure.index.should == 3
156
- failure.expected_string.should == 'foo'
153
+ failure.expected_string.should == '"foo"'
157
154
  end
158
155
  end
159
156
 
@@ -167,7 +164,7 @@ module OccurrenceRangeSpec
167
164
  terminal_failures.size.should == 1
168
165
  failure = terminal_failures.first
169
166
  failure.index.should == 6
170
- failure.expected_string.should == 'foo'
167
+ failure.expected_string.should == '"foo"'
171
168
  end
172
169
  end
173
170
 
@@ -181,7 +178,7 @@ module OccurrenceRangeSpec
181
178
  terminal_failures.size.should == 1
182
179
  failure = terminal_failures.first
183
180
  failure.index.should == 12
184
- failure.expected_string.should == 'foo'
181
+ failure.expected_string.should == '"foo"'
185
182
  end
186
183
  end
187
184
  end
@@ -14,7 +14,7 @@ module OneOrMoreSpec
14
14
  terminal_failures.size.should == 1
15
15
  failure = terminal_failures.first
16
16
  failure.index.should == 0
17
- failure.expected_string.should == 'foo'
17
+ failure.expected_string.should == '"foo"'
18
18
  end
19
19
  end
20
20
 
@@ -28,7 +28,7 @@ module OneOrMoreSpec
28
28
  terminal_failures.size.should == 1
29
29
  failure = terminal_failures.first
30
30
  failure.index.should == 6
31
- failure.expected_string.should == 'foo'
31
+ failure.expected_string.should == '"foo"'
32
32
  end
33
33
  end
34
34
  end
@@ -17,7 +17,7 @@ module OptionalSpec
17
17
  terminal_failures.size.should == 1
18
18
  failure = terminal_failures.first
19
19
  failure.index.should == 0
20
- failure.expected_string.should == 'foo'
20
+ failure.expected_string.should == '"foo"'
21
21
  end
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ module OptionalSpec
30
30
  terminal_failures.size.should == 1
31
31
  failure = terminal_failures.first
32
32
  failure.index.should == 0
33
- failure.expected_string.should == 'foo'
33
+ failure.expected_string.should == '"foo"'
34
34
  end
35
35
  end
36
36
  end
@@ -13,7 +13,21 @@ module ParenthesizedExpressionSpec
13
13
  testing_expression '(!"foo")'
14
14
 
15
15
  it "should behave as normal" do
16
- parse('foo').should be_nil
16
+ parse('foo') do |result|
17
+ result.should be_nil
18
+ parser.terminal_failures.size.should == 1
19
+ end
17
20
  end
18
21
  end
22
+
23
+ describe "An expression with code both inside and outside parentheses" do
24
+ testing_expression '("foo" { def inner; end } ) { def outer; end} '
25
+ it "should extend both code modules " do
26
+ parse('foo') do |result|
27
+ result.should respond_to(:inner)
28
+ result.should respond_to(:outer)
29
+ end
30
+ end
31
+ end
32
+
19
33
  end
@@ -17,7 +17,7 @@ module SemanticPredicateSpec
17
17
  parse('foo', :consume_all_input => false) do |result|
18
18
  result.should be_nil
19
19
  terminal_failures = parser.terminal_failures
20
- terminal_failures.size.should == 0
20
+ terminal_failures.size.should == 1
21
21
  end
22
22
  end
23
23
 
@@ -44,7 +44,7 @@ module SemanticPredicateSpec
44
44
  result.should be_nil
45
45
  $value.should == 'prior '
46
46
  terminal_failures = parser.terminal_failures
47
- terminal_failures.size.should == 0
47
+ terminal_failures.size.should == 1
48
48
  end
49
49
  end
50
50
 
@@ -63,13 +63,13 @@ module SemanticPredicateSpec
63
63
  end
64
64
  end
65
65
 
66
- it "fails with no terminal_failures if the block returns false" do
66
+ it "fails with one terminal_failure if the block returns false" do
67
67
  $ok_to_succeed = false
68
68
  parse('prior foo', :consume_all_input => false) do |result|
69
69
  result.should be_nil
70
70
  $value.should == 'prior '
71
71
  terminal_failures = parser.terminal_failures
72
- terminal_failures.size.should == 0
72
+ terminal_failures.size.should == 1
73
73
  end
74
74
  end
75
75
 
@@ -78,10 +78,12 @@ module SemanticPredicateSpec
78
78
  parse('foo', :consume_all_input => false) do |result|
79
79
  result.should be_nil
80
80
  terminal_failures = parser.terminal_failures
81
- terminal_failures.size.should == 1
82
- failure = terminal_failures[0]
83
- failure.index.should == 0
84
- failure.expected_string.should == 'prior '
81
+ # We should get "prior " failed, and also the predicate block
82
+ terminal_failures.size.should == 2
83
+ terminal_failures[0].index.should == 0
84
+ terminal_failures[0].expected_string.should == '"prior "'
85
+ terminal_failures[1].index.should == 0
86
+ terminal_failures[1].expected_string.should == '<semantic predicate>'
85
87
  end
86
88
  end
87
89
 
@@ -103,7 +105,7 @@ module SemanticPredicateSpec
103
105
  parse('foo', :consume_all_input => false) do |result|
104
106
  result.should be_nil
105
107
  terminal_failures = parser.terminal_failures
106
- terminal_failures.size.should == 0
108
+ terminal_failures.size.should == 1
107
109
  end
108
110
  end
109
111
 
@@ -130,7 +132,7 @@ module SemanticPredicateSpec
130
132
  result.should be_nil
131
133
  $value.should == 'prior '
132
134
  terminal_failures = parser.terminal_failures
133
- terminal_failures.size.should == 0
135
+ terminal_failures.size.should == 1
134
136
  end
135
137
  end
136
138
 
@@ -149,13 +151,13 @@ module SemanticPredicateSpec
149
151
  end
150
152
  end
151
153
 
152
- it "fails with no terminal_failures if the block returns true" do
154
+ it "fails with one terminal_failure if the block returns true" do
153
155
  $ok_to_succeed = true
154
156
  parse('prior foo', :consume_all_input => false) do |result|
155
157
  result.should be_nil
156
158
  $value.should == 'prior '
157
159
  terminal_failures = parser.terminal_failures
158
- terminal_failures.size.should == 0
160
+ terminal_failures.size.should == 1
159
161
  end
160
162
  end
161
163
 
@@ -164,10 +166,9 @@ module SemanticPredicateSpec
164
166
  parse('foo', :consume_all_input => false) do |result|
165
167
  result.should be_nil
166
168
  terminal_failures = parser.terminal_failures
167
- terminal_failures.size.should == 1
168
- failure = terminal_failures[0]
169
- failure.index.should == 0
170
- failure.expected_string.should == 'prior '
169
+ terminal_failures.size.should == 2
170
+ terminal_failures[0].index.should == 0
171
+ terminal_failures[0].expected_string.should == '"prior "'
171
172
  end
172
173
  end
173
174