It's been many, many years since I did anything with expression evaluation and compiling, but yours does seem rather complicated.

For clarity, I always liked recursive descent. As a simple example here's an evaluator for expressions with integer add, subtract, multiply and divide.

update: Now does unary minus, real numbers and parentheses

use strict; use warnings FATAL => 'all'; use Test::More; use constant { TOK_NUM => 1, TOK_MULOP => 2, TOK_ADDOP => 3, TOK_PAREN => 4, TOK_END => 9, }; my ( $expr, $type, $tok ); # Globals. Yuk. #expr ::= factor ( ADDOP factor )* #factor ::= term ( MULOP term )* #term ::= '(' expr ')' | '-' expr | number my @tests = ( '3 + 4', '3 - 4', '3 / 4', '3 * 4', '1 + 2 * 3', '2 * 3 + 1', '2 + 3 + 4', '2 - 3 - 4', '2 * 3 * 4', ' +2 / 3 / 4', '(1 + 2) * 3', '2 * (3 + 1)', '(2 + 3)', '2 - (3)', '-2', '1+-2', '1 + (-2 * -3)', '1.2 + 2.4', '1.2 * -1.4', ); plan tests => scalar @tests; for my $test ( @tests ) { my $exp = eval $test; is evaluate( $test ), $exp, "can do $test"; } sub evaluate { $expr = $_[0]; next_token(); return expr(); } sub expr { my $val = factor(); while ( $type eq TOK_ADDOP ) { if ( $tok eq '+' ) { next_token(); $val += factor(); } elsif ( $tok eq '-' ) { next_token(); $val -= factor(); } } return $val; } sub factor { my $val = term(); while ( $type eq TOK_MULOP ) { if ( $tok eq '*' ) { next_token(); $val *= term(); } elsif ( $tok eq '/' ) { next_token(); $val /= term(); } } return $val; } sub term { if ( $tok eq '(' ) { next_token(); my $val = expr(); die "missing )" unless $tok eq ')'; next_token(); return $val; } elsif ( $tok eq '-' ) { next_token(); return - term(); } die "syntax error at $expr" unless $type eq TOK_NUM; my $number = $tok; next_token(); return $number; } sub next_token { my %toktab = ( qr{^\s*(\d+(\.\d+)?)} => TOK_NUM, qr{^\s*([-+])} => TOK_ADDOP, qr{^\s*([*/])} => TOK_MULOP, qr{^\s*([()])} => TOK_PAREN, ); $type = TOK_END; for my $re ( keys %toktab ) { ( $type, $tok ) = ( $toktab{$re}, $1 ) and last if $expr =~ s/$re//; } }

In reply to Re: a timid approach to parsing arithmetic expressions in perl by FunkyMonk
in thread a timid approach to parsing arithmetic expressions in perl by spx2

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.