File Coverage

blib/lib/Test/Count/Parser.pm
Criterion Covered Total %
statement 68 68 100.0
branch 6 6 100.0
condition n/a
subroutine 17 17 100.0
pod 3 3 100.0
total 94 94 100.0


line stmt bran cond sub pod time code
1             package Test::Count::Parser;
2             $Test::Count::Parser::VERSION = '0.1102';
3 5     5   66389 use warnings;
  5         16  
  5         147  
4 5     5   22 use strict;
  5         9  
  5         95  
5              
6 5     5   432 use parent 'Test::Count::Base';
  5         356  
  5         20  
7              
8 5     5   282 use File::Basename (qw(dirname));
  5         9  
  5         350  
9              
10 5     5   5186 use Parse::RecDescent ();
  5         181320  
  5         2730  
11              
12              
13             sub _get_grammar
14             {
15 19     19   105 return <<'EOF';
16             update_count: expression {$thisparser->{count} += $item[1] * $thisparser->{filter_mults}->[-1]}
17              
18             assignments: statement ';' assignments
19             | statement
20              
21             statement: assignment
22             | expression {$item [1]}
23             | including_file {$item [1]}
24             | start_filter
25             | end_filter
26              
27             start_filter: 'FILTER(MULT(' expression '))' {push @{$thisparser->{filter_mults}}, $thisparser->{filter_mults}->[-1] * $item[2] ; }
28              
29             end_filter: 'ENDFILTER()' {if (@{$thisparser->{filter_mults}} <= 1) { die "Too many ENDFILTER()s"; } pop @{$thisparser->{filter_mults}}; }
30              
31             including_file: 'source' string {push @{$thisparser->{includes}}, $item[2];}
32              
33             assignment: variable '=' statement {$thisparser->{vars}->{$item [1]} = $item [3]}
34             | variable '+=' statement {$thisparser->{vars}->{$item [1]} += $item [3]}
35             | variable '-=' statement {$thisparser->{vars}->{$item [1]} -= $item [3]}
36             | variable '*=' statement {$thisparser->{vars}->{$item [1]} *= $item [3]}
37              
38             expression: variable '++' {$thisparser->{vars}->{$item [1]}++}
39             | term '+' expression {$item [1] + $item [3]}
40             | term '-' expression {$item [1] - $item [3]}
41             | term
42              
43             term: factor '*' term {$item [1] * $item [3]}
44             | factor '/' term {int($item [1] / $item [3])}
45             | factor
46              
47             factor: number
48             | variable {
49             (exists($thisparser->{vars}->{$item [1]})
50             ? $thisparser->{vars}->{$item [1]}
51             : do { die "Undefined variable \"$item[1]\""; } )
52             }
53             | '+' factor {$item [2]}
54             | '-' factor {$item [2] * -1}
55             | '(' statement ')' {$item [2]}
56              
57             number: /\d+/ {$item [1]}
58              
59             variable: /\$[a-z_]\w*/i
60              
61             string: /"[^"]+"/
62              
63             EOF
64             }
65              
66             sub _calc_parser
67             {
68 19     19   40 my $self = shift;
69              
70 19         74 my $parser = Parse::RecDescent->new( $self->_get_grammar() );
71              
72 19         1351529 $parser->{vars} = {};
73 19         72 $parser->{count} = 0;
74 19         58 $parser->{includes} = [];
75 19         73 $parser->{filter_mults} = [1];
76              
77 19         121 return $parser;
78             }
79              
80             sub _parser
81             {
82 228     228   327 my $self = shift;
83 228 100       484 if (@_)
84             {
85 19         58 $self->{'_parser'} = shift;
86             }
87 228         1369 return $self->{'_parser'};
88             }
89              
90             sub _current_fns
91             {
92 46     46   152 my $self = shift;
93 46 100       131 if (@_)
94             {
95 19         55 $self->{'_current_fns'} = shift;
96             }
97 46         199 return $self->{'_current_fns'};
98             }
99              
100             sub _init
101             {
102 19     19   41 my $self = shift;
103              
104 19         70 $self->_current_fns( [] );
105 19         123 $self->_parser( $self->_calc_parser() );
106              
107 19         61 return 0;
108             }
109              
110              
111             sub _push_current_filename
112             {
113 13     13   31 my $self = shift;
114 13         55 my $filename = shift;
115              
116 13         52 push @{ $self->_current_fns() }, $filename;
  13         41  
117              
118 13         28 return;
119             }
120              
121             sub _pop_current_filenames
122             {
123 13     13   32 my $self = shift;
124 13         25 my $filename = shift;
125              
126 13         23 pop( @{ $self->_current_fns() } );
  13         46  
127              
128 13         30 return;
129             }
130              
131             sub _get_current_filename
132             {
133 1     1   2 my $self = shift;
134              
135 1         29 return $self->_current_fns->[-1];
136             }
137              
138             sub _parse_filename
139             {
140 1     1   3 my $self = shift;
141 1         2 my $filename = shift;
142              
143 1         5 $filename =~ s{\A"}{};
144 1         5 $filename =~ s{"\z}{};
145              
146 1         4 my $dirname = dirname( $self->_get_current_filename() );
147 1         7 $filename =~ s{\$\^CURRENT_DIRNAME}{$dirname}g;
148              
149 1         13 return $filename;
150             }
151              
152             sub update_assignments
153             {
154 42     42 1 9782 my ( $self, $args ) = @_;
155              
156 42         117 $self->_parser->{includes} = [];
157 42         96 my $ret = $self->_parser()->assignments( $args->{text} );
158              
159 42 100       1017103 if ( @{ $self->_parser->{includes} } )
  42         174  
160             {
161 1         2 foreach my $include_file ( @{ $self->_parser->{includes} } )
  1         3  
162             {
163 1         4 my $counter = Test::Count->new(
164             {
165             filename => $self->_parse_filename($include_file),
166             },
167             );
168 1         10 $counter->process( { parser => $self } );
169             }
170 1         5 $self->_parser->{includes} = [];
171             }
172             }
173              
174              
175             sub update_count
176             {
177 48     48 1 170 my ( $self, $args ) = @_;
178              
179 48         106 return $self->_parser()->update_count( $args->{text} );
180             }
181              
182              
183             sub get_count
184             {
185 20     20 1 49370 my $self = shift;
186              
187 20         65 return $self->_parser()->{count};
188             }
189              
190              
191             1; # End of Test::Count::Parser
192              
193             __END__