File Coverage

blib/lib/PERLANCAR/Parse/Arithmetic/NoHash.pm
Criterion Covered Total %
statement 27 27 100.0
branch 3 6 50.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 36 39 92.3


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