treetop 1.5.3 → 1.6.2
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.
- checksums.yaml +5 -13
- data/Rakefile +9 -3
- data/doc/pitfalls_and_advanced_techniques.markdown +1 -1
- data/doc/sitegen.rb +1 -1
- data/doc/syntactic_recognition.markdown +2 -0
- data/doc/tt.1 +1 -1
- data/lib/treetop/compiler/metagrammar.rb +81 -13
- data/lib/treetop/compiler/metagrammar.treetop +67 -13
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +5 -1
- data/lib/treetop/compiler/node_classes/character_class.rb +6 -2
- data/lib/treetop/compiler/node_classes/choice.rb +9 -5
- data/lib/treetop/compiler/node_classes/nonterminal.rb +2 -2
- data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +5 -1
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +12 -2
- data/lib/treetop/compiler/node_classes/predicate.rb +8 -1
- data/lib/treetop/compiler/node_classes/predicate_block.rb +7 -0
- data/lib/treetop/compiler/node_classes/repetition.rb +31 -11
- data/lib/treetop/compiler/node_classes/sequence.rb +5 -1
- data/lib/treetop/compiler/node_classes/terminal.rb +12 -2
- data/lib/treetop/runtime/compiled_parser.rb +12 -6
- data/lib/treetop/runtime/syntax_node.rb +24 -15
- data/lib/treetop/runtime/terminal_parse_failure.rb +4 -3
- data/lib/treetop/version.rb +2 -2
- data/spec/compiler/and_predicate_spec.rb +1 -1
- data/spec/compiler/anything_symbol_spec.rb +4 -1
- data/spec/compiler/character_class_spec.rb +4 -1
- data/spec/compiler/choice_spec.rb +20 -11
- data/spec/compiler/failure_propagation_functional_spec.rb +1 -1
- data/spec/compiler/grammar_spec.rb +4 -1
- data/spec/compiler/not_predicate_spec.rb +20 -6
- data/spec/compiler/occurrence_range_spec.rb +25 -28
- data/spec/compiler/one_or_more_spec.rb +2 -2
- data/spec/compiler/optional_spec.rb +2 -2
- data/spec/compiler/parenthesized_expression_spec.rb +15 -1
- data/spec/compiler/semantic_predicate_spec.rb +17 -16
- data/spec/compiler/sequence_spec.rb +1 -1
- data/spec/compiler/terminal_spec.rb +8 -1
- data/spec/compiler/terminal_symbol_spec.rb +4 -1
- data/spec/compiler/zero_or_more_spec.rb +4 -2
- data/spec/runtime/compiled_parser_spec.rb +33 -3
- metadata +20 -21
- data/examples/lambda_calculus/lambda_calculus +0 -0
data/lib/treetop/version.rb
CHANGED
@@ -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')
|
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')
|
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')
|
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 ==
|
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')
|
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 ==
|
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 ==
|
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 ==
|
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
|
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
|
-
|
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 ==
|
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
|
-
|
117
|
+
terminal_failures.size.should == 0
|
121
118
|
end
|
122
119
|
end
|
123
120
|
|
124
|
-
it "fails to parses
|
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
|
-
|
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')
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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 ==
|
168
|
-
|
169
|
-
|
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
|
|