File: demo_calc_list_autoactions.pl

package info (click to toggle)
libregexp-grammars-perl 1.058-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,328 kB
  • sloc: perl: 53,328; makefile: 2
file content (67 lines) | stat: -rw-r--r-- 1,272 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use v5.10;
use warnings;

my $calculator = do{
    use Regexp::Grammars;
    qr{
        \A
        <Answer>

        <rule: Answer>
            <[Operand=Mult]>+ % <[Op=(\+|\-)]>

        <rule: Mult>
            <[Operand=Pow]>+ % <[Op=(\*|/|%)]>

        <rule: Pow>
            <[Operand=Term]>+ % <Op=(\^)>

        <rule: Term>
                <MATCH=Literal>
          |
            \(  <MATCH=Answer>  \)

        <token: Literal>
            <MATCH=( [+-]? \d++ (?: \. \d++ )?+ )>
    }xms
};

package Calculator_Actions;

use List::Util qw< reduce >;

sub Answer {
    my ($self, $MATCH_ref) = @_;

    my $value = shift @{$MATCH_ref->{Operand}};
    for my $term (@{$MATCH_ref->{Operand}}) {
        my $op = shift @{$MATCH_ref->{Op}//=[]};
        if ($op eq '+') { $value += $term; }
        else            { $value -= $term; }
    }

    return $value;
}

sub Mult {
    my ($self, $MATCH_ref) = @_;

    reduce { eval($a . shift(@{$MATCH_ref->{Op}}) . $b) }
           @{$MATCH_ref->{Operand}};
}

sub Pow {
    my ($self, $MATCH_ref) = @_;

    reduce { $b ** $a } reverse @{$MATCH_ref->{Operand}};
}


# and later...

while (my $input = <>) {
    if ($input =~ $calculator->with_actions('Calculator_Actions') ) {
        say '--> ', $/{Answer};
    }
}