File Coverage

blib/lib/Regexp/Parser/Handlers.pm
Criterion Covered Total %
statement 346 586 59.0
branch 76 234 32.4
condition 2 15 13.3
subroutine 41 85 48.2
pod 0 1 0.0
total 465 921 50.4


line stmt bran cond sub pod time code
1             package Regexp::Parser;
2              
3             my ($nest_eval, $nest_logical);
4             $nest_eval = qr[ (?> [^\\{}]+ | \\. | { (??{ $nest_eval }) } )* ]x;
5             $nest_logical = qr[ (?> [^\\{}]+ | \\. | { (??{ $nest_logical }) } )* ]x;
6              
7             sub init {
8 9     9 0 32 my ($self) = @_;
9              
10             # /m, /s, /i, /x flags
11 9     16   137 $self->add_flag('m' => sub { 0x1 });
  16         66  
12 9     20   84 $self->add_flag('s' => sub { 0x2 });
  20         62  
13 9     75   59 $self->add_flag('i' => sub { 0x4 });
  75         255  
14 9     455   53 $self->add_flag('x' => sub { 0x8 });
  455         1157  
15              
16             # (useless) /g, /c, /o flags
17             $self->add_flag('g' => sub {
18 0     0   0 my ($S, $plus) = @_;
19 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "g", $plus ? "" : "don't ", "g");
    0          
20 0         0 return 0x0;
21 9         67 });
22             $self->add_flag('c' => sub {
23 0     0   0 my ($S, $plus) = @_;
24 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "c", $plus ? "" : "don't ", "gc");
    0          
25 0         0 return 0x0;
26 9         55 });
27             $self->add_flag('o' => sub {
28 0     0   0 my ($S, $plus) = @_;
29 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "o", $plus ? "" : "don't ", "o");
    0          
30 0         0 return 0x0;
31 9         54 });
32              
33             $self->add_handler('\a' => sub {
34 2     2   5 my ($S, $cc) = @_;
35 2 50       6 return $S->force_object(anyof_char => "\a", '\a') if $cc;
36 0         0 return $S->object(exact => "\a", '\a');
37 9         66 });
38              
39             $self->add_handler('\e' => sub {
40 0     0   0 my ($S, $cc) = @_;
41 0 0       0 return $S->force_object(anyof_char => "\e", '\e') if $cc;
42 0         0 return $S->object(exact => "\e", '\e');
43 9         58 });
44              
45             $self->add_handler('\f' => sub {
46 2     2   5 my ($S, $cc) = @_;
47 2 50       8 return $S->force_object(anyof_char => "\f", '\f') if $cc;
48 0         0 return $S->object(exact => "\f", '\f');
49 9         55 });
50              
51             $self->add_handler('\n' => sub {
52 0     0   0 my ($S, $cc) = @_;
53 0 0       0 return $S->force_object(anyof_char => "\n", '\n') if $cc;
54 0         0 return $S->object(exact => "\n", '\n');
55 9         56 });
56              
57             $self->add_handler('\r' => sub {
58 0     0   0 my ($S, $cc) = @_;
59 0 0       0 return $S->force_object(anyof_char => "\r", '\r') if $cc;
60 0         0 return $S->object(exact => "\r", '\r');
61 9         56 });
62              
63             $self->add_handler('\t' => sub {
64 0     0   0 my ($S, $cc) = @_;
65 0 0       0 return $S->force_object(anyof_char => "\t", '\t') if $cc;
66 0         0 return $S->object(exact => "\t", '\t');
67 9         52 });
68              
69             # bol, mbol, sbol
70             $self->add_handler('^' => sub {
71 10     10   23 my ($S) = @_;
72 10 50       25 my $type =
    50          
73             &Rf & $S->FLAG_m ? 'mbol' :
74             &Rf & $S->FLAG_s ? 'sbol' :
75             'bol';
76 10         42 return $S->object(bol => $type, '^');
77 9         53 });
78              
79             # sbol (beginning of line in single-line mode)
80             $self->add_handler('\A' => sub {
81 0     0   0 my ($S, $cc) = @_;
82 0 0       0 $S->warn($S->RPe_BADESC, "A", " in character class") if $cc;
83 0 0       0 return $S->force_object(anyof_char => 'A') if $cc;
84 0         0 return $S->object(bol => 'sbol' => '\A');
85 9         51 });
86              
87             # nbound (not a word boundary)
88             $self->add_handler('\B' => sub {
89 0     0   0 my ($S, $cc) = @_;
90 0 0       0 $S->warn($S->RPe_BADESC, "B", " in character class") if $cc;
91 0 0       0 return $S->force_object(anyof_char => 'B') if $cc;
92 0         0 return $S->object(bound => nbound => '\B');
93 9         61 });
94              
95             # bound (not a word boundary)
96             $self->add_handler('\b' => sub {
97 2     2   9 my ($S, $cc) = @_;
98 2 50       8 return $S->force_object(anyof_char => "\b", '\b') if $cc;
99 0         0 return $S->object(bound => bound => '\b');
100 9         54 });
101              
102             # cany (any byte)
103             $self->add_handler('\C' => sub {
104 0     0   0 my ($S, $cc) = @_;
105 0 0       0 $S->warn($S->RPe_BADESC, "C", " in character class") if $cc;
106 0 0       0 return $S->force_object(anyof_char => 'C') if $cc;
107 0         0 return $S->object(reg_any => c_any => '\C');
108 9         56 });
109              
110             # control character
111             $self->add_handler('\c' => sub {
112 0     0   0 my ($S, $cc) = @_;
113 0         0 ${&Rx} =~ m{ \G (.?) }xgc;
  0         0  
114 0         0 my $c = $1;
115 0 0       0 return $S->force_object(anyof_char => chr(64 ^ ord $c), "\\c$c") if $cc;
116 0         0 return $S->object(exact => chr(64 ^ ord $c), "\\c$c");
117 9         55 });
118              
119             # ndigit (not a digit)
120             $self->add_handler('\D' => sub {
121 4     4   9 my ($S, $cc) = @_;
122 4 50       10 return $S->force_object(anyof_class => $S->force_object(digit => 1)) if $cc;
123 4         7 return $S->object(digit => 1);
124 9         53 });
125              
126             # digit (a digit)
127             $self->add_handler('\d' => sub {
128 4     4   7 my ($S, $cc) = @_;
129 4 50       8 return $S->force_object(anyof_class => $S->force_object(digit => 0)) if $cc;
130 4         7 return $S->object(digit => 0);
131 9         50 });
132              
133             # gpos (last global match end)
134             $self->add_handler('\G' => sub {
135 0     0   0 my ($S, $cc) = @_;
136 0 0       0 $S->warn($S->RPe_BADESC, "G", " in character class") if $cc;
137 0 0       0 return $S->force_object(anyof_char => 'G') if $cc;
138 0         0 return $S->object(gpos => gpos => '\G');
139 9         54 });
140              
141             # named (named character)
142             $self->add_handler('\N' => sub {
143 2     2   6 my ($S, $cc) = @_;
144 2 50       3 $S->error($S->RPe_BRACES, 'N') if ${&Rx} !~ m{ \G \{ }xgc;
  2         5  
145 2 50       6 $S->error($S->RPe_RBRACE, 'N') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  2         4  
146              
147 2         6 my $name = $1;
148 2 50       6 return $S->force_object(anyof_char => $S->nchar($name), "\\N{$name}") if $cc;
149 2         16 return $S->object(exact => $S->nchar($name), "\\N{$name}");
150 9         58 });
151              
152             # nprop (not a unicode property)
153             $self->add_handler('\P' => sub {
154 0     0   0 my ($S, $cc) = @_;
155 0 0       0 $S->error($S->RPe_EMPTYB, 'P') if ${&Rx} !~ m{ \G (.) }xgcs;
  0         0  
156              
157 0         0 my $name = $1;
158 0 0       0 if ($name eq '{') {
159 0 0       0 $S->error($S->RPe_RBRACE, 'P') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  0         0  
160 0         0 $name = $1;
161             }
162              
163 0 0       0 return $S->force_object(anyof_class => $S->force_object(prop => $name, 1)) if $cc;
164 0         0 return $S->object(prop => $name, 1);
165 9         57 });
166              
167             # prop (a unicode property)
168             $self->add_handler('\p' => sub {
169 0     0   0 my ($S, $cc) = @_;
170 0 0       0 $S->error($S->RPe_EMPTYB, 'p') if ${&Rx} !~ m{ \G (.) }xgcs;
  0         0  
171              
172 0         0 my $name = $1;
173 0 0       0 if ($name eq '{') {
174 0 0       0 $S->error($S->RPe_RBRACE, 'p') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  0         0  
175 0         0 $name = $1;
176             }
177              
178 0 0       0 return $S->force_object(anyof_class => $S->force_object(prop => $name, 0)) if $cc;
179 0         0 return $S->object(prop => $name, 0);
180 9         59 });
181              
182             # nspace (not a space)
183             $self->add_handler('\S' => sub {
184 0     0   0 my ($S, $cc) = @_;
185 0 0       0 return $S->force_object(anyof_class => $S->force_object(space => 1)) if $cc;
186 0         0 return $S->object(space => 1);
187 9         87 });
188              
189             # space (a space)
190             $self->add_handler('\s' => sub {
191 0     0   0 my ($S, $cc) = @_;
192 0 0       0 return $S->force_object(anyof_class => $S->force_object(space => 0)) if $cc;
193 0         0 return $S->object(space => 0);
194 9         51 });
195              
196             # nalnum (not a word character)
197             $self->add_handler('\W' => sub {
198 0     0   0 my ($S, $cc) = @_;
199 0 0       0 return $S->force_object(anyof_class => $S->force_object(alnum => 1)) if $cc;
200 0         0 return $S->object(alnum => 1);
201 9         53 });
202              
203             # alnum (a word character)
204             $self->add_handler('\w' => sub {
205 0     0   0 my ($S, $cc) = @_;
206 0 0       0 return $S->force_object(anyof_class => $S->force_object(alnum => 0)) if $cc;
207 0         0 return $S->object(alnum => 0);
208 9         49 });
209              
210             # clump (a unicode clump)
211             $self->add_handler('\X' => sub {
212 0     0   0 my ($S, $cc) = @_;
213 0 0       0 $S->warn($S->RPe_BADESC, 'X', ' in character class') if $cc;
214 0 0       0 return $S->force_object(anyof_char => 'X') if $cc;
215 0         0 return $S->object(clump => '\X');
216 9         51 });
217              
218             # hex character
219             $self->add_handler('\x' => sub {
220 0     0   0 my ($S, $cc) = @_;
221 0         0 ${&Rx} =~ m{ \G ( \{ | .{0,2} ) }sxgc;
  0         0  
222 0         0 my $brace = 0;
223 0         0 my $num = $1;
224              
225 0 0       0 if ($num eq '{') {
226 0 0       0 $S->error($S->RPe_RBRACE, 'x') if ${&Rx} !~ m{ \G ( [^\}]* ) \} }xgc;
  0         0  
227 0         0 $num = $1;
228 0         0 $brace = 1;
229             }
230             else {
231 0   0     0 my $good = ($num =~ s/^([a-fA-F0-9]*)// and $1);
232 0         0 &RxPOS -= length $num;
233 0         0 $num = $good;
234             }
235              
236 0 0       0 my $rep = $brace ? "\\x{$num}" : sprintf("\\x%02s", $num);
237 0 0       0 return $S->force_object(anyof_char => chr hex $num, $rep) if $cc;
238 0         0 return $S->object(exact => chr hex $num, $rep);
239 9         58 });
240              
241             # eol, seol, meol
242             $self->add_handler('$' => sub {
243 6     6   18 my ($S) = @_;
244 6 50       20 my $type =
    50          
245             &Rf & $S->FLAG_m ? 'meol' :
246             &Rf & $S->FLAG_s ? 'seol' :
247             'eol';
248 6         43 return $S->object(eol => $type, '$');
249 9         57 });
250              
251             # seol (end of line, in single-line mode)
252             $self->add_handler('\Z' => sub {
253 0     0   0 my ($S, $cc) = @_;
254 0 0       0 $S->warn($S->RPe_BADESC, "Z", " in character class") if $cc;
255 0 0       0 return $S->force_object(anyof_char => 'Z') if $cc;
256 0         0 return $S->object(eol => seol => '\Z');
257 9         52 });
258              
259             # eos (end of string)
260             $self->add_handler('\z' => sub {
261 0     0   0 my ($S, $cc) = @_;
262 0 0       0 $S->warn($S->RPe_BADESC, "z", " in character class") if $cc;
263 0 0       0 return $S->force_object(anyof_char => 'z') if $cc;
264 0         0 return $S->object(eol => eos => '\z');
265 9         50 });
266              
267             # alpha POSIX class
268             $self->add_handler('POSIX_alpha' => sub {
269 0     0   0 my ($S, $neg, $how) = @_;
270 0         0 return $S->force_object(anyof_class => alpha => $neg, \$how);
271 9         49 });
272              
273             # alnum POSIX class
274             $self->add_handler('POSIX_alnum' => sub {
275 0     0   0 my ($S, $neg, $how) = @_;
276 0         0 return $S->force_object(anyof_class => alnum => $neg, \$how);
277 9         54 });
278              
279             # ascii POSIX class
280             $self->add_handler('POSIX_ascii' => sub {
281 0     0   0 my ($S, $neg, $how) = @_;
282 0         0 return $S->force_object(anyof_class => ascii => $neg, \$how);
283 9         49 });
284              
285             # cntrl POSIX class
286             $self->add_handler('POSIX_cntrl' => sub {
287 0     0   0 my ($S, $neg, $how) = @_;
288 0         0 return $S->force_object(anyof_class => cntrl => $neg, \$how);
289 9         53 });
290              
291             # digit POSIX class
292             $self->add_handler('POSIX_digit' => sub {
293 0     0   0 my ($S, $neg, $how) = @_;
294 0         0 return $S->force_object(anyof_class => digit => $neg, \$how);
295 9         51 });
296              
297             # graph POSIX class
298             $self->add_handler('POSIX_graph' => sub {
299 0     0   0 my ($S, $neg, $how) = @_;
300 0         0 return $S->force_object(anyof_class => graph => $neg, \$how);
301 9         53 });
302              
303             # lower POSIX class
304             $self->add_handler('POSIX_lower' => sub {
305 0     0   0 my ($S, $neg, $how) = @_;
306 0         0 return $S->force_object(anyof_class => lower => $neg, \$how);
307 9         54 });
308              
309             # print POSIX class
310             $self->add_handler('POSIX_print' => sub {
311 0     0   0 my ($S, $neg, $how) = @_;
312 0         0 return $S->force_object(anyof_class => print => $neg, \$how);
313 9         49 });
314              
315             # punct POSIX class
316             $self->add_handler('POSIX_punct' => sub {
317 0     0   0 my ($S, $neg, $how) = @_;
318 0         0 return $S->force_object(anyof_class => punct => $neg, \$how);
319 9         48 });
320              
321             # space POSIX class
322             $self->add_handler('POSIX_space' => sub {
323 0     0   0 my ($S, $neg, $how) = @_;
324 0         0 return $S->force_object(anyof_class => space => $neg, \$how);
325 9         56 });
326              
327             # upper POSIX class
328             $self->add_handler('POSIX_upper' => sub {
329 0     0   0 my ($S, $neg, $how) = @_;
330 0         0 return $S->force_object(anyof_class => upper => $neg, \$how);
331 9         49 });
332              
333             # word POSIX class
334             $self->add_handler('POSIX_word' => sub {
335 0     0   0 my ($S, $neg, $how) = @_;
336 0         0 return $S->force_object(anyof_class => word => $neg, \$how);
337 9         57 });
338              
339             # xdigit POSIX class
340             $self->add_handler('POSIX_xdigit' => sub {
341 0     0   0 my ($S, $neg, $how) = @_;
342 0         0 return $S->force_object(anyof_class => xdigit => $neg, \$how);
343 9         75 });
344              
345             $self->add_handler('atom' => sub {
346 293     293   477 my ($S) = @_;
347 293         674 $S->nextchar;
348              
349 293 100       386 ${&Rx} =~ m{ \G (.) }xgcs or return;
  293         469  
350 262         551 my $c = $1;
351              
352 262         330 push @{ $S->{next} }, qw< atom >;
  262         452  
353 262 100       930 return $S->$c if $S->can($c);
354 73         157 return $S->object(exact => $c);
355 9         54 });
356              
357             $self->add_handler('*' => sub {
358 12     12   19 my ($S) = @_;
359 12         16 push @{ $S->{next} }, qw< minmod >;
  12         24  
360 12         30 return $S->object(quant => 0, '');
361 9         51 });
362              
363             $self->add_handler('+' => sub {
364 14     14   36 my ($S) = @_;
365 14         24 push @{ $S->{next} }, qw< minmod >;
  14         36  
366 14         39 return $S->object(quant => 1, '');
367 9         50 });
368              
369             $self->add_handler('?' => sub {
370 2     2   9 my ($S) = @_;
371 2         4 push @{ $S->{next} }, qw< minmod >;
  2         10  
372 2         9 return $S->object(quant => 0, 1);
373 9         47 });
374              
375             $self->add_handler('{' => sub {
376 6     6   9 my ($S) = @_;
377 6 50       7 if (${&Rx} =~ m{ \G (\d+) (,?) (\d*) \} }xgc) {
  6         16  
378 6         23 my ($min, $range, $max) = ($1, $2, $3);
379 6 100       11 $max = $min unless $range;
380 6         10 push @{ $S->{next} }, qw< minmod >;
  6         10  
381 6 50 66     26 $S->error($S->RPe_BCURLY) if length($max) and $min > $max;
382 6         14 return $S->object(quant => $min, $max);
383             }
384 0         0 return $S->object(exact => '{');
385 9         46 });
386              
387             $self->add_handler('minmod' => sub {
388 34     34   59 my ($S) = @_;
389 34         82 $S->nextchar;
390 34 100       50 return $S->object(minmod =>) if ${&Rx} =~ m{ \G \? }xgc;
  34         59  
391 30         80 return;
392 9         43 });
393              
394             # alternation branch
395             $self->add_handler('|' => sub {
396 10     10   21 my ($S) = @_;
397 10         20 return $S->object(branch =>);
398 9         57 });
399              
400             # opening parenthesis (maybe capturing paren)
401             $self->add_handler('(' => sub {
402 55     55   106 my ($S) = @_;
403 55         77 my $c = '(';
404 55         129 $S->nextchar;
405              
406 55 50       70 if (${&Rx} =~ m{ \G (.) }xgcs) {
  55         105  
407 55         136 my $n = "$c$1";
408 55 100       249 return $S->$n if $S->can($n);
409 16         42 &RxPOS--;
410             }
411              
412 16         42 push @{ $S->{next} }, qw< c) atom >;
  16         51  
413 16 100       39 &SIZE_ONLY ? ++$S->{maxpar} : ++$S->{nparen};
414 16         33 push @{ $S->{flags} }, &Rf;
  16         40  
415 16         52 return $S->object(open => $S->{nparen});
416 9         61 });
417              
418             # any character
419             $self->add_handler('.' => sub {
420 4     4   6 my ($S) = @_;
421 4 50       9 my $family =
422             &Rf & $S->FLAG_s ? 'sany' :
423             'reg_any';
424 4         6 return $S->object(reg_any => $family, '.');
425 9         52 });
426              
427             # backslash
428             $self->add_handler('\\' => sub {
429 16     16   28 my ($S, $cc) = @_;
430 16         24 my $c = '\\';
431              
432 16 50       21 if (${&Rx} =~ m{ \G (.) }xgcs) {
  16         27  
433 16         37 $c .= (my $n = $1);
434              
435 16 50       60 return $S->$c($cc) if $S->can($c);
436              
437 0 0       0 if ($n =~ /\d/) {
438 0         0 --&RxPOS;
439 0         0 my $v = "";
440              
441             # outside of char class, \nnn might be backref
442 0 0 0     0 if (!&SIZE_ONLY and !$cc and $n != 0) {
      0        
443 0         0 $v .= $1 while ${&Rx} =~ m{ \G (\d) }xgc;
  0         0  
444 0 0 0     0 if ($v > 9 and $v > $S->{maxpar}) {
    0          
445 0         0 &RxPOS -= length $v;
446 0         0 $v = "";
447             }
448 0         0 elsif ($v > $S->{maxpar}) { $S->error($S->RPe_BGROUP) }
449 0         0 else { return $S->object(ref => $v, "\\$v") }
450             }
451              
452 0         0 $v .= $1 while ${&Rx} =~ m{ \G ([0-7]) }xgc;
  0         0  
453 0         0 return $S->object(exact => chr oct $v, sprintf("\\%03s", $v));
454             }
455              
456 0 0       0 $S->warn($S->RPe_BADESC, $c = $n, "") if $n =~ /[a-zA-Z]/;
457              
458 0         0 return $S->object(exact => $n, $c);
459             }
460              
461 0         0 $S->error($S->RPe_ESLASH);
462 9         68 });
463              
464             # start of char class (and possible negation)
465             $self->add_handler('[' => sub {
466 2     2   4 my ($S) = @_;
467 2         3 push @{ $S->{next} }, qw< cce] cc cc] >;
  2         12  
468 2         3 my $neg = ${&Rx} =~ m{ \G \^ }xgc;
  2         5  
469              
470 2         4 my $pos = &RxPOS;
471 2 50       3 if (${&Rx} =~ m{ \G ([:.=]) .*? \1 ] }xgc) {
  2         3  
472 0         0 $S->warn($S->RPe_OUTPOS, $1, $1);
473 0         0 &RxPOS = $pos;
474             }
475              
476 2         7 return $S->object(anyof => $neg);
477 9         53 });
478              
479             # char class ] at beginning
480             $self->add_handler('cc]' => sub {
481 2     2   5 my ($S) = @_;
482 2 50       5 return unless ${&Rx} =~ m{ \G ] }xgc;
  2         4  
483 0         0 return $S->object(anyof_char => "]");
484 9         44 });
485              
486             # start of char class range (or maybe just char)
487             $self->add_handler('cc' => sub {
488 8     8   12 my ($S) = @_;
489 8 100       10 return if ${&Rx} =~ m{ \G (?= ] | \z ) }xgc;
  8         12  
490 6         9 push @{ $S->{next} }, qw< cc >;
  6         10  
491 6         7 my ($lhs, $rhs, $before_range);
492 6         9 my $ret = \$lhs;
493              
494             {
495 6 50       9 if (${&Rx} =~ m{ \G ( \\ ) }xgcs) {
  6 0       6  
  6 0       10  
496 6         11 my $c = $1;
497 6         14 $$ret = $S->$c(1);
498             }
499 0         0 elsif (${&Rx} =~ m{ \G \[ ([.=:]) (\^?) (.*?) \1 \] }xgcs) {
500 0         0 my ($how, $neg, $name) = ($1, $2, $3);
501 0         0 my $posix = "POSIX_$name";
502 0 0       0 if ($S->can($posix)) { $$ret = $S->$posix($neg, $how) }
  0         0  
503 0         0 else { $S->error($S->RPe_BADPOS, "$how$neg$name$how") }
504             }
505 0         0 elsif (${&Rx} =~ m{ \G (.) }xgcs) {
506 0         0 $$ret = $S->force_object(anyof_char => $1);
507             }
508              
509 6 50       14 if ($ret == \$lhs) {
    0          
510 6 50       9 if (${&Rx} =~ m{ \G (?= - ) }xgc) {
  6         8  
511 0 0       0 if ($lhs->visual =~ /^(?:\[[:.=]|\\[dDsSwWpP])/) {
512 0         0 $S->warn($S->RPe_FRANGE, $lhs->visual, "");
513 0         0 $ret = $lhs;
514 0         0 last;
515             }
516 0         0 $before_range = &RxPOS++;
517 0         0 $ret = \$rhs;
518 0         0 redo;
519             }
520 6         10 $ret = $lhs;
521             }
522             elsif ($ret == \$rhs) {
523 0 0       0 if ($rhs->visual =~ /^(?:\[[:.=]|\\[dDsSwWpP])/) {
    0          
524 0         0 $S->warn($S->RPe_FRANGE, $lhs->visual, $rhs->visual);
525 0         0 &RxPOS = $before_range;
526 0         0 $ret = $lhs;
527             }
528             elsif ($lhs->visual gt $rhs->visual) {
529 0         0 $S->error($S->RPe_IRANGE, $lhs->visual, $rhs->visual);
530             }
531             else {
532 0         0 $ret = $S->object(anyof_range => $lhs, $rhs);
533             }
534             }
535             }
536              
537 6 100       10 return if &SIZE_ONLY;
538 3         7 return $ret;
539 9         57 });
540              
541             # end of char class
542             $self->add_handler('cce]' => sub {
543 2     2   4 my ($S) = @_;
544 2 50       2 $S->error($S->RPe_LBRACK) if ${&Rx} !~ m{ \G ] }xgc;
  2         5  
545 2         6 return $S->object(anyof_close => "]");
546 9         47 });
547              
548             # closing paren coming from 'atom'
549             $self->add_handler(')' => sub {
550 77     77   127 my ($S) = @_;
551 77         94 pop @{ $S->{next} };
  77         143  
552 77         165 &RxPOS--;
553 77         233 return;
554 9         49 });
555              
556             # closing paren coming from an opening paren
557             $self->add_handler('c)' => sub {
558 55     55   91 my ($S) = @_;
559 55 50       66 $S->error($S->RPe_LPAREN) if ${&Rx} !~ m{ \G \) }xgc;
  55         92  
560 55         88 pop @{ $S->{flags} };
  55         106  
561 55         14975 return $S->object(close =>);
562 9         49 });
563              
564             # some kind of assertion...
565             $self->add_handler('(?' => sub {
566 39     39   64 my ($S) = @_;
567 39         53 my $c = '(?';
568              
569 39 50       46 if (${&Rx} =~ m{ \G (.) }xgcs) {
  39         58  
570 39         67 my $n = "$c$1";
571 39 100       115 return $S->$n if $S->can($n);
572 10         17 &RxPOS--;
573             }
574             else {
575 0         0 $S->error($S->RPe_SEQINC);
576             }
577              
578             # flag assertion or non-capturing group
579 10         19 ${&Rx} =~ m{ \G ([a-zA-Z]*) (-? [a-zA-Z]*) }xgc;
  10         13  
580 10         30 my ($on, $off) = ($1, $2);
581 10         18 my ($r_on, $r_off) = ("", "");
582 10         15 my ($f_on, $f_off) = (0,0);
583              
584 10         16 &RxPOS -= length($on.$off);
585 10         20 my $old = &RxPOS;
586              
587 10         25 for (split //, $on) {
588 4         6 &RxPOS++;
589 4 50       16 if (my $f = $S->can("FLAG_$_")) {
590 4 50       9 my $v = $S->$f(1) and $r_on .= $_;
591 4         6 $f_on |= $v;
592 4         9 next;
593             }
594 0         0 my $bad = substr ${&Rx}, $old;
  0         0  
595 0         0 $S->error($S->RPe_NOTREC, &RxPOS - $old, $bad);
596             }
597              
598 10 100       33 &RxPOS++ if $off =~ s/^-//;
599              
600 10         21 for (split //, $off) {
601 2         4 &RxPOS++;
602 2 50       10 if (my $f = $S->can("FLAG_$_")) {
603 2 50       5 my $v = $S->$f(0) and $r_off .= $_;
604 2         4 $f_off |= $v;
605 2         4 next;
606             }
607 0         0 my $bad = substr ${&Rx}, $old;
  0         0  
608 0         0 $S->error($S->RPe_NOTREC, &RxPOS - $old, $bad);
609             }
610              
611 10 50       12 if (${&Rx} =~ m{ \G ([:)]) }xgc) {
  10         16  
612 10 100       24 my $type = $1 eq ':' ? 'group' : 'flags';
613 10 100       17 if ($type eq 'group') {
614 6         13 push @{ $S->{flags} }, &Rf;
  6         13  
615 6         9 push @{ $S->{next} }, qw< c) atom >;
  6         13  
616             }
617 10         19 &Rf |= $f_on;
618 10         19 &Rf &= ~$f_off;
619 10         22 return $S->object($type => $r_on, $r_off);
620             }
621              
622 0         0 &RxPOS++;
623 0         0 my $l = length($on.$off) + 2;
624 0         0 $S->error($S->RPe_NOTREC, $l, substr(${&Rx}, $old));
  0         0  
625 9         103 });
626              
627             # comment
628             $self->add_handler('(?#' => sub {
629 0     0   0 my ($S) = @_;
630 0         0 ${&Rx} =~ m{ \G [^)]* }xgc;
  0         0  
631 0 0       0 $S->error($S->RPe_NOTERM) unless ${&Rx} =~ m{ \G \) }xgc;
  0         0  
632 0         0 return;
633 9         113 });
634              
635             # not implemented (?$...)
636             $self->add_handler('(?$' => sub {
637 0     0   0 my ($S) = @_;
638 0         0 $S->error($S->RPe_NOTREC, 1, substr(${&Rx}, &RxPOS - 1));
  0         0  
639 9         51 });
640              
641             # not implemented (?@...)
642             $self->add_handler('(?@' => sub {
643 0     0   0 my ($S) = @_;
644 0         0 $S->error($S->RPe_NOTREC, 1, substr(${&Rx}, &RxPOS - 1));
  0         0  
645 9         63 });
646              
647             # look-ahead
648             $self->add_handler('(?=' => sub {
649 9     9   11 my ($S) = @_;
650 9         11 push @{ $S->{next} }, qw< c) atom >;
  9         20  
651 9         13 push @{ $S->{flags} }, &Rf;
  9         16  
652 9         13 return $S->object(ifmatch => 1);
653 9         51 });
654              
655             # look-ahead (neg)
656             $self->add_handler('(?!' => sub {
657 2     2   4 my ($S) = @_;
658 2         3 push @{ $S->{next} }, qw< c) atom >;
  2         4  
659 2         3 push @{ $S->{flags} }, &Rf;
  2         5  
660 2         4 return $S->object(unlessm => 1);
661 9         45 });
662              
663             # look-behind prefix
664             $self->add_handler('(?<' => sub {
665 0     0   0 my ($S) = @_;
666 0         0 my $c = '(?<';
667              
668 0 0       0 if (${&Rx} =~ m{ \G (.) }xgcs) {
  0         0  
669 0         0 my $n = "$c$1";
670 0 0       0 return $S->$n if $S->can($n);
671             }
672              
673 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
674 9         57 });
675              
676             # look-behind
677             $self->add_handler('(?<=' => sub {
678 2     2   4 my ($S) = @_;
679 2         3 push @{ $S->{next} }, qw< c) atom >;
  2         5  
680 2         3 push @{ $S->{flags} }, &Rf;
  2         4  
681 2         5 return $S->object(ifmatch => -1);
682 9         55 });
683              
684             # look-behind (neg)
685             $self->add_handler('(? sub {
686 2     2   4 my ($S) = @_;
687 2         4 push @{ $S->{next} }, qw< c) atom >;
  2         5  
688 2         3 push @{ $S->{flags} }, &Rf;
  2         5  
689 2         4 return $S->object(unlessm => -1);
690 9         48 });
691              
692             # suspend
693             $self->add_handler('(?>' => sub {
694 0     0   0 my ($S) = @_;
695 0         0 push @{ $S->{next} }, qw< c) atom >;
  0         0  
696 0         0 push @{ $S->{flags} }, &Rf;
  0         0  
697 0         0 return $S->object(suspend =>);
698 9         50 });
699              
700             # eval
701             $self->add_handler('(?{' => sub {
702 2     2   4 my ($S) = @_;
703 2 50       3 if (${&Rx} =~ m{ \G ($nest_eval) \} \) }xgc) {
  2         5  
704 2         5 push @{ $S->{flags} }, &Rf;
  2         6  
705 2         6 return $S->object(eval => $1);
706             }
707 0         0 $S->error($S->RPe_NOTBAL);
708 9         48 });
709              
710             # logical prefix
711             $self->add_handler('(??' => sub {
712 0     0   0 my ($S) = @_;
713 0         0 my $c = '(??';
714              
715 0 0       0 if (${&Rx} =~ m{ \G (.) }xgcs) {
  0         0  
716 0         0 my $n = "$c$1";
717 0 0       0 return $S->$n if $S->can($n);
718             }
719              
720 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
721 9         53 });
722              
723             # logical
724             $self->add_handler('(??{' => sub {
725 0     0   0 my ($S) = @_;
726 0 0       0 if (${&Rx} =~ m{ \G ($nest_logical) \} \) }xgc) {
  0         0  
727 0         0 push @{ $S->{flags} }, &Rf;
  0         0  
728 0         0 return $S->object(logical => $1);
729             }
730 0         0 $S->error($S->RPe_NOTBAL);
731 9         55 });
732              
733             # logical prefix
734             $self->add_handler('(?p' => sub {
735 0     0   0 my ($S) = @_;
736 0         0 my $c = '(?p';
737              
738 0 0       0 if (${&Rx} =~ m{ \G (.) }xgcs) {
  0         0  
739 0         0 my $n = "$c$1";
740 0 0       0 return $S->$n if $S->can($n);
741             }
742              
743 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
744 9         61 });
745              
746             # logical
747             $self->add_handler('(?p{' => sub {
748 0     0   0 my ($S) = @_;
749 0         0 $S->warn($S->RPe_LOGDEP);
750 0         0 my $c = "(??{";
751 0         0 return $S->$c;
752 9         98 });
753              
754             $self->add_handler('(?(' => sub {
755 29     29   40 my ($S) = @_;
756 29         35 my $c = '(?(';
757              
758 29 50       33 if (${&Rx} =~ m{ \G (.) }xgcs) {
  29         45  
759 29         47 my $n = "$c$1";
760 29 50       77 return $S->$n if $S->can($n);
761 29         46 &RxPOS--;
762             }
763              
764 29         43 push @{ $S->{next} }, qw< ifthen( >;
  29         53  
765 29         36 push @{ $S->{flags} }, &Rf;
  29         49  
766 29         54 return $S->object(ifthen =>);
767 9         61 });
768              
769             # (?(...)t|f) condition
770             $self->add_handler('ifthen(' => sub {
771 29     29   44 my ($S) = @_;
772 29         38 my $c = 'ifthen(';
773              
774 29         31 push @{ $S->{next} }, qw< c) atom >;
  29         49  
775              
776 29 50       34 if (${&Rx} =~ m{ \G (.) }xgcs) {
  29         42  
777 29         55 my $n = "$c$1";
778 29 100       92 return $S->$n if $S->can($n);
779 6         9 &RxPOS--;
780             }
781              
782 6 100       10 if (${&Rx} =~ m{ \G ( [1-9]\d* ) }xgc) {
  6         10  
783 3         6 my $n = $1;
784 3 100       4 $S->error($S->RPe_SWNREC) if ${&Rx} !~ m{ \G \) }xgc;
  3         5  
785 2         3 push @{ $S->{next} }, qw< ifthen|2 ifthen| ifthen_atom >;
  2         5  
786 2         5 return $S->object(groupp => $n);
787             }
788              
789 3         11 $S->error($S->RPe_SWUNKN, &RxCUR);
790 9         59 });
791              
792             # atom inside an ifthen
793             $self->add_handler('ifthen_atom' => sub {
794 73     73   95 my ($S) = @_;
795 73         139 $S->nextchar;
796 73 100       85 ${&Rx} =~ m{ \G ([^|]) }xgcs or return;
  73         102  
797 55         101 my $c = $1;
798              
799 55         64 push @{ $S->{next} }, qw< ifthen_atom >;
  55         87  
800 55 100       148 return $S->$c if $S->can($c);
801 32         58 return $S->object(exact => $c);
802 9         58 });
803              
804             # alternation branch inside ifthen
805             $self->add_handler('ifthen|' => sub {
806 19     19   27 my ($S) = @_;
807 19 100       21 return if ${&Rx} !~ m{ \G \| }xgc;
  19         26  
808 17         27 push @{ $S->{next} }, qw< ifthen_atom >;
  17         23  
809 17         33 return $S->object(branch =>);
810 9         52 });
811              
812             # illegal 2nd alternation branch inside ifthen
813             $self->add_handler('ifthen|2' => sub {
814 19     19   28 my ($S) = @_;
815 19 100       21 return if ${&Rx} !~ m{ \G \| }xgc;
  19         58  
816 1         5 $S->error($S->RPe_SWBRAN);
817 9         49 });
818              
819             $self->add_handler('ifthen(?' => sub {
820 23     23   36 my ($S) = @_;
821 23         27 my $c = '(?';
822              
823 23         28 push @{ $S->{next} }, qw< ifthen|2 ifthen| ifthen_atom >;
  23         53  
824              
825 23 100       28 if (${&Rx} =~ m{ \G ( (?:
  23         31  
826 17         32 my $n = "$c$1";
827 17 50       50 return $S->$n if $S->can($n);
828 0         0 &RxPOS -= length $1;
829             }
830              
831 6         23 $S->error($S->RPe_SEQINC);
832 9         86 });
833             }
834              
835              
836             1;
837              
838             __END__