File Coverage

blib/lib/Regexp/Parser/Handlers.pm
Criterion Covered Total %
statement 582 710 81.9
branch 200 304 65.7
condition 16 24 66.6
subroutine 77 101 76.2
pod 0 1 0.0
total 875 1140 76.7


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 229     229 0 538 my ($self) = @_;
9              
10             # /m, /s, /i, /x flags
11 229     49   1473 $self->add_flag('m' => sub { 0x1 });
  49         174  
12 229     57   1006 $self->add_flag('s' => sub { 0x2 });
  57         148  
13 229     560   1003 $self->add_flag('i' => sub { 0x4 });
  560         1787  
14 229     3560   754 $self->add_flag('x' => sub { 0x8 });
  3560         10817  
15              
16             # /a, /d, /l, /u charset flags (Perl 5.14+)
17             # These are mutually exclusive; the last one set wins.
18 229     2   724 $self->add_flag('a' => sub { 0x10 });
  2         7  
19 229     2   702 $self->add_flag('d' => sub { 0x20 });
  2         6  
20 229     2   768 $self->add_flag('l' => sub { 0x40 });
  2         8  
21 229     5   732 $self->add_flag('u' => sub { 0x80 });
  5         16  
22              
23             # /n (no-capture) flag (Perl 5.22+)
24 229     0   733 $self->add_flag('n' => sub { 0x100 });
  0         0  
25              
26             # (useless) /g, /c, /o flags
27             $self->add_flag('g' => sub {
28 0     0   0 my ($S, $plus) = @_;
29 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "g", $plus ? "" : "don't ", "g");
    0          
30 0         0 return 0x0;
31 229         1021 });
32             $self->add_flag('c' => sub {
33 0     0   0 my ($S, $plus) = @_;
34 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "c", $plus ? "" : "don't ", "gc");
    0          
35 0         0 return 0x0;
36 229         928 });
37             $self->add_flag('o' => sub {
38 0     0   0 my ($S, $plus) = @_;
39 0 0       0 $S->warn($S->RPe_BADFLG, $plus ? "" : "-", "o", $plus ? "" : "don't ", "o");
    0          
40 0         0 return 0x0;
41 229         910 });
42              
43             $self->add_handler('\a' => sub {
44 10     10   19 my ($S, $cc) = @_;
45 10 100       27 return $S->force_object(anyof_char => "\a", '\a') if $cc;
46 4         14 return $S->object(exact => "\a", '\a');
47 229         976 });
48              
49             $self->add_handler('\e' => sub {
50 8     8   21 my ($S, $cc) = @_;
51 8 100       29 return $S->force_object(anyof_char => "\e", '\e') if $cc;
52 4         12 return $S->object(exact => "\e", '\e');
53 229         888 });
54              
55             $self->add_handler('\f' => sub {
56 10     10   19 my ($S, $cc) = @_;
57 10 100       33 return $S->force_object(anyof_char => "\f", '\f') if $cc;
58 4         11 return $S->object(exact => "\f", '\f');
59 229         787 });
60              
61             $self->add_handler('\n' => sub {
62 8     8   34 my ($S, $cc) = @_;
63 8 100       27 return $S->force_object(anyof_char => "\n", '\n') if $cc;
64 4         13 return $S->object(exact => "\n", '\n');
65 229         834 });
66              
67             $self->add_handler('\r' => sub {
68 8     8   15 my ($S, $cc) = @_;
69 8 100       27 return $S->force_object(anyof_char => "\r", '\r') if $cc;
70 4         12 return $S->object(exact => "\r", '\r');
71 229         856 });
72              
73             $self->add_handler('\t' => sub {
74 8     8   18 my ($S, $cc) = @_;
75 8 100       55 return $S->force_object(anyof_char => "\t", '\t') if $cc;
76 4         14 return $S->object(exact => "\t", '\t');
77 229         814 });
78              
79             # bol, mbol, sbol
80             $self->add_handler('^' => sub {
81 22     22   45 my ($S) = @_;
82 22 50       48 my $type =
    100          
83             &Rf & $S->FLAG_m ? 'mbol' :
84             &Rf & $S->FLAG_s ? 'sbol' :
85             'bol';
86 22         64 return $S->object(bol => $type, '^');
87 229         959 });
88              
89             # sbol (beginning of line in single-line mode)
90             $self->add_handler('\A' => sub {
91 8     8   8 my ($S, $cc) = @_;
92 8 50       13 $S->warn($S->RPe_BADESC, "A", " in character class") if $cc;
93 8 50       10 return $S->force_object(anyof_char => 'A') if $cc;
94 8         15 return $S->object(bol => 'sbol' => '\A');
95 229         885 });
96              
97             # nbound (not a word boundary)
98             $self->add_handler('\B' => sub {
99 8     8   11 my ($S, $cc) = @_;
100 8 50       13 $S->warn($S->RPe_BADESC, "B", " in character class") if $cc;
101 8 50       9 return $S->force_object(anyof_char => 'B') if $cc;
102 8         14 return $S->object(bound => nbound => '\B');
103 229         835 });
104              
105             # bound (not a word boundary)
106             $self->add_handler('\b' => sub {
107 14     14   21 my ($S, $cc) = @_;
108 14 100       28 return $S->force_object(anyof_char => "\b", '\b') if $cc;
109 8         12 return $S->object(bound => bound => '\b');
110 229         840 });
111              
112             # cany (any byte)
113             $self->add_handler('\C' => sub {
114 0     0   0 my ($S, $cc) = @_;
115 0 0       0 $S->warn($S->RPe_BADESC, "C", " in character class") if $cc;
116 0 0       0 return $S->force_object(anyof_char => 'C') if $cc;
117 0         0 return $S->object(reg_any => c_any => '\C');
118 229         902 });
119              
120             # control character
121             $self->add_handler('\c' => sub {
122 8     8   19 my ($S, $cc) = @_;
123 8         14 ${&Rx} =~ m{ \G (.?) }xgc;
  8         18  
124 8         20 my $c = $1;
125 8 50       19 return $S->force_object(anyof_char => chr(64 ^ ord $c), "\\c$c") if $cc;
126 8         51 return $S->object(exact => chr(64 ^ ord $c), "\\c$c");
127 229         1107 });
128              
129             # ndigit (not a digit)
130             $self->add_handler('\D' => sub {
131 12     12   22 my ($S, $cc) = @_;
132 12 100       27 return $S->force_object(anyof_class => $S->force_object(digit => 1)) if $cc;
133 8         23 return $S->object(digit => 1);
134 229         863 });
135              
136             # digit (a digit)
137             $self->add_handler('\d' => sub {
138 18     18   61 my ($S, $cc) = @_;
139 18 100       41 return $S->force_object(anyof_class => $S->force_object(digit => 0)) if $cc;
140 14         36 return $S->object(digit => 0);
141 229         859 });
142              
143             # gpos (last global match end)
144             $self->add_handler('\G' => sub {
145 4     4   6 my ($S, $cc) = @_;
146 4 50       6 $S->warn($S->RPe_BADESC, "G", " in character class") if $cc;
147 4 50       8 return $S->force_object(anyof_char => 'G') if $cc;
148 4         5 return $S->object(gpos => gpos => '\G');
149 229         970 });
150              
151             # \g{N}, \g{-N}, \gN backreferences (Perl 5.10+)
152             $self->add_handler('\g' => sub {
153 21     21   43 my ($S, $cc) = @_;
154 21 50       48 if ($cc) {
155 0         0 $S->warn($S->RPe_BADESC, "g", " in character class");
156 0         0 return $S->force_object(anyof_char => 'g');
157             }
158              
159             # \g{...} form
160 21 100       31 if (${&Rx} =~ m{ \G \{ }xgc) {
  21         45  
161             # \g{name} — named backref
162 16 50       25 if (${&Rx} =~ m{ \G ([a-zA-Z_]\w*) \} }xgc) {
  16         32  
163 0         0 my $name = $1;
164 0         0 return $S->object(gref => $name, "\\g{$name}");
165             }
166             # \g{N} or \g{-N} — numeric (possibly relative)
167 16 50       23 if (${&Rx} =~ m{ \G (-?\d+) \} }xgc) {
  16         34  
168 16         40 my $num = $1;
169 16         26 my $abs;
170 16 100       126 if ($num < 0) {
171 8 100       20 $abs = (&SIZE_ONLY ? $S->{maxpar} : $S->{nparen}) + $num + 1;
172 8 100 100     19 $S->error($S->RPe_BGROUP) if !&SIZE_ONLY and $abs < 1;
173             }
174             else {
175 8         11 $abs = $num;
176 8 100 100     21 $S->error($S->RPe_BGROUP) if !&SIZE_ONLY and $abs > $S->{maxpar};
177             }
178 14         59 return $S->object(ref => $abs, "\\g{$num}");
179             }
180 0         0 $S->error($S->RPe_RBRACE, 'g');
181             }
182              
183             # \gN form (no braces, positive only)
184 5 100       9 if (${&Rx} =~ m{ \G (\d+) }xgc) {
  5         13  
185 4         10 my $num = $1;
186 4 50 66     11 $S->error($S->RPe_BGROUP) if !&SIZE_ONLY and $num > $S->{maxpar};
187 4         21 return $S->object(ref => $num, "\\g$num");
188             }
189              
190 1         5 $S->error($S->RPe_BRACES, 'g');
191 229         1155 });
192              
193             # named (named character)
194             $self->add_handler('\N' => sub {
195 6     6   13 my ($S, $cc) = @_;
196 6 50       9 $S->error($S->RPe_BRACES, 'N') if ${&Rx} !~ m{ \G \{ }xgc;
  6         14  
197 6 50       9 $S->error($S->RPe_RBRACE, 'N') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  6         11  
198              
199 6         15 my $name = $1;
200 6 50       69 return $S->force_object(anyof_char => $S->nchar($name), "\\N{$name}") if $cc;
201 6         29 return $S->object(exact => $S->nchar($name), "\\N{$name}");
202 229         1013 });
203              
204             # nprop (not a unicode property)
205             $self->add_handler('\P' => sub {
206 4     4   11 my ($S, $cc) = @_;
207 4 50       6 $S->error($S->RPe_EMPTYB, 'P') if ${&Rx} !~ m{ \G (.) }xgcs;
  4         26  
208              
209 4         11 my $name = $1;
210 4 50       14 if ($name eq '{') {
211 4 50       8 $S->error($S->RPe_RBRACE, 'P') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  4         9  
212 4         9 $name = $1;
213             }
214              
215 4 50       14 return $S->force_object(anyof_class => $S->force_object(prop => $name, 1)) if $cc;
216 4         14 return $S->object(prop => $name, 1);
217 229         966 });
218              
219             # prop (a unicode property)
220             $self->add_handler('\p' => sub {
221 4     4   28 my ($S, $cc) = @_;
222 4 50       7 $S->error($S->RPe_EMPTYB, 'p') if ${&Rx} !~ m{ \G (.) }xgcs;
  4         10  
223              
224 4         12 my $name = $1;
225 4 50       11 if ($name eq '{') {
226 4 50       8 $S->error($S->RPe_RBRACE, 'p') if ${&Rx} !~ m{ \G ([^\}]*) \} }xgc;
  4         10  
227 4         10 $name = $1;
228             }
229              
230 4 50       15 return $S->force_object(anyof_class => $S->force_object(prop => $name, 0)) if $cc;
231 4         14 return $S->object(prop => $name, 0);
232 229         927 });
233              
234             # nspace (not a space)
235             $self->add_handler('\S' => sub {
236 8     8   14 my ($S, $cc) = @_;
237 8 100       20 return $S->force_object(anyof_class => $S->force_object(space => 1)) if $cc;
238 4         14 return $S->object(space => 1);
239 229         830 });
240              
241             # space (a space)
242             $self->add_handler('\s' => sub {
243 16     16   35 my ($S, $cc) = @_;
244 16 100       46 return $S->force_object(anyof_class => $S->force_object(space => 0)) if $cc;
245 12         43 return $S->object(space => 0);
246 229         772 });
247              
248             # nalnum (not a word character)
249             $self->add_handler('\W' => sub {
250 8     8   14 my ($S, $cc) = @_;
251 8 100       20 return $S->force_object(anyof_class => $S->force_object(alnum => 1)) if $cc;
252 4         14 return $S->object(alnum => 1);
253 229         910 });
254              
255             # alnum (a word character)
256             $self->add_handler('\w' => sub {
257 18     18   34 my ($S, $cc) = @_;
258 18 100       51 return $S->force_object(anyof_class => $S->force_object(alnum => 0)) if $cc;
259 10         29 return $S->object(alnum => 0);
260 229         867 });
261              
262             # clump (a unicode clump)
263             $self->add_handler('\X' => sub {
264 4     4   8 my ($S, $cc) = @_;
265 4 50       9 $S->warn($S->RPe_BADESC, 'X', ' in character class') if $cc;
266 4 50       9 return $S->force_object(anyof_char => 'X') if $cc;
267 4         9 return $S->object(clump => '\X');
268 229         878 });
269              
270             # hex character
271             $self->add_handler('\x' => sub {
272 16     16   30 my ($S, $cc) = @_;
273 16         22 ${&Rx} =~ m{ \G ( \{ | .{0,2} ) }sxgc;
  16         34  
274 16         30 my $brace = 0;
275 16         27 my $num = $1;
276              
277 16 100       47 if ($num eq '{') {
278 12 50       15 $S->error($S->RPe_RBRACE, 'x') if ${&Rx} !~ m{ \G ( [^\}]* ) \} }xgc;
  12         21  
279 12         23 $num = $1;
280 12         17 $brace = 1;
281             }
282             else {
283 4   33     35 my $good = ($num =~ s/^([a-fA-F0-9]*)// and $1);
284 4         13 &RxPOS -= length $num;
285 4         11 $num = $good;
286             }
287              
288 16 100       49 my $rep = $brace ? "\\x{$num}" : sprintf("\\x%02s", $num);
289 16 100       56 return $S->force_object(anyof_char => chr hex $num, $rep) if $cc;
290 8         43 return $S->object(exact => chr hex $num, $rep);
291 229         1190 });
292              
293             # eol, seol, meol
294             $self->add_handler('$' => sub {
295 14     14   28 my ($S) = @_;
296 14 50       29 my $type =
    50          
297             &Rf & $S->FLAG_m ? 'meol' :
298             &Rf & $S->FLAG_s ? 'seol' :
299             'eol';
300 14         41 return $S->object(eol => $type, '$');
301 229         865 });
302              
303             # seol (end of line, in single-line mode)
304             $self->add_handler('\Z' => sub {
305 4     4   6 my ($S, $cc) = @_;
306 4 50       10 $S->warn($S->RPe_BADESC, "Z", " in character class") if $cc;
307 4 50       7 return $S->force_object(anyof_char => 'Z') if $cc;
308 4         6 return $S->object(eol => seol => '\Z');
309 229         814 });
310              
311             # eos (end of string)
312             $self->add_handler('\z' => sub {
313 4     4   6 my ($S, $cc) = @_;
314 4 50       5 $S->warn($S->RPe_BADESC, "z", " in character class") if $cc;
315 4 50       8 return $S->force_object(anyof_char => 'z') if $cc;
316 4         6 return $S->object(eol => eos => '\z');
317 229         784 });
318              
319             # alpha POSIX class
320             $self->add_handler('POSIX_alpha' => sub {
321 10     10   32 my ($S, $neg, $how) = @_;
322 10         40 return $S->force_object(anyof_class => alpha => $neg, \$how);
323 229         807 });
324              
325             # alnum POSIX class
326             $self->add_handler('POSIX_alnum' => sub {
327 0     0   0 my ($S, $neg, $how) = @_;
328 0         0 return $S->force_object(anyof_class => alnum => $neg, \$how);
329 229         973 });
330              
331             # ascii POSIX class
332             $self->add_handler('POSIX_ascii' => sub {
333 0     0   0 my ($S, $neg, $how) = @_;
334 0         0 return $S->force_object(anyof_class => ascii => $neg, \$how);
335 229         977 });
336              
337             # cntrl POSIX class
338             $self->add_handler('POSIX_cntrl' => sub {
339 0     0   0 my ($S, $neg, $how) = @_;
340 0         0 return $S->force_object(anyof_class => cntrl => $neg, \$how);
341 229         845 });
342              
343             # digit POSIX class
344             $self->add_handler('POSIX_digit' => sub {
345 4     4   13 my ($S, $neg, $how) = @_;
346 4         17 return $S->force_object(anyof_class => digit => $neg, \$how);
347 229         872 });
348              
349             # graph POSIX class
350             $self->add_handler('POSIX_graph' => sub {
351 0     0   0 my ($S, $neg, $how) = @_;
352 0         0 return $S->force_object(anyof_class => graph => $neg, \$how);
353 229         831 });
354              
355             # lower POSIX class
356             $self->add_handler('POSIX_lower' => sub {
357 0     0   0 my ($S, $neg, $how) = @_;
358 0         0 return $S->force_object(anyof_class => lower => $neg, \$how);
359 229         912 });
360              
361             # print POSIX class
362             $self->add_handler('POSIX_print' => sub {
363 0     0   0 my ($S, $neg, $how) = @_;
364 0         0 return $S->force_object(anyof_class => print => $neg, \$how);
365 229         810 });
366              
367             # punct POSIX class
368             $self->add_handler('POSIX_punct' => sub {
369 0     0   0 my ($S, $neg, $how) = @_;
370 0         0 return $S->force_object(anyof_class => punct => $neg, \$how);
371 229         937 });
372              
373             # space POSIX class
374             $self->add_handler('POSIX_space' => sub {
375 0     0   0 my ($S, $neg, $how) = @_;
376 0         0 return $S->force_object(anyof_class => space => $neg, \$how);
377 229         944 });
378              
379             # upper POSIX class
380             $self->add_handler('POSIX_upper' => sub {
381 0     0   0 my ($S, $neg, $how) = @_;
382 0         0 return $S->force_object(anyof_class => upper => $neg, \$how);
383 229         743 });
384              
385             # word POSIX class
386             $self->add_handler('POSIX_word' => sub {
387 0     0   0 my ($S, $neg, $how) = @_;
388 0         0 return $S->force_object(anyof_class => word => $neg, \$how);
389 229         796 });
390              
391             # xdigit POSIX class
392             $self->add_handler('POSIX_xdigit' => sub {
393 0     0   0 my ($S, $neg, $how) = @_;
394 0         0 return $S->force_object(anyof_class => xdigit => $neg, \$how);
395 229         761 });
396              
397             $self->add_handler('atom' => sub {
398 2820     2820   4494 my ($S) = @_;
399 2820         7121 $S->nextchar;
400              
401 2820 100       3861 ${&Rx} =~ m{ \G (.) }xgcs or return;
  2820         4754  
402 2264         5188 my $c = $1;
403              
404 2264         2910 push @{ $S->{next} }, qw< atom >;
  2264         4306  
405 2264 100       8648 return $S->$c if $S->can($c);
406 925         2076 return $S->object(exact => $c);
407 229         839 });
408              
409             $self->add_handler('*' => sub {
410 42     42   77 my ($S) = @_;
411 42         58 push @{ $S->{next} }, qw< minmod >;
  42         97  
412 42         101 return $S->object(quant => 0, '');
413 229         731 });
414              
415             $self->add_handler('+' => sub {
416 100     100   188 my ($S) = @_;
417 100         139 push @{ $S->{next} }, qw< minmod >;
  100         203  
418 100         253 return $S->object(quant => 1, '');
419 229         797 });
420              
421             $self->add_handler('?' => sub {
422 12     12   19 my ($S) = @_;
423 12         11 push @{ $S->{next} }, qw< minmod >;
  12         21  
424 12         23 return $S->object(quant => 0, 1);
425 229         803 });
426              
427             $self->add_handler('{' => sub {
428 28     28   44 my ($S) = @_;
429 28 50       31 if (${&Rx} =~ m{ \G (\d+) (,?) (\d*) \} }xgc) {
  28         43  
430 28         111 my ($min, $range, $max) = ($1, $2, $3);
431 28 100       59 $max = $min unless $range;
432 28         34 push @{ $S->{next} }, qw< minmod >;
  28         44  
433 28 50 66     97 $S->error($S->RPe_BCURLY) if length($max) and $min > $max;
434 28         65 return $S->object(quant => $min, $max);
435             }
436 0         0 return $S->object(exact => '{');
437 229         920 });
438              
439             $self->add_handler('minmod' => sub {
440 180     180   278 my ($S) = @_;
441 180         408 $S->nextchar;
442 180 100       233 return $S->object(minmod =>) if ${&Rx} =~ m{ \G \? }xgc;
  180         308  
443 156 100       205 return $S->object(possessive =>) if ${&Rx} =~ m{ \G \+ }xgc;
  156         333  
444 140         454 return;
445 229         837 });
446              
447             # alternation branch
448             $self->add_handler('|' => sub {
449 72     72   187 my ($S) = @_;
450 72         232 return $S->object(branch =>);
451 229         776 });
452              
453             # opening parenthesis (maybe capturing paren)
454             $self->add_handler('(' => sub {
455 371     371   737 my ($S) = @_;
456 371         708 my $c = '(';
457 371         1016 $S->nextchar;
458              
459 371 50       556 if (${&Rx} =~ m{ \G (.) }xgcs) {
  371         814  
460 371         1195 my $n = "$c$1";
461 371 100       1533 return $S->$n if $S->can($n);
462 126         284 &RxPOS--;
463             }
464              
465 126         258 push @{ $S->{next} }, qw< c) atom >;
  126         364  
466 126 100       265 &SIZE_ONLY ? ++$S->{maxpar} : ++$S->{nparen};
467 126         220 push @{ $S->{flags} }, &Rf;
  126         278  
468 126         362 return $S->object(open => $S->{nparen});
469 229         1088 });
470              
471             # any character
472             $self->add_handler('.' => sub {
473 18     18   31 my ($S) = @_;
474 18 100       43 my $family =
475             &Rf & $S->FLAG_s ? 'sany' :
476             'reg_any';
477 18         43 return $S->object(reg_any => $family, '.');
478 229         804 });
479              
480             # backslash
481             $self->add_handler('\\' => sub {
482 311     311   569 my ($S, $cc) = @_;
483 311         530 my $c = '\\';
484              
485 311 50       480 if (${&Rx} =~ m{ \G (.) }xgcs) {
  311         530  
486 311         921 $c .= (my $n = $1);
487              
488 311 100       1325 return $S->$c($cc) if $S->can($c);
489              
490 26 100       92 if ($n =~ /\d/) {
491 16         38 --&RxPOS;
492 16         39 my $v = "";
493              
494             # outside of char class, \nnn might be backref
495 16 100 66     33 if (!&SIZE_ONLY and !$cc and $n != 0) {
      66        
496 8         13 $v .= $1 while ${&Rx} =~ m{ \G (\d) }xgc;
  16         34  
497 8 50 33     36 if ($v > 9 and $v > $S->{maxpar}) {
    50          
498 0         0 &RxPOS -= length $v;
499 0         0 $v = "";
500             }
501 0         0 elsif ($v > $S->{maxpar}) { $S->error($S->RPe_BGROUP) }
502 8         33 else { return $S->object(ref => $v, "\\$v") }
503             }
504              
505 8         15 $v .= $1 while ${&Rx} =~ m{ \G ([0-7]) }xgc;
  16         35  
506 8         70 return $S->object(exact => chr oct $v, sprintf("\\%03s", $v));
507             }
508              
509 10 50       20 $S->warn($S->RPe_BADESC, $c = $n, "") if $n =~ /[a-zA-Z]/;
510              
511 10         18 return $S->object(exact => $n, $c);
512             }
513              
514 0         0 $S->error($S->RPe_ESLASH);
515 229         1198 });
516              
517             # start of char class (and possible negation)
518             $self->add_handler('[' => sub {
519 78     78   126 my ($S) = @_;
520 78         101 push @{ $S->{next} }, qw< cce] cc cc] >;
  78         234  
521 78         108 my $neg = ${&Rx} =~ m{ \G \^ }xgc;
  78         141  
522              
523 78         163 my $pos = &RxPOS;
524 78 50       190 if (${&Rx} =~ m{ \G ([:.=]) .*? \1 ] }xgc) {
  78         146  
525 0         0 $S->warn($S->RPe_OUTPOS, $1, $1);
526 0         0 &RxPOS = $pos;
527             }
528              
529 78         223 return $S->object(anyof => $neg);
530 229         982 });
531              
532             # char class ] at beginning
533             $self->add_handler('cc]' => sub {
534 78     78   123 my ($S) = @_;
535 78 50       85 return unless ${&Rx} =~ m{ \G ] }xgc;
  78         137  
536 0         0 return $S->object(anyof_char => "]");
537 229         868 });
538              
539             # start of char class range (or maybe just char)
540             $self->add_handler('cc' => sub {
541 225     225   333 my ($S) = @_;
542 225 100       265 return if ${&Rx} =~ m{ \G (?= ] | \z ) }xgc;
  225         342  
543 147         194 push @{ $S->{next} }, qw< cc >;
  147         272  
544 147         239 my ($lhs, $rhs, $before_range);
545 147         181 my $ret = \$lhs;
546              
547             {
548 147 100       182 if (${&Rx} =~ m{ \G ( \\ ) }xgcs) {
  163 100       218  
  163 50       239  
549 84         174 my $c = $1;
550 84         167 $$ret = $S->$c(1);
551             }
552 79         112 elsif (${&Rx} =~ m{ \G \[ ([.=:]) (\^?) (.*?) \1 \] }xgcs) {
553 14         82 my ($how, $neg, $name) = ($1, $2, $3);
554 14         35 my $posix = "POSIX_$name";
555 14 50       61 if ($S->can($posix)) { $$ret = $S->$posix($neg, $how) }
  14         46  
556 0         0 else { $S->error($S->RPe_BADPOS, "$how$neg$name$how") }
557             }
558 65         122 elsif (${&Rx} =~ m{ \G (.) }xgcs) {
559 65         123 $$ret = $S->force_object(anyof_char => $1);
560             }
561              
562 163 100       360 if ($ret == \$lhs) {
    50          
563 147 100       168 if (${&Rx} =~ m{ \G (?= - (?! ] | \z ) ) }xgc) {
  147         244  
564 16 50       97 if ($lhs->visual =~ /^(?:\[[:.=]|\\[dDsSwWpP])/) {
565 0         0 $S->warn($S->RPe_FRANGE, $lhs->visual, "");
566 0         0 $ret = $lhs;
567 0         0 last;
568             }
569 16         29 $before_range = &RxPOS++;
570 16         24 $ret = \$rhs;
571 16         25 redo;
572             }
573 131         179 $ret = $lhs;
574             }
575             elsif ($ret == \$rhs) {
576 16 50       26 if ($rhs->visual =~ /^(?:\[[:.=]|\\[dDsSwWpP])/) {
    50          
577 0         0 $S->warn($S->RPe_FRANGE, $lhs->visual, $rhs->visual);
578 0         0 &RxPOS = $before_range;
579 0         0 $ret = $lhs;
580             }
581             elsif (ord($lhs->data) > ord($rhs->data)) {
582 0         0 $S->error($S->RPe_IRANGE, $lhs->visual, $rhs->visual);
583             }
584             else {
585 16         30 $ret = $S->object(anyof_range => $lhs, $rhs);
586             }
587             }
588             }
589              
590 147 100       287 return if &SIZE_ONLY;
591 71         159 return $ret;
592 229         1463 });
593              
594             # end of char class
595             $self->add_handler('cce]' => sub {
596 78     78   110 my ($S) = @_;
597 78 100       91 $S->error($S->RPe_LBRACK) if ${&Rx} !~ m{ \G ] }xgc;
  78         206  
598 77         197 return $S->object(anyof_close => "]");
599 229         962 });
600              
601             # closing paren coming from 'atom'
602             $self->add_handler(')' => sub {
603 398     398   750 my ($S) = @_;
604 398         602 pop @{ $S->{next} };
  398         738  
605 398         914 &RxPOS--;
606 398         1662 return;
607 229         863 });
608              
609             # closing paren coming from an opening paren
610             $self->add_handler('c)' => sub {
611 353     353   583 my ($S) = @_;
612 353 100       525 $S->error($S->RPe_LPAREN) if ${&Rx} !~ m{ \G \) }xgc;
  353         728  
613 351         582 pop @{ $S->{flags} };
  351         700  
614 351         947 return $S->object(close =>);
615 229         790 });
616              
617             # some kind of assertion...
618             $self->add_handler('(?' => sub {
619 245     245   423 my ($S) = @_;
620 245         390 my $c = '(?';
621              
622 245 50       370 if (${&Rx} =~ m{ \G (.) }xgcs) {
  245         460  
623 245         562 my $n = "$c$1";
624 245 100       913 return $S->$n if $S->can($n);
625 117         273 &RxPOS--;
626             }
627             else {
628 0         0 $S->error($S->RPe_SEQINC);
629             }
630              
631             # Perl 5.14+ flag reset: (?^...) means default flags
632 117         236 my $caret = 0;
633 117 100       144 if (${&Rx} =~ m{ \G \^ }xgc) {
  117         249  
634 12         13 $caret = 1;
635             }
636              
637             # flag assertion or non-capturing group
638 117         151 ${&Rx} =~ m{ \G ([a-zA-Z]*) (-? [a-zA-Z]*) }xgc;
  117         222  
639 117         406 my ($on, $off) = ($1, $2);
640 117         240 my ($r_on, $r_off) = ("", "");
641 117         198 my ($f_on, $f_off) = (0,0);
642              
643 117         200 &RxPOS -= length($on.$off);
644 117         289 my $old = &RxPOS;
645              
646 117         365 for (split //, $on) {
647 63         97 &RxPOS++;
648 63 50       311 if (my $f = $S->can("FLAG_$_")) {
649 63 50       131 my $v = $S->$f(1) and $r_on .= $_;
650 63         100 $f_on |= $v;
651 63         228 next;
652             }
653 0         0 my $bad = substr ${&Rx}, $old;
  0         0  
654 0         0 $S->error($S->RPe_NOTREC, &RxPOS - $old, $bad);
655             }
656              
657 117 100       254 if (!$caret) {
658 105 100       253 &RxPOS++ if $off =~ s/^-//;
659              
660 105         225 for (split //, $off) {
661 18         28 &RxPOS++;
662 18 50       78 if (my $f = $S->can("FLAG_$_")) {
663 18 50       35 my $v = $S->$f(0) and $r_off .= $_;
664 18         28 $f_off |= $v;
665 18         36 next;
666             }
667 0         0 my $bad = substr ${&Rx}, $old;
  0         0  
668 0         0 $S->error($S->RPe_NOTREC, &RxPOS - $old, $bad);
669             }
670             }
671              
672 117 50       149 if (${&Rx} =~ m{ \G ([:)]) }xgc) {
  117         201  
673 117 100       396 my $type = $1 eq ':' ? 'group' : 'flags';
674 117 100       237 if ($type eq 'group') {
675 96         138 push @{ $S->{flags} }, &Rf;
  96         244  
676 96         143 push @{ $S->{next} }, qw< c) atom >;
  96         229  
677             }
678 117 100       236 if ($caret) {
679 12         17 &Rf = 0; # reset all flags to default
680             }
681 117         217 &Rf |= $f_on;
682 117         353 &Rf &= ~$f_off;
683 117 100       253 my $vis_on = $caret ? "^$r_on" : $r_on;
684 117         303 return $S->object($type => $vis_on, $r_off);
685             }
686              
687 0         0 &RxPOS++;
688 0         0 my $l = length($on.$off) + 2;
689 0         0 $S->error($S->RPe_NOTREC, $l, substr(${&Rx}, $old));
  0         0  
690 229         2081 });
691              
692             # comment
693             $self->add_handler('(?#' => sub {
694 0     0   0 my ($S) = @_;
695 0         0 ${&Rx} =~ m{ \G [^)]* }xgc;
  0         0  
696 0 0       0 $S->error($S->RPe_NOTERM) unless ${&Rx} =~ m{ \G \) }xgc;
  0         0  
697 0         0 return;
698 229         1079 });
699              
700             # not implemented (?$...)
701             $self->add_handler('(?$' => sub {
702 0     0   0 my ($S) = @_;
703 0         0 $S->error($S->RPe_NOTREC, 1, substr(${&Rx}, &RxPOS - 1));
  0         0  
704 229         829 });
705              
706             # not implemented (?@...)
707             $self->add_handler('(?@' => sub {
708 0     0   0 my ($S) = @_;
709 0         0 $S->error($S->RPe_NOTREC, 1, substr(${&Rx}, &RxPOS - 1));
  0         0  
710 229         816 });
711              
712             # look-ahead
713             $self->add_handler('(?=' => sub {
714 21     21   39 my ($S) = @_;
715 21         31 push @{ $S->{next} }, qw< c) atom >;
  21         53  
716 21         29 push @{ $S->{flags} }, &Rf;
  21         46  
717 21         57 return $S->object(ifmatch => 1);
718 229         938 });
719              
720             # look-ahead (neg)
721             $self->add_handler('(?!' => sub {
722 14     14   24 my ($S) = @_;
723 14         19 push @{ $S->{next} }, qw< c) atom >;
  14         37  
724 14         22 push @{ $S->{flags} }, &Rf;
  14         59  
725 14         38 return $S->object(unlessm => 1);
726 229         887 });
727              
728             # look-behind prefix
729             $self->add_handler('(?<' => sub {
730 0     0   0 my ($S) = @_;
731 0         0 my $c = '(?<';
732              
733 0 0       0 if (${&Rx} =~ m{ \G (.) }xgcs) {
  0         0  
734 0         0 my $n = "$c$1";
735 0 0       0 return $S->$n if $S->can($n);
736             }
737              
738 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
739 229         857 });
740              
741             # look-behind
742             $self->add_handler('(?<=' => sub {
743 12     12   26 my ($S) = @_;
744 12         19 push @{ $S->{next} }, qw< c) atom >;
  12         34  
745 12         19 push @{ $S->{flags} }, &Rf;
  12         64  
746 12         47 return $S->object(ifmatch => -1);
747 229         931 });
748              
749             # look-behind (neg)
750             $self->add_handler('(? sub {
751 12     12   23 my ($S) = @_;
752 12         18 push @{ $S->{next} }, qw< c) atom >;
  12         38  
753 12         19 push @{ $S->{flags} }, &Rf;
  12         87  
754 12         35 return $S->object(unlessm => -1);
755 229         852 });
756              
757             # suspend
758             $self->add_handler('(?>' => sub {
759 12     12   20 my ($S) = @_;
760 12         15 push @{ $S->{next} }, qw< c) atom >;
  12         34  
761 12         20 push @{ $S->{flags} }, &Rf;
  12         32  
762 12         34 return $S->object(suspend =>);
763 229         811 });
764              
765             # eval
766             $self->add_handler('(?{' => sub {
767 10     10   25 my ($S) = @_;
768 10 50       19 if (${&Rx} =~ m{ \G ($nest_eval) \} \) }xgc) {
  10         120  
769 10         33 push @{ $S->{flags} }, &Rf;
  10         46  
770 10         40 return $S->object(eval => $1);
771             }
772 0         0 $S->error($S->RPe_NOTBAL);
773 229         1046 });
774              
775             # logical prefix
776             $self->add_handler('(??' => sub {
777 4     4   9 my ($S) = @_;
778 4         9 my $c = '(??';
779              
780 4 50       6 if (${&Rx} =~ m{ \G (.) }xgcs) {
  4         11  
781 4         12 my $n = "$c$1";
782 4 50       20 return $S->$n if $S->can($n);
783             }
784              
785 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
786 229         1103 });
787              
788             # logical
789             $self->add_handler('(??{' => sub {
790 4     4   8 my ($S) = @_;
791 4 50       6 if (${&Rx} =~ m{ \G ($nest_logical) \} \) }xgc) {
  4         10  
792 4         13 push @{ $S->{flags} }, &Rf;
  4         16  
793 4         17 return $S->object(logical => $1);
794             }
795 0         0 $S->error($S->RPe_NOTBAL);
796 229         989 });
797              
798             # logical prefix
799             $self->add_handler('(?p' => sub {
800 0     0   0 my ($S) = @_;
801 0         0 my $c = '(?p';
802              
803 0 0       0 if (${&Rx} =~ m{ \G (.) }xgcs) {
  0         0  
804 0         0 my $n = "$c$1";
805 0 0       0 return $S->$n if $S->can($n);
806             }
807              
808 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
809 229         893 });
810              
811             # logical
812             $self->add_handler('(?p{' => sub {
813 0     0   0 my ($S) = @_;
814 0         0 $S->warn($S->RPe_LOGDEP);
815 0         0 my $c = "(??{";
816 0         0 return $S->$c;
817 229         810 });
818              
819             $self->add_handler('(?(' => sub {
820 62     62   146 my ($S) = @_;
821 62         104 my $c = '(?(';
822              
823 62 50       94 if (${&Rx} =~ m{ \G (.) }xgcs) {
  62         143  
824 62         169 my $n = "$c$1";
825 62 50       292 return $S->$n if $S->can($n);
826 62         168 &RxPOS--;
827             }
828              
829 62         131 push @{ $S->{next} }, qw< ifthen( >;
  62         178  
830 62         146 push @{ $S->{flags} }, &Rf;
  62         147  
831 62         237 return $S->object(ifthen =>);
832 229         846 });
833              
834             # (?(...)t|f) condition
835             $self->add_handler('ifthen(' => sub {
836 62     62   120 my ($S) = @_;
837 62         113 my $c = 'ifthen(';
838              
839 62         89 push @{ $S->{next} }, qw< c) atom >;
  62         167  
840              
841 62 50       122 if (${&Rx} =~ m{ \G (.) }xgcs) {
  62         158  
842 62         186 my $n = "$c$1";
843 62 100       324 return $S->$n if $S->can($n);
844 13         54 &RxPOS--;
845             }
846              
847 13 100       29 if (${&Rx} =~ m{ \G ( [1-9]\d* ) }xgc) {
  13         26  
848 8         21 my $n = $1;
849 8 100       14 $S->error($S->RPe_SWNREC) if ${&Rx} !~ m{ \G \) }xgc;
  8         23  
850 6         12 push @{ $S->{next} }, qw< ifthen|2 ifthen| ifthen_atom >;
  6         54  
851 6         25 return $S->object(groupp => $n);
852             }
853              
854 5         28 $S->error($S->RPe_SWUNKN, &RxCUR);
855 229         912 });
856              
857             # atom inside an ifthen
858             $self->add_handler('ifthen_atom' => sub {
859 169     169   311 my ($S) = @_;
860 169         492 $S->nextchar;
861 169 100       274 ${&Rx} =~ m{ \G ([^|]) }xgcs or return;
  169         365  
862 127         393 my $c = $1;
863              
864 127         191 push @{ $S->{next} }, qw< ifthen_atom >;
  127         306  
865 127 100       593 return $S->$c if $S->can($c);
866 80         227 return $S->object(exact => $c);
867 229         897 });
868              
869             # alternation branch inside ifthen
870             $self->add_handler('ifthen|' => sub {
871 43     43   88 my ($S) = @_;
872 43 100       65 return if ${&Rx} !~ m{ \G \| }xgc;
  43         96  
873 41         87 push @{ $S->{next} }, qw< ifthen_atom >;
  41         95  
874 41         112 return $S->object(branch =>);
875 229         763 });
876              
877             # illegal 2nd alternation branch inside ifthen
878             $self->add_handler('ifthen|2' => sub {
879 43     43   82 my ($S) = @_;
880 43 100       71 return if ${&Rx} !~ m{ \G \| }xgc;
  43         96  
881 1         8 $S->error($S->RPe_SWBRAN);
882 229         835 });
883              
884             $self->add_handler('ifthen(?' => sub {
885 49     49   129 my ($S) = @_;
886 49         90 my $c = '(?';
887              
888 49         71 push @{ $S->{next} }, qw< ifthen|2 ifthen| ifthen_atom >;
  49         176  
889              
890 49 100       79 if (${&Rx} =~ m{ \G ( (?:
  49         105  
891 37         103 my $n = "$c$1";
892 37 50       192 return $S->$n if $S->can($n);
893 0         0 &RxPOS -= length $1;
894             }
895              
896 12         57 $S->error($S->RPe_SEQINC);
897 229         962 });
898              
899             ##
900             ## Perl 5.10+ constructs
901             ##
902              
903             # \K (keep, reset match start)
904             $self->add_handler('\K' => sub {
905 6     6   10 my ($S, $cc) = @_;
906 6 50       10 $S->warn($S->RPe_BADESC, "K", " in character class") if $cc;
907 6 50       12 return $S->force_object(anyof_char => 'K') if $cc;
908 6         14 return $S->object(keep =>);
909 229         817 });
910              
911             # \R (generic linebreak)
912             $self->add_handler('\R' => sub {
913 8     8   16 my ($S, $cc) = @_;
914 8 50       20 $S->warn($S->RPe_BADESC, "R", " in character class") if $cc;
915 8 50       15 return $S->force_object(anyof_char => 'R') if $cc;
916 8         21 return $S->object(lnbreak =>);
917 229         747 });
918              
919             # \h (horizontal whitespace)
920             $self->add_handler('\h' => sub {
921 10     10   16 my ($S, $cc) = @_;
922 10 100       30 return $S->force_object(anyof_class => $S->force_object(hspace => 0)) if $cc;
923 8         21 return $S->object(hspace => 0);
924 229         804 });
925              
926             # \H (not horizontal whitespace)
927             $self->add_handler('\H' => sub {
928 6     6   10 my ($S, $cc) = @_;
929 6 100       14 return $S->force_object(anyof_class => $S->force_object(hspace => 1)) if $cc;
930 4         9 return $S->object(hspace => 1);
931 229         913 });
932              
933             # \v (vertical whitespace)
934             $self->add_handler('\v' => sub {
935 6     6   11 my ($S, $cc) = @_;
936 6 100       15 return $S->force_object(anyof_class => $S->force_object(vspace => 0)) if $cc;
937 4         8 return $S->object(vspace => 0);
938 229         768 });
939              
940             # \V (not vertical whitespace)
941             $self->add_handler('\V' => sub {
942 4     4   7 my ($S, $cc) = @_;
943 4 50       8 return $S->force_object(anyof_class => $S->force_object(vspace => 1)) if $cc;
944 4         8 return $S->object(vspace => 1);
945 229         819 });
946              
947             # \k or \k'name' (named backreference)
948             $self->add_handler('\k' => sub {
949 8     8   14 my ($S, $cc) = @_;
950              
951 8 50       17 if ($cc) {
952 0         0 $S->warn($S->RPe_BADESC, "k", " in character class");
953 0         0 return $S->force_object(anyof_char => 'k');
954             }
955              
956 8 100       9 if (${&Rx} =~ m{ \G < ([^>]+) > }xgc) {
  8 50       32  
957 6         23 return $S->object(named_ref => $1, "\\k<$1>");
958             }
959 2         5 elsif (${&Rx} =~ m{ \G ' ([^']+) ' }xgc) {
960 2         8 return $S->object(named_ref => $1, "\\k'$1'");
961             }
962              
963 0         0 $S->error($S->RPe_BADESC, "k", "");
964 229         917 });
965              
966             # (?...) named capture group
967             # We override the existing '(?<' handler to also support named captures
968             $self->add_handler('(?<' => sub {
969 30     30   44 my ($S) = @_;
970 30         33 my $c = '(?<';
971              
972             # Check for lookbehind first: (?<= and (?
973 30 100       30 if (${&Rx} =~ m{ \G ([!=]) }xgcs) {
  30         42  
974 12         21 my $n = "$c$1";
975 12 50       37 return $S->$n if $S->can($n);
976             }
977              
978             # Named capture: (?...)
979 18 50       20 if (${&Rx} =~ m{ \G ([A-Za-z_]\w*) > }xgc) {
  18         25  
980 18         24 my $name = $1;
981 18         20 push @{ $S->{next} }, qw< c) atom >;
  18         39  
982 18 100       29 &SIZE_ONLY ? ++$S->{maxpar} : ++$S->{nparen};
983 18         20 push @{ $S->{flags} }, &Rf;
  18         29  
984 18 100       52 $S->{named_captures}{$name} = $S->{nparen} unless &SIZE_ONLY;
985 18         38 return $S->object(named_open => $S->{nparen}, $name);
986             }
987              
988 0         0 $S->error($S->RPe_NOTREC, 2, substr(${&Rx}, &RxPOS - 2));
  0         0  
989 229         1000 });
990              
991             # (?'name'...) alternate named capture syntax
992             $self->add_handler("(?\'" => sub {
993 0     0   0 my ($S) = @_;
994              
995 0 0       0 if (${&Rx} =~ m{ \G ([A-Za-z_]\w*) ' }xgc) {
  0         0  
996 0         0 my $name = $1;
997 0         0 push @{ $S->{next} }, qw< c) atom >;
  0         0  
998 0 0       0 &SIZE_ONLY ? ++$S->{maxpar} : ++$S->{nparen};
999 0         0 push @{ $S->{flags} }, &Rf;
  0         0  
1000 0 0       0 $S->{named_captures}{$name} = $S->{nparen} unless &SIZE_ONLY;
1001 0         0 return $S->object(named_open => $S->{nparen}, $name);
1002             }
1003              
1004 0         0 $S->error($S->RPe_NOTREC, 1, substr(${&Rx}, &RxPOS - 1));
  0         0  
1005 229         952 });
1006              
1007             # possessive quantifier modifier (a++, a*+, a?+, a{n,m}+)
1008             $self->add_handler('posmod' => sub {
1009 0     0     my ($S) = @_;
1010 0           $S->nextchar;
1011 0 0         return $S->object(possessive =>) if ${&Rx} =~ m{ \G \+ }xgc;
  0            
1012 0           return;
1013 229         767 });
1014             }
1015              
1016              
1017             1;
1018              
1019             __END__