File Coverage

blib/lib/Regexp/Parser/Handlers.pm
Criterion Covered Total %
statement 706 843 83.7
branch 253 368 68.7
condition 26 36 72.2
subroutine 86 110 78.1
pod 0 1 0.0
total 1071 1358 78.8


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