File Coverage

blib/lib/Perl/ToPerl6/Utils/PPI.pm
Criterion Covered Total %
statement 17 244 6.9
branch 0 180 0.0
condition 0 69 0.0
subroutine 6 43 13.9
pod 5 33 15.1
total 28 569 4.9


line stmt bran cond sub pod time code
1             package Perl::ToPerl6::Utils::PPI;
2              
3 1     1   15 use 5.006001;
  1         3  
4 1     1   4 use strict;
  1         2  
  1         18  
5 1     1   4 use warnings;
  1         2  
  1         19  
6              
7 1     1   5 use Readonly;
  1         1  
  1         40  
8              
9 1     1   4 use Scalar::Util qw< blessed readonly looks_like_number >;
  1         3  
  1         51  
10              
11 1     1   44 use Exporter 'import';
  1         2  
  1         3344  
12              
13             #-----------------------------------------------------------------------------
14              
15             our @EXPORT_OK = qw(
16             dscanf
17              
18             is_ppi_expression_or_generic_statement
19             is_ppi_generic_statement
20             is_ppi_statement_subclass
21             is_ppi_simple_statement
22             is_ppi_constant_element
23              
24             is_package_boundary
25              
26             is_module_name
27             is_version_number
28             is_pragma
29              
30             is_ppi_token_word
31             is_ppi_token_operator
32             is_ppi_statement
33             is_ppi_statement_compound
34              
35             is_ppi_token_quotelike_words_like
36              
37             ppi_list_elements
38              
39             set_string
40              
41             make_ppi_structure_list
42             make_ppi_structure_block
43              
44             build_ppi_structure_block_from
45             build_ppi_structure_list_from
46              
47             remove_expression_remainder
48              
49             remove_trailing_whitespace
50             insert_trailing_whitespace
51              
52             remove_leading_whitespace
53             insert_leading_whitespace
54              
55             replace_remainder_with_block
56             replace_remainder_with_list
57             );
58              
59             our %EXPORT_TAGS = (
60             all => \@EXPORT_OK,
61             );
62              
63             #-----------------------------------------------------------------------------
64             #
65             # List the conversion possibilities separately, for now.
66             # I don't think there's much call for fancy modifiers, but I'll keep it in mind.
67              
68             my @conversions = sort { length($b) <=> length($a) } (
69             'd', 'bd', 'od', 'xd', # Decimals
70             'f', 'ef', 'ff', # Floating-point numbers
71             'o', # Operator
72             'r', 'mr', 'sr', 'tr', # Regular expressions
73             's', 'ds', 'ls', 'ss', 'is', # Strings
74             'v', 'av', 'gv', 'hv', 'sv', # Variables
75             'L', # List
76             'P', # Generic PPI token
77             'W', # Word
78             );
79             my $conversions_re = join '|', @conversions;
80             my %conversion_type = (
81             d => 'PPI::Token::Number',
82             bd => 'PPI::Token::Number::Binary',
83             od => 'PPI::Token::Number::Octal',
84             xd => 'PPI::Token::Number::Hex',
85             f => 'PPI::Token::Number::Float',
86             ef => 'PPI::Token::Number::Exp',
87             o => 'PPI::Token::Operator',
88             r => 'PPI::Token::Regexp',
89             mr => 'PPI::Token::Regexp::Match',
90             sr => 'PPI::Token::Regexp::Substitute',
91             tr => 'PPI::Token::Regexp::Transliterate',
92             s => 'PPI::Token::Quote::Single',
93             ds => 'PPI::Token::Quote::Double',
94             is => 'PPI::Token::Quote::Interpolate',
95             ls => 'PPI::Token::Quote::Literal',
96             ss => 'PPI::Token::Quote::Single',
97             v => 'PPI::Token::Symbol',
98             av => 'PPI::Token::Symbol', # Must be smarter later.
99             gv => 'PPI::Token::Symbol',
100             hv => 'PPI::Token::Symbol',
101             sv => 'PPI::Token::Symbol',
102             L => 'PPI::Structure::List',
103             W => 'PPI::Token::Word',
104             );
105              
106             sub _retokenize {
107 0     0     my (@token) = @_;
108              
109             # Regroup the '%%', '%v' and modified conversions.
110             #
111 0           my @final_token;
112 0           for ( my $i = 0; $i < @token; $i++ ) {
113 0           my $v = $token[$i];
114              
115             # If the token is a '%', then look ahead.
116             # If '%' is next, just tack it on to the existing '%' leaving '%%'.
117             # Otherwise, add whatever modifiers we can find from the next, and
118             # move on.
119             # Failing that, report that we've found a missing modifier.
120             #
121 0 0         if ( $v eq '%' ) {
122 0 0         if ( $token[$i+1] eq '%' ) {
    0          
123 0           push @final_token, $v . $token[$i+1];
124 0           $i++;
125             }
126             elsif ( $token[$i+1] =~ s< ^ ($conversions_re) ><>x ) {
127 0           my $conversion = $1;
128 0 0         if ( $conversion eq 'P' ) {
129 0           $token[$i+1] =~ s< ^ \{ ([^\}]+) \} ><>x;
130 0           my $name = $1;
131 0 0         $name = 'PPI::' . $name unless $name =~ m< ^ PPI\:: >x;
132 0           $conversion .= $name;
133             }
134 0           push @final_token, $v . $conversion;
135 0 0         $i++ if $token[$i+1] eq '';
136             }
137             else {
138 0           die "Unknown conversion '" . $token[$i+1] . "'";
139             }
140             }
141             else {
142 0           push @final_token, $v;
143             }
144             }
145 0           return @final_token;
146             }
147              
148             sub dscanf {
149 0     0 1   my ($format, $options) = @_;
150 0           my @token = grep { $_ ne '' } split / ( \s+ | \% ) /x, $format;
  0            
151 0           @token = _retokenize( @token );
152              
153 0           my @to_find;
154 0           for my $token ( @token ) {
155 0 0         next if $token =~ m< ^ \s+ $ >x;
156              
157 0 0         if ( $token eq '%%' ) {
    0          
158 0           push @to_find, {
159             type => 'PPI::Token::Operator',
160             content => '%'
161             };
162             }
163             elsif ( $token =~ s< ^ \% ><>x ) {
164 0 0         if ( exists $conversion_type{$token} ) {
    0          
165             push @to_find, {
166 0           type => $conversion_type{$token}
167             };
168             }
169             elsif ( $token =~ s< ^ P (.+) $ ><>x ) {
170 0           push @to_find, {
171             type => $1
172             };
173             }
174             else {
175 0           die "Shouldn't happen, but a token type '$token' got here that we don't recognize, bailing.";
176             }
177             }
178             else {
179 0 0         if ( looks_like_number( $token ) ) {
    0          
180 0           push @to_find, {
181             type => 'PPI::Token::Number',
182             content => $token
183             };
184             }
185             elsif ( $token =~ / [^\w] /x ) {
186 0           push @to_find, {
187             type => 'PPI::Token::Operator',
188             content => $token
189             };
190             }
191             else {
192 0           push @to_find, {
193             type => 'PPI::Token::Word',
194             content => $token
195             };
196             }
197             }
198             }
199              
200             return sub {
201 0     0     my $elem = $_[1];
202              
203 0           for my $match ( @to_find ) {
204 0 0         return 0 unless $elem->isa( $match->{type} );
205             return 0 if $match->{content} and
206 0 0 0       $elem->content ne $match->{content};
207 0           $elem = $elem->snext_sibling;
208             }
209 0           return 1;
210 0           };
211             }
212              
213             #-----------------------------------------------------------------------------
214              
215             sub is_ppi_token_word {
216 0     0 0   my ($elem, %map) = @_;
217             $elem and
218             $elem->isa('PPI::Token::Word') and
219 0 0 0       exists $map{$elem->content};
220             }
221              
222             #-----------------------------------------------------------------------------
223              
224             sub is_ppi_token_operator {
225 0     0 0   my ($elem, %map) = @_;
226             $elem and
227             $elem->isa('PPI::Token::Operator') and
228 0 0 0       exists $map{$elem->content};
229             }
230              
231             #-----------------------------------------------------------------------------
232              
233             sub is_ppi_statement {
234 0     0 0   my ($elem, %map) = @_;
235             $elem and
236             $elem->isa('PPI::Statement') and
237 0 0 0       exists $map{$elem->first_element->content};
238             }
239              
240             #-----------------------------------------------------------------------------
241              
242             sub is_ppi_statement_compound {
243 0     0 0   my ($elem, %map) = @_;
244             $elem and
245             $elem->isa('PPI::Statement::Compound') and
246 0 0 0       exists $map{$elem->first_element->content};
247             }
248              
249             #-----------------------------------------------------------------------------
250              
251             sub is_ppi_token_quotelike_words_like {
252 0     0 0   my ($elem, $qr) = @_;
253 0 0 0       $elem and
254             $elem->isa('PPI::Token::QuoteLike::Words') and
255             $elem->content =~ $qr
256             }
257              
258             #-----------------------------------------------------------------------------
259              
260             sub _ppi_list_elements {
261 0     0     my ($elem) = @_;
262 0           my @elements;
263 0           for my $_elem ( $elem->schildren ) {
264 0 0 0       if ( $_elem->isa('PPI::Token::Quote') ) {
    0          
265 0           push @elements, $_elem->string;
266             }
267             elsif ( $_elem->isa('PPI::Structure::List') and
268             $_elem->schildren ) {
269 0           push @elements, _ppi_list_elements($_elem->schild(0));
270             }
271             }
272 0           return @elements;
273             }
274              
275             sub ppi_list_elements {
276 0     0 0   my ($elem) = @_;
277 0 0         return $elem->literal if $elem->isa('PPI::Token::QuoteLike::Words');
278              
279 0 0 0       if ( $elem->isa('PPI::Structure::List') and
      0        
280             $elem->schild(0) and
281             $elem->schild(0)->isa('PPI::Statement::Expression') ) {
282 0           return _ppi_list_elements($elem->schild(0));
283             }
284             }
285              
286             #-----------------------------------------------------------------------------
287              
288             sub is_module_name {
289 0     0 0   my $element = shift;
290              
291 0 0         return if not $element;
292              
293 0 0         return unless $element->isa('PPI::Token::Word');
294 0           my $content = $element->content;
295              
296 0 0         return if looks_like_number($content);
297 0 0         return if $content =~ /^v\d+/;
298              
299 0           return 1;
300             }
301              
302             #-----------------------------------------------------------------------------
303              
304             sub is_version_number {
305 0     0 0   my $element = shift;
306              
307 0 0         return if not $element;
308              
309 0 0 0       return unless $element->isa('PPI::Token::Word') or
      0        
310             $element->isa('PPI::Token::Number::Version') or
311             $element->isa('PPI::Token::Number::Float');
312 0           my $content = $element->content;
313              
314 0 0         return 1 if looks_like_number($content);
315 0 0         return 1 if $content =~ /^v\d+/;
316              
317 0           return;
318             }
319              
320             #-----------------------------------------------------------------------------
321              
322             sub is_pragma {
323 0     0 0   my $element = shift;
324              
325 0 0         return if not $element;
326              
327 0 0         return unless $element->isa('PPI::Token::Word');
328 0           my $content = $element->content;
329              
330 0           my %pragma = (
331             strict => 1,
332             warnings => 1,
333             autodie => 1,
334             base => 1,
335             parent => 1,
336             bigint => 1,
337             bignum => 1,
338             bigrat => 1,
339             constant => 1,
340             mro => 1,
341             encoding => 1,
342             integer => 1,
343             lib => 1,
344             mro => 1,
345             utf8 => 1,
346             vars => 1,
347             );
348              
349 0 0         return 1 if exists $pragma{$content};
350              
351 0           return;
352             }
353              
354             #-----------------------------------------------------------------------------
355              
356             sub set_string {
357 0     0 0   my ($elem, $string) = @_;
358 0 0         $string = '' unless $string;
359              
360 0           my $content = $elem->content;
361 0 0         if ($content =~ m/ ^ ['"] /x ) {
    0          
    0          
    0          
    0          
362 0           substr($content, 1, -1) = $string;
363             }
364             elsif ($content =~ m/^qq ./ ) {
365 0           substr($content, 4, -1) = $string;
366             }
367             elsif ($content =~ m/^qq./ ) {
368 0           substr($content, 3, -1) = $string;
369             }
370             elsif ($content =~ m/^q ./ ) {
371 0           substr($content, 3, -1) = $string;
372             }
373             elsif ($content =~ m/^q./ ) {
374 0           substr($content, 2, -1) = $string;
375             }
376             else {
377 0           die "Unknown string delimiters! >$content<\n";
378             }
379 0           $elem->set_content( $content );
380             }
381              
382             #-----------------------------------------------------------------------------
383              
384             sub make_ppi_structure_block {
385 0     0 0   my $new_list = PPI::Structure::Block->new(
386             PPI::Token::Structure->new('{'),
387             );
388 0           $new_list->{finish} = PPI::Token::Structure->new('}');
389              
390 0           return $new_list;
391             }
392              
393             #-----------------------------------------------------------------------------
394              
395             sub make_ppi_structure_list {
396 0     0 0   my $new_list = PPI::Structure::List->new(
397             PPI::Token::Structure->new('('),
398             );
399 0           $new_list->{finish} = PPI::Token::Structure->new(')');
400              
401 0           return $new_list;
402             }
403              
404             #-----------------------------------------------------------------------------
405              
406             sub build_ppi_structure_block_from {
407 0     0 0   my ($head, $terminator_test) = @_;
408              
409 0           my $new_block = make_ppi_structure_block;
410 0           my $new_statement = PPI::Statement->new;
411              
412 0   0       while ( $head and $head->next_sibling ) {
413 0 0         last if $terminator_test->(undef,$head);
414              
415 0           $new_statement->add_element($head->clone);
416 0           $head = $head->next_sibling;
417             }
418              
419 0           $new_block->add_element($new_statement);
420 0           return $new_block;
421             }
422              
423             #-----------------------------------------------------------------------------
424              
425             sub build_ppi_structure_list_from {
426 0     0 0   my ($head, $terminator_test) = @_;
427              
428 0           my $new_list = make_ppi_structure_list;
429 0           my $new_statement = PPI::Statement->new;
430              
431 0   0       while ( $head and $head->next_sibling ) {
432 0 0         last if $terminator_test->(undef,$head);
433              
434 0           $new_statement->add_element($head->clone);
435 0           $head = $head->next_sibling;
436             }
437              
438 0           $new_list->add_element($new_statement);
439 0           return $new_list;
440             }
441              
442             #-----------------------------------------------------------------------------
443              
444             sub remove_expression_remainder {
445 0     0 0   my ($head, $callback) = @_;
446 0   0       while ( $head and not $callback->(undef,$head) ) {
447 0           my $temp = $head->next_sibling;
448 0           $head->remove;
449 0           $head = $temp;
450             }
451             }
452              
453             #-----------------------------------------------------------------------------
454              
455             sub remove_trailing_whitespace {
456 0     0 0   my ($head) = @_;
457 0 0         return unless $head->next_sibling;
458 0 0         return unless $head->next_sibling->isa('PPI::Token::Whitespace');
459 0           my $white = $head->next_sibling->clone;
460 0           $head->next_sibling->remove;
461 0           return $white;
462             }
463              
464             #-----------------------------------------------------------------------------
465              
466             sub insert_trailing_whitespace {
467 0     0 0   my ($head, $optional_whitespace) = @_;
468 0 0         $optional_whitespace = ' ' unless defined $optional_whitespace;
469 0 0 0       return if $head->next_sibling and
470             $head->next_sibling->isa('PPI::Token::Whitespace');
471 0           $head->insert_after(
472             PPI::Token::Whitespace->new($optional_whitespace)
473             );
474             }
475              
476             #-----------------------------------------------------------------------------
477              
478             sub remove_leading_whitespace {
479 0     0 0   my ($head) = @_;
480 0 0         return unless $head->previous_sibling;
481 0 0         return unless $head->previous_sibling->isa('PPI::Token::Whitespace');
482 0           my $white = $head->previous_sibling->clone;
483 0           $head->previous_sibling->remove;
484 0           return $white;
485             }
486              
487             #-----------------------------------------------------------------------------
488              
489             sub insert_leading_whitespace {
490 0     0 0   my ($head, $optional_whitespace) = @_;
491 0 0         $optional_whitespace = ' ' unless defined $optional_whitespace;
492 0 0 0       return if $head->previous_sibling and
493             $head->previous_sibling->isa('PPI::Token::Whitespace');
494 0           $head->insert_before(
495             PPI::Token::Whitespace->new($optional_whitespace)
496             );
497             }
498             #-----------------------------------------------------------------------------
499              
500             sub replace_remainder_with_block {
501 0     0 0   my ($head, $callback) = @_;
502 0           my $new_block = build_ppi_structure_block_from( $head, $callback );
503              
504 0           $head->insert_before($new_block);
505 0           remove_expression_remainder( $head, $callback );
506             }
507              
508             #-----------------------------------------------------------------------------
509              
510             sub replace_remainder_with_list {
511 0     0 0   my ($head, $callback) = @_;
512 0           my $new_list = build_ppi_structure_list_from( $head, $callback );
513              
514 0           $head->insert_before($new_list);
515 0           remove_expression_remainder( $head, $callback );
516             }
517              
518             #-----------------------------------------------------------------------------
519              
520             sub is_ppi_generic_statement {
521 0     0 1   my $element = shift;
522              
523 0           my $element_class = blessed($element);
524              
525 0 0         return if not $element_class;
526 0 0         return if not $element->isa('PPI::Statement');
527              
528 0           return $element_class eq 'PPI::Statement';
529             }
530              
531             #-----------------------------------------------------------------------------
532              
533             sub is_ppi_statement_subclass {
534 0     0 1   my $element = shift;
535              
536 0           my $element_class = blessed($element);
537              
538 0 0         return if not $element_class;
539 0 0         return if not $element->isa('PPI::Statement');
540              
541 0           return $element_class ne 'PPI::Statement';
542             }
543              
544             #-----------------------------------------------------------------------------
545              
546             # Can not use hashify() here because Perl::Critic::Utils already depends on
547             # this module.
548             Readonly::Hash my %SIMPLE_STATEMENT_CLASS => map { $_ => 1 } qw<
549             PPI::Statement
550             PPI::Statement::Break
551             PPI::Statement::Include
552             PPI::Statement::Null
553             PPI::Statement::Package
554             PPI::Statement::Variable
555             >;
556              
557             sub is_ppi_simple_statement {
558 0 0   0 1   my $element = shift or return;
559              
560 0 0         my $element_class = blessed( $element ) or return;
561              
562 0           return $SIMPLE_STATEMENT_CLASS{ $element_class };
563             }
564              
565             #-----------------------------------------------------------------------------
566              
567             sub is_ppi_constant_element {
568 0 0   0 0   my $element = shift or return;
569              
570 0 0         blessed( $element ) or return;
571              
572             # TODO implement here documents once PPI::Token::HereDoc grows the
573             # necessary PPI::Token::Quote interface.
574             return
575 0   0       $element->isa( 'PPI::Token::Number' )
576             || $element->isa( 'PPI::Token::Quote::Literal' )
577             || $element->isa( 'PPI::Token::Quote::Single' )
578             || $element->isa( 'PPI::Token::QuoteLike::Words' )
579             || (
580             $element->isa( 'PPI::Token::Quote::Double' )
581             || $element->isa( 'PPI::Token::Quote::Interpolate' ) )
582             && $element->string() !~ m< (?: \A | [^\\] ) (?: \\\\)* [\$\@] >smx
583             ;
584             }
585              
586             #-----------------------------------------------------------------------------
587              
588             sub is_package_boundary {
589 0     0 0   my ($elem) = @_;
590 0 0         return unless $elem;
591 0 0         return 1 if $elem->isa('PPI::Statement::Package');
592 0 0         return 1 if $elem->isa('PPI::Statement::End');
593 0 0         return 1 if $elem->isa('PPI::Statement::Data');
594 0 0         return 1 if $elem->isa('PPI::Token::Separator');
595 0           return;
596             }
597              
598             #-----------------------------------------------------------------------------
599              
600             sub is_subroutine_declaration {
601 0     0 0   my $element = shift;
602              
603 0 0         return if not $element;
604              
605 0 0         return 1 if $element->isa('PPI::Statement::Sub');
606              
607 0 0         if ( is_ppi_generic_statement($element) ) {
608 0           my $first_element = $element->first_element();
609              
610 0 0 0       return 1 if
      0        
611             $first_element
612             and $first_element->isa('PPI::Token::Word')
613             and $first_element->content() eq 'sub';
614             }
615              
616 0           return;
617             }
618              
619             #-----------------------------------------------------------------------------
620              
621             sub is_in_subroutine {
622 0     0 0   my ($element) = @_;
623              
624 0 0         return if not $element;
625 0 0         return 1 if is_subroutine_declaration($element);
626              
627 0           while ( $element = $element->parent() ) {
628 0 0         return 1 if is_subroutine_declaration($element);
629             }
630              
631 0           return;
632             }
633              
634             #-----------------------------------------------------------------------------
635              
636             sub get_constant_name_element_from_declaring_statement {
637 0     0 0   my ($element) = @_;
638              
639 0           warnings::warnif(
640             'deprecated',
641             'Perl::Critic::Utils::PPI::get_constant_name_element_from_declaring_statement() is deprecated. Use PPIx::Utilities::Statement::get_constant_name_elements_from_declaring_statement() instead.',
642             );
643              
644 0 0         return if not $element;
645 0 0         return if not $element->isa('PPI::Statement');
646              
647 0 0 0       if ( $element->isa('PPI::Statement::Include') ) {
    0          
648 0           my $pragma;
649 0 0 0       if ( $pragma = $element->pragma() and $pragma eq 'constant' ) {
650 0           return _constant_name_from_constant_pragma($element);
651             }
652             }
653             elsif (
654             is_ppi_generic_statement($element)
655             and $element->schild(0)->content() =~ m< \A Readonly \b >xms
656             ) {
657 0           return $element->schild(2);
658             }
659              
660 0           return;
661             }
662              
663             sub _constant_name_from_constant_pragma {
664 0     0     my ($include) = @_;
665              
666 0 0         my @arguments = $include->arguments() or return;
667              
668 0           my $follower = $arguments[0];
669 0 0         return if not defined $follower;
670              
671 0           return $follower;
672             }
673              
674             #-----------------------------------------------------------------------------
675              
676             sub get_next_element_in_same_simple_statement {
677 0 0   0 0   my $element = shift or return;
678              
679 0   0       while ( $element and (
      0        
680             not is_ppi_simple_statement( $element )
681             or $element->parent()
682             and $element->parent()->isa( 'PPI::Structure::List' ) ) ) {
683 0           my $next;
684 0 0         $next = $element->snext_sibling() and return $next;
685 0           $element = $element->parent();
686             }
687 0           return;
688              
689             }
690              
691             #-----------------------------------------------------------------------------
692              
693             sub get_previous_module_used_on_same_line {
694 0 0   0 0   my $element = shift or return;
695              
696 0 0         my ( $line ) = @{ $element->location() || []};
  0            
697              
698 0           while (not is_ppi_simple_statement( $element )) {
699 0 0         $element = $element->parent() or return;
700             }
701              
702 0           while ( $element = $element->sprevious_sibling() ) {
703 0 0         ( @{ $element->location() || []} )[0] == $line or return;
  0 0          
704 0 0         $element->isa( 'PPI::Statement::Include' )
705             and return $element->schild( 1 );
706             }
707              
708 0           return;
709             }
710              
711             #-----------------------------------------------------------------------------
712              
713             sub is_ppi_expression_or_generic_statement {
714 0     0 1   my $element = shift;
715              
716 0 0         return if not $element;
717 0 0         return if not $element->isa('PPI::Statement');
718 0 0         return 1 if $element->isa('PPI::Statement::Expression');
719              
720 0           my $element_class = blessed($element);
721              
722 0 0         return if not $element_class;
723 0           return $element_class eq 'PPI::Statement';
724             }
725             #-----------------------------------------------------------------------------
726              
727             1;
728              
729             __END__
730              
731             =pod
732              
733             =for stopwords
734              
735             =head1 NAME
736              
737             Perl::ToPerl6::Utils::PPI - Utility functions for dealing with PPI objects.
738              
739              
740             =head1 DESCRIPTION
741              
742             Provides classification of L<PPI::Elements|PPI::Elements>.
743              
744              
745             =head1 INTERFACE SUPPORT
746              
747             This is considered to be a public module. Any changes to its
748             interface will go through a deprecation cycle.
749              
750              
751             =head1 IMPORTABLE SUBS
752              
753             =over
754              
755             =item C<dscanf( $format_string, {options=>1} )>
756              
757             'a' -
758             'b' -
759             'c' -
760             'd' - Specify an integer in an arbitrary base.
761             If you want integers in a base other than decimal, add a modifier:
762             'bd' - Binary integer
763             'od' - Octal integer
764             'xd' - Hexadecimal integer
765             'e' -
766             'f' - Specify a floating-point number.
767             If you want floating-point numbers in exponential notation, add
768             a modifier:
769             'ef' - Exponential number
770             'g' -
771             'h' -
772             'i' -
773             'j' -
774             'k' -
775             'l' -
776             'm' -
777             'n' -
778             'o' -
779             'p' -
780             'q' -
781             'r' - Specify a regular expression.
782             Note that this will match C</foo/>, C<s/foo/bar/>, C<y/a-m/n-z/>.
783             If you want to match a specific regex type, then preface 'r' with:
784             'mr' - Matching regular expression
785             'sr' - Substitution regular expression
786             'tr' - Transliterating regular expression
787             's' - Specify a quoted string.
788             This will match both C<'foo'> and C<qq qfooq> by default.
789             If you want to match a specific string type, then preface 's' with:
790             'ds' - Double-quoted string
791             'ls' - Literal string type
792             'ss' - Single-quoted string
793             'is' - Interpolated string
794             't' -
795             'u' -
796             'v' - Specify a Perl variable.
797             If you want a specific type of variable, add one of these modifiers:
798             'av' - Array variable
799             'gv' - GLOB variable
800             'hv' - Hash variable
801             'sv' - Scalar variable
802             'w' -
803             'x' -
804             'y' -
805             'z' -
806              
807             'A' -
808             'B' -
809             'C' -
810             'D' -
811             'E' -
812             'F' -
813             'G' -
814             'H' -
815             'I' -
816             'J' -
817             'K' -
818             'L' - A list.
819             'M' -
820             'N' -
821             'O' -
822             'P' - An explicit L<PPI> node type, C<'%P{Token::Word}'> for instance.
823             You can prefix this with C<'PPI::'> but it's considered redundant.
824             'Q' -
825             'R' -
826             'S' -
827             'T' -
828             'U' -
829             'V' -
830             'W' -
831             'X' -
832             'Y' -
833             'Z' -
834              
835             =item C<is_ppi_expression_or_generic_statement( $element )>
836              
837             Answers whether the parameter is an expression or an undifferentiated
838             statement. I.e. the parameter either is a
839             L<PPI::Statement::Expression|PPI::Statement::Expression> or the class
840             of the parameter is L<PPI::Statement|PPI::Statement> and not one of
841             its subclasses other than C<Expression>.
842              
843              
844             =item C<is_ppi_generic_statement( $element )>
845              
846             Answers whether the parameter is an undifferentiated statement, i.e.
847             the parameter is a L<PPI::Statement|PPI::Statement> but not one of its
848             subclasses.
849              
850              
851             =item C<is_ppi_statement_subclass( $element )>
852              
853             Answers whether the parameter is a specialized statement, i.e. the
854             parameter is a L<PPI::Statement|PPI::Statement> but the class of the
855             parameter is not L<PPI::Statement|PPI::Statement>.
856              
857              
858             =item C<is_ppi_simple_statement( $element )>
859              
860             Answers whether the parameter represents a simple statement, i.e. whether the
861             parameter is a L<PPI::Statement|PPI::Statement>,
862             L<PPI::Statement::Break|PPI::Statement::Break>,
863             L<PPI::Statement::Include|PPI::Statement::Include>,
864             L<PPI::Statement::Null|PPI::Statement::Null>,
865             L<PPI::Statement::Package|PPI::Statement::Package>, or
866             L<PPI::Statement::Variable|PPI::Statement::Variable>.
867              
868             =back
869              
870             =head1 AUTHOR
871              
872             Jeffrey Goff <drforr@pobox.com>
873              
874             =head1 AUTHOR EMERITUS
875              
876             Elliot Shank <perl@galumph.com>
877              
878              
879             =head1 COPYRIGHT
880              
881             Copyright (c) 2007-2011 Elliot Shank.
882              
883             This program is free software; you can redistribute it and/or modify
884             it under the same terms as Perl itself. The full text of this license
885             can be found in the LICENSE file included with this module.
886              
887             =cut
888              
889             # Local Variables:
890             # mode: cperl
891             # cperl-indent-level: 4
892             # fill-column: 78
893             # indent-tabs-mode: nil
894             # c-indentation-style: bsd
895             # End:
896             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :