Arithmetic evaluation: Difference between revisions

Content added Content deleted
(→‎{{header|C}}: Link to separate example page)
(Added Perl 6.)
Line 808: Line 808:
$_ = ev_ast($_) foreach @operands;
$_ = ev_ast($_) foreach @operands;
return $ops{$op}->(@operands);}}</lang>
return $ops{$op}->(@operands);}}</lang>

=={{header|Perl 6}}==
{{works with|Rakudo|#22 "Thousand Oaks"}}

<lang perl6>sub ev (Str $s --> Num) {

grammar expr {
token TOP { ^ <sum> $ }
token sum { <product> (('+' || '-') <product>)* }
token product { <factor> (('*' || '/') <factor>)* }
token factor { <unary_minus>? [ <parens> || <literal> ] }
token unary_minus { '-' }
token parens { '(' <sum> ')' }
token literal { \d+ ['.' \d+]? || '.' \d+ }
}
my sub minus ($b) { $b ?? -1 !! +1 }

my sub sum ($x) {
[+] product($x<product>), map
{ minus($^y[0] eq '-') * product $^y<product> },
|($x[0] or [])
}
my sub product ($x) {
[*] factor($x<factor>), map
{ factor($^y<factor>) ** minus($^y[0] eq '/') },
|($x[0] or [])
}
my sub factor ($x) {
minus($x<unary_minus>) * ($x<parens>
?? sum $x<parens><sum>
!! $x<literal>)
}

expr.parse([~] split /\s+/, $s);
$/ or fail 'No parse.';
sum $/<sum>;

}</lang>

Testing:

<lang perl6>say ev '5'; # 5
say ev '1 + 2 - 3 * 4 / 5'; # 0.6
say ev '1 + 5*3.4 - .5 -4 / -2 * (3+4) -6'; # 25.5
say ev '((11+15)*15)* 2 + (3) * -4 *1'; # 768</lang>


=={{header|Pop11}}==
=={{header|Pop11}}==