rattler 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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