srl_ruby 0.4.5 → 0.4.9
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.
- 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
|