rattler 0.3.0 → 0.4.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.rdoc +57 -37
- data/features/command_line/dest_option.feature +8 -21
- data/features/command_line/lib_option.feature +37 -0
- data/features/command_line/parser_generator.feature +7 -4
- data/features/grammar/back_reference.feature +37 -0
- data/features/grammar/fail.feature +3 -3
- data/features/grammar/labels.feature +11 -3
- data/features/grammar/list_matching.feature +14 -5
- data/features/grammar/literal.feature +30 -4
- data/features/grammar/nonterminal.feature +1 -1
- data/features/grammar/ordered_choice.feature +2 -2
- data/features/grammar/skip_operator.feature +1 -1
- data/features/grammar/symantic_action.feature +7 -7
- data/features/grammar/whitespace.feature +2 -2
- data/features/step_definitions/grammar_steps.rb +2 -2
- data/lib/rattler/back_end.rb +1 -0
- data/lib/rattler/back_end/compiler.rb +19 -20
- data/lib/rattler/back_end/optimizer.rb +100 -0
- data/lib/rattler/back_end/optimizer/composite_reducing.rb +18 -0
- data/lib/rattler/back_end/optimizer/flatten_choice.rb +31 -0
- data/lib/rattler/back_end/optimizer/flatten_sequence.rb +59 -0
- data/lib/rattler/back_end/optimizer/flattening.rb +17 -0
- data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +46 -0
- data/lib/rattler/back_end/optimizer/join_match_capturing_sequence.rb +71 -0
- data/lib/rattler/back_end/optimizer/join_match_choice.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_match_matching_sequence.rb +38 -0
- data/lib/rattler/back_end/optimizer/join_match_sequence.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_nested_match.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_nested_match.rb +36 -0
- data/lib/rattler/back_end/optimizer/match_joining.rb +60 -0
- data/lib/rattler/back_end/optimizer/optimization.rb +94 -0
- data/lib/rattler/back_end/optimizer/optimization_context.rb +72 -0
- data/lib/rattler/back_end/optimizer/optimization_sequence.rb +37 -0
- data/lib/rattler/back_end/optimizer/optimize_children.rb +46 -0
- data/lib/rattler/back_end/optimizer/reduce_repeat_match.rb +44 -0
- data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +32 -0
- data/lib/rattler/back_end/optimizer/simplify_redundant_repeat.rb +43 -0
- data/lib/rattler/back_end/optimizer/simplify_token_match.rb +38 -0
- data/lib/rattler/back_end/parser_generator.rb +21 -14
- data/lib/rattler/back_end/parser_generator/apply_generator.rb +35 -35
- data/lib/rattler/back_end/parser_generator/assert_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/back_reference_generator.rb +93 -0
- data/lib/rattler/back_end/parser_generator/choice_generator.rb +33 -49
- data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +14 -14
- data/lib/rattler/back_end/parser_generator/disallow_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +11 -13
- data/lib/rattler/back_end/parser_generator/expr_generator.rb +36 -56
- data/lib/rattler/back_end/parser_generator/fail_generator.rb +18 -18
- data/lib/rattler/back_end/parser_generator/group_match.rb +18 -0
- data/lib/rattler/back_end/parser_generator/group_match_generator.rb +76 -0
- data/lib/rattler/back_end/parser_generator/label_generator.rb +25 -6
- data/lib/rattler/back_end/parser_generator/list1_generator.rb +7 -7
- data/lib/rattler/back_end/parser_generator/list_generating.rb +19 -20
- data/lib/rattler/back_end/parser_generator/list_generator.rb +5 -5
- data/lib/rattler/back_end/parser_generator/match_generator.rb +52 -52
- data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +6 -6
- data/lib/rattler/back_end/parser_generator/optional_generator.rb +30 -29
- data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +8 -8
- data/lib/rattler/back_end/parser_generator/repeat_generating.rb +23 -25
- data/lib/rattler/back_end/parser_generator/rule_generator.rb +27 -79
- data/lib/rattler/back_end/parser_generator/rule_set_generator.rb +102 -0
- data/lib/rattler/back_end/parser_generator/sequence_generator.rb +49 -41
- data/lib/rattler/back_end/parser_generator/skip_generator.rb +14 -20
- data/lib/rattler/back_end/parser_generator/skip_propogating.rb +4 -4
- data/lib/rattler/back_end/parser_generator/sub_generating.rb +6 -0
- data/lib/rattler/back_end/parser_generator/token_generator.rb +12 -12
- data/lib/rattler/back_end/parser_generator/token_propogating.rb +2 -2
- data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +4 -4
- data/lib/rattler/grammar.rb +4 -3
- data/lib/rattler/grammar/analysis.rb +91 -0
- data/lib/rattler/grammar/grammar.rb +37 -25
- data/lib/rattler/grammar/grammar_parser.rb +19 -11
- data/lib/rattler/grammar/metagrammar.rb +569 -800
- data/lib/rattler/grammar/rattler.rtlr +162 -144
- data/lib/rattler/parsers.rb +5 -1
- data/lib/rattler/parsers/action_code.rb +29 -15
- data/lib/rattler/parsers/apply.rb +5 -5
- data/lib/rattler/parsers/assert.rb +4 -18
- data/lib/rattler/parsers/back_reference.rb +46 -0
- data/lib/rattler/parsers/choice.rb +6 -39
- data/lib/rattler/parsers/combinator_parser.rb +32 -0
- data/lib/rattler/parsers/combining.rb +3 -29
- data/lib/rattler/parsers/direct_action.rb +27 -30
- data/lib/rattler/parsers/disallow.rb +4 -18
- data/lib/rattler/parsers/dispatch_action.rb +30 -25
- data/lib/rattler/parsers/label.rb +9 -18
- data/lib/rattler/parsers/list.rb +3 -34
- data/lib/rattler/parsers/list1.rb +4 -36
- data/lib/rattler/parsers/list_parser.rb +64 -0
- data/lib/rattler/parsers/match.rb +7 -42
- data/lib/rattler/parsers/node_code.rb +44 -0
- data/lib/rattler/parsers/one_or_more.rb +7 -27
- data/lib/rattler/parsers/optional.rb +5 -25
- data/lib/rattler/parsers/parser.rb +16 -44
- data/lib/rattler/parsers/parser_dsl.rb +13 -3
- data/lib/rattler/parsers/predicate.rb +4 -12
- data/lib/rattler/parsers/rule.rb +18 -19
- data/lib/rattler/parsers/rule_set.rb +63 -0
- data/lib/rattler/parsers/sequence.rb +12 -46
- data/lib/rattler/parsers/skip.rb +12 -26
- data/lib/rattler/parsers/token.rb +6 -21
- data/lib/rattler/parsers/zero_or_more.rb +6 -26
- data/lib/rattler/runner.rb +66 -28
- data/lib/rattler/runtime/extended_packrat_parser.rb +26 -20
- data/lib/rattler/runtime/packrat_parser.rb +17 -21
- data/lib/rattler/runtime/parser.rb +12 -2
- data/lib/rattler/runtime/recursive_descent_parser.rb +3 -11
- data/lib/rattler/util.rb +2 -1
- data/lib/rattler/util/graphviz.rb +29 -0
- data/lib/rattler/util/graphviz/digraph_builder.rb +71 -0
- data/lib/rattler/util/graphviz/node_builder.rb +84 -0
- data/lib/rattler/util/node.rb +37 -19
- data/lib/rattler/util/parser_spec_helper.rb +61 -35
- data/spec/rattler/back_end/compiler_spec.rb +6 -860
- data/spec/rattler/back_end/optimizer/flatten_choice_spec.rb +70 -0
- data/spec/rattler/back_end/optimizer/flatten_sequence_spec.rb +130 -0
- data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +80 -0
- data/spec/rattler/back_end/optimizer/join_match_capturing_sequence_spec.rb +241 -0
- data/spec/rattler/back_end/optimizer/join_match_choice_spec.rb +100 -0
- data/spec/rattler/back_end/optimizer/join_match_matching_sequence_spec.rb +112 -0
- data/spec/rattler/back_end/optimizer/join_predicate_bare_match_spec.rb +194 -0
- data/spec/rattler/back_end/optimizer/join_predicate_nested_match_spec.rb +180 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_bare_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_nested_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb +98 -0
- data/spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb +226 -0
- data/spec/rattler/back_end/optimizer/simplify_token_match_spec.rb +85 -0
- data/spec/rattler/back_end/parser_generator/apply_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/assert_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb +181 -0
- data/spec/rattler/back_end/parser_generator/choice_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/disallow_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +185 -0
- data/spec/rattler/back_end/parser_generator/label_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/match_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/one_or_more_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/optional_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/rule_generator_spec.rb +13 -46
- data/spec/rattler/back_end/parser_generator/rule_set_generator_spec.rb +97 -0
- data/spec/rattler/back_end/parser_generator/sequence_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/skip_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/token_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/zero_or_more_generator_spec.rb +39 -34
- data/spec/rattler/back_end/shared_compiler_examples.rb +885 -0
- data/spec/rattler/grammar/analysis_spec.rb +167 -0
- data/spec/rattler/grammar/grammar_parser_spec.rb +169 -179
- data/spec/rattler/grammar/grammar_spec.rb +24 -21
- data/spec/rattler/parsers/action_code_spec.rb +64 -19
- data/spec/rattler/parsers/apply_spec.rb +9 -9
- data/spec/rattler/parsers/back_reference_spec.rb +38 -0
- data/spec/rattler/parsers/combinator_parser_spec.rb +14 -0
- data/spec/rattler/parsers/direct_action_spec.rb +16 -2
- data/spec/rattler/parsers/dispatch_action_spec.rb +15 -32
- data/spec/rattler/parsers/fail_spec.rb +6 -4
- data/spec/rattler/parsers/label_spec.rb +10 -28
- data/spec/rattler/parsers/node_code_spec.rb +48 -0
- data/spec/rattler/parsers/parser_dsl_spec.rb +1 -1
- data/spec/rattler/parsers/rule_set_spec.rb +35 -0
- data/spec/rattler/parsers/sequence_spec.rb +15 -24
- data/spec/rattler/runtime/extended_packrat_parser_spec.rb +22 -17
- data/spec/rattler/runtime/packrat_parser_spec.rb +1 -1
- data/spec/rattler/runtime/parse_node_spec.rb +15 -19
- data/spec/rattler/runtime/recursive_descent_parser_spec.rb +1 -1
- data/spec/rattler/runtime/shared_parser_examples.rb +61 -28
- data/spec/rattler/util/graphviz/node_builder_spec.rb +84 -0
- data/spec/rattler/util/node_spec.rb +92 -65
- data/spec/rattler_spec.rb +16 -16
- data/spec/support/combinator_parser_spec_helper.rb +19 -18
- data/spec/support/compiler_spec_helper.rb +56 -87
- data/spec/support/runtime_parser_spec_helper.rb +6 -14
- metadata +117 -22
- data/features/grammar/regex.feature +0 -24
- data/lib/rattler/parsers/match_joining.rb +0 -67
- data/lib/rattler/parsers/rules.rb +0 -43
@@ -3,53 +3,56 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
3
3
|
include Rattler::Parsers
|
4
4
|
|
5
5
|
describe Rattler::Grammar::Grammar do
|
6
|
-
|
7
|
-
let(:rules) {
|
6
|
+
|
7
|
+
let(:rules) { RuleSet[rule_a, rule_b] }
|
8
|
+
|
9
|
+
let :rule_a do
|
8
10
|
Rule[:a, Choice[
|
9
11
|
Match['a'],
|
10
12
|
Apply[:b]
|
11
|
-
]]
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
]]
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:rule_b) { Rule[:b, Match['b']] }
|
17
|
+
|
15
18
|
describe '#start_rule' do
|
16
19
|
context 'when no start_rule option was specified' do
|
17
|
-
|
20
|
+
|
18
21
|
subject { Rattler::Grammar::Grammar.new(rules) }
|
19
|
-
|
20
|
-
it 'returns the
|
21
|
-
subject.start_rule.should ==
|
22
|
+
|
23
|
+
it 'returns the first rule' do
|
24
|
+
subject.start_rule.should == rule_a
|
22
25
|
end
|
23
26
|
end
|
24
|
-
|
27
|
+
|
25
28
|
context 'when an explicit start_rule option was specified' do
|
26
|
-
|
29
|
+
|
27
30
|
subject { Rattler::Grammar::Grammar.new(rules, :start_rule => :b) }
|
28
|
-
|
31
|
+
|
29
32
|
it 'uses the specified start_rule option' do
|
30
|
-
subject.start_rule.should ==
|
33
|
+
subject.start_rule.should == rule_b
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
34
|
-
|
37
|
+
|
35
38
|
describe '#rules' do
|
36
39
|
context 'when no start_rule option was specified' do
|
37
|
-
|
40
|
+
|
38
41
|
subject { Rattler::Grammar::Grammar.new(rules) }
|
39
|
-
|
42
|
+
|
40
43
|
it 'returns rules with the default start_rule' do
|
41
44
|
subject.rules.start_rule.should == :a
|
42
45
|
end
|
43
46
|
end
|
44
|
-
|
47
|
+
|
45
48
|
context 'when an explicit start_rule option was specified' do
|
46
|
-
|
49
|
+
|
47
50
|
subject { Rattler::Grammar::Grammar.new(rules, :start_rule => :b) }
|
48
|
-
|
51
|
+
|
49
52
|
it 'returns rules with the specified start_rule option' do
|
50
53
|
subject.rules.start_rule.should == :b
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
54
|
-
|
57
|
+
|
55
58
|
end
|
@@ -2,6 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
|
3
3
|
describe Rattler::Parsers::ActionCode do
|
4
4
|
|
5
|
+
subject { ActionCode.new(code) }
|
6
|
+
|
5
7
|
describe '#param_names' do
|
6
8
|
context 'when the code has block parameters' do
|
7
9
|
|
@@ -53,15 +55,20 @@ describe Rattler::Parsers::ActionCode do
|
|
53
55
|
end
|
54
56
|
|
55
57
|
context 'given one argument' do
|
56
|
-
it 'binds "_" to the argument' do
|
57
|
-
subject.blank_binding(['r0']).should == {
|
58
|
+
it 'binds "_" and "*_" to the argument' do
|
59
|
+
subject.blank_binding(['r0']).should == {
|
60
|
+
/\*_\b/ => 'r0',
|
61
|
+
/\b_\b/ => 'r0'
|
62
|
+
}
|
58
63
|
end
|
59
64
|
end
|
60
65
|
|
61
66
|
context 'given more than one argument' do
|
62
|
-
it 'binds "_" to the array of arguments' do
|
63
|
-
subject.blank_binding(['r0_0', 'r0_1']).
|
64
|
-
|
67
|
+
it 'binds "*_" to the arguments and "_" to the array of arguments' do
|
68
|
+
subject.blank_binding(['r0_0', 'r0_1']).should == {
|
69
|
+
/\*_\b/ => 'r0_0, r0_1',
|
70
|
+
/\b_\b/ => '[r0_0, r0_1]'
|
71
|
+
}
|
65
72
|
end
|
66
73
|
end
|
67
74
|
end
|
@@ -73,12 +80,12 @@ describe Rattler::Parsers::ActionCode do
|
|
73
80
|
|
74
81
|
it 'associates the parameter names with arguments' do
|
75
82
|
subject.arg_bindings(['r0_0', 'r0_1']).
|
76
|
-
should == {
|
83
|
+
should == {/\ba\b/ => 'r0_0', /\bb\b/ => 'r0_1'}
|
77
84
|
end
|
78
85
|
|
79
86
|
it 'allows more args than param names' do
|
80
87
|
subject.arg_bindings(['r0_0', 'r0_1', 'r0_2']).
|
81
|
-
should == {
|
88
|
+
should == {/\ba\b/ => 'r0_0', /\bb\b/ => 'r0_1'}
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
@@ -93,57 +100,95 @@ describe Rattler::Parsers::ActionCode do
|
|
93
100
|
end
|
94
101
|
|
95
102
|
describe '#bind' do
|
103
|
+
|
104
|
+
let(:scope) { {} }
|
105
|
+
|
96
106
|
context 'when the code uses block parameters' do
|
97
107
|
|
98
|
-
|
108
|
+
let(:code) { '|a, b| a + b' }
|
99
109
|
|
100
110
|
it 'replaces block parameter names with corresponding arguments' do
|
101
|
-
subject.bind(['r0_0', 'r0_1']).should == 'r0_0 + r0_1'
|
111
|
+
subject.bind(scope, ['r0_0', 'r0_1']).should == 'r0_0 + r0_1'
|
102
112
|
end
|
103
113
|
end
|
104
114
|
|
105
115
|
context 'when the code refers to labels' do
|
106
116
|
|
107
|
-
|
117
|
+
let(:scope) { {:l => 'r0_3', :r => 'r0_5'} }
|
118
|
+
|
119
|
+
let(:code) { 'l + r' }
|
108
120
|
|
109
121
|
it 'replaces label names with associated arguments' do
|
110
|
-
subject.bind(
|
122
|
+
subject.bind(scope, []).should == 'r0_3 + r0_5'
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
114
126
|
context 'when the code uses block parameters and label names' do
|
115
127
|
|
116
|
-
|
128
|
+
let(:scope) { {:c => 'r0_3', :d => 'r0_5'} }
|
129
|
+
|
130
|
+
let(:code) { '|a, b| a * c + b * d' }
|
117
131
|
|
118
132
|
it 'replaces both block parameter names and label names' do
|
119
|
-
subject.bind(['r0_0', 'r0_1']
|
133
|
+
subject.bind(scope, ['r0_0', 'r0_1']).
|
120
134
|
should == 'r0_0 * r0_3 + r0_1 * r0_5'
|
121
135
|
end
|
122
136
|
end
|
123
137
|
|
138
|
+
context 'when the code uses block parameters that are label names' do
|
139
|
+
|
140
|
+
let(:scope) { {:b => 'r0_3', :c => 'r0_5'} }
|
141
|
+
|
142
|
+
let(:code) { '|a, b| a * c + b' }
|
143
|
+
|
144
|
+
it 'the block parameters shadow the label names' do
|
145
|
+
subject.bind(scope, ['r0_0', 'r0_1']).
|
146
|
+
should == 'r0_0 * r0_5 + r0_1'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
124
150
|
context 'when the code uses "_"' do
|
125
151
|
|
126
|
-
|
152
|
+
let(:code) { '_.to_s' }
|
127
153
|
|
128
154
|
context 'given one argument' do
|
129
155
|
it 'replaces "_" with the argument' do
|
130
|
-
subject.bind(['r0']).should == 'r0.to_s'
|
156
|
+
subject.bind(scope, ['r0']).should == 'r0.to_s'
|
131
157
|
end
|
132
158
|
end
|
133
159
|
|
134
160
|
context 'given multiple arguments' do
|
135
161
|
it 'replaces "_" with the array of arguments' do
|
136
|
-
subject.bind(['r0_0', 'r0_1']).
|
162
|
+
subject.bind(scope, ['r0_0', 'r0_1']).
|
163
|
+
should == '[r0_0, r0_1].to_s'
|
137
164
|
end
|
138
165
|
end
|
139
166
|
end
|
140
167
|
|
141
168
|
context 'when the code uses "_" as a block parameter' do
|
142
169
|
|
143
|
-
|
170
|
+
let(:code) { '|_| _.to_f' }
|
171
|
+
|
172
|
+
it 'the block parameter shadows the default "_" binding' do
|
173
|
+
subject.bind(scope, ['r0_0', 'r0_1']).should == 'r0_0.to_f'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'when the code uses "*_"' do
|
178
|
+
|
179
|
+
let(:code) { 'do_stuff *_' }
|
144
180
|
|
145
|
-
|
146
|
-
|
181
|
+
context 'given one argument' do
|
182
|
+
it 'replaces "*_" with the argument' do
|
183
|
+
subject.bind(scope, ['r0']).should == 'do_stuff r0'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'given multiple arguments' do
|
188
|
+
it 'replaces "*_" with the arguments' do
|
189
|
+
subject.bind(scope, ['r0_0', 'r0_1']).
|
190
|
+
should == 'do_stuff r0_0, r0_1'
|
191
|
+
end
|
147
192
|
end
|
148
193
|
end
|
149
194
|
end
|
@@ -2,31 +2,31 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
|
3
3
|
describe Apply do
|
4
4
|
include CombinatorParserSpecHelper
|
5
|
-
|
5
|
+
|
6
6
|
subject { Apply[:word] }
|
7
|
-
|
8
|
-
let(:rules) {
|
9
|
-
|
7
|
+
|
8
|
+
let(:rules) { RuleSet[Rule[:word, Match[/\w+/]]] }
|
9
|
+
|
10
10
|
describe '#parse' do
|
11
|
-
|
11
|
+
|
12
12
|
context 'when the referenced rule matches' do
|
13
13
|
it 'succeeds returns the result' do
|
14
14
|
parsing('abc123 ').should result_in('abc123').at(6)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
context 'when the referenced rule fails' do
|
19
19
|
it 'fails' do
|
20
20
|
parsing('==').should fail
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
describe '#capturing?' do
|
27
27
|
it 'is true' do
|
28
28
|
subject.should be_capturing
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Rattler::Parsers::BackReference do
|
4
|
+
include CombinatorParserSpecHelper
|
5
|
+
|
6
|
+
subject { BackReference[:a] }
|
7
|
+
|
8
|
+
describe '#parse' do
|
9
|
+
|
10
|
+
let(:scope) { {:a => 'foo'} }
|
11
|
+
|
12
|
+
context 'when the referenced parse result is next in the input' do
|
13
|
+
it 'succeeds returning the matched string' do
|
14
|
+
parsing('foobar ').should result_in('foo').at(3)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when the referenced parse result is not next in the input' do
|
19
|
+
it 'fails' do
|
20
|
+
parsing('abc').should fail
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#capturing?' do
|
27
|
+
it 'is true' do
|
28
|
+
subject.should be_capturing
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#re_source' do
|
33
|
+
it 'returns the source for a Regexp that will match the referenced result' do
|
34
|
+
subject.re_source(:a => 'r0').should == '#{r0}'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../runtime/shared_parser_examples')
|
3
|
+
|
4
|
+
describe Rattler::Parsers::CombinatorParser do
|
5
|
+
include Rattler::Util::ParserSpecHelper
|
6
|
+
include RuntimeParserSpecHelper
|
7
|
+
|
8
|
+
it_behaves_like 'a recursive descent parser'
|
9
|
+
|
10
|
+
let :parser_class do
|
11
|
+
Rattler::Parsers::CombinatorParser.as_class(grammar.start_rule, grammar.rules)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -95,11 +95,11 @@ describe DirectAction do
|
|
95
95
|
|
96
96
|
context 'with a one-or-more parser' do
|
97
97
|
|
98
|
-
subject { DirectAction[OneOrMore[Match[/\d/]], '|s| s'] }
|
98
|
+
subject { DirectAction[OneOrMore[Match[/\d/]], '|s| s * 2'] }
|
99
99
|
|
100
100
|
context 'when the nested parser matches' do
|
101
101
|
it 'applies the action to an array containing the matches' do
|
102
|
-
parsing('451a').should result_in(
|
102
|
+
parsing('451a').should result_in(%w{4 5 1 4 5 1}).at(3)
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -131,6 +131,20 @@ describe DirectAction do
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
+
context 'with a labeled parser' do
|
135
|
+
subject do
|
136
|
+
DirectAction[
|
137
|
+
Label[:word, Match[/[[:alpha:]]+/]],
|
138
|
+
"word * 2"
|
139
|
+
]
|
140
|
+
end
|
141
|
+
context 'when the parser matches' do
|
142
|
+
it 'applies the action binding the label to the result' do
|
143
|
+
parsing('foo ').should result_in('foofoo').at(3)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
134
148
|
context 'with a sequence of labeled parsers' do
|
135
149
|
subject do
|
136
150
|
DirectAction[
|
@@ -2,34 +2,34 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
|
3
3
|
describe DispatchAction do
|
4
4
|
include CombinatorParserSpecHelper
|
5
|
-
|
5
|
+
|
6
6
|
describe '#parse' do
|
7
|
-
|
7
|
+
|
8
8
|
context 'with a capturing parser' do
|
9
9
|
subject do
|
10
10
|
DispatchAction[
|
11
11
|
Sequence[Match[/[[:alpha:]]+/], Match[/\=/], Match[/[[:digit:]]+/]]
|
12
12
|
]
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
context 'when the parser matches' do
|
16
16
|
it 'applies the action to the result' do
|
17
17
|
parsing('val=42').
|
18
18
|
should result_in(Rattler::Runtime::ParseNode.parsed(['val','=','42'])).at(6)
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
context 'when the parser fails' do
|
23
23
|
it 'fails' do
|
24
24
|
parsing('val=x').should fail
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
context 'with a token parser' do
|
30
|
-
|
30
|
+
|
31
31
|
subject { DispatchAction[Token[Match[/\w+/]]] }
|
32
|
-
|
32
|
+
|
33
33
|
context 'when the parser matches' do
|
34
34
|
it 'applies the action to the matched string' do
|
35
35
|
parsing('foo ').
|
@@ -37,11 +37,11 @@ describe DispatchAction do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
context 'with a non-capturing parser' do
|
42
|
-
|
42
|
+
|
43
43
|
subject { DispatchAction[Skip[Match[/\w+/]]] }
|
44
|
-
|
44
|
+
|
45
45
|
context 'when the parser matches' do
|
46
46
|
it 'applies the action to an empty array' do
|
47
47
|
parsing('abc123 ').
|
@@ -49,24 +49,7 @@ describe DispatchAction do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
context 'with a choice of labeled parsers' do
|
54
|
-
subject do
|
55
|
-
DispatchAction[
|
56
|
-
Choice[
|
57
|
-
Label[:word, Match[/[[:alpha:]]+/]],
|
58
|
-
Label[:num, Match[/[[:digit:]]+/]]
|
59
|
-
]
|
60
|
-
]
|
61
|
-
end
|
62
|
-
it 'applies the action with a labeled result' do
|
63
|
-
parsing('foo ').should result_in(
|
64
|
-
Rattler::Runtime::ParseNode.parsed(['foo'], :labeled => {:word => 'foo'}))
|
65
|
-
parsing('42 ').should result_in(
|
66
|
-
Rattler::Runtime::ParseNode.parsed(['42'], :labeled => {:num => '42'}))
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
52
|
+
|
70
53
|
context 'with a sequence of labeled parsers' do
|
71
54
|
subject do
|
72
55
|
DispatchAction[
|
@@ -86,16 +69,16 @@ describe DispatchAction do
|
|
86
69
|
end
|
87
70
|
end
|
88
71
|
end
|
89
|
-
|
72
|
+
|
90
73
|
describe '#capturing?' do
|
91
|
-
|
74
|
+
|
92
75
|
context 'with a capturing parser' do
|
93
76
|
subject { DispatchAction[Match[/\w+/]] }
|
94
77
|
it 'is true' do
|
95
78
|
subject.should be_capturing
|
96
79
|
end
|
97
80
|
end
|
98
|
-
|
81
|
+
|
99
82
|
context 'with a non-capturing parser' do
|
100
83
|
subject { DispatchAction[Skip[Match[/\s*/]]] }
|
101
84
|
it 'is false' do
|
@@ -103,5 +86,5 @@ describe DispatchAction do
|
|
103
86
|
end
|
104
87
|
end
|
105
88
|
end
|
106
|
-
|
89
|
+
|
107
90
|
end
|