File Coverage

blib/lib/PERLANCAR/Parse/Arithmetic.pm
Criterion Covered Total %
statement 28 28 100.0
branch 3 6 50.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 37 40 92.5


line stmt bran cond sub pod time code
1             package PERLANCAR::Parse::Arithmetic;
2              
3 1     1   474 use 5.010001;
  1         2  
4 1     1   3 use strict;
  1         1  
  1         14  
5 1     1   2 use warnings;
  1         1  
  1         23  
6              
7             my %match;
8              
9 1     1   3 use Exporter qw(import);
  1         2  
  1         378  
10             our @EXPORT_OK = qw(parse_arithmetic);
11              
12             sub parse_arithmetic {
13             state $RE =
14             qr{
15             (?&TOP)
16             (?{
17 3         21 $match{top} = $^R;
18             })
19              
20             (?(DEFINE)
21              
22             (?
23             ^\s* (?&EXPR) \s*$
24             )
25              
26             (?
27             (?&MULT_EXPR)
28             (?{
29 4         8 $match{add} = $^R
30             })
31             (?: \s* ([+-])
32             (?{
33 2         13 $match{op_add} = $^N;
34             })
35             \s* (?&MULT_EXPR)
36             (?{
37 2 50       8 $match{add} = $match{op_add} eq '+' ? $match{add} + $^R : $match{add} - $^R;
38             })
39             )*
40             )
41              
42             (?
43             (?&POW_EXPR)
44             (?{
45 6         11 $match{mult} = $^R;
46             })
47             (?: \s* ([*/])
48             (?{
49 2         5 $match{op_mult} = $^N;
50             }) \s*
51             (?&POW_EXPR)
52             (?{
53 2 50       9 $match{mult} = $match{op_mult} eq '*' ? $match{mult} * $^R : $match{mult} / $^R;
54             })
55             )*
56             )
57              
58             (?
59             (?&TERM)
60             (?{
61 8         20 $match{pow} = [$^R];
62             })
63             (?: \s* \*\* \s* (?&TERM)
64             (?{
65 2         1 unshift @{$match{pow}}, $^R;
  2         7  
66             })
67             )*
68             (?{
69             # because ** is right-to-left, we collect first then
70             # apply from right to left
71 8         6 my $res = $match{pow}[0];
72 8         7 for (1..$#{$match{pow}}) {
  8         16  
73 2         4 $res = $match{pow}[$_] ** $res;
74             }
75             $res;
76             })
77             )
78              
79             (?
80             \( \s* (?&EXPR)
81             (?{
82             $^R;
83             })
84             \s* \)
85             | (?&LITERAL)
86             (?{
87             $^R;
88             })
89             )
90              
91             (?
92             (-?(?:\d+|\d*\.\d+))
93             (?{
94             $^N;
95             })
96             )
97             )
98 3     3 1 13 }x;
99 3 50       24 $_[0] =~ $RE or return undef;
100 3         10 $match{top};
101             }
102              
103             1;
104             # ABSTRACT: Parse arithmetic expmatchsion
105              
106             __END__