> In any case, I was wondering if someone could provide me with an example of
> a mathematical expression parser (and evaluator).
> To properly compare to the others, it would need to handle the following
> operators
>
> +, -     (left associative)
> *, /, % (left associative)
> ^         (right associative)
>
> handle parens 12 - (3 + 4)
>
> handle two functions sqrt() and abs() both of which must include the
> parens.
>
> If someone has time to do this for me, I would be appreciative.  It might
> also serve as example documentation or cookbook ideas.
>
> I am specifically interested in examples that can be run in Perl 5 today
> without needing Pugs or Parrot.

It isn't specifically a parser designed for general language parsing, but 
CGI::Ex::Template does have a mathematical expression parser.  The parser is 
located near the end of the parse_expr method.  The output of the parse_expr 
is an opcode data structure that can be played out through the play_expr 
method.

The basic functionality is that a chain of operators is tokenized into a 
single array.  The apply_precedence method is then used to split the array
into the optree based upon the precedence and associativity of the operators.

The following is a sampling of the resulting "optrees" for the given 
expressions (taken from the perldoc):

 1 + 2         =>   [ \ [ '+', 1, 2 ], 0]
 a + b         =>   [ \ [ '+', ['a', 0], ['b', 0] ], 0 ]
 a * (b + c)   =>   [ \ [ '*', ['a', 0], [ \ ['+', ['b', 0], ['c', 0]], 0 ]], 
0 ]
 (a + b)       =>   [ \ [ '+', ['a', 0], ['b', 0] ]], 0 ]
 (a + b) * c   =>   [ \ [ '*', [ \ [ '+', ['a', 0], ['b', 0] ], 0 ], ['c', 
0] ], 0 ]

perl -e 'use CGI::Ex::Template; $s=CGI::Ex::Template::dump_parse("3 * 4 ** 2 + 
5"); $s =~ s/\s+/ /g; print "$s\n"'

$VAR1 = [ \[ '+', [ \[ '*', '3', [ \[ '**', '4', '2' ], 0 ] ], 0 ], '5' ], 
0 ];

I apologize that the expression parsing isn't a little more abstracted for 
you, but the result should be usable.  Also, the parse_expr is designed for 
also parsing variable names in the TT2 language, so the first portion of the 
method applies variable names.  The entire thing could be cut down 
considerably if all you want to parse is math (no variables).

Paul Seamons

Reply via email to