File Coverage

blib/lib/PERLANCAR/Parse/Arithmetic/Pegex.pm
Criterion Covered Total %
statement 28 28 100.0
branch 8 12 66.6
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 45 49 91.8


line stmt bran cond sub pod time code
1             package PERLANCAR::Parse::Arithmetic::Pegex;
2              
3             our $DATE = '2016-06-18'; # DATE
4             our $VERSION = '0.004'; # VERSION
5              
6 1     1   410 use 5.010001;
  1         2  
7 1     1   3 use strict;
  1         0  
  1         13  
8 1     1   3 use warnings;
  1         1  
  1         14  
9              
10 1     1   314 use Pegex;
  1         8886  
  1         42  
11              
12 1     1   5 use Exporter qw(import);
  1         1  
  1         46  
13             our @EXPORT_OK = qw(parse_arithmetic);
14              
15             my $grammar = <<'...';
16             # Precedence Climbing grammar:
17             expr: add-sub
18             add-sub: mul-div+ % /- ( [ '+-' ])/
19             mul-div: power+ % /- ([ '*/' ])/
20             power: token+ % /- '**' /
21             token: /- '(' -/ expr /- ')'/ | number
22             number: /- ( '-'? DIGIT+ '.'? DIGIT* )/
23             ...
24              
25             {
26             package
27             Calculator;
28 1     1   4 use base 'Pegex::Tree';
  1         1  
  1         354  
29              
30             sub gotrule {
31 41     41   65492 my ($self, $list) = @_;
32 41 100       98 return $list unless ref $list;
33              
34             # Right associative:
35 19 100       31 if ($self->rule eq 'power') {
36 8         36 while (@$list > 1) {
37 2         5 my ($a, $b) = splice(@$list, -2, 2);
38 2         6 push @$list, $a ** $b;
39             }
40             }
41             # Left associative:
42             else {
43 11         41 while (@$list > 1) {
44 4         8 my ($a, $op, $b) = splice(@$list, 0, 3);
45 4 0       20 unshift @$list,
    50          
    50          
    100          
46             ($op eq '+') ? ($a + $b) :
47             ($op eq '-') ? ($a - $b) :
48             ($op eq '*') ? ($a * $b) :
49             ($op eq '/') ? ($a / $b) :
50             die;
51             }
52             }
53 19         41 return @$list;
54             }
55             }
56              
57             sub parse_arithmetic {
58 3     3 1 1251 pegex($grammar, 'Calculator')->parse($_[0]);
59             }
60              
61             1;
62             # ABSTRACT: Parse arithmetic expression (Pegex version)
63              
64             __END__