-
Notifications
You must be signed in to change notification settings - Fork 0
/
calc.pl
executable file
·119 lines (97 loc) · 2.31 KB
/
calc.pl
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/perl
use v5.10;
use Data::Dumper;
my $calculator = do{
use Regexp::Grammars;
qr{
<grammar>
<objrule: grammar>
<MATCH=SUM> | <MATCH=MIN> | <MATCH=MAX> | <MATCH=AVERAGE> | <error: Expected SUM, MIN, MAX or AVERAGE >
<objrule: SUM>
^SUM:\s? ( <[Y=Literal]> , )* <X=Literal> $
<objrule: MIN>
^MIN:\s? ( <[Y=Literal]> , )* <X=Literal> $
<objrule: MAX>
^MAX:\s? ( <[Y=Literal]> , )* <X=Literal> $
<objrule: AVERAGE>
^AVERAGE:\s? ( <[Y=Literal]> , )* <X=Literal> $
<objtoken: Literal>
<value=( \d+ )>
}xms
};
$num_args = scalar @ARGV;
if($num_args != 1){
print "Usage: calc.pl file_name\n";
exit;
}
my $file_name = @ARGV[0];
open my $file, $file_name or die "Could not open $file: $!";
while (my $input = <$file>) {
chomp($input);
my $debug = $input =~ s{^show \s+}{}xms;
if ($input =~ /$calculator/ ) {
$val = $/{grammar}->eval();
say $val;
} else{
say "Failure on '$input'; Invalid syntax or unknown command.";
}
close (ASM);
}
sub SUM::eval{
my ($self) = @_;
my $x = $self->{X}->eval();
my $y = $self->{Y};
my $sum = 0;
$sum+=$x;
foreach my $a (@$y) {
my $val = $a->eval();
$sum += $val;
}
return "SUM $sum";
}
sub AVERAGE::eval{
my ($self) = @_;
my $x = $self->{X}->eval();
my $y = $self->{Y};
my $sum = 0;
$sum+=$x;
my $count =1;
foreach my $a (@$y) {
my $val = $a->eval();
$sum += $val;
$count++;
}
my $avg = $sum/$count;
return "AVERAGE $avg";
}
sub MIN::eval{
my ($self) = @_;
my $x = $self->{X}->eval();
my $y = $self->{Y};
my $min = $x;
foreach my $a (@$y) {
my $val = $a->eval();
if($val < $min){
$min = $val;
}
}
return "MIN $min";
}
sub MAX::eval{
my ($self) = @_;
my $x = $self->{X}->eval();
my $y = $self->{Y};
my $max = $x;
foreach my $a (@$y) {
my $val = $a->eval();
if($val > $max){
$max = $val;
}
}
return "MAX $max";
}
sub Literal::eval {
my ($self) = @_;
my $val = $self->{value};
return $val;
}