File Coverage

blib/lib/PPIx/Regexp/Structure/Switch.pm
Criterion Covered Total %
statement 36 36 100.0
branch 16 18 88.8
condition 5 9 55.5
subroutine 6 6 100.0
pod n/a
total 63 69 91.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             PPIx::Regexp::Structure::Switch - Represent a switch
4              
5             =head1 SYNOPSIS
6              
7             use PPIx::Regexp::Dumper;
8             PPIx::Regexp::Dumper->new( 'qr{(?(1)foo|bar)}smx' )
9             ->print();
10              
11             =head1 INHERITANCE
12              
13             C is a
14             L.
15              
16             C has no descendants.
17              
18             =head1 DESCRIPTION
19              
20             This class represents a switch, or conditional expression. The condition
21             will be the first child.
22              
23             =head1 METHODS
24              
25             This class provides no public methods beyond those provided by its
26             superclass.
27              
28             =cut
29              
30             package PPIx::Regexp::Structure::Switch;
31              
32 9     9   96 use strict;
  9         21  
  9         242  
33 9     9   44 use warnings;
  9         23  
  9         247  
34              
35 9     9   58 use base qw{ PPIx::Regexp::Structure };
  9         17  
  9         786  
36              
37 9     9   61 use PPIx::Regexp::Constant qw{ @CARP_NOT };
  9         17  
  9         3638  
38              
39             our $VERSION = '0.087_01';
40              
41             sub __raw_width {
42 18     18   52 my ( $self ) = @_;
43 18         31 my $cond;
44 18 100 33     59 $cond = $self->schild( 0 )
      66        
45             and $cond->isa( 'PPIx::Regexp::Token::Condition' )
46             and $cond->content() eq '(DEFINE)'
47             and return ( 0, 0, 1 );
48 12         49 my ( $node_min, $node_max, $alternatives ) = $self->SUPER::__raw_width();
49 12 100 66     75 defined $node_min
50             and $alternatives < 2
51             and $node_min = 0;
52 12         43 return ( $node_min, $node_max, $alternatives );
53             }
54              
55             sub __PPIX_LEXER__finalize {
56 26     26   91 my ( $self, $lexer ) = @_;
57              
58             # Assume no errors.
59 26         55 my $rslt = 0;
60              
61             # Number of allowed alternations not known yet.
62 26         44 my $alternations;
63              
64             # If we are a valid switch, the first child is the condition. Make
65             # sure we have a first child and that it is of the expected class.
66             # If it is, determine how many alternations are allowed.
67 26 50       104 if ( my $condition = $self->child( 0 ) ) {
68 26         73 foreach my $class ( qw{
69             PPIx::Regexp::Structure::Assertion
70             PPIx::Regexp::Structure::Code
71             PPIx::Regexp::Token::Condition
72             } ) {
73 71 100       2120 $condition->isa( $class ) or next;
74 25 100       102 $alternations = $condition->content() eq '(DEFINE)' ? 0 : 1;
75 25         65 last;
76             }
77             }
78              
79 26 100       81 if ( defined $alternations ) {
80             # If we figured out how many alternations were allowed, count
81             # them, changing surplus ones to the unknown token.
82 25         109 foreach my $kid ( $self->children () ) {
83 82 100       346 $kid->isa( 'PPIx::Regexp::Token::Operator' ) or next;
84 5 50       28 $kid->content() eq '|' or next;
85 5 100       69 --$alternations >= 0 and next;
86 1         13 $kid->__error( 'Too many alternatives for switch' );
87             }
88             } else {
89             # If we could not figure out how many alternations were allowed,
90             # it means we did not understand our condition. Rebless
91             # ourselves to the unknown structure and count a parse failure.
92 1         23 $self->__error( 'Switch condition not understood' );
93 1         3 $rslt++;
94             }
95              
96             # Delegate to the superclass to finalize our children, now that we
97             # have finished messing with them.
98 26         180 $rslt += $self->SUPER::__PPIX_LEXER__finalize( $lexer );
99              
100 26         85 return $rslt;
101             }
102              
103             1;
104              
105             __END__