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.
Files changed (182) hide show
  1. data/README.rdoc +57 -37
  2. data/features/command_line/dest_option.feature +8 -21
  3. data/features/command_line/lib_option.feature +37 -0
  4. data/features/command_line/parser_generator.feature +7 -4
  5. data/features/grammar/back_reference.feature +37 -0
  6. data/features/grammar/fail.feature +3 -3
  7. data/features/grammar/labels.feature +11 -3
  8. data/features/grammar/list_matching.feature +14 -5
  9. data/features/grammar/literal.feature +30 -4
  10. data/features/grammar/nonterminal.feature +1 -1
  11. data/features/grammar/ordered_choice.feature +2 -2
  12. data/features/grammar/skip_operator.feature +1 -1
  13. data/features/grammar/symantic_action.feature +7 -7
  14. data/features/grammar/whitespace.feature +2 -2
  15. data/features/step_definitions/grammar_steps.rb +2 -2
  16. data/lib/rattler/back_end.rb +1 -0
  17. data/lib/rattler/back_end/compiler.rb +19 -20
  18. data/lib/rattler/back_end/optimizer.rb +100 -0
  19. data/lib/rattler/back_end/optimizer/composite_reducing.rb +18 -0
  20. data/lib/rattler/back_end/optimizer/flatten_choice.rb +31 -0
  21. data/lib/rattler/back_end/optimizer/flatten_sequence.rb +59 -0
  22. data/lib/rattler/back_end/optimizer/flattening.rb +17 -0
  23. data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +46 -0
  24. data/lib/rattler/back_end/optimizer/join_match_capturing_sequence.rb +71 -0
  25. data/lib/rattler/back_end/optimizer/join_match_choice.rb +37 -0
  26. data/lib/rattler/back_end/optimizer/join_match_matching_sequence.rb +38 -0
  27. data/lib/rattler/back_end/optimizer/join_match_sequence.rb +17 -0
  28. data/lib/rattler/back_end/optimizer/join_predicate_bare_match.rb +68 -0
  29. data/lib/rattler/back_end/optimizer/join_predicate_match.rb +17 -0
  30. data/lib/rattler/back_end/optimizer/join_predicate_nested_match.rb +37 -0
  31. data/lib/rattler/back_end/optimizer/join_predicate_or_bare_match.rb +68 -0
  32. data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +17 -0
  33. data/lib/rattler/back_end/optimizer/join_predicate_or_nested_match.rb +36 -0
  34. data/lib/rattler/back_end/optimizer/match_joining.rb +60 -0
  35. data/lib/rattler/back_end/optimizer/optimization.rb +94 -0
  36. data/lib/rattler/back_end/optimizer/optimization_context.rb +72 -0
  37. data/lib/rattler/back_end/optimizer/optimization_sequence.rb +37 -0
  38. data/lib/rattler/back_end/optimizer/optimize_children.rb +46 -0
  39. data/lib/rattler/back_end/optimizer/reduce_repeat_match.rb +44 -0
  40. data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +32 -0
  41. data/lib/rattler/back_end/optimizer/simplify_redundant_repeat.rb +43 -0
  42. data/lib/rattler/back_end/optimizer/simplify_token_match.rb +38 -0
  43. data/lib/rattler/back_end/parser_generator.rb +21 -14
  44. data/lib/rattler/back_end/parser_generator/apply_generator.rb +35 -35
  45. data/lib/rattler/back_end/parser_generator/assert_generator.rb +29 -30
  46. data/lib/rattler/back_end/parser_generator/back_reference_generator.rb +93 -0
  47. data/lib/rattler/back_end/parser_generator/choice_generator.rb +33 -49
  48. data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +14 -14
  49. data/lib/rattler/back_end/parser_generator/disallow_generator.rb +29 -30
  50. data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +11 -13
  51. data/lib/rattler/back_end/parser_generator/expr_generator.rb +36 -56
  52. data/lib/rattler/back_end/parser_generator/fail_generator.rb +18 -18
  53. data/lib/rattler/back_end/parser_generator/group_match.rb +18 -0
  54. data/lib/rattler/back_end/parser_generator/group_match_generator.rb +76 -0
  55. data/lib/rattler/back_end/parser_generator/label_generator.rb +25 -6
  56. data/lib/rattler/back_end/parser_generator/list1_generator.rb +7 -7
  57. data/lib/rattler/back_end/parser_generator/list_generating.rb +19 -20
  58. data/lib/rattler/back_end/parser_generator/list_generator.rb +5 -5
  59. data/lib/rattler/back_end/parser_generator/match_generator.rb +52 -52
  60. data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +6 -6
  61. data/lib/rattler/back_end/parser_generator/optional_generator.rb +30 -29
  62. data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +8 -8
  63. data/lib/rattler/back_end/parser_generator/repeat_generating.rb +23 -25
  64. data/lib/rattler/back_end/parser_generator/rule_generator.rb +27 -79
  65. data/lib/rattler/back_end/parser_generator/rule_set_generator.rb +102 -0
  66. data/lib/rattler/back_end/parser_generator/sequence_generator.rb +49 -41
  67. data/lib/rattler/back_end/parser_generator/skip_generator.rb +14 -20
  68. data/lib/rattler/back_end/parser_generator/skip_propogating.rb +4 -4
  69. data/lib/rattler/back_end/parser_generator/sub_generating.rb +6 -0
  70. data/lib/rattler/back_end/parser_generator/token_generator.rb +12 -12
  71. data/lib/rattler/back_end/parser_generator/token_propogating.rb +2 -2
  72. data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +4 -4
  73. data/lib/rattler/grammar.rb +4 -3
  74. data/lib/rattler/grammar/analysis.rb +91 -0
  75. data/lib/rattler/grammar/grammar.rb +37 -25
  76. data/lib/rattler/grammar/grammar_parser.rb +19 -11
  77. data/lib/rattler/grammar/metagrammar.rb +569 -800
  78. data/lib/rattler/grammar/rattler.rtlr +162 -144
  79. data/lib/rattler/parsers.rb +5 -1
  80. data/lib/rattler/parsers/action_code.rb +29 -15
  81. data/lib/rattler/parsers/apply.rb +5 -5
  82. data/lib/rattler/parsers/assert.rb +4 -18
  83. data/lib/rattler/parsers/back_reference.rb +46 -0
  84. data/lib/rattler/parsers/choice.rb +6 -39
  85. data/lib/rattler/parsers/combinator_parser.rb +32 -0
  86. data/lib/rattler/parsers/combining.rb +3 -29
  87. data/lib/rattler/parsers/direct_action.rb +27 -30
  88. data/lib/rattler/parsers/disallow.rb +4 -18
  89. data/lib/rattler/parsers/dispatch_action.rb +30 -25
  90. data/lib/rattler/parsers/label.rb +9 -18
  91. data/lib/rattler/parsers/list.rb +3 -34
  92. data/lib/rattler/parsers/list1.rb +4 -36
  93. data/lib/rattler/parsers/list_parser.rb +64 -0
  94. data/lib/rattler/parsers/match.rb +7 -42
  95. data/lib/rattler/parsers/node_code.rb +44 -0
  96. data/lib/rattler/parsers/one_or_more.rb +7 -27
  97. data/lib/rattler/parsers/optional.rb +5 -25
  98. data/lib/rattler/parsers/parser.rb +16 -44
  99. data/lib/rattler/parsers/parser_dsl.rb +13 -3
  100. data/lib/rattler/parsers/predicate.rb +4 -12
  101. data/lib/rattler/parsers/rule.rb +18 -19
  102. data/lib/rattler/parsers/rule_set.rb +63 -0
  103. data/lib/rattler/parsers/sequence.rb +12 -46
  104. data/lib/rattler/parsers/skip.rb +12 -26
  105. data/lib/rattler/parsers/token.rb +6 -21
  106. data/lib/rattler/parsers/zero_or_more.rb +6 -26
  107. data/lib/rattler/runner.rb +66 -28
  108. data/lib/rattler/runtime/extended_packrat_parser.rb +26 -20
  109. data/lib/rattler/runtime/packrat_parser.rb +17 -21
  110. data/lib/rattler/runtime/parser.rb +12 -2
  111. data/lib/rattler/runtime/recursive_descent_parser.rb +3 -11
  112. data/lib/rattler/util.rb +2 -1
  113. data/lib/rattler/util/graphviz.rb +29 -0
  114. data/lib/rattler/util/graphviz/digraph_builder.rb +71 -0
  115. data/lib/rattler/util/graphviz/node_builder.rb +84 -0
  116. data/lib/rattler/util/node.rb +37 -19
  117. data/lib/rattler/util/parser_spec_helper.rb +61 -35
  118. data/spec/rattler/back_end/compiler_spec.rb +6 -860
  119. data/spec/rattler/back_end/optimizer/flatten_choice_spec.rb +70 -0
  120. data/spec/rattler/back_end/optimizer/flatten_sequence_spec.rb +130 -0
  121. data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +80 -0
  122. data/spec/rattler/back_end/optimizer/join_match_capturing_sequence_spec.rb +241 -0
  123. data/spec/rattler/back_end/optimizer/join_match_choice_spec.rb +100 -0
  124. data/spec/rattler/back_end/optimizer/join_match_matching_sequence_spec.rb +112 -0
  125. data/spec/rattler/back_end/optimizer/join_predicate_bare_match_spec.rb +194 -0
  126. data/spec/rattler/back_end/optimizer/join_predicate_nested_match_spec.rb +180 -0
  127. data/spec/rattler/back_end/optimizer/join_predicate_or_bare_match_spec.rb +153 -0
  128. data/spec/rattler/back_end/optimizer/join_predicate_or_nested_match_spec.rb +153 -0
  129. data/spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb +98 -0
  130. data/spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb +226 -0
  131. data/spec/rattler/back_end/optimizer/simplify_token_match_spec.rb +85 -0
  132. data/spec/rattler/back_end/parser_generator/apply_generator_spec.rb +38 -33
  133. data/spec/rattler/back_end/parser_generator/assert_generator_spec.rb +38 -33
  134. data/spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb +181 -0
  135. data/spec/rattler/back_end/parser_generator/choice_generator_spec.rb +38 -33
  136. data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +38 -33
  137. data/spec/rattler/back_end/parser_generator/disallow_generator_spec.rb +38 -33
  138. data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +38 -33
  139. data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +185 -0
  140. data/spec/rattler/back_end/parser_generator/label_generator_spec.rb +38 -33
  141. data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +10 -5
  142. data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +10 -5
  143. data/spec/rattler/back_end/parser_generator/match_generator_spec.rb +38 -33
  144. data/spec/rattler/back_end/parser_generator/one_or_more_generator_spec.rb +38 -33
  145. data/spec/rattler/back_end/parser_generator/optional_generator_spec.rb +38 -33
  146. data/spec/rattler/back_end/parser_generator/rule_generator_spec.rb +13 -46
  147. data/spec/rattler/back_end/parser_generator/rule_set_generator_spec.rb +97 -0
  148. data/spec/rattler/back_end/parser_generator/sequence_generator_spec.rb +38 -33
  149. data/spec/rattler/back_end/parser_generator/skip_generator_spec.rb +38 -33
  150. data/spec/rattler/back_end/parser_generator/token_generator_spec.rb +38 -33
  151. data/spec/rattler/back_end/parser_generator/zero_or_more_generator_spec.rb +39 -34
  152. data/spec/rattler/back_end/shared_compiler_examples.rb +885 -0
  153. data/spec/rattler/grammar/analysis_spec.rb +167 -0
  154. data/spec/rattler/grammar/grammar_parser_spec.rb +169 -179
  155. data/spec/rattler/grammar/grammar_spec.rb +24 -21
  156. data/spec/rattler/parsers/action_code_spec.rb +64 -19
  157. data/spec/rattler/parsers/apply_spec.rb +9 -9
  158. data/spec/rattler/parsers/back_reference_spec.rb +38 -0
  159. data/spec/rattler/parsers/combinator_parser_spec.rb +14 -0
  160. data/spec/rattler/parsers/direct_action_spec.rb +16 -2
  161. data/spec/rattler/parsers/dispatch_action_spec.rb +15 -32
  162. data/spec/rattler/parsers/fail_spec.rb +6 -4
  163. data/spec/rattler/parsers/label_spec.rb +10 -28
  164. data/spec/rattler/parsers/node_code_spec.rb +48 -0
  165. data/spec/rattler/parsers/parser_dsl_spec.rb +1 -1
  166. data/spec/rattler/parsers/rule_set_spec.rb +35 -0
  167. data/spec/rattler/parsers/sequence_spec.rb +15 -24
  168. data/spec/rattler/runtime/extended_packrat_parser_spec.rb +22 -17
  169. data/spec/rattler/runtime/packrat_parser_spec.rb +1 -1
  170. data/spec/rattler/runtime/parse_node_spec.rb +15 -19
  171. data/spec/rattler/runtime/recursive_descent_parser_spec.rb +1 -1
  172. data/spec/rattler/runtime/shared_parser_examples.rb +61 -28
  173. data/spec/rattler/util/graphviz/node_builder_spec.rb +84 -0
  174. data/spec/rattler/util/node_spec.rb +92 -65
  175. data/spec/rattler_spec.rb +16 -16
  176. data/spec/support/combinator_parser_spec_helper.rb +19 -18
  177. data/spec/support/compiler_spec_helper.rb +56 -87
  178. data/spec/support/runtime_parser_spec_helper.rb +6 -14
  179. metadata +117 -22
  180. data/features/grammar/regex.feature +0 -24
  181. data/lib/rattler/parsers/match_joining.rb +0 -67
  182. 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