How would Chomsky categorise this? (Update: Corrected c&p typo per Erez post below.)
#! perl -slw
use strict;
$|++;
my %ops = (
'+' => sub{ $_[ 0 ] + $_[ 1 ] },
'-' => sub{ $_[ 0 ] - $_[ 1 ] },
'*' => sub{ $_[ 0 ] * $_[ 1 ] },
'/' => sub{ $_[ 0 ] / $_[ 1 ] },
'**'=> sub{ $_[ 0 ] ** $_[ 1 ] },
);
my @presedence = (
qr[\*\*],
qr[\*|/],
qr[\+|-],
);
my $reVar = qr[[a-z]+];
my $reConst = qr[ [+-]? (?:\d+\.)? \d+ (?: [eE] [+-]? \d+ )? ]x;
my $reArg = qr[$reVar|$reConst];
my $reOps = qr[@{[ join '|', map{ quotemeta } keys %ops ]}];
my $reTokenise = qr[\s*($reArg)(?:\s*($reOps))?];
sub parseEvalExpr {
my $expr = shift;
if( $expr =~ m[$reOps \s+ $reArg \s+ $reOps]x ) {
for my $opset ( @presedence ) {
return "($expr)"
if $expr =~ s[ ( $reArg \s+ $opset \s+ $reArg ) ]{($1)
+}x;
}
}
my @tokens = $expr =~ m[$reTokenise]g;
pop @tokens unless defined $tokens[ $#tokens ];
while( @tokens > 1 ) {
( my( $arg1, $op, $arg2 ), @tokens ) = @tokens;
unshift @tokens, $ops{ $op }->( $arg1, $arg2 );
}
return $tokens[ 0 ];
}
while( <DATA> ) {
chomp;
my $testResult = eval;
printf "'$_' = ";
warn "Unbalanced parens '$_'" and next unless tr[(][] == tr[)][];
while( m[[()\s]] ) {
s[ \( ( [^()]+ ) \) ]{ parseEvalExpr( $1 ) }xe while m[[()]];
$_ = parseEvalExpr( $_ );
}
print;
printf STDERR "*** Discrepancy! Eval gets: %s\n", $testResult
unless $_ eq $testResult;
}
__DATA__
1 + 2
2 - 1
2 * 1
1 / 2
(((7 + 5) * (9 + 13)) / ((4 + 3) * (17 - 2 + 3)))
23 ** 2
1.1e10 ** -10
1 + 2 * 3
3 + 2 ** 2 ** 2 * 3
Output
c:\test>expr_parser.pl
'1 + 2' = 3
'2 - 1' = 1
'2 * 1' = 2
'1 / 2' = 0.5
'(((7 + 5) * (9 + 13)) / ((4 + 3) * (17 - 2 + 3)))' = 2.0952380952381
'23 ** 2' = 529
'1.1e10 ** -10' = 3.85543289429532e-101
'1 + 2 * 3' = 7
'3 + 2 ** 2 ** 2 * 3' = 51
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.