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,100 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::Parsers
|
4
|
+
|
5
|
+
describe Rattler::BackEnd::Optimizer::JoinMatchChoice do
|
6
|
+
|
7
|
+
describe '#apply' do
|
8
|
+
|
9
|
+
context 'given a choice of all matches' do
|
10
|
+
|
11
|
+
let(:choice) { Choice[Match[/a/], Match[/b/], Match[/c/]] }
|
12
|
+
|
13
|
+
it 'joins them into a single match' do
|
14
|
+
subject.apply(choice, :any).should == Match[/a|b|c/]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given a choice of matches followed by something else' do
|
19
|
+
|
20
|
+
let(:choice) { Choice[Match[/a/], Match[/b/], Apply[:c]] }
|
21
|
+
|
22
|
+
it 'joins the consecutive matches into a single match' do
|
23
|
+
subject.apply(choice, :any).should == Choice[
|
24
|
+
Match[/a|b/],
|
25
|
+
Apply[:c]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'given a choice of matches following something else' do
|
31
|
+
|
32
|
+
let(:choice) { Choice[Apply[:a], Match[/b/], Match[/c/]] }
|
33
|
+
|
34
|
+
it 'joins the consecutive matches into a single match' do
|
35
|
+
subject.apply(choice, :any).should == Choice[
|
36
|
+
Apply[:a],
|
37
|
+
Match[/b|c/]
|
38
|
+
]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#applies_to?' do
|
44
|
+
|
45
|
+
context 'given a choice of all matches' do
|
46
|
+
|
47
|
+
let(:choice) { Choice[Match[/a/], Match[/b/], Match[/c/]] }
|
48
|
+
|
49
|
+
it 'returns true' do
|
50
|
+
subject.applies_to?(choice, :any).should be_true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'given a choice of matches followed by something else' do
|
55
|
+
|
56
|
+
let(:choice) { Choice[Match[/a/], Match[/b/], Apply[:c]] }
|
57
|
+
|
58
|
+
it 'returns true' do
|
59
|
+
subject.applies_to?(choice, :any).should be_true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'given a choice of matches following something else' do
|
64
|
+
|
65
|
+
let(:choice) { Choice[Apply[:a], Match[/b/], Match[/c/]] }
|
66
|
+
|
67
|
+
it 'returns true' do
|
68
|
+
subject.applies_to?(choice, :any).should be_true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'given a choice with only one match' do
|
73
|
+
|
74
|
+
let(:choice) { Choice[Apply[:a], Match[/b/], Apply[:c]] }
|
75
|
+
|
76
|
+
it 'returns true' do
|
77
|
+
subject.applies_to?(choice, :any).should be_false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'given a choice of non-consecutive matches' do
|
82
|
+
|
83
|
+
let(:choice) { Choice[Match[/a/], Apply[:b], Match[/c/]] }
|
84
|
+
|
85
|
+
it 'returns false' do
|
86
|
+
subject.applies_to?(choice, :any).should be_false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'given a non-choice' do
|
91
|
+
|
92
|
+
let(:sequence) { Sequence[Match[/a/], Match[/b/], Match[/c/]] }
|
93
|
+
|
94
|
+
it 'returns false' do
|
95
|
+
subject.applies_to?(sequence, :any).should be_false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::BackEnd::Optimizer
|
4
|
+
include Rattler::Parsers
|
5
|
+
|
6
|
+
describe JoinMatchMatchingSequence do
|
7
|
+
|
8
|
+
let(:matching) { OptimizationContext[:type => :matching] }
|
9
|
+
let(:capturing) { OptimizationContext[:type => :capturing] }
|
10
|
+
|
11
|
+
describe '#apply' do
|
12
|
+
|
13
|
+
context 'given a sequence of all matches' do
|
14
|
+
|
15
|
+
let(:sequence) { Sequence[Match[/a/], Match[/b/], Match[/c/]] }
|
16
|
+
|
17
|
+
it 'joins them into a single match' do
|
18
|
+
subject.apply(sequence, matching).should == Match[/(?>a)(?>b)(?>c)/]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'given a sequence of matches followed by something else' do
|
23
|
+
|
24
|
+
let(:sequence) { Sequence[Match[/a/], Match[/b/], Apply[:c]] }
|
25
|
+
|
26
|
+
it 'joins the consecutive matches into a single match' do
|
27
|
+
subject.apply(sequence, matching).should == Sequence[
|
28
|
+
Match[/(?>a)(?>b)/],
|
29
|
+
Apply[:c]
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'given a sequence of matches following something else' do
|
35
|
+
|
36
|
+
let(:sequence) { Sequence[Apply[:a], Match[/b/], Match[/c/]] }
|
37
|
+
|
38
|
+
it 'joins the consecutive matches into a single match' do
|
39
|
+
subject.apply(sequence, matching).should == Sequence[
|
40
|
+
Apply[:a],
|
41
|
+
Match[/(?>b)(?>c)/]
|
42
|
+
]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#applies_to?' do
|
48
|
+
|
49
|
+
context 'given a sequence of all matches' do
|
50
|
+
|
51
|
+
let(:sequence) { Sequence[Match[/a/], Match[/b/], Match[/c/]] }
|
52
|
+
|
53
|
+
context 'in the :matching context' do
|
54
|
+
it 'returns true' do
|
55
|
+
subject.applies_to?(sequence, matching).should be_true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'in the :matching context' do
|
60
|
+
it 'returns false' do
|
61
|
+
subject.applies_to?(sequence, capturing).should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'given a sequence of matches followed by something else' do
|
67
|
+
|
68
|
+
let(:sequence) { Sequence[Match[/a/], Match[/b/], Apply[:c]] }
|
69
|
+
|
70
|
+
it 'returns true' do
|
71
|
+
subject.applies_to?(sequence, matching).should be_true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'given a sequence of matches following something else' do
|
76
|
+
|
77
|
+
let(:sequence) { Sequence[Apply[:a], Match[/b/], Match[/c/]] }
|
78
|
+
|
79
|
+
it 'returns true' do
|
80
|
+
subject.applies_to?(sequence, matching).should be_true
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'given a sequence with only one match' do
|
85
|
+
|
86
|
+
let(:sequence) { Sequence[Apply[:a], Match[/b/], Apply[:c]] }
|
87
|
+
|
88
|
+
it 'returns true' do
|
89
|
+
subject.applies_to?(sequence, matching).should be_false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'given a sequence of non-consecutive matches' do
|
94
|
+
|
95
|
+
let(:sequence) { Sequence[Match[/a/], Apply[:b], Match[/c/]] }
|
96
|
+
|
97
|
+
it 'returns false' do
|
98
|
+
subject.applies_to?(sequence, matching).should be_false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'given a non-sequence' do
|
103
|
+
|
104
|
+
let(:choice) { Choice[Match[/a/], Match[/b/], Match[/c/]] }
|
105
|
+
|
106
|
+
it 'returns false' do
|
107
|
+
subject.applies_to?(choice, matching).should be_false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::Parsers
|
4
|
+
|
5
|
+
describe Rattler::BackEnd::Optimizer::JoinPredicateBareMatch do
|
6
|
+
|
7
|
+
describe '#apply' do
|
8
|
+
|
9
|
+
let(:match) { Match[/a/] }
|
10
|
+
|
11
|
+
let(:assert) { Assert[Match[/b/]] }
|
12
|
+
let(:disallow) { Disallow[Match[/b/]] }
|
13
|
+
|
14
|
+
context 'given a sequence with a match followed by a predicate' do
|
15
|
+
|
16
|
+
let(:sequence) { Sequence[Apply[:a], match, predicate, Apply[:b]] }
|
17
|
+
|
18
|
+
context 'with an assert of a match' do
|
19
|
+
|
20
|
+
let(:predicate) { assert }
|
21
|
+
|
22
|
+
it 'reduces the match and assert into an equivalent single match' do
|
23
|
+
subject.apply(sequence, :any).should ==
|
24
|
+
Sequence[Apply[:a], Match[/(?>a)(?=b)/], Apply[:b]]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with a disallow of a match' do
|
29
|
+
|
30
|
+
let(:predicate) { disallow }
|
31
|
+
|
32
|
+
it 'reduces the match and disallow into an equivalent single match' do
|
33
|
+
subject.apply(sequence, :any).should ==
|
34
|
+
Sequence[Apply[:a], Match[/(?>a)(?!b)/], Apply[:b]]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with Eof' do
|
39
|
+
|
40
|
+
let(:predicate) { Eof[] }
|
41
|
+
|
42
|
+
it 'reduces the match and Eof into an equivalent single match' do
|
43
|
+
subject.apply(sequence, :any).should ==
|
44
|
+
Sequence[Apply[:a], Match[/(?>a)\z/], Apply[:b]]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'given a sequence with a predicate followed by a match' do
|
50
|
+
|
51
|
+
let(:sequence) { Sequence[Apply[:a], predicate, match, Apply[:b]] }
|
52
|
+
|
53
|
+
context 'with an assert of a match' do
|
54
|
+
|
55
|
+
let(:predicate) { assert }
|
56
|
+
|
57
|
+
it 'reduces the match and assert into an equivalent single match' do
|
58
|
+
subject.apply(sequence, :any).should ==
|
59
|
+
Sequence[Apply[:a], Match[/(?=b)(?>a)/], Apply[:b]]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'with a disallow of a match' do
|
64
|
+
|
65
|
+
let(:predicate) { disallow }
|
66
|
+
|
67
|
+
it 'reduces the match and disallow into an equivalent single match' do
|
68
|
+
subject.apply(sequence, :any).should ==
|
69
|
+
Sequence[Apply[:a], Match[/(?!b)(?>a)/], Apply[:b]]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#applies_to?' do
|
76
|
+
|
77
|
+
let(:match) { Match[/a/] }
|
78
|
+
|
79
|
+
let(:assert) { Assert[Match[/b/]] }
|
80
|
+
let(:disallow) { Disallow[Match[/b/]] }
|
81
|
+
|
82
|
+
context 'given a sequence with a match followed by a predicate' do
|
83
|
+
|
84
|
+
let(:sequence) { Sequence[Apply[:a], match, predicate, Apply[:b]] }
|
85
|
+
|
86
|
+
context 'with an assert of a match' do
|
87
|
+
|
88
|
+
let(:predicate) { assert }
|
89
|
+
|
90
|
+
it 'returns true' do
|
91
|
+
subject.applies_to?(sequence, :any).should be_true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with a disallow of a match' do
|
96
|
+
|
97
|
+
let(:predicate) { disallow }
|
98
|
+
|
99
|
+
it 'returns true' do
|
100
|
+
subject.applies_to?(sequence, :any).should be_true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'with Eof' do
|
105
|
+
|
106
|
+
let(:predicate) { Eof[] }
|
107
|
+
|
108
|
+
it 'returns true' do
|
109
|
+
subject.applies_to?(sequence, :any).should be_true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with an assert of something else' do
|
114
|
+
|
115
|
+
let(:predicate) { Assert[Apply[:a]]}
|
116
|
+
|
117
|
+
it 'returns false' do
|
118
|
+
subject.applies_to?(sequence, :any).should be_false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'with a disallow of something else' do
|
123
|
+
|
124
|
+
let(:predicate) { Assert[Apply[:a]]}
|
125
|
+
|
126
|
+
it 'returns false' do
|
127
|
+
subject.applies_to?(sequence, :any).should be_false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
context 'given a sequence with a predicate followed by a match' do
|
134
|
+
|
135
|
+
let(:sequence) { Sequence[Apply[:a], predicate, match, Apply[:b]] }
|
136
|
+
|
137
|
+
context 'with an assert of a match' do
|
138
|
+
|
139
|
+
let(:predicate) { assert }
|
140
|
+
|
141
|
+
it 'returns true' do
|
142
|
+
subject.applies_to?(sequence, :any).should be_true
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'with a disallow of a match' do
|
148
|
+
|
149
|
+
let(:predicate) { disallow }
|
150
|
+
|
151
|
+
it 'returns true' do
|
152
|
+
subject.applies_to?(sequence, :any).should be_true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'with an assert of something else' do
|
157
|
+
|
158
|
+
let(:predicate) { Assert[Apply[:a]]}
|
159
|
+
|
160
|
+
it 'returns false' do
|
161
|
+
subject.applies_to?(sequence, :any).should be_false
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'with a disallow of something else' do
|
166
|
+
|
167
|
+
let(:predicate) { Assert[Apply[:a]]}
|
168
|
+
|
169
|
+
it 'returns false' do
|
170
|
+
subject.applies_to?(sequence, :any).should be_false
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'with Eof' do
|
175
|
+
|
176
|
+
let(:predicate) { Eof[] }
|
177
|
+
|
178
|
+
it 'returns true' do
|
179
|
+
subject.applies_to?(sequence, :any).should be_true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'given a sequence with a match and a predicate not adjacent' do
|
185
|
+
|
186
|
+
let(:sequence) { Sequence[Apply[:a], match, Apply[:b], assert] }
|
187
|
+
|
188
|
+
it 'returns false' do
|
189
|
+
subject.applies_to?(sequence, :any).should be_false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
include Rattler::Parsers
|
4
|
+
|
5
|
+
describe Rattler::BackEnd::Optimizer::JoinPredicateNestedMatch do
|
6
|
+
|
7
|
+
let(:skip) { Skip[Match[/a/]] }
|
8
|
+
let(:token) { Token[Match[/a/]] }
|
9
|
+
|
10
|
+
let(:assert) { Assert[Match[/b/]] }
|
11
|
+
let(:disallow) { Disallow[Match[/b/]] }
|
12
|
+
|
13
|
+
describe '#apply' do
|
14
|
+
|
15
|
+
context 'given a sequence with a skip of a match followed by a predicate' do
|
16
|
+
|
17
|
+
let(:sequence) { Sequence[Apply[:a], skip, predicate, Apply[:b]] }
|
18
|
+
|
19
|
+
context 'with an assert of a match' do
|
20
|
+
|
21
|
+
let(:predicate) { assert }
|
22
|
+
|
23
|
+
it 'reduces the match and assert into an equivalent skipping match' do
|
24
|
+
subject.apply(sequence, :any).should ==
|
25
|
+
Sequence[Apply[:a], Skip[Match[/(?>a)(?=b)/]], Apply[:b]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a disallow of a match' do
|
30
|
+
|
31
|
+
let(:predicate) { disallow }
|
32
|
+
|
33
|
+
it 'reduces the match and disallow into an equivalent skipping match' do
|
34
|
+
subject.apply(sequence, :any).should ==
|
35
|
+
Sequence[Apply[:a], Skip[Match[/(?>a)(?!b)/]], Apply[:b]]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with Eof' do
|
40
|
+
|
41
|
+
let(:predicate) { Eof[] }
|
42
|
+
|
43
|
+
it 'reduces the match and Eof into an equivalent skipping match' do
|
44
|
+
subject.apply(sequence, :any).should ==
|
45
|
+
Sequence[Apply[:a], Skip[Match[/(?>a)\z/]], Apply[:b]]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'given a sequence with a predicate followed by a skip of a match' do
|
51
|
+
|
52
|
+
let(:sequence) { Sequence[Apply[:a], predicate, skip, Apply[:b]] }
|
53
|
+
|
54
|
+
context 'with an assert of a match' do
|
55
|
+
|
56
|
+
let(:predicate) { assert }
|
57
|
+
|
58
|
+
it 'reduces the match and assert into an equivalent skipping match' do
|
59
|
+
subject.apply(sequence, :any).should ==
|
60
|
+
Sequence[Apply[:a], Skip[Match[/(?=b)(?>a)/]], Apply[:b]]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with a disallow of a match' do
|
65
|
+
|
66
|
+
let(:predicate) { disallow }
|
67
|
+
|
68
|
+
it 'reduces the match and disallow into an equivalent skipping match' do
|
69
|
+
subject.apply(sequence, :any).should ==
|
70
|
+
Sequence[Apply[:a], Skip[Match[/(?!b)(?>a)/]], Apply[:b]]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#applies_to?' do
|
77
|
+
|
78
|
+
context 'given a sequence with a skip of a match followed by a predicate' do
|
79
|
+
|
80
|
+
let(:sequence) { Sequence[Apply[:a], skip, predicate, Apply[:b]] }
|
81
|
+
|
82
|
+
context 'with an assert of a match' do
|
83
|
+
|
84
|
+
let(:predicate) { assert }
|
85
|
+
|
86
|
+
it 'returns true' do
|
87
|
+
subject.applies_to?(sequence, :any).should be_true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'with a disallow of a match' do
|
92
|
+
|
93
|
+
let(:predicate) { disallow }
|
94
|
+
|
95
|
+
it 'returns true' do
|
96
|
+
subject.applies_to?(sequence, :any).should be_true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'with Eof' do
|
101
|
+
|
102
|
+
let(:predicate) { Eof[] }
|
103
|
+
|
104
|
+
it 'returns true' do
|
105
|
+
subject.applies_to?(sequence, :any).should be_true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with an assert of something else' do
|
110
|
+
|
111
|
+
let(:predicate) { Assert[Apply[:a]]}
|
112
|
+
|
113
|
+
it 'returns false' do
|
114
|
+
subject.applies_to?(sequence, :any).should be_false
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'with a disallow of something else' do
|
119
|
+
|
120
|
+
let(:predicate) { Disallow[Apply[:a]]}
|
121
|
+
|
122
|
+
it 'returns false' do
|
123
|
+
subject.applies_to?(sequence, :any).should be_false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
context 'given a sequence with a predicate followed by a skip of match' do
|
130
|
+
|
131
|
+
let(:sequence) { Sequence[Apply[:a], predicate, skip, Apply[:b]] }
|
132
|
+
|
133
|
+
context 'with an assert of a match' do
|
134
|
+
|
135
|
+
let(:predicate) { assert }
|
136
|
+
|
137
|
+
it 'returns true' do
|
138
|
+
subject.applies_to?(sequence, :any).should be_true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with a disallow of a match' do
|
143
|
+
|
144
|
+
let(:predicate) { disallow }
|
145
|
+
|
146
|
+
it 'returns true' do
|
147
|
+
subject.applies_to?(sequence, :any).should be_true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'with an assert of something else' do
|
152
|
+
|
153
|
+
let(:predicate) { Assert[Apply[:a]]}
|
154
|
+
|
155
|
+
it 'returns false' do
|
156
|
+
subject.applies_to?(sequence, :any).should be_false
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'with a disallow of something else' do
|
161
|
+
|
162
|
+
let(:predicate) { Disallow[Apply[:a]]}
|
163
|
+
|
164
|
+
it 'returns false' do
|
165
|
+
subject.applies_to?(sequence, :any).should be_false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'given a sequence with a match and a predicate not adjacent' do
|
171
|
+
|
172
|
+
let(:sequence) { Sequence[Apply[:a], skip, Apply[:b], assert] }
|
173
|
+
|
174
|
+
it 'returns false' do
|
175
|
+
subject.applies_to?(sequence, :any).should be_false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|