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.
- checksums.yaml +5 -5
- data/.rubocop.yml +298 -23
- data/CHANGELOG.md +41 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/Rakefile +3 -0
- data/appveyor.yml +14 -12
- data/bin/srl2ruby +13 -9
- data/bin/srl2ruby_cli_parser.rb +3 -3
- data/features/lib/step_definitions/srl_testing_steps.rb +2 -0
- data/features/lib/support/env..rb +2 -0
- data/lib/regex/abstract_method.rb +2 -0
- data/lib/regex/alternation.rb +3 -3
- data/lib/regex/anchor.rb +3 -0
- data/lib/regex/atomic_expression.rb +2 -0
- data/lib/regex/capturing_group.rb +8 -3
- data/lib/regex/char_class.rb +4 -2
- data/lib/regex/char_range.rb +3 -3
- data/lib/regex/char_shorthand.rb +3 -0
- data/lib/regex/character.rb +5 -2
- data/lib/regex/compound_expression.rb +2 -0
- data/lib/regex/concatenation.rb +3 -1
- data/lib/regex/expression.rb +6 -1
- data/lib/regex/lookaround.rb +3 -1
- data/lib/regex/match_option.rb +2 -0
- data/lib/regex/monadic_expression.rb +2 -0
- data/lib/regex/multiplicity.rb +8 -9
- data/lib/regex/non_capturing_group.rb +3 -1
- data/lib/regex/polyadic_expression.rb +2 -0
- data/lib/regex/quantifiable.rb +3 -1
- data/lib/regex/raw_expression.rb +2 -0
- data/lib/regex/repetition.rb +2 -0
- data/lib/regex/wildcard.rb +2 -5
- data/lib/srl_ruby/ast_builder.rb +81 -121
- data/lib/srl_ruby/grammar.rb +80 -92
- data/lib/srl_ruby/regex_repr.rb +2 -0
- data/lib/srl_ruby/tokenizer.rb +10 -4
- data/lib/srl_ruby/version.rb +3 -1
- data/lib/srl_ruby.rb +2 -0
- data/spec/acceptance/srl_test_suite_spec.rb +2 -0
- data/spec/acceptance/support/rule_file_ast_builder.rb +2 -0
- data/spec/acceptance/support/rule_file_grammar.rb +7 -5
- data/spec/acceptance/support/rule_file_nodes.rb +2 -0
- data/spec/acceptance/support/rule_file_parser.rb +2 -0
- data/spec/acceptance/support/rule_file_tokenizer.rb +10 -3
- data/spec/regex/atomic_expression_spec.rb +2 -0
- data/spec/regex/character_spec.rb +16 -6
- data/spec/regex/match_option_spec.rb +2 -0
- data/spec/regex/monadic_expression_spec.rb +2 -0
- data/spec/regex/multiplicity_spec.rb +4 -0
- data/spec/regex/repetition_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/srl_ruby/srl_ruby_spec.rb +2 -0
- data/spec/srl_ruby/tokenizer_spec.rb +2 -0
- data/spec/srl_ruby_spec.rb +8 -6
- data/srl_ruby.gemspec +6 -4
- metadata +13 -14
data/lib/srl_ruby/ast_builder.rb
CHANGED
@@ -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' =>
|
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' =>
|
127
|
+
# rule('pattern' => 'subpattern (separator sub_pattern)*').tag 'pattern_sequence'
|
123
128
|
def reduce_pattern_sequence(_production, _range, _tokens, theChildren)
|
124
|
-
|
125
|
-
|
126
|
-
|
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],
|
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').
|
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' =>
|
144
|
+
# rule('flags' => '(separator single_flag)+').tag 'flag_sequence'
|
144
145
|
def reduce_flag_sequence(_production, _range, _tokens, theChildren)
|
145
|
-
theChildren[0]
|
146
|
+
theChildren[0].map { |(_, flag)| flag }
|
146
147
|
end
|
147
148
|
|
148
|
-
# rule('
|
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]).
|
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]).
|
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
|
169
|
-
def
|
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]).
|
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' =>
|
184
|
+
# rule('assertion' => 'IF NOT? FOLLOWED BY assertable')
|
199
185
|
def reduce_if_followed(_production, _range, _tokens, theChildren)
|
200
|
-
|
201
|
-
|
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' =>
|
190
|
+
# rule('assertion' => 'IF NOT? ALREADY HAD assertable')
|
209
191
|
def reduce_if_had(_production, _range, _tokens, theChildren)
|
210
|
-
|
192
|
+
polarity = theChildren[1] ? :negative : :positive
|
193
|
+
Regex::Lookaround.new(theChildren.last, :behind, polarity)
|
211
194
|
end
|
212
195
|
|
213
|
-
# rule('
|
214
|
-
def
|
215
|
-
|
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('
|
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]).
|
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').
|
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]).
|
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]).
|
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]).
|
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]).
|
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').
|
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]).
|
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').
|
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]).
|
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').
|
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]).
|
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]).
|
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').
|
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').
|
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').
|
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]).
|
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]).
|
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]).
|
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]).
|
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]).
|
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]).
|
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]).
|
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]).
|
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').
|
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]).
|
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' =>
|
427
|
-
#
|
428
|
-
def
|
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
|
-
|
407
|
+
(_, until_expr) = theChildren[2]
|
408
|
+
Regex::Concatenation.new(group, until_expr)
|
434
409
|
end
|
435
410
|
|
436
|
-
# rule('capturing_group' =>
|
437
|
-
#
|
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
|
-
|
420
|
+
(_, until_expr) = theChildren[4]
|
421
|
+
return Regex::Concatenation.new(group, until_expr)
|
452
422
|
end
|
453
423
|
|
454
|
-
# rule('quantifier' => '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').
|
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]).
|
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' =>
|
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').
|
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]).
|
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]).
|
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]).
|
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
|