Arithmetic evaluation: Difference between revisions

Line 1,446:
astTree = Lex( expr, Yaccer())
print expr, '=',astTree.eval()</lang>
 
=={{header|Tcl}}==
The code below delivers the AST for an expression in a form that it can be immediately eval-led, using Tcl's prefix operators.
<lang Tcl>
namespace import tcl::mathop::*
 
proc arieval str {
# produce abstract syntax tree for an expression
regsub -all {[-+*/()]} $str { & } str ;# "tokenizer"
s $str
}
proc s {args} {
# parse "(a + b) * c + d" to "+ [* [+ a b] c] d"
if {[llength $args]==1} {set args [lindex $args 0]}
if [regexp {[()]} $args] {
eval s [string map {( "\[s " ) \]} $args]
} elseif {[lsearch -exact $args *]>=0} {
s [s_group args *]
} elseif {[lsearch -exact $args /]>=0} {
s [s_group args /]
} elseif {[lsearch -exact $args +]>=0} {
s [s_group args +]
} elseif {[lsearch -exact $args -]>=0} {
s [s_group args -]
} else {
string map {\{ \[ \} \]} [join $args]
}
}
proc s_group {listName op} {
# turn ".. a op b .." to ".. {op a b} .."
upvar 1 $listName list
set pos [lsearch -exact $list $op]
set p_1 [- $pos 1]
set p1 [+ $pos 1]
set list [lreplace $list $p_1 $p1 \
[list $op [lindex $list $p_1] [lindex $list $p1]]]
}
#-- Test suite
foreach test [split {
arieval 2-2
arieval 1-2-3
arieval (1-2)-3
arieval 1-(2-3)
arieval (1+2)*3
arieval (1+2)/3-4*5
arieval ((1+2)/3-4)*5
} \n] {
puts "$test ..... [eval $test] ..... [eval [eval $test]]"
}
</lang>
Output:<pre>
arieval 2-2 ..... - 2 2 ..... 0
arieval 1-2-3 ..... - [- 1 2] 3 ..... -4
arieval (1-2)-3 ..... - [- 1 2] 3 ..... -4
arieval 1-(2-3) ..... - 1 [- 2 3] ..... 2
arieval (1+2)*3 ..... * [+ 1 2] 3 ..... 9
arieval (1+2)/3-4*5 ..... - [/ [+ 1 2] 3] [* 4 5] ..... -19
arieval ((1+2)/3-4)*5 ..... * [- [/ [+ 1 2] 3] 4] 5 ..... -15
</pre>
Anonymous user