File Coverage

blib/lib/PPIx/Regexp/Tokenizer.pm
Criterion Covered Total %
statement 494 522 94.6
branch 177 238 74.3
condition 44 64 68.7
subroutine 85 89 95.5
pod 29 29 100.0
total 829 942 88.0


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