File Coverage

blib/lib/PPIx/Regexp/Tokenizer.pm
Criterion Covered Total %
statement 497 525 94.6
branch 177 238 74.3
condition 44 64 68.7
subroutine 86 90 95.5
pod 29 29 100.0
total 833 946 88.0


line stmt bran cond sub pod time code
1             package PPIx::Regexp::Tokenizer;
2              
3 9     9   51 use strict;
  9         10  
  9         252  
4 9     9   29 use warnings;
  9         11  
  9         347  
5              
6 9     9   31 use base qw{ PPIx::Regexp::Support };
  9         10  
  9         2173  
7              
8 9     9   40 use Carp qw{ carp croak confess };
  9         12  
  9         495  
9 9     9   2309 use PPI::Document;
  9         771711  
  9         397  
10 9         1230 use PPIx::Regexp::Constant qw{
11             ARRAY_REF
12             CODE_REF
13             HASH_REF
14             LOCATION_LINE
15             LOCATION_CHARACTER
16             LOCATION_COLUMN
17             LOCATION_LOGICAL_LINE
18             MINIMUM_PERL
19             REGEXP_REF
20             TOKEN_LITERAL
21             TOKEN_UNKNOWN
22             @CARP_NOT
23 9     9   59 };
  9         13  
24 9     9   3739 use PPIx::Regexp::Token::Assertion ();
  9         24  
  9         183  
25 9     9   3653 use PPIx::Regexp::Token::Backreference ();
  9         26  
  9         230  
26 9     9   3205 use PPIx::Regexp::Token::Backtrack ();
  9         24  
  9         181  
27 9     9   3356 use PPIx::Regexp::Token::CharClass::POSIX ();
  9         23  
  9         204  
28 9     9   3477 use PPIx::Regexp::Token::CharClass::POSIX::Unknown ();
  9         26  
  9         171  
29 9     9   4081 use PPIx::Regexp::Token::CharClass::Simple ();
  9         25  
  9         199  
30 9     9   3442 use PPIx::Regexp::Token::Code ();
  9         24  
  9         176  
31 9     9   3654 use PPIx::Regexp::Token::Comment ();
  9         22  
  9         169  
32 9     9   3431 use PPIx::Regexp::Token::Condition ();
  9         25  
  9         227  
33 9     9   3206 use PPIx::Regexp::Token::Control ();
  9         22  
  9         229  
34 9     9   3100 use PPIx::Regexp::Token::Delimiter ();
  9         26  
  9         190  
35 9     9   3047 use PPIx::Regexp::Token::Greediness ();
  9         22  
  9         159  
36 9     9   3342 use PPIx::Regexp::Token::GroupType::Assertion ();
  9         25  
  9         228  
37 9     9   3557 use PPIx::Regexp::Token::GroupType::Atomic_Script_Run ();
  9         24  
  9         195  
38 9     9   3401 use PPIx::Regexp::Token::GroupType::BranchReset ();
  9         23  
  9         182  
39 9     9   3511 use PPIx::Regexp::Token::GroupType::Code ();
  9         23  
  9         242  
40 9     9   3580 use PPIx::Regexp::Token::GroupType::Modifier ();
  9         25  
  9         219  
41 9     9   3190 use PPIx::Regexp::Token::GroupType::NamedCapture ();
  9         24  
  9         173  
42 9     9   3290 use PPIx::Regexp::Token::GroupType::Script_Run ();
  9         22  
  9         197  
43 9     9   3398 use PPIx::Regexp::Token::GroupType::Subexpression ();
  9         23  
  9         161  
44 9     9   3401 use PPIx::Regexp::Token::GroupType::Switch ();
  9         23  
  9         189  
45 9     9   3716 use PPIx::Regexp::Token::Interpolation ();
  9         23  
  9         182  
46 9     9   8490 use PPIx::Regexp::Token::Literal ();
  9         28  
  9         230  
47 9     9   50 use PPIx::Regexp::Token::Modifier ();
  9         11  
  9         93  
48 9     9   5257 use PPIx::Regexp::Token::Operator ();
  9         25  
  9         170  
49 9     9   3582 use PPIx::Regexp::Token::Quantifier ();
  9         21  
  9         171  
50 9     9   43 use PPIx::Regexp::Token::Recursion ();
  9         13  
  9         87  
51 9     9   27 use PPIx::Regexp::Token::Structure ();
  9         9  
  9         76  
52 9     9   3500 use PPIx::Regexp::Token::Unknown ();
  9         32  
  9         146  
53 9     9   3478 use PPIx::Regexp::Token::Whitespace ();
  9         23  
  9         220  
54 9         473 use PPIx::Regexp::Util qw{
55             is_ppi_regexp_element
56             __instance
57 9     9   56 };
  9         13  
58              
59 9     9   38 use Scalar::Util qw{ looks_like_number };
  9         12  
  9         48880  
60              
61             our $VERSION = '0.092';
62              
63             our $DEFAULT_POSTDEREF;
64             defined $DEFAULT_POSTDEREF
65             or $DEFAULT_POSTDEREF = 1;
66              
67             {
68             # Names of classes containing tokenization machinery. There are few
69             # known ordering requirements, since each class recognizes its own,
70             # and I have tried to prevent overlap. Absent such constraints, the
71             # order is in perceived frequency of acceptance, to keep the search
72             # as short as possible. If I were conscientious I would gather
73             # statistics on this.
74             my @classes = ( # TODO make readonly when acceptable way appears
75             'PPIx::Regexp::Token::Literal',
76             'PPIx::Regexp::Token::Interpolation',
77             'PPIx::Regexp::Token::Control', # Note 1
78             'PPIx::Regexp::Token::CharClass::Simple', # Note 2
79             'PPIx::Regexp::Token::Quantifier',
80             'PPIx::Regexp::Token::Greediness',
81             'PPIx::Regexp::Token::CharClass::POSIX', # Note 3
82             'PPIx::Regexp::Token::Structure',
83             'PPIx::Regexp::Token::Assertion',
84             'PPIx::Regexp::Token::Backreference',
85             'PPIx::Regexp::Token::Operator', # Note 4
86             );
87              
88             # Note 1: If we are in quote mode ( \Q ... \E ), Control makes a
89             # literal out of anything it sees other than \E. So it
90             # needs to come before almost all other tokenizers. Not
91             # Literal, which already makes literals, and not
92             # Interpolation, which is legal in quote mode, but
93             # everything else.
94              
95             # Note 2: CharClass::Simple must come after Literal, because it
96             # relies on Literal to recognize a Unicode named character
97             # ( \N{something} ), so any \N that comes through to it
98             # must be the \N simple character class (which represents
99             # anything but a newline, and was introduced in Perl
100             # 5.11.0.
101              
102             # Note 3: CharClass::POSIX has to come before Structure, since both
103             # look for square brackets, and CharClass::POSIX is the
104             # more particular.
105              
106             # Note 4: Operator relies on Literal making the characters literal
107             # if they appear in a context where they can not be
108             # operators, and Control making them literals if quoting,
109             # so it must come after both.
110              
111             # Return the declared tokenizer classes.
112             sub __tokenizer_classes {
113 543     543   1699 return @classes;
114             }
115              
116             }
117              
118             {
119             my $errstr;
120              
121             sub new {
122 742     742 1 399726 my ( $class, $re, %args ) = @_;
123 742 50       1668 ref $class and $class = ref $class;
124              
125 742         1155 $errstr = undef;
126              
127             exists $args{default_modifiers}
128             and ARRAY_REF ne ref $args{default_modifiers}
129 742 50 66     2066 and do {
130 0         0 $errstr = 'default_modifiers must be an array reference';
131 0         0 return;
132             };
133              
134             my $self = {
135             index_locations => $args{index_locations}, # Index locations
136             capture => undef, # Captures from find_regexp.
137             content => undef, # The string we are tokenizing.
138             cookie => {}, # Cookies
139             cursor_curr => 0, # The current position in the string.
140             cursor_limit => undef, # The end of the portion of the
141             # string being tokenized.
142             cursor_orig => undef, # Position of cursor when tokenizer
143             # called. Used by get_token to prevent
144             # recursion.
145             cursor_modifiers => undef, # Position of modifiers.
146             default_modifiers => $args{default_modifiers} || [],
147             delimiter_finish => undef, # Finishing delimiter of regexp.
148             delimiter_start => undef, # Starting delimiter of regexp.
149             encoding => $args{encoding}, # Character encoding.
150             expect => undef, # Extra classes to expect.
151             expect_next => undef, # Extra classes as of next parse cycle
152             failures => 0, # Number of parse failures.
153             find => undef, # String for find_regexp
154             known => {}, # Known tokenizers, by mode.
155             location => $args{location},
156             match => undef, # Match from find_regexp.
157             mode => 'init', # Initialize
158             modifiers => [{}], # Modifier hash.
159             pending => [], # Tokens made but not returned.
160             prior => TOKEN_UNKNOWN, # Prior significant token.
161             source => $re, # The object we were initialized with.
162             strict => $args{strict}, # like "use re 'strict';".
163             trace => __PACKAGE__->__defined_or(
164 742   100     8047 $args{trace}, $ENV{PPIX_REGEXP_TOKENIZER_TRACE}, 0 ),
165             };
166              
167 742 100       2648 if ( __instance( $re, 'PPI::Element' ) ) {
    100          
168 11 50       28 is_ppi_regexp_element( $re )
169             or return __set_errstr( ref $re, 'not supported by', $class );
170             # TODO conditionalizstion on PPI class does not really
171             # belong here, but at the moment I have no other idea of
172             # where to put it.
173 11 50       69 $self->{content} = $re->isa( 'PPI::Token::HereDoc' ) ?
174             join( '', $re->content(), "\n", $re->heredoc(),
175             $re->terminator(), "\n" ) :
176             $re->content();
177             } elsif ( ref $re ) {
178 2         5 return __set_errstr( ref $re, 'not supported' );
179             } else {
180 729         1393 $self->{content} = $re;
181             }
182              
183 740         1417 bless $self, $class;
184              
185 740         2169 $self->{content} = $self->decode( $self->{content} );
186              
187 740         1480 $self->{cursor_limit} = length $self->{content};
188              
189             $self->{trace}
190 740 50       1609 and warn "\ntokenizing '$self->{content}'\n";
191              
192 740         2044 return $self;
193             }
194              
195             sub __set_errstr {
196 2     2   7 $errstr = join ' ', @_;
197 2         11 return;
198             }
199              
200             sub errstr {
201 2     2 1 4 return $errstr;
202             }
203              
204             }
205              
206             sub capture {
207 715     715 1 1269 my ( $self ) = @_;
208 715 100       1321 $self->{capture} or return;
209 694 50       1237 defined wantarray or return;
210 694 50       1014 return wantarray ? @{ $self->{capture} } : $self->{capture};
  694         2467  
211             }
212              
213             sub content {
214 1     1 1 2 my ( $self ) = @_;
215 1         4 return $self->{content};
216             }
217              
218             sub cookie {
219 10182     10182 1 13568 my ( $self, $name, @args ) = @_;
220 10182 50       12869 defined $name
221             or confess "Programming error - undefined cookie name";
222 10182 50       13584 if ( $self->{trace} ) {
223 0         0 local $" = ', ';
224 0         0 warn "cookie( '$name', @args )\n";
225             }
226 10182 100       24069 @args or return $self->{cookie}{$name};
227 721         1010 my $cookie = shift @args;
228 721 100       2191 if ( CODE_REF eq ref $cookie ) {
    50          
229 593         1873 return ( $self->{cookie}{$name} = $cookie );
230             } elsif ( defined $cookie ) {
231 0         0 confess "Programming error - cookie must be CODE ref or undef";
232             } else {
233 128         330 return delete $self->{cookie}{$name};
234             }
235             }
236              
237             # NOTE: Currently this is called only against
238             # COOKIE_LOOKAROUND_ASSERTION, once in PPIx::Token::GroupType::Assertion
239             # to prevent the cookie from being remade if it already exists, and once
240             # in PPIx::Regexp::Token::Assertion to determine if \K is inside a
241             # lookaround assertion. If it gets used other places, or if there is
242             # call for it, I should consider removing the underscores and
243             # documenting it as public.
244             sub __cookie_exists {
245 57     57   101 my ( $self, $name ) = @_;
246 57 50       116 defined $name
247             or confess "Programming error - undefined cookie name";
248 57         186 return $self->{cookie}{$name};
249             }
250              
251             sub default_modifiers {
252 0     0 1 0 my ( $self ) = @_;
253 0         0 return [ @{ $self->{default_modifiers} } ];
  0         0  
254             }
255              
256             sub __effective_modifiers {
257 334     334   515 my ( $self ) = @_;
258             HASH_REF eq ref $self->{effective_modifiers}
259 334 100       864 or return {};
260 326         394 return { %{ $self->{effective_modifiers} } };
  326         958  
261             }
262              
263             sub encoding {
264 0     0 1 0 my ( $self ) = @_;
265 0         0 return $self->{encoding};
266             }
267              
268             sub expect {
269 330     330 1 832 my ( $self, @args ) = @_;
270              
271             @args
272 330 50       548 or return;
273              
274             $self->{expect_next} = [
275 330 50       514 map { m/ \A PPIx::Regexp:: /smx ? $_ : 'PPIx::Regexp::' . $_ }
  2602         5031  
276             @args
277             ];
278 330         669 $self->{expect} = undef;
279 330         620 return;
280             }
281              
282             sub failures {
283 8     8 1 17 my ( $self ) = @_;
284 8         15 return $self->{failures};
285             }
286              
287             sub find_matching_delimiter {
288 589     589 1 864 my ( $self ) = @_;
289 589   100     1728 $self->{cursor_curr} ||= 0;
290             my $start = substr
291             $self->{content},
292             $self->{cursor_curr},
293 589         1127 1;
294              
295 589         727 my $inx = $self->{cursor_curr};
296 589   66     1632 my $finish = (
297             my $bracketed = $self->close_bracket( $start ) ) || $start;
298              
299             =begin comment
300              
301             $self->{trace}
302             and warn "Find matching delimiter: Start with '$start' at $self->{cursor_curr}, end with '$finish' at or before $self->{cursor_limit}\n";
303              
304             =end comment
305              
306             =cut
307              
308 589         773 my $nest = 0;
309              
310 589         1291 while ( ++$inx < $self->{cursor_limit} ) {
311 6144         6809 my $char = substr $self->{content}, $inx, 1;
312              
313             =begin comment
314              
315             $self->{trace}
316             and warn " looking at '$char' at $inx, nest level $nest\n";
317              
318             =end comment
319              
320             =cut
321              
322 6144 100 100     15423 if ( $char eq '\\' && $finish ne '\\' ) {
    100 100        
    100          
323 317         514 ++$inx;
324             } elsif ( $bracketed && $char eq $start ) {
325 1         2 ++$nest;
326             } elsif ( $char eq $finish ) {
327             --$nest < 0
328 588 100       1998 and return $inx - $self->{cursor_curr};
329             }
330             }
331              
332 2         6 return;
333             }
334              
335             sub find_regexp {
336 16627     16627 1 20502 my ( $self, $regexp ) = @_;
337              
338 16627 50 0     24229 REGEXP_REF eq ref $regexp
339             or confess
340             'Argument is a ', ( ref $regexp || 'scalar' ), ' not a Regexp';
341              
342 16627 100       26189 defined $self->{find} or $self->_remainder();
343              
344 16627 100       62277 $self->{find} =~ $regexp
345             or return;
346              
347 1848         2211 my @capture;
348 1848         4913 foreach my $inx ( 0 .. $#+ ) {
349 4267 100 66     12874 if ( defined $-[$inx] && defined $+[$inx] ) {
350             push @capture, $self->{capture} = substr
351             $self->{find},
352 3778         15164 $-[$inx],
353             $+[$inx] - $-[$inx];
354             } else {
355 489         747 push @capture, undef;
356             }
357             }
358 1848         2992 $self->{match} = shift @capture;
359 1848         2738 $self->{capture} = \@capture;
360              
361             # The following circumlocution seems to be needed under Perl 5.13.0
362             # for reasons I do not fathom -- at least in the case where
363             # wantarray is false. RT 56864 details the symptoms, which I was
364             # never able to reproduce outside Perl::Critic. But returning $+[0]
365             # directly, the value could transmogrify between here and the
366             # calling module.
367             ## my @data = ( $-[0], $+[0] );
368             ## return wantarray ? @data : $data[1];
369 1848 50       6562 return wantarray ? ( $-[0] + 0, $+[0] + 0 ) : $+[0] + 0;
370             }
371              
372             sub get_mode {
373 2598     2598 1 2984 my ( $self ) = @_;
374 2598         4627 return $self->{mode};
375             }
376              
377             sub get_start_delimiter {
378 1794     1794 1 2008 my ( $self ) = @_;
379 1794         4597 return $self->{delimiter_start};
380             }
381              
382             sub get_token {
383 4133     4133 1 4965 my ( $self ) = @_;
384              
385             caller eq __PACKAGE__ or $self->{cursor_curr} > $self->{cursor_orig}
386 4133 50 66     9613 or confess 'Programming error - get_token() called without ',
387             'first calling make_token()';
388              
389 4133         5855 my $handler = '__PPIX_TOKENIZER__' . $self->{mode};
390              
391             my $code = $self->can( $handler )
392             or confess 'Programming error - ',
393             "Getting token in mode '$self->{mode}'. ",
394             "cursor_curr = $self->{cursor_curr}; ",
395             "cursor_limit = $self->{cursor_limit}; ",
396             "length( content ) = ", length $self->{content},
397 4133 50       13088 "; content = '$self->{content}'";
398              
399             my $character = substr(
400             $self->{content},
401             $self->{cursor_curr},
402 4133         7924 1
403             );
404              
405             $self->{trace}
406 4133 50       6527 and warn "get_token() got '$character' from $self->{cursor_curr}\n";
407              
408 4133         6788 return ( $code->( $self, $character ) );
409             }
410              
411             sub interpolates {
412 141     141 1 204 my ( $self ) = @_;
413 141         448 return $self->{delimiter_start} ne q{'};
414             }
415              
416             sub make_token {
417 5243     5243 1 8409 my ( $self, $length, $class, $arg ) = @_;
418 5243 100       7528 defined $class or $class = caller;
419              
420 5243 50       9507 if ( $length + $self->{cursor_curr} > $self->{cursor_limit} ) {
421             $length = $self->{cursor_limit} - $self->{cursor_curr}
422 0 0       0 or return;
423             }
424              
425 5243 50       11701 $class =~ m/ \A PPIx::Regexp:: /smx
426             or $class = 'PPIx::Regexp::' . $class;
427             my $content = substr
428             $self->{content},
429             $self->{cursor_curr},
430 5243         8596 $length;
431              
432             $self->{trace}
433 5243 50       7672 and warn "make_token( $length, '$class' ) => '$content'\n";
434 5243 50       7654 $self->{trace} > 1
435             and warn " make_token: cursor_curr = $self->{cursor_curr}; ",
436             "cursor_limit = $self->{cursor_limit}\n";
437             my $token = $class->__new( $content,
438             tokenizer => $self,
439 5243 100       5979 %{ $arg || {} } )
  5243 50       22370  
440             or return;
441              
442             $self->{index_locations}
443 5243 100       10676 and $self->_update_location( $token );
444              
445             $token->significant()
446 5243 100       11100 and $self->{expect} = undef;
447              
448 5243 100       17835 $token->isa( TOKEN_UNKNOWN ) and $self->{failures}++;
449              
450 5243         6482 $self->{cursor_curr} += $length;
451 5243         6131 $self->{find} = undef;
452 5243         6139 $self->{match} = undef;
453 5243         5680 $self->{capture} = undef;
454              
455 5243         6273 foreach my $name ( keys %{ $self->{cookie} } ) {
  5243         9734  
456 3615         4394 my $cookie = $self->{cookie}{$name};
457             $cookie->( $self, $token )
458 3615 100       6416 or delete $self->{cookie}{$name};
459             }
460              
461             # Record this token as the prior token if it is significant. We must
462             # do this after processing cookies, so that the cookies have access
463             # to the old token if they want.
464             $token->significant()
465 5243 100       8653 and $self->{prior_significant_token} = $token;
466              
467 5243         14417 return $token;
468             }
469              
470             sub match {
471 86     86 1 133 my ( $self ) = @_;
472 86         162 return $self->{match};
473             }
474              
475             sub modifier {
476 4932     4932 1 6073 my ( $self, $modifier ) = @_;
477             return PPIx::Regexp::Token::Modifier::__asserts(
478 4932         9322 $self->{modifiers}[-1], $modifier );
479             }
480              
481             sub modifier_duplicate {
482 292     292 1 447 my ( $self ) = @_;
483 292         486 push @{ $self->{modifiers} },
484 292         312 { %{ $self->{modifiers}[-1] } };
  292         803  
485 292         467 return;
486             }
487              
488             sub modifier_modify {
489 595     595 1 1078 my ( $self, %args ) = @_;
490              
491             # Modifier code is centralized in PPIx::Regexp::Token::Modifier
492             $self->{modifiers}[-1] =
493             PPIx::Regexp::Token::Modifier::__PPIX_TOKENIZER__modifier_modify(
494 595         1553 $self->{modifiers}[-1], \%args );
495              
496 595         1013 return;
497              
498             }
499              
500             sub modifier_pop {
501 288     288 1 498 my ( $self ) = @_;
502 288         659 @{ $self->{modifiers} } > 1
503 288 100       353 and pop @{ $self->{modifiers} };
  282         483  
504 288         611 return;
505             }
506              
507             sub modifier_seen {
508 8     8 1 18 my ( $self, $modifier ) = @_;
509 8         11 foreach my $mod ( reverse @{ $self->{modifiers} } ) {
  8         17  
510 10 100       35 exists $mod->{$modifier}
511             and return 1;
512             }
513 5         18 return;
514             }
515              
516             sub next_token {
517 5780     5780 1 6922 my ( $self ) = @_;
518              
519             {
520              
521 5780 100       5715 if ( @{ $self->{pending} } ) {
  9896         9185  
  9896         14215  
522 5241         5231 return shift @{ $self->{pending} };
  5241         13068  
523             }
524              
525 4655 100       8054 if ( $self->{cursor_curr} >= $self->{cursor_limit} ) {
526             $self->{cursor_limit} >= length $self->{content}
527 1099 100       3040 and return;
528 560 50       1213 $self->{mode} eq 'finish' and return;
529 560         1436 $self->_set_mode( 'finish' );
530 560         929 $self->{cursor_limit} += length $self->{delimiter_finish};
531             }
532              
533 4116 50       6915 if ( my @tokens = $self->get_token() ) {
534 4116         4721 push @{ $self->{pending} }, @tokens;
  4116         6324  
535 4116         5952 redo;
536              
537             }
538              
539             }
540              
541 0         0 return;
542              
543             }
544              
545             sub peek {
546 379     379 1 532 my ( $self, $offset ) = @_;
547 379 100       621 defined $offset or $offset = 0;
548 379 50       619 $offset < 0 and return;
549 379         495 $offset += $self->{cursor_curr};
550 379 50       618 $offset >= $self->{cursor_limit} and return;
551 379         1139 return substr $self->{content}, $offset, 1;
552             }
553              
554             sub ppi_document {
555 83     83 1 116 my ( $self ) = @_;
556              
557 83 50       171 defined $self->{find} or $self->_remainder();
558              
559 83         449 return PPI::Document->new( \"$self->{find}" );
560             }
561              
562             sub prior_significant_token {
563 2413     2413 1 3078 my ( $self, $method, @args ) = @_;
564 2413 100       3154 defined $method or return $self->{prior_significant_token};
565             $self->{prior_significant_token}->can( $method )
566             or confess 'Programming error - ',
567             ( ref $self->{prior_significant_token} ||
568 2394 50 0     6350 $self->{prior_significant_token} ),
569             ' does not support method ', $method;
570 2394         5499 return $self->{prior_significant_token}->$method( @args );
571             }
572              
573             # my $length = $token->__recognize_postderef( $tokenizer, $iterator ).
574             #
575             # This method is private to the PPIx-Regexp package, and may be changed
576             # or retracted without warning. What it does is to recognize postfix
577             # dereferences. It returns the length in characters of the first postfix
578             # dereference found, or a false value if none is found.
579             #
580             # The optional $iterator argument can be one of the following:
581             # - A code reference, which will be called to provide PPI::Element
582             # objects to be checked to see if they represent a postfix
583             # dereference.
584             # - A PPI::Element, which is checked to see if it is a postfix
585             # dereference.
586             # - Undef, or omitted, in which case ppi() is called on the invocant,
587             # and everything that follows the '->' operator is checked to see if
588             # it is a postfix dereference.
589             # - Anything else results in an exception and stack trace.
590              
591             {
592             sub __recognize_postderef {
593 149     149   241 my ( $self, $token, $iterator ) = @_;
594              
595             # Note that if ppi() gets called I have to hold a reference to
596             # the returned object until I am done with all its children.
597 149         177 my $ppi;
598 149 100       252 if ( ! defined $iterator ) {
    50          
    0          
599              
600             # This MUST be done before ppi() is called.
601             $self->{index_locations}
602 145 100       276 and $self->_update_location( $token );
603              
604 145         336 $ppi = $token->ppi();
605 29         6027 my @ops = grep { '->' eq $_->content() } @{
606 145 100       260 $ppi->find( 'PPI::Token::Operator' ) || [] };
  145         405  
607             $iterator = sub {
608 151 100   151   504 my $op = shift @ops
609             or return;
610 15         56 return $op->snext_sibling();
611 145         29755 };
612             } elsif ( $iterator->isa( 'PPI::Element' ) ) {
613 4         9 my @eles = ( $iterator );
614             $iterator = sub {
615 4     4   13 return shift @eles;
616 4         12 };
617             } elsif ( CODE_REF ne ref $iterator ) {
618 0         0 confess 'Programming error - Iterator not understood';
619             }
620              
621 149         672 my $accept = $token->__postderef_accept_cast();
622              
623 149         256 while ( my $elem = $iterator->() ) {
624              
625 19         472 my $content = $elem->content();
626              
627             # As of PPI 1.238, all postfix dereferences are parsed as
628             # casts. So if we find a cast of the correct content we have
629             # a postfix deref.
630 19 100       131 $elem->isa( 'PPI::Token::Cast' )
631             or next;
632              
633 15 100       66 if ( $content =~ m/ ( .* ) \* \z /smx ) {
    50          
634             # If we're an acceptable cast ending in a glob, accept
635             # it.
636 10 100       82 $accept->{$1}
637             and return length $content;
638             } elsif ( $accept->{$content} ) {
639             # If we're an acceptable cast followed by a subscript,
640             # we're a slice -- accept both cast and subscript.
641 5 50       20 my $next = $elem->snext_sibling()
642             or next;
643 5 50       90 $next->isa( 'PPI::Structure::Subscript' )
644             or next;
645 5         17 return length( $content ) + length( $next->content() );
646             }
647              
648             # Otherwise, we're not a postfix dereference; try the next
649             # iteration.
650             }
651              
652             # No postfix dereference found.
653 136         582 return;
654             }
655             }
656              
657             sub significant {
658 0     0 1 0 return 1;
659             }
660              
661             sub strict {
662 4     4 1 6 my ( $self ) = @_;
663 4         21 return $self->{strict};
664             }
665              
666             sub _known_tokenizers {
667 3036     3036   3904 my ( $self ) = @_;
668              
669 3036         3740 my $mode = $self->{mode};
670              
671 3036         2976 my @expect;
672 3036 100       4697 if ( $self->{expect_next} ) {
673 328         598 $self->{expect} = $self->{expect_next};
674 328         440 $self->{expect_next} = undef;
675             }
676 3036 100       4562 if ( $self->{expect} ) {
677             @expect = $self->_known_tokenizer_check(
678 334         416 @{ $self->{expect} } );
  334         661  
679             }
680              
681             exists $self->{known}{$mode} and return (
682 3036 100       5797 @expect, @{ $self->{known}{$mode} } );
  2493         7207  
683              
684 543         1228 my @found = $self->_known_tokenizer_check(
685             $self->__tokenizer_classes() );
686              
687 543         1554 $self->{known}{$mode} = \@found;
688 543         1733 return (@expect, @found);
689             }
690              
691             sub _known_tokenizer_check {
692 877     877   2130 my ( $self, @args ) = @_;
693              
694 877         1082 my $handler = '__PPIX_TOKENIZER__' . $self->{mode};
695 877         1796 my @found;
696              
697 877         1272 foreach my $class ( @args ) {
698              
699 8611 100       30194 $class->can( $handler ) or next;
700 8408         10335 push @found, $class;
701              
702             }
703              
704 877         3242 return @found;
705             }
706              
707             sub tokens {
708 205     205 1 389 my ( $self ) = @_;
709              
710 205         288 my @rslt;
711 205         629 while ( my $token = $self->next_token() ) {
712 1933         3343 push @rslt, $token;
713             }
714              
715 205         1146 return @rslt;
716             }
717              
718             # $self->_deprecation_notice( $type, $name );
719             #
720             # This method centralizes deprecation. Type is 'attribute' or
721             # 'method'. Deprecation is driven of the %deprecate hash. Values
722             # are:
723             # false - no warning
724             # 1 - warn on first use
725             # 2 - warn on each use
726             # 3 - die on each use.
727             #
728             # $self->_deprecation_in_progress( $type, $name )
729             #
730             # This method returns true if the deprecation is in progress. In
731             # fact it returns the deprecation level.
732              
733             =begin comment
734              
735             {
736              
737             my %deprecate = (
738             attribute => {
739             postderef => 3,
740             },
741             );
742              
743             sub _deprecation_notice {
744             my ( undef, $type, $name, $repl ) = @_; # Invocant unused
745             $deprecate{$type} or return;
746             $deprecate{$type}{$name} or return;
747             my $msg = sprintf 'The %s %s is %s', $name, $type,
748             $deprecate{$type}{$name} > 2 ? 'removed' : 'deprecated';
749             defined $repl
750             and $msg .= "; use $repl instead";
751             $deprecate{$type}{$name} >= 3
752             and croak $msg;
753             warnings::enabled( 'deprecated' )
754             and carp $msg;
755             $deprecate{$type}{$name} == 1
756             and $deprecate{$type}{$name} = 0;
757             return;
758             }
759              
760             sub _deprecation_in_progress {
761             my ( $self, $type, $name ) = @_;
762             $deprecate{$type} or return;
763             return $deprecate{$type}{$name};
764             }
765              
766             }
767              
768             =end comment
769              
770             =cut
771              
772             sub _remainder {
773 3623     3623   4750 my ( $self ) = @_;
774              
775             $self->{cursor_curr} > $self->{cursor_limit}
776 3623 50       6461 and confess "Programming error - Trying to find past end of string";
777             $self->{find} = substr(
778             $self->{content},
779             $self->{cursor_curr},
780             $self->{cursor_limit} - $self->{cursor_curr}
781 3623         7459 );
782              
783 3623         4586 return;
784             }
785              
786             sub _make_final_token {
787 10     10   57 my ( $self, $len, $class, $arg ) = @_;
788 10         30 my $token = $self->make_token( $len, $class, $arg );
789 10         24 $self->_set_mode( 'kaput' );
790 10         47 return $token;
791             }
792              
793             sub _set_mode {
794 1657     1657   2382 my ( $self, $mode ) = @_;
795             $self->{trace}
796 1657 50       2680 and warn "Tokenizer going from mode $self->{mode} to $mode\n";
797 1657         2227 $self->{mode} = $mode;
798 1657 100       2662 if ( 'kaput' eq $mode ) {
799             $self->{cursor_curr} = $self->{cursor_limit} =
800 537         940 length $self->{content};
801             }
802 1657         1995 return;
803             }
804              
805             sub __init_error {
806 10     10   22 my ( $self , $err ) = @_;
807 10 100       18 defined $err
808             or $err = 'Tokenizer found illegal first characters';
809             return $self->_make_final_token(
810 10         53 length $self->{content}, TOKEN_UNKNOWN, {
811             error => $err,
812             },
813             );
814             }
815              
816             sub _update_location {
817 107     107   139 my ( $self, $token ) = @_;
818             $token->{location} # Idempotent
819 107 100       170 and return;
820 105   66     184 my $loc = $self->{_location} ||= do {
821             my %loc = (
822             location => $self->{location},
823 12         35 );
824 12 100       53 if ( __instance( $self->{source}, 'PPI::Element' ) ) {
825 11   33     69 $loc{location} ||= $self->{source}->location();
826 11 50       1467 if ( my $doc = $self->{source}->document() ) {
827 11         234 $loc{tab_width} = $doc->tab_width();
828             }
829             }
830 12   100     81 $loc{tab_width} ||= 1;
831 12         36 \%loc;
832             };
833             $loc->{location}
834 105 50       156 or return;
835 105         102 $token->{location} = [ @{ $loc->{location} } ];
  105         232  
836 105 50       222 if ( defined( my $content = $token->content() ) ) {
837              
838 105         103 my $lines;
839 105         205 pos( $content ) = 0;
840 105         248 $lines++ while $content =~ m/ \n /smxgc;
841 105 100       148 if ( pos $content ) {
842 2         3 $loc->{location}[LOCATION_LINE] += $lines;
843 2         3 $loc->{location}[LOCATION_LOGICAL_LINE] += $lines;
844             $loc->{location}[LOCATION_CHARACTER] =
845 2         3 $loc->{location}[LOCATION_COLUMN] = 1;
846             }
847              
848 105 100       209 if ( my $chars = length( $content ) - pos( $content ) ) {
849 102         126 $loc->{location}[LOCATION_CHARACTER] += $chars;
850 102 100 100     230 if ( $loc->{tab_width} > 1 && $content =~ m/ \t /smx ) {
851 5         7 my $pos = $loc->{location}[LOCATION_COLUMN];
852 5         6 my $tab_width = $loc->{tab_width};
853             # Stolen shamelessly from PPI::Document::_visual_length
854 5         6 my ( $vis_inc );
855 5         14 foreach my $part ( split /(\t)/, $content ) {
856 10 100       15 if ($part eq "\t") {
857 5         6 $vis_inc = $tab_width - ($pos-1) % $tab_width;
858             } else {
859 5         6 $vis_inc = length $part;
860             }
861 10         10 $pos += $vis_inc;
862             }
863 5         8 $loc->{location}[LOCATION_COLUMN] = $pos;
864             } else {
865 97         129 $loc->{location}[LOCATION_COLUMN] += $chars;
866             }
867             }
868              
869             }
870 105         182 return;
871             }
872              
873             sub __PPIX_TOKENIZER__init {
874 537     537   865 my ( $self ) = @_;
875              
876 537 50       2538 $self->find_regexp(
877             qr{ \A ( \s* ) ( qr | m | s )? ( \s* ) ( . ) }smx )
878             or return $self->__init_error();
879              
880 537         1794 my ( $leading_white, $type, $next_white, $delim_start ) = $self->capture();
881              
882 537 100       1249 defined $type
883             or $type = '';
884              
885 537 100 100     2242 $type
886             or $delim_start =~ m< \A [/?] \z >smx
887             or return $self->__init_error();
888 531 100 100     2015 $type
      100        
889             and not $next_white
890             and $delim_start =~ m< \A \w \z >smx
891             and return $self->__init_error();
892              
893 529         1073 $self->{type} = $type;
894              
895 529         757 my @tokens;
896              
897 529 100       1211 '' ne $leading_white
898             and push @tokens, $self->make_token( length $leading_white,
899             'PPIx::Regexp::Token::Whitespace' );
900 529         1411 push @tokens, $self->make_token( length $type,
901             'PPIx::Regexp::Token::Structure' );
902 529 100       1245 '' ne $next_white
903             and push @tokens, $self->make_token( length $next_white,
904             'PPIx::Regexp::Token::Whitespace' );
905              
906 529         927 $self->{delimiter_start} = $delim_start;
907              
908             $self->{trace}
909 529 50       1281 and warn "Tokenizer found regexp start delimiter '$delim_start' at $self->{cursor_curr}\n";
910              
911 529 50       1167 if ( my $offset = $self->find_matching_delimiter() ) {
912 529         968 my $cursor_limit = $self->{cursor_curr} + $offset;
913             $self->{trace}
914 529 50       911 and warn "Tokenizer found regexp end delimiter at $cursor_limit\n";
915 529 100       1319 if ( $self->__number_of_extra_parts() ) {
916             ### my $found_embedded_comments;
917 46 100       125 if ( $self->close_bracket(
918             $self->{delimiter_start} ) ) {
919             pos $self->{content} = $self->{cursor_curr} +
920 7         28 $offset + 1;
921             # If we're bracketed, there may be Perl comments between
922             # the regex and the replacement. PPI gets the parse
923             # wrong as of 1.220, but if we get the handling of the
924             # underlying string right, we will Just Work when PPI
925             # gets it right.
926 7         46 while ( $self->{content} =~
927             m/ \G \s* \n \s* \# [^\n]* /smxgc ) {
928             ## $found_embedded_comments = 1;
929             }
930 7         24 $self->{content} =~ m/ \s* /smxgc;
931             } else {
932             pos $self->{content} = $self->{cursor_curr} +
933 39         152 $offset;
934             }
935             # Localizing cursor_curr and delimiter_start would be
936             # cleaner, but I don't want the old values restored if a
937             # parse error occurs.
938 46         89 my $cursor_curr = $self->{cursor_curr};
939 46         74 my $delimiter_start = $self->{delimiter_start};
940 46         90 $self->{cursor_curr} = pos $self->{content};
941             $self->{delimiter_start} = substr
942             $self->{content},
943             $self->{cursor_curr},
944 46         100 1;
945             $self->{trace}
946 46 50       89 and warn "Tokenizer found replacement start delimiter '$self->{delimiter_start}' at $self->{cursor_curr}\n";
947 46 100       84 if ( my $s_off = $self->find_matching_delimiter() ) {
948             $self->{cursor_modifiers} =
949 44         96 $self->{cursor_curr} + $s_off + 1;
950             $self->{trace}
951 44 50       108 and warn "Tokenizer found replacement end delimiter at @{[
952 0         0 $self->{cursor_curr} + $s_off ]}\n";
953 44         84 $self->{cursor_curr} = $cursor_curr;
954 44         89 $self->{delimiter_start} = $delimiter_start;
955             } else {
956             $self->{trace}
957 2 50       5 and warn 'Tokenizer failed to find replacement',
958             "end delimiter starting at $self->{cursor_curr}\n";
959 2         3 $self->{cursor_curr} = 0;
960             # TODO If I were smart enough here I could check for
961             # PPI mis-parses like s{foo}
962             # #{bar}
963             # {baz}
964             # here, doing so if $found_embedded_comments (commented
965             # out above) is true. The problem is that there seem to
966             # as many mis-parses as there are possible delimiters.
967 2         6 return $self->__init_error(
968             'Tokenizer found mismatched replacement delimiters',
969             );
970             }
971             } else {
972 483         828 $self->{cursor_modifiers} = $cursor_limit + 1;
973             }
974 527         887 $self->{cursor_limit} = $cursor_limit;
975             } else {
976 0         0 $self->{cursor_curr} = 0;
977             return $self->_make_final_token(
978 0         0 length( $self->{content} ), TOKEN_UNKNOWN, {
979             error => 'Tokenizer found mismatched regexp delimiters',
980             },
981             );
982             }
983              
984             {
985             # We have to instantiate the trailing tokens now so we can
986             # figure out what modifiers are in effect. But we can't
987             # index their locations (if desired) because they are being
988             # instantiated out of order
989              
990 527         579 local $self->{index_locations} = 0;
  527         1115  
991              
992 527         603 my @mods = @{ $self->{default_modifiers} };
  527         888  
993 527         1613 pos $self->{content} = $self->{cursor_modifiers};
994 527         1033 local $self->{cursor_curr} = $self->{cursor_modifiers};
995 527         812 local $self->{cursor_limit} = length $self->{content};
996 527         647 my @trailing;
997             {
998 527         676 my $len = $self->find_regexp( qr{ \A [[:lower:]]* }smx );
  527         1660  
999 527         1292 push @trailing, $self->make_token( $len,
1000             'PPIx::Regexp::Token::Modifier' );
1001             }
1002 527 100       1612 if ( my $len = $self->find_regexp( qr{ \A \s+ }smx ) ) {
1003 1         4 push @trailing, $self->make_token( $len,
1004             'PPIx::Regexp::Token::Whitespace' );
1005             }
1006 527 100       1410 if ( my $len = $self->find_regexp( qr{ \A .+ }smx ) ) {
1007 1         4 push @trailing, $self->make_token( $len, TOKEN_UNKNOWN, {
1008             error => 'Trailing characters after expression',
1009             } );
1010             }
1011 527         1068 $self->{trailing_tokens} = \@trailing;
1012 527         1222 push @mods, $trailing[0]->content();
1013             $self->{effective_modifiers} =
1014 527         1049 PPIx::Regexp::Token::Modifier::__aggregate_modifiers (
1015             @mods );
1016             $self->{modifiers} = [
1017 527         835 { %{ $self->{effective_modifiers} } },
  527         2408  
1018             ];
1019             }
1020              
1021             $self->{delimiter_finish} = substr
1022             $self->{content},
1023             $self->{cursor_limit},
1024 527         1249 1;
1025              
1026 527         1011 push @tokens, $self->make_token( 1,
1027             'PPIx::Regexp::Token::Delimiter' );
1028              
1029 527         1278 $self->_set_mode( 'regexp' );
1030              
1031 527         672 $self->{find} = undef;
1032              
1033 527         1786 return @tokens;
1034             }
1035              
1036             # Match the initial part of the regexp including any leading white
1037             # space. The initial delimiter is the first thing not consumed, though
1038             # we check it for sanity.
1039             sub __initial_match {
1040 0     0   0 my ( $self ) = @_;
1041              
1042 0 0       0 $self->find_regexp(
1043             qr{ \A ( \s* ) ( qr | m | s )? ( \s* ) (?: [^\w\s] ) }smx )
1044             or return;
1045              
1046 0         0 my ( $leading_white, $type, $next_white ) = $self->capture();
1047              
1048 0 0       0 defined $type
1049             or $type = '';
1050              
1051 0         0 $self->{type} = $type;
1052              
1053 0         0 my @tokens;
1054              
1055 0 0       0 '' ne $leading_white
1056             and push @tokens, $self->make_token( length $leading_white,
1057             'PPIx::Regexp::Token::Whitespace' );
1058 0         0 push @tokens, $self->make_token( length $type,
1059             'PPIx::Regexp::Token::Structure' );
1060 0 0       0 '' ne $next_white
1061             and push @tokens, $self->make_token( length $next_white,
1062             'PPIx::Regexp::Token::Whitespace' );
1063              
1064 0         0 return @tokens;
1065             }
1066              
1067             {
1068             my %extra_parts = (
1069             s => 1,
1070             );
1071              
1072             # Return the number of extra delimited parts. This will be 0 except
1073             # for s///, which will be 1.
1074             sub __number_of_extra_parts {
1075 855     855   1234 my ( $self ) = @_;
1076 855   100     2721 return $extra_parts{$self->{type}} || 0;
1077             }
1078             }
1079              
1080             {
1081             my @part_class = qw{
1082             PPIx::Regexp::Structure::Regexp
1083             PPIx::Regexp::Structure::Replacement
1084             };
1085              
1086             # Return the classes for the parts of the expression.
1087             sub __part_classes {
1088 326     326   538 my ( $self ) = @_;
1089 326         676 my $max = $self->__number_of_extra_parts();
1090 326         1267 return @part_class[ 0 .. $max ];
1091             }
1092             }
1093              
1094             sub __PPIX_TOKENIZER__regexp {
1095 3036     3036   4326 my ( $self, $character ) = @_;
1096              
1097 3036         3702 my $mode = $self->{mode};
1098 3036         3744 my $handler = '__PPIX_TOKENIZER__' . $mode;
1099              
1100 3036         4184 $self->{cursor_orig} = $self->{cursor_curr};
1101 3036         5494 foreach my $class ( $self->_known_tokenizers() ) {
1102 13478         36231 my @tokens = grep { $_ } $class->$handler( $self, $character );
  3867         6566  
1103             $self->{trace}
1104 13478 50       18931 and warn $class, "->$handler( \$self, '$character' )",
1105             " => (@tokens)\n";
1106             @tokens
1107             and return ( map {
1108 13478 100       19863 ref $_ ? $_ : $self->make_token( $_,
  3033 100       7662  
1109             $class ) } @tokens );
1110             }
1111              
1112             # Find a fallback processor for the character.
1113 27   33     209 my $fallback = __PACKAGE__->can( '__PPIX_TOKEN_FALLBACK__' . $mode )
1114             || __PACKAGE__->can( '__PPIX_TOKEN_FALLBACK__regexp' )
1115             || confess "Programming error - unable to find fallback for $mode";
1116 27         60 return $fallback->( $self, $character );
1117             }
1118              
1119             *__PPIX_TOKENIZER__repl = \&__PPIX_TOKENIZER__regexp;
1120              
1121             sub __PPIX_TOKEN_FALLBACK__regexp {
1122 18     18   47 my ( $self, $character ) = @_;
1123              
1124             # As a fallback in regexp mode, any escaped character is a literal.
1125 18 100 66     102 if ( $character eq '\\'
1126             && $self->{cursor_limit} - $self->{cursor_curr} > 1
1127             ) {
1128 2         8 return $self->make_token( 2, TOKEN_LITERAL );
1129             }
1130              
1131             # Any normal character is unknown.
1132 16         72 return $self->make_token( 1, TOKEN_UNKNOWN, {
1133             error => 'Tokenizer found unexpected literal',
1134             },
1135             );
1136             }
1137              
1138             sub __PPIX_TOKEN_FALLBACK__repl {
1139 9     9   17 my ( $self, $character ) = @_;
1140              
1141             # As a fallback in replacement mode, any escaped character is a literal.
1142 9 100 66     33 if ( $character eq '\\'
1143             && defined ( my $next = $self->peek( 1 ) ) ) {
1144              
1145 5 0 33     9 if ( $self->interpolates() || $next eq q<'> || $next eq '\\' ) {
      33        
1146 5         13 return $self->make_token( 2, TOKEN_LITERAL );
1147             }
1148 0         0 return $self->make_token( 1, TOKEN_LITERAL );
1149             }
1150              
1151             # So is any normal character.
1152 4         7 return $self->make_token( 1, TOKEN_LITERAL );
1153             }
1154              
1155             sub __PPIX_TOKENIZER__finish {
1156 560     560   930 my ( $self ) = @_; # $character unused
1157              
1158             $self->{cursor_limit} > length $self->{content}
1159 560 50       1270 and confess "Programming error - ran off string";
1160              
1161             my @tokens = $self->make_token( length $self->{delimiter_finish},
1162 560         1239 'PPIx::Regexp::Token::Delimiter' );
1163              
1164 560 100       1298 if ( $self->{cursor_curr} == $self->{cursor_modifiers} ) {
1165              
1166             # We are out of string. Add the trailing tokens (created when we
1167             # did the initial bracket scan) and close up shop.
1168            
1169 516         1225 push @tokens, $self->_get_trailing_tokens();
1170              
1171 516         909 $self->_set_mode( 'kaput' );
1172              
1173             } else {
1174              
1175             # Clear the cookies, because we are going around again.
1176 44         160 $self->{cookie} = {};
1177              
1178             # Move the cursor limit to just before the modifiers.
1179 44         117 $self->{cursor_limit} = $self->{cursor_modifiers} - 1;
1180              
1181             # If the preceding regular expression was bracketed, we need to
1182             # consume possible whitespace and find another delimiter.
1183              
1184 44 100       146 if ( $self->close_bracket( $self->{delimiter_start} ) ) {
1185 7         17 my $accept;
1186             # If we are bracketed, there can be honest-to-God Perl
1187             # comments between the regexp and the replacement, not just
1188             # regexp comments. As of version 1.220, PPI does not get
1189             # this parse right, but if we can handle this is a string,
1190             # then we will Just Work when PPI gets itself straight.
1191 7         33 while ( $self->find_regexp(
1192             qr{ \A ( \s* \n \s* ) ( \# [^\n]* \n ) }smx ) ) {
1193 2         5 my ( $white_space, $comment ) = $self->capture();
1194 2         5 push @tokens, $self->make_token(
1195             length $white_space,
1196             'PPIx::Regexp::Token::Whitespace',
1197             ), $self->make_token(
1198             length $comment,
1199             'PPIx::Regexp::Token::Comment',
1200             );
1201             }
1202 7 100       30 $accept = $self->find_regexp( qr{ \A \s+ }smx )
1203             and push @tokens, $self->make_token(
1204             $accept, 'PPIx::Regexp::Token::Whitespace' );
1205 7         23 my $character = $self->peek();
1206 7         17 $self->{delimiter_start} = $character;
1207 7         14 push @tokens, $self->make_token(
1208             1, 'PPIx::Regexp::Token::Delimiter' );
1209             $self->{delimiter_finish} = substr
1210             $self->{content},
1211 7         22 $self->{cursor_limit} - 1,
1212             1;
1213             }
1214              
1215 44 100       89 if ( $self->modifier( 'e*' ) ) {
1216             # With /e or /ee, the replacement portion is code. We make
1217             # it all into one big PPIx::Regexp::Token::Code, slap on the
1218             # trailing delimiter and modifiers, and return it all.
1219             push @tokens, $self->make_token(
1220             $self->{cursor_limit} - $self->{cursor_curr},
1221 11         46 'PPIx::Regexp::Token::Code',
1222             { perl_version_introduced => MINIMUM_PERL },
1223             );
1224 11         35 $self->{cursor_limit} = length $self->{content};
1225 11         32 push @tokens, $self->make_token( 1,
1226             'PPIx::Regexp::Token::Delimiter' ),
1227             $self->_get_trailing_tokens();
1228 11         29 $self->_set_mode( 'kaput' );
1229             } else {
1230             # Put our mode to replacement.
1231 33         73 $self->_set_mode( 'repl' );
1232             }
1233              
1234             }
1235              
1236 560         1310 return @tokens;
1237              
1238             }
1239              
1240             # To common processing on trailing tokens.
1241             sub _get_trailing_tokens {
1242 527     527   859 my ( $self ) = @_;
1243 527 100       938 if ( $self->{index_locations} ) {
1244             # We turned off index_locations when these were created, because
1245             # they were done out of order. Fix that now.
1246 11         27 foreach my $token ( @{ $self->{trailing_tokens} } ) {
  11         24  
1247 11         19 $self->_update_location( $token );
1248             }
1249             }
1250 527         665 return @{ delete $self->{trailing_tokens} };
  527         1305  
1251             }
1252              
1253             1;
1254              
1255             __END__