regextest 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ebc162f43002fb402e523b7d9a504a9593cce57
4
- data.tar.gz: ef3b47e4e0b53e2d8a0c2eac831688fe805fe6c2
3
+ metadata.gz: dee3ca4abbe70edabbe42f690c1a3c586fe689e0
4
+ data.tar.gz: 7bfe0081c0432cb7e9f9da3e4918042a36770bc1
5
5
  SHA512:
6
- metadata.gz: 642b88f4089090dad4b15a4b7b9486987d5d6ffd9a8c7ff7e76e6a95c6d6e51852718adc76e09e9a7589f66815d302dfa7c4ef44af70c7672667cd93b73cc545
7
- data.tar.gz: 04c4b88d7f133428f2594fc6a7d623030702d01444f3846ca3d34839b2bd46b3d30e4c5a0a7da718bed5468c8e515aeebee16d5aca8f928235f2ee1af65fad22
6
+ metadata.gz: 4b2bf4c54259660e4f4509ee944676388530e6203266820b22a4cc32bb82d1adb849e8c535b8d4044057517fa8169ad9c39ec2ff23391ff43672042a492515f4
7
+ data.tar.gz: 8f9faee644cd13ade02be3cdcc1ab51eb8e4f14985402eb6ea732bfb988ac2eb363c82fa2da595bd39c2f3e2bbc514ead114a33603275000fd717167eae77fc3
@@ -89,6 +89,11 @@ class RegextestPreUnicode
89
89
  # Generate hash of properties
90
90
  def self.property(class_name)
91
91
  case class_name.downcase
92
+ # Regextest defined char classes (from underscore)
93
+ when "_asciiprint"
94
+ ([[32, 126]])
95
+
96
+ # Unicode.org defined char classes
92
97
  #{ranges_source}
93
98
  else
94
99
  warn "Class name (#\{class_name\}) not found. Ignored."
@@ -72,8 +72,11 @@ class Regextest
72
72
  # @raise [RuntimeError] if something wrong...
73
73
  # @raise [Regextest::RegextestTimeout] if detected timeout while verification. Option 'verification: false' may be workaround.
74
74
  def generate
75
- TstConstRetryMax.times do | retry_count |
76
-
75
+ start_time = Time.now
76
+ 0.step(TstFixnumMax) do | retry_count |
77
+ duration = Time.now - start_time
78
+ break if retry_count >= TstConstRetryMax && duration >= TstConstRetryMaxSecond
79
+
77
80
  # generate string
78
81
  reset_random_called
79
82
  @result = @back_end.generate(retry_count)
@@ -114,6 +117,7 @@ class Regextest
114
117
  def to_json
115
118
  @front_end.get_json_string
116
119
  end
120
+
117
121
  #---------------#
118
122
  private
119
123
 
@@ -143,7 +147,7 @@ class Regextest
143
147
  when Regexp
144
148
  @reg_exp = param
145
149
  @@parse_options[:reg_options].set(@reg_exp.options) # inner regex options have priorty
146
- @reg_string = "#{@reg_exp}" # this generates string with options
150
+ @reg_string = @@parse_options[:reg_options].prefix_reg + @reg_exp.source
147
151
  else
148
152
  raise "Error: string or regular expression required"
149
153
  end
@@ -8,10 +8,14 @@ require 'regextest/common'
8
8
  class Regextest::Back::Element
9
9
  include Regextest::Common
10
10
  def initialize(param)
11
- # puts "Element param:#{param[:cmd]} data:#{param[:data].size}"
12
- @command = param[:cmd]
11
+ # puts "Element param:#{param[:cmd]} data:#{param[:ranges].size}"
13
12
  @param = param
14
- @candidates = param[:data] if @command == :CMD_SELECT
13
+ @command = param[:cmd]
14
+ @charset = param[:charset]
15
+ if @command == :CMD_SELECT
16
+ @candidates = param[:ranges].inject([]){|result, range| result += range.to_a}
17
+ end
18
+ # @candidates = param[:data] if @command == :CMD_SELECT
15
19
  end
16
20
 
17
21
  attr_reader :param, :command, :candidates
@@ -33,7 +37,8 @@ class Regextest::Back::Element
33
37
  if(@candidates)
34
38
  @candidates.size
35
39
  else
36
- raise "internal error: candidates not found at size-method"
40
+ # raise "internal error: candidates not found at size-method"
41
+ 0
37
42
  end
38
43
  end
39
44
 
@@ -82,13 +87,14 @@ class Regextest::Back::Element
82
87
  if(@candidates)
83
88
  @candidates.inspect
84
89
  else
85
- @param[:data].inspect
90
+ @param[:ranges].inspect
86
91
  end
87
92
  when :CMD_LOOK_BEHIND, :CMD_LOOK_AHEAD, :CMD_NOT_LOOK_BEHIND, :CMD_NOT_LOOK_AHEAD
88
93
  @param.inspect
89
94
  when :CMD_ANC_LINE_BEGIN, :CMD_ANC_LINE_END, :CMD_ANC_WORD_BOUND, :CMD_ANC_WORD_UNBOUND,
90
95
  :CMD_ANC_STRING_BEGIN, :CMD_ANC_STRING_END, :CMD_ANC_STRING_END2, :CMD_ANC_MATCH_START,
91
- :CMD_ANC_LOOK_BEHIND2, :CMD_ANC_RELUCTANT_BEGIN, :CMD_ANC_RELUCTANT_END
96
+ :CMD_ANC_LOOK_BEHIND2, :CMD_ANC_RELUCTANT_BEGIN, :CMD_ANC_RELUCTANT_END,
97
+ :CMD_ANC_POSSESSIVE_BEGIN, :CMD_ANC_POSSESSIVE_END
92
98
  @param.inspect
93
99
  else
94
100
  raise "inner error, invalid command #{@command}"
@@ -107,24 +113,41 @@ class Regextest::Back::Element
107
113
 
108
114
  # Is word-elements only?
109
115
  def word_elements?
110
- letters = @candidates.map{|elem| [elem].pack("U*")}
111
- letters.join("").match(/^\p{Word}+$/)
116
+ letters = @candidates.map{|elem| [elem].pack("U*")}.join("")
117
+ if @charset == "u" || @charset == "d"
118
+ letters.match(/^\p{Word}+$/)
119
+ else
120
+ letters.match(/^\w+$/)
121
+ end
112
122
  end
113
123
 
114
124
  # is non-word-elements only?
115
125
  def non_word_elements?
116
- letters = @candidates.map{|elem| [elem].pack("U*")}
117
- letters.join("").match(/^\p{^Word}+$/)
126
+ letters = @candidates.map{|elem| [elem].pack("U*")}.join("")
127
+ if @charset == "u" || @charset == "d"
128
+ letters.match(/^\p{^Word}+$/)
129
+ else
130
+ letters.match(/^\W+$/)
131
+ end
118
132
  end
119
133
 
120
134
  # set word-elements
121
135
  def set_word_elements
122
- @candidates.select!{|elem| [elem].pack("U*").match(/^\w$/)}
136
+ if @charset == "u" || @charset == "d"
137
+ @candidates.select!{|elem| [elem].pack("U*").match(/^\p{Word}$/)}
138
+ else
139
+ @candidates.select!{|elem| [elem].pack("U*").match(/^\w$/)}
140
+ end
123
141
  end
124
142
 
125
143
  # set non_word-elements
126
144
  def set_non_word_elements
127
- @candidates.select!{|elem| [elem].pack("U*").match(/^\W$/)}
145
+ if @charset == "u" || @charset == "d"
146
+ @candidates.select!{|elem| [elem].pack("U*").match(/^\p{^Word}$/)}
147
+ #@candidates.select!{|elem| [elem].pack("U*").match(/^[[:^word:]]$/)}
148
+ else
149
+ @candidates.select!{|elem| [elem].pack("U*").match(/^[[:^word:]]$/)}
150
+ end
128
151
  end
129
152
 
130
153
  # checks empty
@@ -135,7 +158,7 @@ class Regextest::Back::Element
135
158
  # factory method to generate any char element
136
159
  def self.any_char
137
160
  # BUG: must consider other character set!
138
- Regextest::Back::Element.new({cmd: :CMD_SELECT, data: (0x20..0x7e).to_a})
161
+ Regextest::Back::Element.new({cmd: :CMD_SELECT, ranges: [0x20..0x7e]})
139
162
  end
140
163
 
141
164
  # factory method to generate any char element
@@ -12,6 +12,7 @@ class Regextest::Back::Main
12
12
  def initialize(json_obj, max_nest, retry_count = 0)
13
13
  @json_obj = json_obj
14
14
  @max_nest = max_nest
15
+ @past_max_nest = 0 # max nest of the past
15
16
  @retry_count = retry_count
16
17
  @parens_hash = {} # hash to keep string generated by parentheses
17
18
  @nest = 0 # current nest of back-reference
@@ -24,15 +25,15 @@ class Regextest::Back::Main
24
25
  seek_parens(@json_obj)
25
26
 
26
27
  # generate pre-result of matched string (pre-result contains candidates of letters)
27
- pre_result = generate_candidates({json: @json_obj})
28
+ param = {}
29
+ pre_result = generate_candidates(@json_obj, param)
28
30
  return nil unless pre_result
29
- TstLog("pre_result1:\n" + pre_result.inspect)
30
-
31
+ TstLog("pre_result1:\n" + pre_result.map{|elem| elem.inspect}.join("\n"))
32
+
31
33
  # narrow down the candidates
32
34
  result = narrow_down_candidates(pre_result)
33
35
  TstLog("pre_result2:\n" + result.inspect)
34
36
  return nil if !result || !result.narrow_down
35
-
36
37
  # fixes result
37
38
  result.fix
38
39
 
@@ -54,32 +55,31 @@ class Regextest::Back::Main
54
55
  end
55
56
 
56
57
  # generate pre-result of matched string (pre-result contains candidates of letters)
57
- def generate_candidates(param)
58
- target = param[:json]
58
+ def generate_candidates(target, param)
59
59
  # puts "MATCH type:#{target["type"]}"
60
60
 
61
61
  result = nil
62
62
  case target["type"]
63
63
  when "LEX_SEQ" # sequence of letters or parentheses
64
- result = generate_candidates_seq(param)
64
+ result = generate_candidates_seq(target, param)
65
65
  when "LEX_SELECT"
66
- result = generate_candidates_select(param)
66
+ result = generate_candidates_select(target, param)
67
67
  when "LEX_PAREN"
68
- result = generate_candidates_paren(param)
68
+ result = generate_candidates_paren(target, param)
69
69
  when "LEX_CHAR_CLASS"
70
- result = generate_candidates_char_class(param)
71
- when "LEX_BRACKET", "LEX_SIMPLIFIED_CLASS", "LEX_ANY_LETTER", "LEX_POSIX_CHAR_CLASS", "LEX_UNICODE_CLASS"
72
- result = generate_candidates({json: target["value"]})
70
+ result = generate_candidates_char_class(target, param)
71
+ when "LEX_BRACKET", "LEX_SIMPLIFIED_CLASS", "LEX_ANY_LETTER", "LEX_POSIX_CHAR_CLASS", "LEX_UNICODE_CLASS", "LEX_UNICODE_CLASS_BRACKET"
72
+ result = generate_candidates(target["value"], param)
73
73
  when "LEX_REPEAT"
74
- result = generate_candidates_repeat(param)
74
+ result = generate_candidates_repeat(target, param)
75
75
  when "LEX_RANGE"
76
- result = generate_candidates_range(param)
76
+ result = generate_candidates_range(target, param)
77
77
  when "LEX_BACK_REFER", "LEX_NAMED_REFER"
78
- result = generate_candidates_back_refer(param)
78
+ result = generate_candidates_back_refer(target, param)
79
79
  when "LEX_NAMED_GENERATE"
80
- result = generate_candidates_named_generate(param)
80
+ result = generate_candidates_named_generate(target, param)
81
81
  when "LEX_CHAR"
82
- result = generate_candidates_char(param)
82
+ result = generate_candidates_char(target, param)
83
83
  when "LEX_ANC_LINE_BEGIN"
84
84
  result = Regextest::Back::Element.new({cmd: :CMD_ANC_LINE_BEGIN})
85
85
  when "LEX_ANC_LINE_END"
@@ -109,11 +109,10 @@ class Regextest::Back::Main
109
109
  end
110
110
 
111
111
  # sequence of letters or parentheses
112
- def generate_candidates_seq(param)
113
- target = param[:json]
112
+ def generate_candidates_seq(target, param)
114
113
  results = []
115
114
  target["value"].each do |elem|
116
- generated_string = generate_candidates({json: elem})
115
+ generated_string = generate_candidates(elem, param)
117
116
  if(Array === generated_string)
118
117
  generated_string.flatten!(1)
119
118
  results += generated_string
@@ -132,12 +131,13 @@ class Regextest::Back::Main
132
131
  end
133
132
 
134
133
  # selection of sequence. such as (aa|b|c)
135
- def generate_candidates_select(param)
136
- target = param[:json]
134
+ def generate_candidates_select(target, param)
137
135
  if param[:forced_select]
138
- # index is specified by condition
139
- if target["value"][param[:forced_select]]
140
- result = generate_candidates({json: target["value"][param[:forced_select]]})
136
+ # index is specified by condition
137
+ offset = param[:forced_select]
138
+ param.delete :forced_select
139
+ if target["value"][offset]
140
+ result = generate_candidates(target["value"][offset], param)
141
141
  else
142
142
  # regexp such as /^(?:b|(a))(?(1)1)$/ match "b"!
143
143
  result = []
@@ -145,43 +145,72 @@ class Regextest::Back::Main
145
145
  else
146
146
  # success if there is at least one result
147
147
  offsets = (0 ... target["value"].size).to_a
148
- if !param[:atomic] && offsets.size > 1
149
- offsets = TstShuffle(offsets) # shuffle if not atomic group (this proceduce is not sufficient...)
150
- end
148
+
149
+ # shuffle if element size more than 1
150
+ offsets = TstShuffle(offsets) if offsets.size > 1
151
+
151
152
  result = nil
152
- offsets.each do | offset |
153
- result = generate_candidates({json: target["value"][offset]})
154
- break if(result)
153
+ if param[:atomic]
154
+ param.delete :atomic
155
+ # if atomic, assure proceeding results not appeared
156
+ offsets.each do | offset |
157
+ result = []
158
+ (0...offset).each do | prev |
159
+ la_result = generate_candidates(target["value"][prev], param)
160
+ result.push Regextest::Back::Element.new({cmd: :CMD_NOT_LOOK_AHEAD, result: la_result})
161
+ end
162
+ result.push generate_candidates(target["value"][offset], param)
163
+ break if(!result.find{|elem| !elem })
164
+ end
165
+ elsif negative_type = param[:negative]
166
+ # if negative, assure all results not appeared
167
+ result = []
168
+ offsets.each do | offset |
169
+ la_result = generate_candidates(target["value"][offset], param)
170
+ la_result.each do | elem |
171
+ if elem.command == :CMD_NOT_LOOK_AHEAD
172
+ result.push elem
173
+ else
174
+ result.push Regextest::Back::Element.new({cmd: negative_type, result: la_result})
175
+ end
176
+ end
177
+ end
178
+ param.delete :negative
179
+ else
180
+ offsets.each do | offset |
181
+ result = generate_candidates(target["value"][offset], param)
182
+ break if(result)
183
+ end
155
184
  end
156
185
  end
157
186
  result
158
187
  end
159
188
 
160
189
  # parenthesis
161
- def generate_candidates_paren(param)
162
- target = param[:json]
190
+ def generate_candidates_paren(target, param)
163
191
  # analyze options of the parenthesis
164
192
  paren_prefix = target["prefix"]
165
193
  # pp target["prefix"]
166
194
  if(paren_prefix == "<=")
167
- lb_result = generate_candidates({json: target["value"]})
195
+ lb_result = generate_candidates(target["value"], param)
168
196
  result = Regextest::Back::Element.new({cmd: :CMD_LOOK_BEHIND, result: lb_result})
169
197
  elsif(paren_prefix == "=")
170
- la_result = generate_candidates({json: target["value"]})
198
+ la_result = generate_candidates(target["value"], param)
171
199
  result = Regextest::Back::Element.new({cmd: :CMD_LOOK_AHEAD, result: la_result})
172
200
  elsif(paren_prefix == "<!")
173
- lb_result = generate_candidates({json: target["value"]})
174
- result = Regextest::Back::Element.new({cmd: :CMD_NOT_LOOK_BEHIND, result: lb_result})
201
+ param[:negative] = :CMD_NOT_LOOK_BEHIND
202
+ result = generate_candidates(target["value"], param)
175
203
  elsif(paren_prefix == "!")
176
- la_result = generate_candidates({json: target["value"]})
177
- result = Regextest::Back::Element.new({cmd: :CMD_NOT_LOOK_AHEAD, result: la_result})
204
+ param[:negative] = :CMD_NOT_LOOK_AHEAD
205
+ result = generate_candidates(target["value"], param)
178
206
  elsif(paren_prefix == ">") # atomic group
179
- generate_string = generate_candidates({json: target["value"], atomic: true})
207
+ param[:atomic] = true
208
+ generate_string = generate_candidates(target["value"], param)
180
209
  @parens_hash[target["refer_name"]][:generated] ||= []
181
210
  @parens_hash[target["refer_name"]][:generated][@nest] = generate_string
182
211
  result = generate_string
183
212
  elsif(paren_prefix == "") # simple parenthesis
184
- generate_string = generate_candidates({json: target["value"]})
213
+ generate_string = generate_candidates(target["value"], param)
185
214
  @parens_hash[target["refer_name"]][:generated] ||= []
186
215
  @parens_hash[target["refer_name"]][:generated][@nest] = generate_string
187
216
  result = generate_string
@@ -199,7 +228,8 @@ class Regextest::Back::Main
199
228
  if(select_num == 1 && target["value"]["type"] != "LEX_SELECT")
200
229
  result = nil
201
230
  else
202
- generate_string = generate_candidates({json: target["value"], forced_select: select_num})
231
+ param[:forced_select] = select_num
232
+ generate_string = generate_candidates(target["value"], param)
203
233
 
204
234
  @parens_hash[target["refer_name"]][:generated] ||= []
205
235
  @parens_hash[target["refer_name"]][:generated][@nest] = generate_string
@@ -210,11 +240,11 @@ class Regextest::Back::Main
210
240
  end
211
241
 
212
242
  # char class
213
- def generate_candidates_char_class(param)
214
- target = param[:json]
215
- results = Regextest::Back::Element.new({cmd: :CMD_SELECT, data: []})
243
+ def generate_candidates_char_class(target, param)
244
+ charset = target["charset"]
245
+ results = Regextest::Back::Element.new({cmd: :CMD_SELECT, ranges: [], charset: charset})
216
246
  target["value"].each do | elem |
217
- if sub_results = generate_candidates({json: elem})
247
+ if sub_results = generate_candidates(elem, param)
218
248
  results.union sub_results
219
249
  end
220
250
  end
@@ -227,12 +257,12 @@ class Regextest::Back::Main
227
257
  end
228
258
 
229
259
  # repeat
230
- def generate_candidates_repeat(param)
231
- target = param[:json]
260
+ def generate_candidates_repeat(target, param)
232
261
  max_repeat = target["max_repeat"]
233
262
  min_repeat = target["min_repeat"]
234
263
 
235
- if @retry_count > 0
264
+ # reduce repeat count if retry and there are one or more \g<foo> calls
265
+ if @retry_count > 0 && @past_max_nest > 0
236
266
  @retry_count.times{ max_repeat = (max_repeat + 1)/2 }
237
267
  end
238
268
 
@@ -243,13 +273,15 @@ class Regextest::Back::Main
243
273
  else
244
274
  repeat = min_repeat
245
275
  end
276
+
246
277
  result = []
247
278
  if target["repeat_option"].index("reluctant")
248
279
  result.push Regextest::Back::Element.new({cmd: :CMD_ANC_RELUCTANT_BEGIN, id: target["id"]})
249
280
  end
281
+
250
282
  # puts "repeat=#{repeat} quit=#{@quit_mode} nest=#{@nest}"
251
283
  repeat.times do
252
- if( elem = generate_candidates({json: target["value"]}))
284
+ if( elem = generate_candidates(target["value"], param))
253
285
  result.push elem
254
286
  else
255
287
  result = nil
@@ -263,23 +295,28 @@ class Regextest::Back::Main
263
295
  break if elem[0].command == :CMD_ANC_STRING_BEGIN
264
296
  end
265
297
  end
298
+
266
299
  if target["repeat_option"].index("reluctant")
267
300
  result.push Regextest::Back::Element.new({cmd: :CMD_ANC_RELUCTANT_END, id: target["id"]})
268
301
  end
302
+
303
+ if target["repeat_option"].index("possessive")
304
+ la_result = [ generate_candidates(target["value"], param) ].flatten
305
+ result.push Regextest::Back::Element.new({cmd: :CMD_NOT_LOOK_AHEAD, result: la_result})
306
+ end
269
307
  result
270
308
  end
271
309
 
272
310
  # range
273
- def generate_candidates_range(param)
274
- target = param[:json]
311
+ def generate_candidates_range(target, param)
312
+ charset = target["charset"]
275
313
  letter = []
276
- codepoints = (target["begin"]..target["end"]).to_a
277
- result = Regextest::Back::Element.new({cmd: :CMD_SELECT, data: codepoints})
314
+ codepoints = (target["begin"]..target["end"])
315
+ result = Regextest::Back::Element.new({cmd: :CMD_SELECT, ranges: [codepoints], charset: charset})
278
316
  end
279
317
 
280
318
  # back_refer
281
- def generate_candidates_back_refer(param)
282
- target = param[:json]
319
+ def generate_candidates_back_refer(target, param)
283
320
  if @parens_hash[target["refer_name"]][:generated]
284
321
  relative_num = -1 # default value
285
322
  if target["relative_num"] != ""
@@ -289,6 +326,13 @@ class Regextest::Back::Main
289
326
  end
290
327
  # puts "relative: #{relative_num}, nest=#{@nest}, :#{target}"
291
328
  result = @parens_hash[target["refer_name"]][:generated][relative_num]
329
+
330
+ # Somehow /(^a)\1/ must match with "aa"
331
+ if result.size > 0 &&
332
+ (result[0].command == :CMD_ANC_LINE_BEGIN ||
333
+ result[0].command == :CMD_ANC_STRING_BEGIN)
334
+ result = result[1..-1] # ignore first anchor
335
+ end
292
336
  else
293
337
  result = nil
294
338
  end
@@ -296,17 +340,17 @@ class Regextest::Back::Main
296
340
  end
297
341
 
298
342
  # named generate
299
- def generate_candidates_named_generate(param)
300
- target = param[:json]
343
+ def generate_candidates_named_generate(target, param)
301
344
  @quit_mode = true if(@nest >= @max_nest)
302
345
  if(@quit_mode)
303
346
  result = nil
304
347
  else
305
348
  @nest += 1
349
+ @past_max_nest = @nest if @nest > @past_max_nest
306
350
  if target["refer_name"] == "$$_0" # recursively call whole expression
307
- result = generate_candidates({json: @json_obj})
351
+ result = generate_candidates(@json_obj, param)
308
352
  else
309
- result = generate_candidates({json: @parens_hash[target["refer_name"]][:target]})
353
+ result = generate_candidates(@parens_hash[target["refer_name"]][:target], param)
310
354
  end
311
355
  @nest -= 1
312
356
  end
@@ -314,14 +358,20 @@ class Regextest::Back::Main
314
358
  end
315
359
 
316
360
  # char
317
- def generate_candidates_char(param)
318
- target = param[:json]
361
+ def generate_candidates_char(target, param)
362
+ charset = target["charset"]
319
363
  case target["value"]
320
364
  when String
321
365
  codepoint = target["value"].unpack("U*")[0]
322
- result = Regextest::Back::Element.new({cmd: :CMD_SELECT, data: [codepoint]})
366
+ result = Regextest::Back::Element.new(
367
+ {
368
+ cmd: :CMD_SELECT,
369
+ ranges: [codepoint..codepoint],
370
+ charset: charset
371
+ }
372
+ )
323
373
  else
324
- result = generate_candidates({json: target["value"]})
374
+ result = generate_candidates(target["value"], param)
325
375
  end
326
376
  result
327
377
  end
@@ -351,7 +401,8 @@ class Regextest::Back::Main
351
401
  :CMD_ANC_STRING_BEGIN, :CMD_ANC_STRING_END, :CMD_ANC_STRING_END2, :CMD_ANC_MATCH_START,
352
402
  :CMD_ANC_LOOK_BEHIND2
353
403
  results.add_anchor(command)
354
- when :CMD_ANC_RELUCTANT_BEGIN, :CMD_ANC_RELUCTANT_END
404
+ when :CMD_ANC_RELUCTANT_BEGIN, :CMD_ANC_RELUCTANT_END,
405
+ :CMD_ANC_POSSESSIVE_BEGIN, :CMD_ANC_POSSESSIVE_END
355
406
  results.add_reluctant_repeat(elem)
356
407
  else
357
408
  raise "inner error, invalid command at checking anchors: #{command}"