File Coverage

blib/lib/Acme/Your/Filter.pm
Criterion Covered Total %
statement 43 44 97.7
branch 10 12 83.3
condition 1 3 33.3
subroutine 9 9 100.0
pod n/a
total 63 68 92.6


line stmt bran cond sub pod time code
1             package Acme::Your::Filter;
2 5     5   27 use strict;
  5         9  
  5         178  
3 5     5   35 use warnings;
  5         9  
  5         158  
4 5     5   310318 use Filter::Simple;
  5         1037028  
  5         41  
5 5     5   10940 use Parse::RecDescent;
  5         138654  
  5         90  
6              
7             FILTER_ONLY executable => \&_filter_code;
8              
9             # it's also all on one line because I don't want to disturb the line
10             # numbers too much
11              
12 5     5   5265 use Data::Dumper;
  5         32767  
  5         2927  
13             sub _filter_code {
14 5     5   94634 s/\b((?:have|your)\b.*?;)/ _transform_statement( $1 ) /ge;
  5         27  
15             }
16              
17             my $grammar = q
18             {
19             list : identifier
20             | '(' plist ')'
21              
22             plist : identifier ',' plist
23             | identifier
24              
25             identifier : /[@%\$]\w+/
26              
27             keyword : 'your'
28             | 'have'
29              
30             declaration : keyword list ';'
31             | keyword list '=' /[^;]+/ ';'
32             |
33             };
34              
35             my $parse;
36              
37             sub _transform_statement {
38 5     5   23 my $statement = shift;
39              
40 5         36 $::RD_AUTOACTION = q{ [ @item ] };
41              
42 5   33     81 $parse ||= new Parse::RecDescent $grammar;
43 5         124689 my $tree = $parse->declaration($statement);
44              
45 5 50       9623 my $pattern = $tree->[1][1] eq 'your' ? 'your' : 'have';
46              
47 5         12 my $assign;
48 5 100       38 if ($tree->[-3] eq '=') {
49 2         6 $assign = $tree->[-2];
50             }
51              
52 5         26 my @ids = _walk_tree($tree);
53              
54 5         15 my $new_statement = join('', map { _variable_declaration($pattern, $_) } @ids );
  7         27  
55 5 100       22 if ($assign) {
56 2         9 $new_statement .= "(". join(', ', @ids) .") = $assign;";
57             }
58             #print $new_statement;
59 5         90 return $new_statement;
60             }
61              
62             sub _variable_declaration {
63 7     7   16 my $keyword = shift;
64 7         15 my $name = shift;
65              
66 7         28 $name =~ s/^([\$@%])//;
67 7         20 my $sigil = $1;
68              
69 7 50       25 if ($keyword eq 'your') {
70             return
71 7         83 join('',
72             qq{ our $sigil$name; },
73             qq{ local $sigil$Acme::Your::into\::$name },
74             qq{ = $sigil$Acme::Your::into\::$name; },
75             qq{ *$name = \\$sigil$Acme::Your::into\::$name; },
76             );
77             }
78              
79             # have
80 0         0 return join('',
81             qq{ our $sigil$name; },
82             qq{ local *$Acme::Your::into\::$name = \\$sigil$name; },
83             );
84             }
85              
86             # extract identifiers from the parse tree
87             sub _walk_tree {
88 26     26   40 my $tree = shift;
89              
90 26         29 my @id;
91 26 100       69 push @id, $tree->[1] if $tree->[0] eq 'identifier';
92 26         38 for (@$tree) {
93 74 100       181 push @id, _walk_tree($_) if ref $_;
94              
95             }
96 26         74 return @id;
97             }
98              
99             1;
100             __END__