File Coverage

blib/lib/HTML/Template/Parser/ExprParser.pm
Criterion Covered Total %
statement 19 19 100.0
branch 2 2 100.0
condition n/a
subroutine 6 6 100.0
pod 0 1 0.0
total 27 28 96.4


line stmt bran cond sub pod time code
1             package HTML::Template::Parser::ExprParser;
2              
3 21     21   1208829 use strict;
  21         56  
  21         744  
4 21     21   119 use warnings;
  21         39  
  21         648  
5              
6 21     21   119 use base qw(Class::Accessor::Fast);
  21         39  
  21         15747  
7             __PACKAGE__->mk_accessors(qw());
8              
9 21     21   102613 use Parse::RecDescent;
  21         799973  
  21         171  
10              
11             sub parse {
12 128     128 0 3704104 my($self, $expr) = @_;
13              
14 128         591 $self->_get_parser_instance->expr($expr);
15             }
16              
17             my $_instance;
18              
19             sub _get_parser_instance {
20 128 100   128   1387 return $_instance if $_instance;
21 18         45 $::RD_ERRORS=1;
22 18         38 $::RD_WARN=1;
23 18         42 $::RD_HINT=1;
24             # $::RD_TRACE=1; # @@@
25 18         161 return $_instance = Parse::RecDescent->new(<<'END;');
26             {
27             use strict;
28             use warnings;
29              
30             sub unexpand {
31             if(@_ == 1 and ref($_[0]) eq 'ARRAY'){
32             return $_[0];
33             }
34              
35             my $right = pop;
36             my $op = pop;
37             [ 'op', $op, unexpand(@_), $right ];
38             }
39             }
40              
41             expr: xxx_op
42              
43             xxx_op: or_sym_op
44             or_sym_op: { unexpand(@{$item[1]}); }
45             and_sym_op: { unexpand(@{$item[1]}); }
46             not_sym_op: NOT_SYM or_op { [ 'op', $item[1], $item[2] ] }
47             | or_op
48             or_op: { unexpand(@{$item[1]}); }
49             and_op: { unexpand(@{$item[1]}); }
50             comp_op: { unexpand(@{$item[1]}); }
51             sum_op: { unexpand(@{$item[1]}); }
52             prod_op: { unexpand(@{$item[1]}); }
53             match_op: not_op MATCH REGEXP { [ 'op', $item[2], $item[1], $item[3] ] }
54             | not_op
55             not_op: (NOT|NOT_SYM) term { [ 'op', $item[1], $item[2] ] }
56             | term
57              
58             NOT: '!'
59             MATCH: '=~'
60             PROD: '*' | '/' | '%'
61             SUM: '+' | '-'
62             COMP: />=?|<=?|!=|==|le|ge|eq|ne|lt|gt/
63             AND: '&&'
64             OR: '||'
65             NOT_SYM: /not(?!\w)/
66             AND_SYM: /and(?!\w)/
67             OR_SYM: /or(?!\w)/
68              
69             term:
70             function
71             | '(' xxx_op ')' { $item[2] }
72             | NUMBER
73             | STRING
74             | VARIABLE
75              
76             function: NAME '(' expr(s? /,/) ')' { [ 'function', $item[1], @{$item[3]} ] }
77              
78             REGEXP: m!/[^/]*/i?! { [ 'regexp', $item[1] ] }
79             NUMBER: /[+-]?\d+(\.\d+)?/ { [ 'number', $item[1]+0 ]; }
80             STRING: /"([^\"]*)"/ { [ 'string', $1, ]; }
81             STRING: /'([^\']*)'/ { [ 'string', $1, ]; }
82             VARIABLE: /[_a-z][_a-z0-9]*/i { [ 'variable', $item[1] ] }
83             VARIABLE: /\$?{([^}]+)}/ { [ 'variable', $1 ] }
84             NAME: /[_a-z][_a-z0-9]*/i { [ 'name', $item[1] ] }
85             END;
86             }
87              
88             1;