Lösungsvorschlag mit Parse::RecDescent:
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
#!/user/bin/perl
use strict;
use warnings;
use Parse::RecDescent;
my $parser = new Parse::RecDescent (q(
{
my $operators = {
'+' => sub { my $i = shift @_; $i += $_ for @_; return $i },
'-' => sub { my $i = shift @_; $i -= $_ for @_; return $i },
'*' => sub { my $i = shift @_; $i *= $_ for @_; return $i },
'/' => sub { my $i = shift @_; $i /= $_ for @_; return $i },
};
}
line: paren /^\Z/
{ $item[1] }
paren: '(' op arg arg(s) ')'
{ $operators->{$item[2]}->($item[3], @{$item[4]}) }
op: '+' | '-' | '*' | '/'
arg: paren | /^[+-]?(?:\d+|\d*\.\d+)/
));
my $task = "(+3 4(*2 7(+1 -1))(/6 2))";
my $calc = $parser->line($task) || die "Syntax error in $task\n";
print $calc, $/;
Edit: Um sich den Restriktionen der oberen Lösungen (Leerzeichen) etwas anzunäheren, könnte in der Produktion für
op erzwingen, dass nach dem Op keine Zahl folgen dar:
\n\n
<!--EDIT|pKai|1118056898-->
I sense a soul in search of answers.