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,153 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ include Rattler::BackEnd::Optimizer
4
+ include Rattler::Parsers
5
+
6
+ describe JoinPredicateOrBareMatch do
7
+
8
+ let(:match) { 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 choice with a match followed by a predicate' do
16
+
17
+ let(:choice) { Choice[Apply[:a], match, predicate] }
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 single match' do
24
+ subject.apply(choice, :any).should ==
25
+ Choice[Apply[:a], Match[/a|(?=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 single match' do
34
+ subject.apply(choice, :any).should ==
35
+ Choice[Apply[:a], Match[/a|(?!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 single match' do
44
+ subject.apply(choice, :any).should ==
45
+ Choice[Apply[:a], Match[/a|\z/]]
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'given a choice with a predicate followed by a match' do
51
+
52
+ let(:choice) { Choice[Apply[:a], predicate, match] }
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 single match' do
59
+ subject.apply(choice, :any).should ==
60
+ Choice[Apply[:a], Match[/(?=b)|a/]]
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 single match' do
69
+ subject.apply(choice, :any).should ==
70
+ Choice[Apply[:a], Match[/(?!b)|a/]]
71
+ end
72
+ end
73
+
74
+ context 'with Eof' do
75
+
76
+ let(:predicate) { Eof[] }
77
+
78
+ it 'reduces the match and Eof into an equivalent single match' do
79
+ subject.apply(choice, :any).should ==
80
+ Choice[Apply[:a], Match[/\z|a/]]
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#applies_to?' do
87
+
88
+ context 'given a choice with a match followed by a predicate' do
89
+
90
+ let(:choice) { Choice[Apply[:a], match, predicate] }
91
+
92
+ context 'with an assert of a match' do
93
+
94
+ let(:predicate) { assert }
95
+
96
+ it 'returns true' do
97
+ subject.applies_to?(choice, :any).should be_true
98
+ end
99
+ end
100
+
101
+ context 'with a disallow of a match' do
102
+
103
+ let(:predicate) { disallow }
104
+
105
+ it 'returns true' do
106
+ subject.applies_to?(choice, :any).should be_true
107
+ end
108
+ end
109
+
110
+ context 'with Eof' do
111
+
112
+ let(:predicate) { Eof[] }
113
+
114
+ it 'returns true' do
115
+ subject.applies_to?(choice, :any).should be_true
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'given a choice with a predicate followed by a match' do
121
+
122
+ let(:choice) { Choice[Apply[:a], predicate, match] }
123
+
124
+ context 'with an assert of a match' do
125
+
126
+ let(:predicate) { assert }
127
+
128
+ it 'returns true' do
129
+ subject.applies_to?(choice, :any).should be_true
130
+ end
131
+ end
132
+
133
+ context 'with a disallow of a match' do
134
+
135
+ let(:predicate) { disallow }
136
+
137
+ it 'returns true' do
138
+ subject.applies_to?(choice, :any).should be_true
139
+ end
140
+ end
141
+
142
+ context 'with Eof' do
143
+
144
+ let(:predicate) { Eof[] }
145
+
146
+ it 'returns true' do
147
+ subject.applies_to?(choice, :any).should be_true
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ end
@@ -0,0 +1,153 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ include Rattler::BackEnd::Optimizer
4
+ include Rattler::Parsers
5
+
6
+ describe JoinPredicateOrNestedMatch do
7
+
8
+ let(:skip) { Skip[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 choice with a skip of a match followed by a predicate' do
16
+
17
+ let(:choice) { Choice[Apply[:a], skip, predicate] }
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 skip of a match' do
24
+ subject.apply(choice, :any).should ==
25
+ Choice[Apply[:a], Skip[Match[/a|(?=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 skip of a match' do
34
+ subject.apply(choice, :any).should ==
35
+ Choice[Apply[:a], Skip[Match[/a|(?!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 skip of a match' do
44
+ subject.apply(choice, :any).should ==
45
+ Choice[Apply[:a], Skip[Match[/a|\z/]]]
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'given a choice with a predicate followed by a skip of a match' do
51
+
52
+ let(:choice) { Choice[Apply[:a], predicate, skip] }
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 skip of a match' do
59
+ subject.apply(choice, :any).should ==
60
+ Choice[Apply[:a], Skip[Match[/(?=b)|a/]]]
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 skip of a match' do
69
+ subject.apply(choice, :any).should ==
70
+ Choice[Apply[:a], Skip[Match[/(?!b)|a/]]]
71
+ end
72
+ end
73
+
74
+ context 'with Eof' do
75
+
76
+ let(:predicate) { Eof[] }
77
+
78
+ it 'reduces the match and Eof into an equivalent skip of a match' do
79
+ subject.apply(choice, :any).should ==
80
+ Choice[Apply[:a], Skip[Match[/\z|a/]]]
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#applies_to?' do
87
+
88
+ context 'given a choice with a skip of a match followed by a predicate' do
89
+
90
+ let(:choice) { Choice[Apply[:a], skip, predicate] }
91
+
92
+ context 'with an assert of a match' do
93
+
94
+ let(:predicate) { assert }
95
+
96
+ it 'returns true' do
97
+ subject.applies_to?(choice, :any).should be_true
98
+ end
99
+ end
100
+
101
+ context 'with a disallow of a match' do
102
+
103
+ let(:predicate) { disallow }
104
+
105
+ it 'returns true' do
106
+ subject.applies_to?(choice, :any).should be_true
107
+ end
108
+ end
109
+
110
+ context 'with Eof' do
111
+
112
+ let(:predicate) { Eof[] }
113
+
114
+ it 'returns true' do
115
+ subject.applies_to?(choice, :any).should be_true
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'given a choice with a predicate followed by a skip of a match' do
121
+
122
+ let(:choice) { Choice[Apply[:a], predicate, skip] }
123
+
124
+ context 'with an assert of a match' do
125
+
126
+ let(:predicate) { assert }
127
+
128
+ it 'returns true' do
129
+ subject.applies_to?(choice, :any).should be_true
130
+ end
131
+ end
132
+
133
+ context 'with a disallow of a match' do
134
+
135
+ let(:predicate) { disallow }
136
+
137
+ it 'returns true' do
138
+ subject.applies_to?(choice, :any).should be_true
139
+ end
140
+ end
141
+
142
+ context 'with Eof' do
143
+
144
+ let(:predicate) { Eof[] }
145
+
146
+ it 'returns true' do
147
+ subject.applies_to?(choice, :any).should be_true
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ include Rattler::BackEnd::Optimizer
4
+ include Rattler::Parsers
5
+
6
+ describe ReduceRepeatMatch do
7
+
8
+ let(:matching) { OptimizationContext[:type => :matching] }
9
+ let(:capturing) { OptimizationContext[:type => :capturing] }
10
+
11
+ describe '#apply' do
12
+
13
+ context 'given a zero-or-more match' do
14
+
15
+ let(:repeat) { ZeroOrMore[Match[/a/]] }
16
+
17
+ it 'converts it to an equivalent match' do
18
+ subject.apply(repeat, matching).should == Match[/(?>a)*/]
19
+ end
20
+ end
21
+
22
+ context 'given a one-or-more of a match' do
23
+
24
+ let(:repeat) { OneOrMore[Match[/a/]] }
25
+
26
+ it 'returns true' do
27
+ subject.apply(repeat, matching).should == Match[/(?>a)+/]
28
+ end
29
+ end
30
+
31
+ context 'given an optional match' do
32
+
33
+ let(:repeat) { Optional[Match[/a/]] }
34
+
35
+ it 'returns true' do
36
+ subject.apply(repeat, matching).should == Match[/(?>a)?/]
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#applies_to?' do
42
+
43
+ context 'in the :capturing context' do
44
+
45
+ let(:repeat) { ZeroOrMore[Match[/a/]] }
46
+
47
+ it 'returns false' do
48
+ subject.applies_to?(repeat, capturing).should be_false
49
+ end
50
+ end
51
+
52
+ context 'given a zero-or-more of a match' do
53
+
54
+ let(:repeat) { ZeroOrMore[Match[/a/]] }
55
+
56
+ it 'returns true' do
57
+ subject.applies_to?(repeat, matching).should be_true
58
+ end
59
+ end
60
+
61
+ context 'given a one-or-more of a match' do
62
+
63
+ let(:repeat) { OneOrMore[Match[/a/]] }
64
+
65
+ it 'returns true' do
66
+ subject.applies_to?(repeat, matching).should be_true
67
+ end
68
+ end
69
+
70
+ context 'given an optional match' do
71
+
72
+ let(:repeat) { Optional[Match[/a/]] }
73
+
74
+ it 'returns true' do
75
+ subject.applies_to?(repeat, matching).should be_true
76
+ end
77
+ end
78
+
79
+ context 'given a repeat of something other than a match' do
80
+
81
+ let(:repeat) { ZeroOrMore[Apply[:a]] }
82
+
83
+ it 'returns false' do
84
+ subject.applies_to?(repeat, matching).should be_false
85
+ end
86
+ end
87
+
88
+ context 'given something other than a repeat' do
89
+
90
+ let(:other) { Assert[Match[/a/]] }
91
+
92
+ it 'returns false' do
93
+ subject.applies_to?(other, matching).should be_false
94
+ end
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,226 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ include Rattler::BackEnd::Optimizer
4
+ include Rattler::Parsers
5
+
6
+ describe SimplifyRedundantRepeat do
7
+
8
+ let(:matching) { OptimizationContext[:type => :matching] }
9
+ let(:capturing) { OptimizationContext[:type => :capturing] }
10
+
11
+ describe '#apply' do
12
+
13
+ context 'given a zero-or-more' do
14
+
15
+ let(:parser) { ZeroOrMore[child] }
16
+
17
+ context 'with a zero-or-more' do
18
+
19
+ let(:child) { ZeroOrMore[Match[/a/]] }
20
+
21
+ it 'returns the inner ZeroOrMore' do
22
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
23
+ end
24
+ end
25
+
26
+ context 'with a one-or-more' do
27
+
28
+ let(:child) { OneOrMore[Match[/a/]] }
29
+
30
+ it 'returns a ZeroOrMore' do
31
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
32
+ end
33
+ end
34
+
35
+ context 'with an optional' do
36
+
37
+ let(:child) { Optional[Match[/a/]] }
38
+
39
+ it 'returns a ZeroOrMore' do
40
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'given a one-or-more' do
46
+
47
+ let(:parser) { OneOrMore[child] }
48
+
49
+ context 'with a zero-or-more' do
50
+
51
+ let(:child) { ZeroOrMore[Match[/a/]] }
52
+
53
+ it 'returns the inner ZeroOrMore' do
54
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
55
+ end
56
+ end
57
+
58
+ context 'with a one-or-more' do
59
+
60
+ let(:child) { OneOrMore[Match[/a/]] }
61
+
62
+ it 'returns the inner OneOrMore' do
63
+ subject.apply(parser, matching).should == OneOrMore[Match[/a/]]
64
+ end
65
+ end
66
+
67
+ context 'with an optional' do
68
+
69
+ let(:child) { Optional[Match[/a/]] }
70
+
71
+ it 'returns a ZeroOrMore' do
72
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'given an optional' do
78
+
79
+ let(:parser) { Optional[child] }
80
+
81
+ context 'with a zero-or-more' do
82
+
83
+ let(:child) { ZeroOrMore[Match[/a/]] }
84
+
85
+ it 'returns the inner ZeroOrMore' do
86
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
87
+ end
88
+ end
89
+
90
+ context 'with a one-or-more' do
91
+
92
+ let(:child) { OneOrMore[Match[/a/]] }
93
+
94
+ it 'returns a ZeroOrMore' do
95
+ subject.apply(parser, matching).should == ZeroOrMore[Match[/a/]]
96
+ end
97
+ end
98
+
99
+ context 'with an optional' do
100
+
101
+ let(:child) { Optional[Match[/a/]] }
102
+
103
+ it 'returns the inner Optional' do
104
+ subject.apply(parser, matching).should == Optional[Match[/a/]]
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ describe '#applies_to?' do
111
+
112
+ context 'given a zero-or-more' do
113
+
114
+ let(:parser) { ZeroOrMore[child] }
115
+
116
+ context 'with a zero-or-more' do
117
+
118
+ let(:child) { ZeroOrMore[Match[/a/]] }
119
+
120
+ context 'in the :matching context' do
121
+ it 'returns true' do
122
+ subject.applies_to?(parser, matching).should be_true
123
+ end
124
+ end
125
+
126
+ context 'in the :capturing context' do
127
+ it 'returns false' do
128
+ subject.applies_to?(parser, capturing).should be_false
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'with something other than a repeat' do
134
+
135
+ let(:child) { Match[/a/] }
136
+
137
+ it 'returns false' do
138
+ subject.applies_to?(parser, matching).should be_false
139
+ end
140
+ end
141
+
142
+ context 'with a one-or-more' do
143
+
144
+ let(:child) { OneOrMore[Match[/a/]] }
145
+
146
+ it 'returns true' do
147
+ subject.applies_to?(parser, matching).should be_true
148
+ end
149
+ end
150
+
151
+ context 'with an optional' do
152
+
153
+ let(:child) { Optional[Match[/a/]] }
154
+
155
+ it 'returns true' do
156
+ subject.applies_to?(parser, matching).should be_true
157
+ end
158
+ end
159
+ end
160
+
161
+ context 'given a one-or-more' do
162
+
163
+ let(:parser) { OneOrMore[child] }
164
+
165
+ context 'with a zero-or-more' do
166
+
167
+ let(:child) { ZeroOrMore[Match[/a/]] }
168
+
169
+ it 'returns true' do
170
+ subject.applies_to?(parser, matching).should be_true
171
+ end
172
+ end
173
+
174
+ context 'with a one-or-more' do
175
+
176
+ let(:child) { OneOrMore[Match[/a/]] }
177
+
178
+ it 'returns true' do
179
+ subject.applies_to?(parser, matching).should be_true
180
+ end
181
+ end
182
+
183
+ context 'with an optional' do
184
+
185
+ let(:child) { Optional[Match[/a/]] }
186
+
187
+ it 'returns true' do
188
+ subject.applies_to?(parser, matching).should be_true
189
+ end
190
+ end
191
+ end
192
+
193
+ context 'given an optional' do
194
+
195
+ let(:parser) { Optional[child] }
196
+
197
+ context 'with a zero-or-more' do
198
+
199
+ let(:child) { ZeroOrMore[Match[/a/]] }
200
+
201
+ it 'returns true' do
202
+ subject.applies_to?(parser, matching).should be_true
203
+ end
204
+ end
205
+
206
+ context 'with a one-or-more' do
207
+
208
+ let(:child) { OneOrMore[Match[/a/]] }
209
+
210
+ it 'returns true' do
211
+ subject.applies_to?(parser, matching).should be_true
212
+ end
213
+ end
214
+
215
+ context 'with an optional' do
216
+
217
+ let(:child) { Optional[Match[/a/]] }
218
+
219
+ it 'returns true' do
220
+ subject.applies_to?(parser, matching).should be_true
221
+ end
222
+ end
223
+ end
224
+ end
225
+
226
+ end