Skip to content

Instantly share code, notes, and snippets.

@agentzh

agentzh/calc.fan Secret

Created February 1, 2017 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agentzh/9b9d6799726657c99a210cf1e9566ff2 to your computer and use it in GitHub Desktop.
Save agentzh/9b9d6799726657c99a210cf1e9566ff2 to your computer and use it in GitHub Desktop.
grammar Arith {
expr:
- term(s add-op) -
add-op:
/ \s* ( [+-] ) \s* /
term: factor(s mul-op)
mul-op:
/ \s* ( [*\/] ) \s* /
factor: atom(s '^')
atom:
| number
| '(' expr ')'
number:
/ ( -? \d+ (?: \. \d+ )? ) /
}
class Calc {
method expr (@terms, @ops) {
#say "terms: ", @terms;
#say "ops: ", @ops;
my $res = shift @terms;
while @terms {
my $op = shift @ops;
my $other = shift @terms;
if $op eq '+' {
$res += $other;
} else {
$res -= $other;
}
}
return $res;
}
method term (@factors, @ops) {
#say "factors: ", @factors;
my $res = shift @factors;
while @factors {
my $op = shift @ops;
my $other = shift @factors;
if $op eq '*' {
$res *= $other;
} else {
$res /= $other;
}
}
return $res;
}
method factor (@atoms) {
my $res = pop @atoms;
while @atoms {
$res = pow pop(@atoms), $res;
}
$res;
}
}
my $input = slurp "expr.txt";
my $begin = now;
my ($res, $err) = Arith.parse: $input, Calc.new;
printf "elapsed: %.03f sec\n", now - $begin;
if !defined $res {
die "failed to parse: ", $err;
}
say "res: $res";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment