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