It had to be either that, or a sentinel. So, the following expression => RPN would be correct?
P:\test>423305 "max( a, b, c, d ) * atan( pi*4, -1 )"
a, b, c, d, 4, max, pi, 4, *, -1, 2, atan, *
Modified code
#! perl -slw
use strict;
use List::Util qw[ reduce ]; $a=$b;
our $XLATE ||= 0;
sub nestedOk{
index( $_[ 0 ], '(' ) <= index( $_[ 0 ], ')' ) and
0 == reduce{
$a + ( $b eq '(' ) - ( $b eq ')' )
} 0, split'[^()]*', $_[ 0 ]
}
my $re_var = qr[ [a-zA-Z]\w* ]x;
my $re_subex = qr[ \{\d+\} ]x;
my $re_func = qr[ $re_var $re_subex ]x;
my $re_num = qr[ -? \d+ (?: \. \d+ )? (?: [Ee] [+-]? \d+ )? ]x;
my $re_term = qr[ $re_func | $re_subex | $re_var | $re_num ]x;
my $re_op = qr[[,%+*/^-]];
my %ops = ( qw[ % MOD + ADD * MULT / DIV ^ POW - SUBT ] );
sub exp2rpn {
my( $exp, $aStack, $aBits ) = @_;
die "Unbalanced parens: '$exp'" unless nestedOk $exp;
my $varargs = 0;
{
my( $left, $op, $right, $rest ) = $exp =~ m[
^ ( $re_term )? ( $re_op )? ( $re_term ) ( .* ) $
]x or die "malformed (sub)expression '$exp'";
$varargs++ if $op eq ',';
for ( $left, $right ) {
next unless $_;
if( my( $func, $subex ) = m[^ ( $re_var )? \{ ( \d+ ) \} $
+]x ) {
exp2rpn( $aBits->[ $subex ], $aStack, $aBits );
push @$aStack, $func if $func
}
else{
push( @$aStack, $_ );
}
}
push @$aStack, ++$varargs if $op eq ',' and not $rest;
push @$aStack, $XLATE ? $ops{ $op } : $op
if $op and $op ne ',';
$exp = $rest, redo if $rest;
}
return $aStack;
}
sub parseExp {
local $_ = $_[ 0 ];
s[\s+][]g;
my( $bit, @bits ) = 0;
s[\( ( [^()]+ ) \)]{ push @bits, $1; "{${ \( $bit++ ) }}"; }ex
while m[[()]];
my $toplvl = $_;
return @{ exp2rpn $toplvl, [], \@bits };
}
die "No expression given\n" unless @ARGV;
print join', ', parseExp $ARGV[ 0 ];
__END__
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.