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
@@ -3,53 +3,56 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
3
  include Rattler::Parsers
4
4
 
5
5
  describe Rattler::Grammar::Grammar do
6
-
7
- let(:rules) { Rules[
6
+
7
+ let(:rules) { RuleSet[rule_a, rule_b] }
8
+
9
+ let :rule_a do
8
10
  Rule[:a, Choice[
9
11
  Match['a'],
10
12
  Apply[:b]
11
- ]],
12
- Rule[:b, Match['b']]
13
- ] }
14
-
13
+ ]]
14
+ end
15
+
16
+ let(:rule_b) { Rule[:b, Match['b']] }
17
+
15
18
  describe '#start_rule' do
16
19
  context 'when no start_rule option was specified' do
17
-
20
+
18
21
  subject { Rattler::Grammar::Grammar.new(rules) }
19
-
20
- it 'returns the name of the first rule' do
21
- subject.start_rule.should == :a
22
+
23
+ it 'returns the first rule' do
24
+ subject.start_rule.should == rule_a
22
25
  end
23
26
  end
24
-
27
+
25
28
  context 'when an explicit start_rule option was specified' do
26
-
29
+
27
30
  subject { Rattler::Grammar::Grammar.new(rules, :start_rule => :b) }
28
-
31
+
29
32
  it 'uses the specified start_rule option' do
30
- subject.start_rule.should == :b
33
+ subject.start_rule.should == rule_b
31
34
  end
32
35
  end
33
36
  end
34
-
37
+
35
38
  describe '#rules' do
36
39
  context 'when no start_rule option was specified' do
37
-
40
+
38
41
  subject { Rattler::Grammar::Grammar.new(rules) }
39
-
42
+
40
43
  it 'returns rules with the default start_rule' do
41
44
  subject.rules.start_rule.should == :a
42
45
  end
43
46
  end
44
-
47
+
45
48
  context 'when an explicit start_rule option was specified' do
46
-
49
+
47
50
  subject { Rattler::Grammar::Grammar.new(rules, :start_rule => :b) }
48
-
51
+
49
52
  it 'returns rules with the specified start_rule option' do
50
53
  subject.rules.start_rule.should == :b
51
54
  end
52
55
  end
53
56
  end
54
-
57
+
55
58
  end
@@ -2,6 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  describe Rattler::Parsers::ActionCode do
4
4
 
5
+ subject { ActionCode.new(code) }
6
+
5
7
  describe '#param_names' do
6
8
  context 'when the code has block parameters' do
7
9
 
@@ -53,15 +55,20 @@ describe Rattler::Parsers::ActionCode do
53
55
  end
54
56
 
55
57
  context 'given one argument' do
56
- it 'binds "_" to the argument' do
57
- subject.blank_binding(['r0']).should == { '_' => 'r0' }
58
+ it 'binds "_" and "*_" to the argument' do
59
+ subject.blank_binding(['r0']).should == {
60
+ /\*_\b/ => 'r0',
61
+ /\b_\b/ => 'r0'
62
+ }
58
63
  end
59
64
  end
60
65
 
61
66
  context 'given more than one argument' do
62
- it 'binds "_" to the array of arguments' do
63
- subject.blank_binding(['r0_0', 'r0_1']).
64
- should == { '_' => '[r0_0, r0_1]' }
67
+ it 'binds "*_" to the arguments and "_" to the array of arguments' do
68
+ subject.blank_binding(['r0_0', 'r0_1']).should == {
69
+ /\*_\b/ => 'r0_0, r0_1',
70
+ /\b_\b/ => '[r0_0, r0_1]'
71
+ }
65
72
  end
66
73
  end
67
74
  end
@@ -73,12 +80,12 @@ describe Rattler::Parsers::ActionCode do
73
80
 
74
81
  it 'associates the parameter names with arguments' do
75
82
  subject.arg_bindings(['r0_0', 'r0_1']).
76
- should == {'a' => 'r0_0', 'b' => 'r0_1'}
83
+ should == {/\ba\b/ => 'r0_0', /\bb\b/ => 'r0_1'}
77
84
  end
78
85
 
79
86
  it 'allows more args than param names' do
80
87
  subject.arg_bindings(['r0_0', 'r0_1', 'r0_2']).
81
- should == {'a' => 'r0_0', 'b' => 'r0_1'}
88
+ should == {/\ba\b/ => 'r0_0', /\bb\b/ => 'r0_1'}
82
89
  end
83
90
  end
84
91
 
@@ -93,57 +100,95 @@ describe Rattler::Parsers::ActionCode do
93
100
  end
94
101
 
95
102
  describe '#bind' do
103
+
104
+ let(:scope) { {} }
105
+
96
106
  context 'when the code uses block parameters' do
97
107
 
98
- subject { ActionCode.new('|a, b| a + b') }
108
+ let(:code) { '|a, b| a + b' }
99
109
 
100
110
  it 'replaces block parameter names with corresponding arguments' do
101
- subject.bind(['r0_0', 'r0_1']).should == 'r0_0 + r0_1'
111
+ subject.bind(scope, ['r0_0', 'r0_1']).should == 'r0_0 + r0_1'
102
112
  end
103
113
  end
104
114
 
105
115
  context 'when the code refers to labels' do
106
116
 
107
- subject { ActionCode.new('l + r') }
117
+ let(:scope) { {:l => 'r0_3', :r => 'r0_5'} }
118
+
119
+ let(:code) { 'l + r' }
108
120
 
109
121
  it 'replaces label names with associated arguments' do
110
- subject.bind({:l => 'r0_3', :r => 'r0_5'}).should == 'r0_3 + r0_5'
122
+ subject.bind(scope, []).should == 'r0_3 + r0_5'
111
123
  end
112
124
  end
113
125
 
114
126
  context 'when the code uses block parameters and label names' do
115
127
 
116
- subject { ActionCode.new('|a, b| a * c + b * d') }
128
+ let(:scope) { {:c => 'r0_3', :d => 'r0_5'} }
129
+
130
+ let(:code) { '|a, b| a * c + b * d' }
117
131
 
118
132
  it 'replaces both block parameter names and label names' do
119
- subject.bind(['r0_0', 'r0_1'], {:c => 'r0_3', :d => 'r0_5'}).
133
+ subject.bind(scope, ['r0_0', 'r0_1']).
120
134
  should == 'r0_0 * r0_3 + r0_1 * r0_5'
121
135
  end
122
136
  end
123
137
 
138
+ context 'when the code uses block parameters that are label names' do
139
+
140
+ let(:scope) { {:b => 'r0_3', :c => 'r0_5'} }
141
+
142
+ let(:code) { '|a, b| a * c + b' }
143
+
144
+ it 'the block parameters shadow the label names' do
145
+ subject.bind(scope, ['r0_0', 'r0_1']).
146
+ should == 'r0_0 * r0_5 + r0_1'
147
+ end
148
+ end
149
+
124
150
  context 'when the code uses "_"' do
125
151
 
126
- subject { ActionCode.new('_.to_s') }
152
+ let(:code) { '_.to_s' }
127
153
 
128
154
  context 'given one argument' do
129
155
  it 'replaces "_" with the argument' do
130
- subject.bind(['r0']).should == 'r0.to_s'
156
+ subject.bind(scope, ['r0']).should == 'r0.to_s'
131
157
  end
132
158
  end
133
159
 
134
160
  context 'given multiple arguments' do
135
161
  it 'replaces "_" with the array of arguments' do
136
- subject.bind(['r0_0', 'r0_1']).should == '[r0_0, r0_1].to_s'
162
+ subject.bind(scope, ['r0_0', 'r0_1']).
163
+ should == '[r0_0, r0_1].to_s'
137
164
  end
138
165
  end
139
166
  end
140
167
 
141
168
  context 'when the code uses "_" as a block parameter' do
142
169
 
143
- subject { ActionCode.new('|_| _.to_f') }
170
+ let(:code) { '|_| _.to_f' }
171
+
172
+ it 'the block parameter shadows the default "_" binding' do
173
+ subject.bind(scope, ['r0_0', 'r0_1']).should == 'r0_0.to_f'
174
+ end
175
+ end
176
+
177
+ context 'when the code uses "*_"' do
178
+
179
+ let(:code) { 'do_stuff *_' }
144
180
 
145
- it 'shadows the default "_" binding' do
146
- subject.bind(['r0_0', 'r0_1']).should == 'r0_0.to_f'
181
+ context 'given one argument' do
182
+ it 'replaces "*_" with the argument' do
183
+ subject.bind(scope, ['r0']).should == 'do_stuff r0'
184
+ end
185
+ end
186
+
187
+ context 'given multiple arguments' do
188
+ it 'replaces "*_" with the arguments' do
189
+ subject.bind(scope, ['r0_0', 'r0_1']).
190
+ should == 'do_stuff r0_0, r0_1'
191
+ end
147
192
  end
148
193
  end
149
194
  end
@@ -2,31 +2,31 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  describe Apply do
4
4
  include CombinatorParserSpecHelper
5
-
5
+
6
6
  subject { Apply[:word] }
7
-
8
- let(:rules) { Rules[Rule[:word, Match[/\w+/]]] }
9
-
7
+
8
+ let(:rules) { RuleSet[Rule[:word, Match[/\w+/]]] }
9
+
10
10
  describe '#parse' do
11
-
11
+
12
12
  context 'when the referenced rule matches' do
13
13
  it 'succeeds returns the result' do
14
14
  parsing('abc123 ').should result_in('abc123').at(6)
15
15
  end
16
16
  end
17
-
17
+
18
18
  context 'when the referenced rule fails' do
19
19
  it 'fails' do
20
20
  parsing('==').should fail
21
21
  end
22
22
  end
23
-
23
+
24
24
  end
25
-
25
+
26
26
  describe '#capturing?' do
27
27
  it 'is true' do
28
28
  subject.should be_capturing
29
29
  end
30
30
  end
31
-
31
+
32
32
  end
@@ -0,0 +1,38 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Rattler::Parsers::BackReference do
4
+ include CombinatorParserSpecHelper
5
+
6
+ subject { BackReference[:a] }
7
+
8
+ describe '#parse' do
9
+
10
+ let(:scope) { {:a => 'foo'} }
11
+
12
+ context 'when the referenced parse result is next in the input' do
13
+ it 'succeeds returning the matched string' do
14
+ parsing('foobar ').should result_in('foo').at(3)
15
+ end
16
+ end
17
+
18
+ context 'when the referenced parse result is not next in the input' do
19
+ it 'fails' do
20
+ parsing('abc').should fail
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ describe '#capturing?' do
27
+ it 'is true' do
28
+ subject.should be_capturing
29
+ end
30
+ end
31
+
32
+ describe '#re_source' do
33
+ it 'returns the source for a Regexp that will match the referenced result' do
34
+ subject.re_source(:a => 'r0').should == '#{r0}'
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../runtime/shared_parser_examples')
3
+
4
+ describe Rattler::Parsers::CombinatorParser do
5
+ include Rattler::Util::ParserSpecHelper
6
+ include RuntimeParserSpecHelper
7
+
8
+ it_behaves_like 'a recursive descent parser'
9
+
10
+ let :parser_class do
11
+ Rattler::Parsers::CombinatorParser.as_class(grammar.start_rule, grammar.rules)
12
+ end
13
+
14
+ end
@@ -95,11 +95,11 @@ describe DirectAction do
95
95
 
96
96
  context 'with a one-or-more parser' do
97
97
 
98
- subject { DirectAction[OneOrMore[Match[/\d/]], '|s| s'] }
98
+ subject { DirectAction[OneOrMore[Match[/\d/]], '|s| s * 2'] }
99
99
 
100
100
  context 'when the nested parser matches' do
101
101
  it 'applies the action to an array containing the matches' do
102
- parsing('451a').should result_in(['4', '5', '1']).at(3)
102
+ parsing('451a').should result_in(%w{4 5 1 4 5 1}).at(3)
103
103
  end
104
104
  end
105
105
 
@@ -131,6 +131,20 @@ describe DirectAction do
131
131
  end
132
132
  end
133
133
 
134
+ context 'with a labeled parser' do
135
+ subject do
136
+ DirectAction[
137
+ Label[:word, Match[/[[:alpha:]]+/]],
138
+ "word * 2"
139
+ ]
140
+ end
141
+ context 'when the parser matches' do
142
+ it 'applies the action binding the label to the result' do
143
+ parsing('foo ').should result_in('foofoo').at(3)
144
+ end
145
+ end
146
+ end
147
+
134
148
  context 'with a sequence of labeled parsers' do
135
149
  subject do
136
150
  DirectAction[
@@ -2,34 +2,34 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  describe DispatchAction do
4
4
  include CombinatorParserSpecHelper
5
-
5
+
6
6
  describe '#parse' do
7
-
7
+
8
8
  context 'with a capturing parser' do
9
9
  subject do
10
10
  DispatchAction[
11
11
  Sequence[Match[/[[:alpha:]]+/], Match[/\=/], Match[/[[:digit:]]+/]]
12
12
  ]
13
13
  end
14
-
14
+
15
15
  context 'when the parser matches' do
16
16
  it 'applies the action to the result' do
17
17
  parsing('val=42').
18
18
  should result_in(Rattler::Runtime::ParseNode.parsed(['val','=','42'])).at(6)
19
19
  end
20
20
  end
21
-
21
+
22
22
  context 'when the parser fails' do
23
23
  it 'fails' do
24
24
  parsing('val=x').should fail
25
25
  end
26
26
  end
27
27
  end
28
-
28
+
29
29
  context 'with a token parser' do
30
-
30
+
31
31
  subject { DispatchAction[Token[Match[/\w+/]]] }
32
-
32
+
33
33
  context 'when the parser matches' do
34
34
  it 'applies the action to the matched string' do
35
35
  parsing('foo ').
@@ -37,11 +37,11 @@ describe DispatchAction do
37
37
  end
38
38
  end
39
39
  end
40
-
40
+
41
41
  context 'with a non-capturing parser' do
42
-
42
+
43
43
  subject { DispatchAction[Skip[Match[/\w+/]]] }
44
-
44
+
45
45
  context 'when the parser matches' do
46
46
  it 'applies the action to an empty array' do
47
47
  parsing('abc123 ').
@@ -49,24 +49,7 @@ describe DispatchAction do
49
49
  end
50
50
  end
51
51
  end
52
-
53
- context 'with a choice of labeled parsers' do
54
- subject do
55
- DispatchAction[
56
- Choice[
57
- Label[:word, Match[/[[:alpha:]]+/]],
58
- Label[:num, Match[/[[:digit:]]+/]]
59
- ]
60
- ]
61
- end
62
- it 'applies the action with a labeled result' do
63
- parsing('foo ').should result_in(
64
- Rattler::Runtime::ParseNode.parsed(['foo'], :labeled => {:word => 'foo'}))
65
- parsing('42 ').should result_in(
66
- Rattler::Runtime::ParseNode.parsed(['42'], :labeled => {:num => '42'}))
67
- end
68
- end
69
-
52
+
70
53
  context 'with a sequence of labeled parsers' do
71
54
  subject do
72
55
  DispatchAction[
@@ -86,16 +69,16 @@ describe DispatchAction do
86
69
  end
87
70
  end
88
71
  end
89
-
72
+
90
73
  describe '#capturing?' do
91
-
74
+
92
75
  context 'with a capturing parser' do
93
76
  subject { DispatchAction[Match[/\w+/]] }
94
77
  it 'is true' do
95
78
  subject.should be_capturing
96
79
  end
97
80
  end
98
-
81
+
99
82
  context 'with a non-capturing parser' do
100
83
  subject { DispatchAction[Skip[Match[/\s*/]]] }
101
84
  it 'is false' do
@@ -103,5 +86,5 @@ describe DispatchAction do
103
86
  end
104
87
  end
105
88
  end
106
-
89
+
107
90
  end