1 USING: accessors kernel locals math math.parser peg.ebnf ;
2 IN: rosetta-code.arithmetic-evaluation
4 ! http://rosettacode.org/wiki/Arithmetic_evaluation
6 ! Create a program which parses and evaluates arithmetic
11 ! * An abstract-syntax tree (AST) for the expression must be
12 ! created from parsing the input.
13 ! * The AST must be used in evaluation, also, so the input may not
14 ! be directly evaluated (e.g. by calling eval or a similar
16 ! * The expression will be a string or list of symbols like
18 ! * The four symbols + - * / must be supported as binary operators
19 ! with conventional precedence rules.
20 ! * Precedence-control parentheses must also be supported.
24 ! For those who don't remember, mathematical precedence is as
28 ! * Multiplication/Division (left to right)
29 ! * Addition/Subtraction (left to right)
31 TUPLE: operator left right ;
32 TUPLE: add < operator ; C: <add> add
33 TUPLE: sub < operator ; C: <sub> sub
34 TUPLE: mul < operator ; C: <mul> mul
35 TUPLE: div < operator ; C: <div> div
40 number = (digit)+ => [[ string>number ]]
42 value = spaces number:n => [[ n ]]
43 | spaces "(" exp:e spaces ")" => [[ e ]]
45 fac = fac:a spaces "*" value:b => [[ a b <mul> ]]
46 | fac:a spaces "/" value:b => [[ a b <div> ]]
49 exp = exp:a spaces "+" fac:b => [[ a b <add> ]]
50 | exp:a spaces "-" fac:b => [[ a b <sub> ]]
53 main = exp:e spaces !(.) => [[ e ]]
56 GENERIC: eval-ast ( ast -- result )
60 : recursive-eval ( ast -- left-result right-result )
61 [ left>> eval-ast ] [ right>> eval-ast ] bi ;
63 M: add eval-ast recursive-eval + ;
64 M: sub eval-ast recursive-eval - ;
65 M: mul eval-ast recursive-eval * ;
66 M: div eval-ast recursive-eval / ;
68 : evaluate ( string -- result )