srl_ruby 0.4.5 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +298 -23
  3. data/CHANGELOG.md +41 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +1 -1
  7. data/Rakefile +3 -0
  8. data/appveyor.yml +14 -12
  9. data/bin/srl2ruby +13 -9
  10. data/bin/srl2ruby_cli_parser.rb +3 -3
  11. data/features/lib/step_definitions/srl_testing_steps.rb +2 -0
  12. data/features/lib/support/env..rb +2 -0
  13. data/lib/regex/abstract_method.rb +2 -0
  14. data/lib/regex/alternation.rb +3 -3
  15. data/lib/regex/anchor.rb +3 -0
  16. data/lib/regex/atomic_expression.rb +2 -0
  17. data/lib/regex/capturing_group.rb +8 -3
  18. data/lib/regex/char_class.rb +4 -2
  19. data/lib/regex/char_range.rb +3 -3
  20. data/lib/regex/char_shorthand.rb +3 -0
  21. data/lib/regex/character.rb +5 -2
  22. data/lib/regex/compound_expression.rb +2 -0
  23. data/lib/regex/concatenation.rb +3 -1
  24. data/lib/regex/expression.rb +6 -1
  25. data/lib/regex/lookaround.rb +3 -1
  26. data/lib/regex/match_option.rb +2 -0
  27. data/lib/regex/monadic_expression.rb +2 -0
  28. data/lib/regex/multiplicity.rb +8 -9
  29. data/lib/regex/non_capturing_group.rb +3 -1
  30. data/lib/regex/polyadic_expression.rb +2 -0
  31. data/lib/regex/quantifiable.rb +3 -1
  32. data/lib/regex/raw_expression.rb +2 -0
  33. data/lib/regex/repetition.rb +2 -0
  34. data/lib/regex/wildcard.rb +2 -5
  35. data/lib/srl_ruby/ast_builder.rb +81 -121
  36. data/lib/srl_ruby/grammar.rb +80 -92
  37. data/lib/srl_ruby/regex_repr.rb +2 -0
  38. data/lib/srl_ruby/tokenizer.rb +10 -4
  39. data/lib/srl_ruby/version.rb +3 -1
  40. data/lib/srl_ruby.rb +2 -0
  41. data/spec/acceptance/srl_test_suite_spec.rb +2 -0
  42. data/spec/acceptance/support/rule_file_ast_builder.rb +2 -0
  43. data/spec/acceptance/support/rule_file_grammar.rb +7 -5
  44. data/spec/acceptance/support/rule_file_nodes.rb +2 -0
  45. data/spec/acceptance/support/rule_file_parser.rb +2 -0
  46. data/spec/acceptance/support/rule_file_tokenizer.rb +10 -3
  47. data/spec/regex/atomic_expression_spec.rb +2 -0
  48. data/spec/regex/character_spec.rb +16 -6
  49. data/spec/regex/match_option_spec.rb +2 -0
  50. data/spec/regex/monadic_expression_spec.rb +2 -0
  51. data/spec/regex/multiplicity_spec.rb +4 -0
  52. data/spec/regex/repetition_spec.rb +2 -0
  53. data/spec/spec_helper.rb +2 -0
  54. data/spec/srl_ruby/srl_ruby_spec.rb +2 -0
  55. data/spec/srl_ruby/tokenizer_spec.rb +2 -0
  56. data/spec/srl_ruby_spec.rb +8 -6
  57. data/srl_ruby.gemspec +6 -4
  58. metadata +13 -14
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringio'
2
4
  require_relative 'regex_repr'
3
5
 
@@ -66,6 +68,8 @@ module SrlRuby
66
68
  return Regex::Multiplicity.new(lowerBound, upperBound, :greedy)
67
69
  end
68
70
 
71
+ # rubocop: disable Style/OptionalBooleanParameter
72
+
69
73
  def string_literal(aString, to_escape = true)
70
74
  if aString.size > 1
71
75
  chars = []
@@ -86,6 +90,7 @@ module SrlRuby
86
90
 
87
91
  return result
88
92
  end
93
+ # rubocop: enable Style/OptionalBooleanParameter
89
94
 
90
95
  def char_range(lowerBound, upperBound)
91
96
  lower = Regex::Character.new(lowerBound)
@@ -113,71 +118,52 @@ module SrlRuby
113
118
  Regex::Anchor.new('^')
114
119
  end
115
120
 
116
- # rule('expression' => %w[pattern flags]).as 'flagged_expr'
121
+ # rule('expression' => 'pattern (flags)?').tag 'flagged_expr'
117
122
  def reduce_flagged_expr(_production, aRange, theTokens, theChildren)
118
- @options = theChildren[1] if theChildren[1]
123
+ @options = theChildren[1].first if theChildren[1]
119
124
  return_first_child(aRange, theTokens, theChildren)
120
125
  end
121
126
 
122
- # rule('pattern' => %w[pattern separator sub_pattern]).as 'pattern_sequence'
127
+ # rule('pattern' => 'subpattern (separator sub_pattern)*').tag 'pattern_sequence'
123
128
  def reduce_pattern_sequence(_production, _range, _tokens, theChildren)
124
- third_member = theChildren[2]
125
- if third_member.kind_of?(Regex::Lookaround) && third_member.dir == :behind
126
- Regex::Concatenation.new(theChildren[2], theChildren[0])
129
+ return theChildren[0] if theChildren[1].empty?
130
+
131
+ successors = theChildren[1].map { |pair| pair[1] }
132
+ if successors[0].kind_of?(Regex::Lookaround) && successors[0].dir == :behind
133
+ Regex::Concatenation.new(successors.shift, theChildren[0], *successors)
127
134
  else
128
- Regex::Concatenation.new(theChildren[0], theChildren[2])
135
+ Regex::Concatenation.new(theChildren[0], *successors)
129
136
  end
130
-
131
- end
132
-
133
- # rule('pattern' => 'sub_pattern').as 'basic_pattern'
134
- def reduce_basic_pattern(_production, aRange, theTokens, theChildren)
135
- return_first_child(aRange, theTokens, theChildren)
136
137
  end
137
138
 
138
- # rule('sub_pattern' => 'assertion').as 'assertion_sub_pattern'
139
+ # rule('sub_pattern' => 'assertion').tag 'assertion_sub_pattern'
139
140
  def reduce_assertion_sub_pattern(_production, aRange, theTokens, theChildren)
140
141
  return_first_child(aRange, theTokens, theChildren)
141
142
  end
142
143
 
143
- # rule('flags' => %[flags separator single_flag]).as 'flag_sequence'
144
+ # rule('flags' => '(separator single_flag)+').tag 'flag_sequence'
144
145
  def reduce_flag_sequence(_production, _range, _tokens, theChildren)
145
- theChildren[0] << theChildren[2]
146
+ theChildren[0].map { |(_, flag)| flag }
146
147
  end
147
148
 
148
- # rule('flags' => %w[separator single_flag]).as 'flag_simple'
149
- def reduce_flag_simple(_production, _range, _tokens, theChildren)
150
- [theChildren.last]
151
- end
152
-
153
- # rule('single_flag' => %w[CASE INSENSITIVE]).as 'case_insensitive'
149
+ # rule('single_flag' => %w[CASE INSENSITIVE]).tag 'case_insensitive'
154
150
  def reduce_case_insensitive(_production, _range, _tokens, _children)
155
151
  Regexp::IGNORECASE
156
152
  end
157
153
 
158
- # rule('single_flag' => %w[MULTI LINE]).as 'multi_line'
154
+ # rule('single_flag' => %w[MULTI LINE]).tag 'multi_line'
159
155
  def reduce_multi_line(_production, _range, _tokens, _children)
160
156
  Regexp::MULTILINE
161
157
  end
162
158
 
163
- # rule('single_flag' => %w[ALL LAZY]).as 'all_lazy'
159
+ # rule('single_flag' => %w[ALL LAZY]).tag 'all_lazy'
164
160
  def reduce_all_lazy(_production, _range, _tokens, _children)
165
161
  :ALL_LAZY
166
162
  end
167
163
 
168
- # rule 'quantifiable' => %w[begin_anchor anchorable end_anchor]
169
- def reduce_pinned_quantifiable(_production, _range, _tokens, theChildren)
170
- Regex::Concatenation.new(*theChildren)
171
- end
172
-
173
- # rule 'quantifiable' => %w[begin_anchor anchorable]
174
- def reduce_begin_anchor_quantifiable(_production, _range, _tokens, theChildren)
175
- Regex::Concatenation.new(*theChildren)
176
- end
177
-
178
- # rule 'quantifiable' => %w[anchorable end_anchor]
179
- def reduce_end_anchor_quantifiable(_production, _range, _tokens, theChildren)
180
- return Regex::Concatenation.new(*theChildren)
164
+ # rule('quantifiable' => 'begin_anchor? anchorable end_anchor?')
165
+ def reduce_quantifiable(_production, _range, _tokens, theChildren)
166
+ Regex::Concatenation.new(*theChildren.flatten.compact)
181
167
  end
182
168
 
183
169
  # rule 'begin_anchor' => %w[STARTS WITH]
@@ -190,39 +176,30 @@ module SrlRuby
190
176
  begin_anchor
191
177
  end
192
178
 
193
- # rule('end_anchor' => %w[separator MUST END]).as 'end_anchor'
179
+ # rule('end_anchor' => %w[separator MUST END]).tag 'end_anchor'
194
180
  def reduce_end_anchor(_production, _range, _tokens, _children)
195
181
  Regex::Anchor.new('$')
196
182
  end
197
183
 
198
- # rule('assertion' => %w[IF FOLLOWED BY assertable]).as 'if_followed'
184
+ # rule('assertion' => 'IF NOT? FOLLOWED BY assertable')
199
185
  def reduce_if_followed(_production, _range, _tokens, theChildren)
200
- Regex::Lookaround.new(theChildren.last, :ahead, :positive)
201
- end
202
-
203
- # rule('assertion' => %w[IF NOT FOLLOWED BY assertable]).as 'if_not_followed'
204
- def reduce_if_not_followed(_production, _range, _tokens, theChildren)
205
- Regex::Lookaround.new(theChildren.last, :ahead, :negative)
186
+ polarity = theChildren[1] ? :negative : :positive
187
+ Regex::Lookaround.new(theChildren.last, :ahead, polarity)
206
188
  end
207
189
 
208
- # rule('assertion' => %w[IF ALREADY HAD assertable]).as 'if_had'
190
+ # rule('assertion' => 'IF NOT? ALREADY HAD assertable')
209
191
  def reduce_if_had(_production, _range, _tokens, theChildren)
210
- Regex::Lookaround.new(theChildren.last, :behind, :positive)
192
+ polarity = theChildren[1] ? :negative : :positive
193
+ Regex::Lookaround.new(theChildren.last, :behind, polarity)
211
194
  end
212
195
 
213
- # rule('assertion' => %w[IF NOT ALREADY HAD assertable]).as 'if_not_had'
214
- def reduce_if_not_had(_production, _range, _tokens, theChildren)
215
- Regex::Lookaround.new(theChildren.last, :behind, :negative)
196
+ # rule('assertable' => 'term quantifier?').tag 'assertable'
197
+ def reduce_assertable(_production, _range, _tokens, theChildren)
198
+ (term, quantifier) = theChildren.flatten
199
+ quantifier ? repetition(term, quantifier) : term
216
200
  end
217
201
 
218
- # rule('assertable' => %w[term quantifier]).as 'quantified_assertable'
219
- def reduce_quantified_assertable(_production, _range, _tokens, theChildren)
220
- quantifier = theChildren[1]
221
- term = theChildren[0]
222
- repetition(term, quantifier)
223
- end
224
-
225
- # rule('letter_range' => %w[LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'lowercase_from_to'
202
+ # rule('letter_range' => %w[LETTER FROM LETTER_LIT TO LETTER_LIT]).tag 'lowercase_from_to'
226
203
  def reduce_lowercase_from_to(_production, _range, _tokens, theChildren)
227
204
  raw_range = [theChildren[2].token.lexeme, theChildren[4].token.lexeme]
228
205
  range_sorted = raw_range.sort
@@ -230,7 +207,7 @@ module SrlRuby
230
207
  char_class(false, ch_range)
231
208
  end
232
209
 
233
- # rule('letter_range' => %w[UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'uppercase_from_to'
210
+ # rule('letter_range' => %w[UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT]).tag 'uppercase_from_to'
234
211
  def reduce_uppercase_from_to(_production, _range, _tokens, theChildren)
235
212
  raw_range = [theChildren[3].token.lexeme, theChildren[5].token.lexeme]
236
213
  range_sorted = raw_range.sort
@@ -238,19 +215,19 @@ module SrlRuby
238
215
  char_class(false, ch_range)
239
216
  end
240
217
 
241
- # rule('letter_range' => 'LETTER').as 'any_lowercase'
218
+ # rule('letter_range' => 'LETTER').tag 'any_lowercase'
242
219
  def reduce_any_lowercase(_production, _range, _tokens, _children)
243
220
  ch_range = char_range('a', 'z')
244
221
  char_class(false, ch_range)
245
222
  end
246
223
 
247
- # rule('letter_range' => %w[UPPERCASE LETTER]).as 'any_uppercase'
224
+ # rule('letter_range' => %w[UPPERCASE LETTER]).tag 'any_uppercase'
248
225
  def reduce_any_uppercase(_production, _range, _tokens, _children)
249
226
  ch_range = char_range('A', 'Z')
250
227
  char_class(false, ch_range)
251
228
  end
252
229
 
253
- # rule('digit_range' => %w[digit_or_number FROM DIGIT_LIT TO DIGIT_LIT]).as 'digits_from_to'
230
+ # rule('digit_range' => %w[digit_or_number FROM DIGIT_LIT TO DIGIT_LIT]).tag 'digits_from_to'
254
231
  def reduce_digits_from_to(_production, _range, _tokens, theChildren)
255
232
  raw_range = [theChildren[2].token.lexeme, theChildren[4].token.lexeme]
256
233
  range_sorted = raw_range.map(&:to_i).sort
@@ -258,42 +235,42 @@ module SrlRuby
258
235
  char_class(false, ch_range)
259
236
  end
260
237
 
261
- # rule('character_class' => %w[ANY CHARACTER]).as 'any_character'
238
+ # rule('character_class' => %w[ANY CHARACTER]).tag 'any_character'
262
239
  def reduce_any_character(_production, _range, _tokens, _children)
263
240
  char_shorthand('w')
264
241
  end
265
242
 
266
- # rule('character_class' => %w[NO CHARACTER]).as 'no_character'
243
+ # rule('character_class' => %w[NO CHARACTER]).tag 'no_character'
267
244
  def reduce_no_character(_production, _range, _tokens, _children)
268
245
  char_shorthand('W')
269
246
  end
270
247
 
271
- # rule('character_class' => 'digit_or_number').as 'digit'
248
+ # rule('character_class' => 'digit_or_number').tag 'digit'
272
249
  def reduce_digit(_production, _range, _tokens, _children)
273
250
  char_shorthand('d')
274
251
  end
275
252
 
276
- # rule('character_class' => %w[NO DIGIT]).as 'non_digit'
253
+ # rule('character_class' => %w[NO DIGIT]).tag 'non_digit'
277
254
  def reduce_non_digit(_production, _range, _tokens, _children)
278
255
  char_shorthand('D')
279
256
  end
280
257
 
281
- # rule('character_class' => 'WHITESPACE').as 'whitespace'
258
+ # rule('character_class' => 'WHITESPACE').tag 'whitespace'
282
259
  def reduce_whitespace(_production, _range, _tokens, _children)
283
260
  char_shorthand('s')
284
261
  end
285
262
 
286
- # rule('character_class' => %w[NO WHITESPACE]).as 'no_whitespace'
263
+ # rule('character_class' => %w[NO WHITESPACE]).tag 'no_whitespace'
287
264
  def reduce_no_whitespace(_production, _range, _tokens, _children)
288
265
  char_shorthand('S')
289
266
  end
290
267
 
291
- # rule('character_class' => 'ANYTHING').as 'anything'
268
+ # rule('character_class' => 'ANYTHING').tag 'anything'
292
269
  def reduce_anything(_production, _range, _tokens, _children)
293
270
  wildcard
294
271
  end
295
272
 
296
- # rule('character_class' => %w[ONE OF STRING_LIT]).as 'one_of'
273
+ # rule('character_class' => %w[ONE OF STRING_LIT]).tag 'one_of'
297
274
  def reduce_one_of(_production, _range, _tokens, theChildren)
298
275
  raw_literal = theChildren[-1].token.lexeme.dup
299
276
  alternatives = raw_literal.chars.map do |ch|
@@ -309,7 +286,7 @@ module SrlRuby
309
286
  return Regex::CharClass.new(false, *alternatives)
310
287
  end
311
288
 
312
- # rule('character_class' => %w[NONE OF STRING_LIT]).as 'none_of'
289
+ # rule('character_class' => %w[NONE OF STRING_LIT]).tag 'none_of'
313
290
  def reduce_none_of(_production, _range, _tokens, theChildren)
314
291
  raw_literal = theChildren[-1].token.lexeme.dup
315
292
  chars = raw_literal.chars.map do |ch|
@@ -318,44 +295,44 @@ module SrlRuby
318
295
  Regex::CharClass.new(true, *chars)
319
296
  end
320
297
 
321
- # rule('special_char' => 'TAB').as 'tab'
298
+ # rule('special_char' => 'TAB').tag 'tab'
322
299
  def reduce_tab(_production, _range, _tokens, _children)
323
300
  Regex::Character.new('\t')
324
301
  end
325
302
 
326
- # rule('special_char' => ' VERTICAL TAB').as 'vtab'
303
+ # rule('special_char' => ' VERTICAL TAB').tag 'vtab'
327
304
  def reduce_vtab(_production, _range, _tokens, _children)
328
305
  Regex::Character.new('\v')
329
306
  end
330
307
 
331
- # rule('special_char' => 'BACKSLASH').as 'backslash'
308
+ # rule('special_char' => 'BACKSLASH').tag 'backslash'
332
309
  def reduce_backslash(_production, _range, _tokens, _children)
333
310
  # Double the backslash (because of escaping)
334
311
  string_literal('\\', true)
335
312
  end
336
313
 
337
- # rule('special_char' => %w[NEW LINE]).as 'new_line'
314
+ # rule('special_char' => %w[NEW LINE]).tag 'new_line'
338
315
  def reduce_new_line(_production, _range, _tokens, _children)
339
316
  # TODO: control portability
340
317
  Regex::Character.new('\n')
341
318
  end
342
319
 
343
- # rule('special_char' => %w[CARRIAGE RETURN]).as 'carriage_return'
320
+ # rule('special_char' => %w[CARRIAGE RETURN]).tag 'carriage_return'
344
321
  def reduce_carriage_return(_production, _range, _tokens, _children)
345
322
  Regex::Character.new('\r')
346
323
  end
347
324
 
348
- # rule('special_char' => %w[WORD]).as 'word'
325
+ # rule('special_char' => %w[WORD]).tag 'word'
349
326
  def reduce_word(_production, _range, _tokens, _children)
350
327
  Regex::Anchor.new('\b')
351
328
  end
352
329
 
353
- # rule('special_char' => %w[NO WORD]).as 'no word'
330
+ # rule('special_char' => %w[NO WORD]).tag 'no word'
354
331
  def reduce_no_word(_production, _range, _tokens, _children)
355
332
  Regex::Anchor.new('\B')
356
333
  end
357
334
 
358
- # rule('literal' => %w[LITERALLY STRING_LIT]).as 'literally'
335
+ # rule('literal' => %w[LITERALLY STRING_LIT]).tag 'literally'
359
336
  def reduce_literally(_production, _range, _tokens, theChildren)
360
337
  # What if literal is empty?...
361
338
 
@@ -363,13 +340,13 @@ module SrlRuby
363
340
  return string_literal(raw_literal)
364
341
  end
365
342
 
366
- # rule('raw' => %w[RAW STRING_LIT]).as 'raw_literal'
343
+ # rule('raw' => %w[RAW STRING_LIT]).tag 'raw_literal'
367
344
  def reduce_raw_literal(_production, _range, _tokens, theChildren)
368
345
  raw_literal = theChildren[-1].token.lexeme.dup
369
346
  return Regex::RawExpression.new(raw_literal)
370
347
  end
371
348
 
372
- # rule('alternation' => %w[ANY OF LPAREN alternatives RPAREN]).as 'any_of'
349
+ # rule('alternation' => %w[ANY OF LPAREN alternatives RPAREN]).tag 'any_of'
373
350
  def reduce_any_of(_production, _range, _tokens, theChildren)
374
351
  first_alternative = theChildren[3].first
375
352
  result = nil
@@ -384,26 +361,21 @@ module SrlRuby
384
361
  return result
385
362
  end
386
363
 
387
- # rule('alternatives' => %w[alternatives separator quantifiable]).as 'alternative_list'
364
+ # rule('alternatives' => %w[alternatives separator quantifiable]).tag 'alternative_list'
388
365
  def reduce_alternative_list(_production, _range, _tokens, theChildren)
389
366
  return theChildren[0] << theChildren[-1]
390
367
  end
391
368
 
392
- # rule('alternatives' => 'quantifiable').as 'simple_alternative'
369
+ # rule('alternatives' => 'quantifiable').tag 'simple_alternative'
393
370
  def reduce_simple_alternative(_production, _range, _tokens, theChildren)
394
371
  [theChildren.last]
395
372
  end
396
373
 
397
- # rule('grouping' => %w[LPAREN pattern RPAREN]).as 'grouping_parenthenses'
374
+ # rule('grouping' => %w[LPAREN pattern RPAREN]).tag 'grouping_parenthenses'
398
375
  def reduce_grouping_parenthenses(_production, _range, _tokens, theChildren)
399
376
  Regex::NonCapturingGroup.new(theChildren[1])
400
377
  end
401
378
 
402
- # rule('capturing_group' => %w[CAPTURE assertable]).as 'capture'
403
- def reduce_capture(_production, _range, _tokens, theChildren)
404
- Regex::CapturingGroup.new(theChildren[1])
405
- end
406
-
407
379
  # If the rightmost (sub)expression is a repetition, then make it lazy
408
380
  def make_last_repetition_lazy(anExpr)
409
381
  sub_expr = anExpr
@@ -423,51 +395,49 @@ module SrlRuby
423
395
  end
424
396
  end
425
397
 
426
- # rule('capturing_group' => %w[CAPTURE assertable UNTIL assertable]).as
427
- # 'capture_until'
428
- def reduce_capture_until(_production, _range, _tokens, theChildren)
398
+ # rule('capturing_group' => 'CAPTURE assertable (UNTIL assertable)?').tag
399
+ # 'capture'
400
+ def reduce_capture(_production, _range, _tokens, theChildren)
401
+ return Regex::CapturingGroup.new(theChildren[1]) unless theChildren[2]
402
+
429
403
  # Until semantic requires that the last pattern in capture to be lazy
430
404
  make_last_repetition_lazy(theChildren[1])
431
405
 
432
406
  group = Regex::CapturingGroup.new(theChildren[1])
433
- return Regex::Concatenation.new(group, theChildren[3])
407
+ (_, until_expr) = theChildren[2]
408
+ Regex::Concatenation.new(group, until_expr)
434
409
  end
435
410
 
436
- # rule('capturing_group' => %w[CAPTURE assertable AS var_name]).as
437
- # 'named_capture'
411
+ # rule('capturing_group' => 'CAPTURE assertable AS var_name (UNTIL assertable)?').tag
412
+ # 'named_capture'
438
413
  def reduce_named_capture(_production, _range, _tokens, theChildren)
439
414
  name = theChildren[3].token.lexeme.dup
440
- return Regex::CapturingGroup.new(theChildren[1], name)
441
- end
415
+ return Regex::CapturingGroup.new(theChildren[1], name) unless theChildren[4]
442
416
 
443
- # rule('capturing_group' => %w[CAPTURE assertable AS var_name
444
- # UNTIL assertable]).as 'named_capture_until'
445
- def reduce_named_capture_until(_production, _range, _tokens, theChildren)
446
417
  # Until semantic requires that the last pattern in capture to be lazy
447
418
  make_last_repetition_lazy(theChildren[1])
448
-
449
- name = theChildren[3].token.lexeme.dup
450
419
  group = Regex::CapturingGroup.new(theChildren[1], name)
451
- return Regex::Concatenation.new(group, theChildren[5])
420
+ (_, until_expr) = theChildren[4]
421
+ return Regex::Concatenation.new(group, until_expr)
452
422
  end
453
423
 
454
- # rule('quantifier' => 'ONCE').as 'once'
424
+ # rule('quantifier' => 'ONCE').tag 'once'
455
425
  def reduce_once(_production, _range, _tokens, _children)
456
426
  multiplicity(1, 1)
457
427
  end
458
428
 
459
- # rule('quantifier' => 'TWICE').as 'twice'
429
+ # rule('quantifier' => 'TWICE').tag 'twice'
460
430
  def reduce_twice(_production, _range, _tokens, _children)
461
431
  multiplicity(2, 2)
462
432
  end
463
433
 
464
- # rule('quantifier' => %w[EXACTLY count TIMES]).as 'exactly'
434
+ # rule('quantifier' => %w[EXACTLY count TIMES]).tag 'exactly'
465
435
  def reduce_exactly(_production, _range, _tokens, theChildren)
466
436
  count = theChildren[1].token.lexeme.to_i
467
437
  multiplicity(count, count)
468
438
  end
469
439
 
470
- # rule('quantifier' => %w[BETWEEN count AND count times_suffix]).as
440
+ # rule('quantifier' => 'BETWEEN count AND count times_suffix').tag
471
441
  # 'between_and'
472
442
  def reduce_between_and(_production, _range, _tokens, theChildren)
473
443
  lower = theChildren[1].token.lexeme.to_i
@@ -475,36 +445,26 @@ module SrlRuby
475
445
  multiplicity(lower, upper)
476
446
  end
477
447
 
478
- # rule('quantifier' => 'OPTIONAL').as 'optional'
448
+ # rule('quantifier' => 'OPTIONAL').tag 'optional'
479
449
  def reduce_optional(_production, _range, _tokens, _children)
480
450
  multiplicity(0, 1)
481
451
  end
482
452
 
483
- # rule('quantifier' => %w[ONCE OR MORE]).as 'once_or_more'
453
+ # rule('quantifier' => %w[ONCE OR MORE]).tag 'once_or_more'
484
454
  def reduce_once_or_more(_production, _range, _tokens, _children)
485
455
  multiplicity(1, :more)
486
456
  end
487
457
 
488
- # rule('quantifier' => %w[NEVER OR MORE]).as 'never_or_more'
458
+ # rule('quantifier' => %w[NEVER OR MORE]).tag 'never_or_more'
489
459
  def reduce_never_or_more(_production, _range, _tokens, _children)
490
460
  multiplicity(0, :more)
491
461
  end
492
462
 
493
- # rule('quantifier' => %w[AT LEAST count TIMES]).as 'at_least'
463
+ # rule('quantifier' => %w[AT LEAST count TIMES]).tag 'at_least'
494
464
  def reduce_at_least(_production, _range, _tokens, theChildren)
495
465
  count = theChildren[2].token.lexeme.to_i
496
466
  multiplicity(count, :more)
497
467
  end
498
-
499
- # rule('times_suffix' => 'TIMES').as 'times_keyword'
500
- def reduce_times_keyword(_production, _range, _tokens, _children)
501
- nil
502
- end
503
-
504
- # rule('times_suffix' => []).as 'times_dropped'
505
- def reduce_times_dropped(_production, _range, _tokens, _children)
506
- nil
507
- end
508
468
  end # class
509
469
  end # module
510
470
  # End of file