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
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::Parsers
|
4
|
+
|
5
|
+
describe Rattler::BackEnd::Optimizer::FlattenChoice do
|
6
|
+
|
7
|
+
describe '#apply' do
|
8
|
+
|
9
|
+
context 'given a choice with choice terms' do
|
10
|
+
|
11
|
+
let(:choice) { Choice[
|
12
|
+
Match[/a/],
|
13
|
+
Choice[Match[/b/], Match[/c/]],
|
14
|
+
Sequence[Match[/d/], Match[/e/]]
|
15
|
+
] }
|
16
|
+
|
17
|
+
it 'flattens the choice' do
|
18
|
+
subject.apply(choice, :any).should == Choice[
|
19
|
+
Match[/a/],
|
20
|
+
Match[/b/],
|
21
|
+
Match[/c/],
|
22
|
+
Sequence[Match[/d/], Match[/e/]]
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#applies_to?' do
|
29
|
+
|
30
|
+
context 'given a choice with choice terms' do
|
31
|
+
|
32
|
+
let(:choice) { Choice[
|
33
|
+
Match[/a/],
|
34
|
+
Choice[Match[/b/], Match[/c/]],
|
35
|
+
Sequence[Match[/d/], Match[/e/]]
|
36
|
+
] }
|
37
|
+
|
38
|
+
it 'returns true' do
|
39
|
+
subject.applies_to?(choice, :any).should be_true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'given a choice without choice terms' do
|
44
|
+
|
45
|
+
let(:choice) { Choice[
|
46
|
+
Match[/a/],
|
47
|
+
Match[/b/],
|
48
|
+
Sequence[Match[/c/], Match[/d/]]
|
49
|
+
] }
|
50
|
+
|
51
|
+
it 'returns false' do
|
52
|
+
subject.applies_to?(choice, :any).should be_false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'given something other than a choie' do
|
57
|
+
|
58
|
+
let(:choice) { Sequence[
|
59
|
+
Match[/a/],
|
60
|
+
Choice[Match[/b/], Match[/c/]],
|
61
|
+
Sequence[Match[/d/], Match[/e/]]
|
62
|
+
] }
|
63
|
+
|
64
|
+
it 'returns false' do
|
65
|
+
subject.applies_to?(choice, :any).should be_false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::BackEnd::Optimizer
|
4
|
+
include Rattler::Parsers
|
5
|
+
|
6
|
+
describe FlattenSequence do
|
7
|
+
|
8
|
+
let(:matching) { OptimizationContext[:type => :matching] }
|
9
|
+
let(:capturing) { OptimizationContext[:type => :capturing] }
|
10
|
+
|
11
|
+
describe '#apply' do
|
12
|
+
|
13
|
+
context 'in the matching context' do
|
14
|
+
|
15
|
+
context 'given a sequence with sequence terms' do
|
16
|
+
|
17
|
+
let(:sequence) { Sequence[
|
18
|
+
Match[/a/],
|
19
|
+
Sequence[Match[/b/], Match[/c/]],
|
20
|
+
Choice[Match[/c/], Match[/d/]]
|
21
|
+
] }
|
22
|
+
|
23
|
+
it 'flattens the sequence' do
|
24
|
+
subject.apply(sequence, matching).should == Sequence[
|
25
|
+
Match[/a/],
|
26
|
+
Match[/b/],
|
27
|
+
Match[/c/],
|
28
|
+
Choice[Match[/c/], Match[/d/]],
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'in the capturing context' do
|
35
|
+
|
36
|
+
context 'given a sequence with single-capturing sequence terms' do
|
37
|
+
|
38
|
+
let(:sequence) { Sequence[
|
39
|
+
Match[/a/],
|
40
|
+
Sequence[Skip[Match[/b/]], Skip[Match[/c/]]],
|
41
|
+
Sequence[Match[/b/], Skip[Match[/c/]]]
|
42
|
+
] }
|
43
|
+
|
44
|
+
it 'flattens the sequences' do
|
45
|
+
subject.apply(sequence, capturing).should == Sequence[
|
46
|
+
Match[/a/],
|
47
|
+
Skip[Match[/b/]],
|
48
|
+
Skip[Match[/c/]],
|
49
|
+
Match[/b/],
|
50
|
+
Skip[Match[/c/]]
|
51
|
+
]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'given a sequence with multi-capturing sequence terms' do
|
56
|
+
|
57
|
+
let(:sequence) { Sequence[
|
58
|
+
Match[/a/],
|
59
|
+
Sequence[Skip[Match[/b/]], Skip[Match[/c/]]],
|
60
|
+
Sequence[Match[/b/], Match[/c/]]
|
61
|
+
] }
|
62
|
+
|
63
|
+
it 'avoids flattening the capturing sequences' do
|
64
|
+
subject.apply(sequence, capturing).should == Sequence[
|
65
|
+
Match[/a/],
|
66
|
+
Skip[Match[/b/]],
|
67
|
+
Skip[Match[/c/]],
|
68
|
+
Sequence[Match[/b/], Match[/c/]]
|
69
|
+
]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#applies_to?' do
|
77
|
+
|
78
|
+
context 'given a sequence with only capturing sequence terms' do
|
79
|
+
|
80
|
+
let(:sequence) { Sequence[
|
81
|
+
Match[/a/],
|
82
|
+
Sequence[Match[/b/], Match[/c/]],
|
83
|
+
Choice[Match[/c/], Match[/d/]]
|
84
|
+
] }
|
85
|
+
|
86
|
+
context 'in the matching context' do
|
87
|
+
it 'returns true' do
|
88
|
+
subject.applies_to?(sequence, matching).should be_true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'in the capturing context' do
|
93
|
+
it 'returns false' do
|
94
|
+
subject.applies_to?(sequence, capturing).should be_false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'given a sequence with non-capturing sequence terms' do
|
100
|
+
|
101
|
+
let(:sequence) { Sequence[
|
102
|
+
Match[/a/],
|
103
|
+
Sequence[Skip[Match[/b/]], Skip[Match[/c/]]],
|
104
|
+
Choice[Match[/c/], Match[/d/]]
|
105
|
+
] }
|
106
|
+
|
107
|
+
context 'in the capturing context' do
|
108
|
+
it 'returns true' do
|
109
|
+
subject.applies_to?(sequence, capturing).should be_true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'given a sequence with single-capturing sequence terms' do
|
115
|
+
|
116
|
+
let(:sequence) { Sequence[
|
117
|
+
Match[/a/],
|
118
|
+
Sequence[Skip[Match[/b/]], Skip[Match[/c/]]],
|
119
|
+
Sequence[Match[/b/], Skip[Match[/c/]]]
|
120
|
+
] }
|
121
|
+
|
122
|
+
context 'in the capturing context' do
|
123
|
+
it 'returns true' do
|
124
|
+
subject.applies_to?(sequence, capturing).should be_true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::BackEnd::Optimizer
|
4
|
+
include Rattler::Parsers
|
5
|
+
|
6
|
+
describe InlineRegularRules do
|
7
|
+
|
8
|
+
let(:standalone) { OptimizationContext[
|
9
|
+
:type => :capturing,
|
10
|
+
:rules => rule_set,
|
11
|
+
:standalone => true
|
12
|
+
] }
|
13
|
+
|
14
|
+
let(:modular) { OptimizationContext[
|
15
|
+
:type => :capturing,
|
16
|
+
:rules => rule_set
|
17
|
+
] }
|
18
|
+
|
19
|
+
let(:rule_set) { RuleSet[rule_a, {:start_rule => :a}] }
|
20
|
+
|
21
|
+
describe '#apply' do
|
22
|
+
|
23
|
+
context 'given a reference to a regular rule' do
|
24
|
+
|
25
|
+
let(:rule_a) { Rule[:a, Match[/a/]] }
|
26
|
+
|
27
|
+
it 'inlines the regular rule' do
|
28
|
+
subject.apply(Apply[:a], standalone).should == Match[/a/]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#_applies_to?' do
|
34
|
+
|
35
|
+
context 'with the :standalone option set' do
|
36
|
+
|
37
|
+
context 'given a reference to a regular rule' do
|
38
|
+
|
39
|
+
let(:rule_a) { Rule[:a, Match[/a/]] }
|
40
|
+
|
41
|
+
it 'returns true' do
|
42
|
+
subject.applies_to?(Apply[:a], standalone).should be_true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'given a reference to a recursive rule' do
|
47
|
+
|
48
|
+
let(:rule_a) { Rule[:a, Sequence[Match[/a/], Apply[:a]]] }
|
49
|
+
|
50
|
+
it 'returns false' do
|
51
|
+
subject.applies_to?(Apply[:a], standalone).should be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'without the :standalone option set' do
|
57
|
+
|
58
|
+
context 'given a reference to a regular rule' do
|
59
|
+
|
60
|
+
context 'tagged as :inline' do
|
61
|
+
|
62
|
+
let(:rule_a) { Rule[:a, Match[/a/], {:inline => true}] }
|
63
|
+
|
64
|
+
it 'returns true' do
|
65
|
+
subject.applies_to?(Apply[:a], modular).should be_true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'not tagged as :inline' do
|
70
|
+
|
71
|
+
let(:rule_a) { Rule[:a, Match[/a/]] }
|
72
|
+
|
73
|
+
it 'returns false' do
|
74
|
+
subject.applies_to?(Apply[:a], modular).should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::BackEnd::Optimizer
|
4
|
+
include Rattler::Parsers
|
5
|
+
include Rattler::BackEnd::ParserGenerator
|
6
|
+
|
7
|
+
describe JoinMatchCapturingSequence do
|
8
|
+
|
9
|
+
let(:capturing) { OptimizationContext[:type => :capturing] }
|
10
|
+
let(:matching) { OptimizationContext[:type => :matching] }
|
11
|
+
|
12
|
+
describe '#apply' do
|
13
|
+
|
14
|
+
context 'given a sequence of all skipping matches' do
|
15
|
+
|
16
|
+
let(:sequence) { Sequence[
|
17
|
+
Skip[Match[/a/]],
|
18
|
+
Skip[Match[/b/]],
|
19
|
+
Skip[Match[/c/]]
|
20
|
+
] }
|
21
|
+
|
22
|
+
it 'joins them into a single skipping match' do
|
23
|
+
subject.apply(sequence, capturing).
|
24
|
+
should == Skip[Match[/(?>a)(?>b)(?>c)/]]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'given a sequence of skipping matches followed by something else' do
|
29
|
+
|
30
|
+
let(:sequence) { Sequence[
|
31
|
+
Skip[Match[/a/]],
|
32
|
+
Skip[Match[/b/]],
|
33
|
+
Apply[:c]
|
34
|
+
] }
|
35
|
+
|
36
|
+
it 'joins the consecutive skipping matches into a single match' do
|
37
|
+
subject.apply(sequence, capturing).should == Sequence[
|
38
|
+
Skip[Match[/(?>a)(?>b)/]],
|
39
|
+
Apply[:c]
|
40
|
+
]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'given a sequence of skipping matches following something else' do
|
45
|
+
|
46
|
+
let(:sequence) { Sequence[
|
47
|
+
Apply[:a],
|
48
|
+
Skip[Match[/b/]],
|
49
|
+
Skip[Match[/c/]]
|
50
|
+
] }
|
51
|
+
|
52
|
+
it 'joins the consecutive skipping matches into a single match' do
|
53
|
+
subject.apply(sequence, capturing).should == Sequence[
|
54
|
+
Apply[:a],
|
55
|
+
Skip[Match[/(?>b)(?>c)/]]
|
56
|
+
]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'given a sequence of matches' do
|
61
|
+
|
62
|
+
let(:sequence) { Sequence[
|
63
|
+
Match[/a/],
|
64
|
+
Match[/b/],
|
65
|
+
Match[/c/]
|
66
|
+
] }
|
67
|
+
|
68
|
+
it 'joins them into a single group match' do
|
69
|
+
subject.apply(sequence, capturing).
|
70
|
+
should == GroupMatch[Match[/(a)(b)(c)/], {:num_groups => 3}]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'given a sequence of single-group matches' do
|
75
|
+
|
76
|
+
let(:sequence) { Sequence[
|
77
|
+
GroupMatch[Match[/\s*(a)/], {:num_groups => 1}],
|
78
|
+
GroupMatch[Match[/\s*(b)/], {:num_groups => 1}],
|
79
|
+
GroupMatch[Match[/\s*(c)/], {:num_groups => 1}]
|
80
|
+
] }
|
81
|
+
|
82
|
+
it 'joins them into a single group match' do
|
83
|
+
subject.apply(sequence, capturing).
|
84
|
+
should == GroupMatch[Match[/(?>\s*(a))(?>\s*(b))(?>\s*(c))/], {:num_groups => 3}]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'give a mix of bare and single-group matches' do
|
89
|
+
|
90
|
+
let(:sequence) { Sequence[
|
91
|
+
GroupMatch[Match[/\s*(a)/], {:num_groups => 1}],
|
92
|
+
Match[/[+\-*\/]/],
|
93
|
+
GroupMatch[Match[/\s*(b)/], {:num_groups => 1}],
|
94
|
+
] }
|
95
|
+
|
96
|
+
it 'joins them into a single group match' do
|
97
|
+
subject.apply(sequence, capturing).
|
98
|
+
should == GroupMatch[Match[/(?>\s*(a))([+\-*\/])(?>\s*(b))/], {:num_groups => 3}]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#applies_to?' do
|
104
|
+
|
105
|
+
context 'given a sequence of matches followed by something else' do
|
106
|
+
|
107
|
+
let(:sequence) { Sequence[
|
108
|
+
Match[/a/],
|
109
|
+
Match[/b/],
|
110
|
+
Apply[:c]
|
111
|
+
] }
|
112
|
+
|
113
|
+
it 'returns true' do
|
114
|
+
subject.applies_to?(sequence, capturing).should be_true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'given a sequence of matches following something else' do
|
119
|
+
|
120
|
+
let(:sequence) { Sequence[
|
121
|
+
Apply[:a],
|
122
|
+
Match[/b/],
|
123
|
+
Match[/c/]
|
124
|
+
] }
|
125
|
+
|
126
|
+
it 'returns true' do
|
127
|
+
subject.applies_to?(sequence, capturing).should be_true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'given a sequence of skipping matches followed by something else' do
|
132
|
+
|
133
|
+
let(:sequence) { Sequence[
|
134
|
+
Skip[Match[/a/]],
|
135
|
+
Skip[Match[/b/]],
|
136
|
+
Apply[:c]
|
137
|
+
] }
|
138
|
+
|
139
|
+
it 'returns true' do
|
140
|
+
subject.applies_to?(sequence, capturing).should be_true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'given a sequence of skipping matches following something else' do
|
145
|
+
|
146
|
+
let(:sequence) { Sequence[
|
147
|
+
Apply[:a],
|
148
|
+
Skip[Match[/b/]],
|
149
|
+
Skip[Match[/c/]]
|
150
|
+
] }
|
151
|
+
|
152
|
+
it 'returns true' do
|
153
|
+
subject.applies_to?(sequence, capturing).should be_true
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'given a sequence of single-group matches followed by something else' do
|
158
|
+
|
159
|
+
let(:sequence) { Sequence[
|
160
|
+
GroupMatch[Match[/a/], {:num_groups => 1}],
|
161
|
+
GroupMatch[Match[/b/], {:num_groups => 1}],
|
162
|
+
Apply[:c]
|
163
|
+
] }
|
164
|
+
|
165
|
+
it 'returns true' do
|
166
|
+
subject.applies_to?(sequence, capturing).should be_true
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'given a sequence of single-group matches following something else' do
|
171
|
+
|
172
|
+
let(:sequence) { Sequence[
|
173
|
+
Apply[:a],
|
174
|
+
GroupMatch[Match[/b/], {:num_groups => 1}],
|
175
|
+
GroupMatch[Match[/c/], {:num_groups => 1}]
|
176
|
+
] }
|
177
|
+
|
178
|
+
it 'returns true' do
|
179
|
+
subject.applies_to?(sequence, capturing).should be_true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'given a sequence of multi-group matches followed by something else' do
|
184
|
+
|
185
|
+
let(:sequence) { Sequence[
|
186
|
+
GroupMatch[Match[/a/], {:num_groups => 2}],
|
187
|
+
GroupMatch[Match[/b/], {:num_groups => 2}],
|
188
|
+
Apply[:c]
|
189
|
+
] }
|
190
|
+
|
191
|
+
it 'returns false' do
|
192
|
+
subject.applies_to?(sequence, capturing).should be_false
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'given a sequence of multi-group matches following something else' do
|
197
|
+
|
198
|
+
let(:sequence) { Sequence[
|
199
|
+
Apply[:a],
|
200
|
+
GroupMatch[Match[/b/], {:num_groups => 2}],
|
201
|
+
GroupMatch[Match[/c/], {:num_groups => 2}]
|
202
|
+
] }
|
203
|
+
|
204
|
+
it 'returns false' do
|
205
|
+
subject.applies_to?(sequence, capturing).should be_false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'given a sequence with only one match' do
|
210
|
+
|
211
|
+
let(:sequence) { Sequence[Apply[:a], Skip[Match[/b/]], Apply[:c]] }
|
212
|
+
|
213
|
+
it 'returns false' do
|
214
|
+
subject.applies_to?(sequence, capturing).should be_false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'given a sequence of non-consecutive matches' do
|
219
|
+
|
220
|
+
let(:sequence) { Sequence[Skip[Match[/a/]], Apply[:b], Skip[Match[/c/]]] }
|
221
|
+
|
222
|
+
it 'returns false' do
|
223
|
+
subject.applies_to?(sequence, capturing).should be_false
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context 'given a non-sequence' do
|
228
|
+
|
229
|
+
let(:parser) { Choice[
|
230
|
+
Skip[Match[/a/]],
|
231
|
+
Skip[Match[/b/]],
|
232
|
+
Skip[Match[/c/]]
|
233
|
+
] }
|
234
|
+
|
235
|
+
it 'returns false' do
|
236
|
+
subject.applies_to?(parser, capturing).should be_false
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|