File Coverage

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