[EMAIL PROTECTED] writes:
> If anyone has a working tpr05a solution using Parse::RecDescent
> or other CPAN module can you please post it to the list, as I
> am also interested in comparing that solution to the others.
#!perl
use Parse::RecDescent;
sub Parse::RecDescent::reorder {
my ($list) = @_;
my $val = shift @$list;
while (@$list) {
my ($op, $arg) = splice @$list, 0, 2;
$val .= " $arg $op";
}
return $val;
}
my $grammar = <<'EndGrammar';
INPUT: INFIX /\Z/ { $item[1] }
INFIX: <leftop:FACTOR m!(\+|\-)! FACTOR> { reorder($item[1]) }
FACTOR: <leftop:EXPR m!(\/|\*)! EXPR> { reorder($item[1]) }
EXPR: '(' INFIX ')' { $item[2] }
| m!(-?)\s*([0-9]+)! { "$1$2" }
EndGrammar
my $parser = new Parse::RecDescent ($grammar);
while (<>) {
print $parser->INPUT($_),"\n";
}
__END__
I haven't tested this against the full battery of tests but I'm
confident it will pass---eventually (since we're no longer in
competition the important thing is the algorithm, right?).
The grammar is pretty simple, but there are probably three points to
explain:
1) INPUT: INFIX /\Z/
The /\Z/ token needs to be matched so that the INPUT rule tries to
consume all the input; otherwise the program will stop after
matching just one INFIX.
2) EXPR: m!(-?)\s*([0-9]+)! { "$1$2" }
This is the "single number" version of an expression; previous
versions made this rule more explicit:
INTEGER: '-' INTEGER { "-$item[2]" }
| m/[0-9]+/
3) C<reorder> simply transforms something like:
"1 + 2 + 3 - 9" into "1 2 + 3 + 9 -".
The grammar is much simpler if it uses the <leftop> pragma to deal
with expressions like that one instead of trying to parse them
piece by piece. See the <leftop> section in the Parse::RecDescent
manpage for further explanation.
Cheers,
jason
--
||----|---|------------|--|-------|------|-----------|-#---|-|--|------||
| ``Ooooaah! |
| I'm getting so excited about cheese-making I can't stand it!'' |
||--|--------|--------------|----|-------------|------|---------|-----|-|