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.1105';
3 4     4   68150 use warnings;
  4         18  
  4         126  
4 4     4   20 use strict;
  4         9  
  4         80  
5              
6 4     4   455 use parent 'Test::Count::Base';
  4         317  
  4         18  
7              
8 4     4   241 use File::Basename (qw(dirname));
  4         7  
  4         348  
9              
10 4     4   4461 use Parse::RecDescent ();
  4         150340  
  4         2232  
11              
12              
13             sub _get_grammar
14             {
15 19     19   119 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   36 my $self = shift;
69              
70 19         82 my $parser = Parse::RecDescent->new( $self->_get_grammar() );
71              
72 19         1491901 $parser->{vars} = {};
73 19         85 $parser->{count} = 0;
74 19         66 $parser->{includes} = [];
75 19         76 $parser->{filter_mults} = [1];
76              
77 19         138 return $parser;
78             }
79              
80             sub _parser
81             {
82 228     228   435 my $self = shift;
83 228 100       595 if (@_)
84             {
85 19         62 $self->{'_parser'} = shift;
86             }
87 228         1821 return $self->{'_parser'};
88             }
89              
90             sub _current_fns
91             {
92 46     46   99 my $self = shift;
93 46 100       156 if (@_)
94             {
95 19         58 $self->{'_current_fns'} = shift;
96             }
97 46         209 return $self->{'_current_fns'};
98             }
99              
100             sub _init
101             {
102 19     19   39 my $self = shift;
103              
104 19         76 $self->_current_fns( [] );
105 19         77 $self->_parser( $self->_calc_parser() );
106              
107 19         82 return 0;
108             }
109              
110              
111             sub _push_current_filename
112             {
113 13     13   29 my $self = shift;
114 13         27 my $filename = shift;
115              
116 13         30 push @{ $self->_current_fns() }, $filename;
  13         126  
117              
118 13         32 return;
119             }
120              
121             sub _pop_current_filenames
122             {
123 13     13   37 my $self = shift;
124 13         38 my $filename = shift;
125              
126 13         28 pop( @{ $self->_current_fns() } );
  13         50  
127              
128 13         37 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   2 my $self = shift;
141 1         2 my $filename = shift;
142              
143 1         6 $filename =~ s{\A"}{};
144 1         5 $filename =~ s{"\z}{};
145              
146 1         5 my $dirname = dirname( $self->_get_current_filename() );
147 1         5 $filename =~ s{\$\^CURRENT_DIRNAME}{$dirname}g;
148              
149 1         24 return $filename;
150             }
151              
152             sub update_assignments
153             {
154 42     42 1 9860 my ( $self, $args ) = @_;
155              
156 42         150 $self->_parser->{includes} = [];
157 42         116 my $ret = $self->_parser()->assignments( $args->{text} );
158              
159 42 100       1127721 if ( @{ $self->_parser->{includes} } )
  42         203  
160             {
161 1         2 foreach my $include_file ( @{ $self->_parser->{includes} } )
  1         2  
162             {
163 1         5 my $counter = Test::Count->new(
164             {
165             filename => $self->_parse_filename($include_file),
166             },
167             );
168 1         9 $counter->process( { parser => $self } );
169             }
170 1         5 $self->_parser->{includes} = [];
171             }
172             }
173              
174              
175             sub update_count
176             {
177 48     48 1 185 my ( $self, $args ) = @_;
178              
179 48         143 return $self->_parser()->update_count( $args->{text} );
180             }
181              
182              
183             sub get_count
184             {
185 20     20 1 49227 my $self = shift;
186              
187 20         61 return $self->_parser()->{count};
188             }
189              
190              
191             1; # End of Test::Count::Parser
192              
193             __END__