Arithmetic evaluation/Phix: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring the hard way
m (→‎{{header|Phix}}: more grumpoid comments)
m (→‎{{header|Phix}}: added syntax colouring the hard way)
Line 1:
=={{header|Phix}}==
Translation of [[Arithmetic_evaluation#D]], just for fun / in order to decipher all that abstract class Visitor/accept/visit pointless indirection stuff, when in fact a plain and simple recursion is all that it needs. For me <code>visit(ast)</code> and <code>visit(node[LHS/RHS])</code> do exactly what it says on the tin, whereas <code>a.root.accept(c)</code> and <code>xp.LHS/RHS.accept(this)</code> do not. Plus, 221 lines -> 166 lines, should you wrongly care about that, I know I shouldn't...
<!--<lang Phix>(phixonline)-->
<lang Phix>-- demo\rosetta\Arithmetic_evaluationD.exw
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Arithmetic_evaluationD.exw</span>
enum Num, OBkt, CBkt, Add, Sub, Mul, Div
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
constant opChar = {"#", "(", ")", "+", "-", "*", "/"},
<span style="color: #008080;">enum</span> <span style="color: #000000;">Num</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">OBkt</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CBkt</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Add</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Sub</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Mul</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Div</span>
opPrec = {0, -9, -9, 1, 1, 2, 2}
<span style="color: #008080;">constant</span> <span style="color: #000000;">opChar</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"#"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"/"</span><span style="color: #0000FF;">},</span>
enum TYPE,STR,POS,LHS,RHS -- (for nodes in opr and num)
<span style="color: #000000;">opPrec</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">}</span>
sequence opr, num
<span style="color: #008080;">enum</span> <span style="color: #000000;">TYPE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">STR</span><span style="color: #0000FF;">,</span><span style="color: #000000;">POS</span><span style="color: #0000FF;">,</span><span style="color: #000000;">LHS</span><span style="color: #0000FF;">,</span><span style="color: #000000;">RHS</span> <span style="color: #000080;font-style:italic;">-- (for nodes in opr and num)</span>
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">opr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">num</span>
function pop_opr()
sequence res = opr[$]; opr = opr[1..-2]
<span style="color: #008080;">function</span> <span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">()</span>
return res
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opr</span><span style="color: #0000FF;">[$];</span> <span style="color: #000000;">opr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure joinXP(sequence x)
x[RHS] = num[$]; num = num[1..-2]
<span style="color: #008080;">procedure</span> <span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
x[LHS] = num[$]
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RHS</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">[$];</span> <span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
num[$] = x
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">LHS</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">[$]</span>
end procedure
<span style="color: #000000;">num</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
function isDigit(integer ch)
return ch>='0' and ch<='9'
<span style="color: #008080;">function</span> <span style="color: #000000;">isDigit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
string xpr, token, resultStr
integer xpHead, xpTail, result, level
<span style="color: #004080;">string</span> <span style="color: #000000;">xpr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">resultStr</span>
sequence Tree
<span style="color: #004080;">integer</span> <span style="color: #000000;">xpHead</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xpTail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">result</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">level</span>
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">Tree</span>
function nextToken()
while xpHead<=length(xpr) and xpr[xpHead]==' ' do
<span style="color: #008080;">function</span> <span style="color: #000000;">nextToken</span><span style="color: #0000FF;">()</span>
xpHead += 1 -- Skip spaces
<span style="color: #008080;">while</span> <span style="color: #000000;">xpHead</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">xpr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">xpHead</span><span style="color: #0000FF;">]==</span><span style="color: #008000;">' '</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">xpHead</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- Skip spaces</span>
xpTail = xpHead
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if xpHead<=length(xpr) then
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xpHead</span>
integer ch = xpr[xpHead]
<span style="color: #008080;">if</span> <span style="color: #000000;">xpHead</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
if find(ch,"()+-*/") then -- valid non-number
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xpr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">xpHead</span><span style="color: #0000FF;">]</span>
xpTail += 1
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"()+-*/"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- valid non-number</span>
elsif isDigit(ch) then
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
while xpTail<=length(xpr) and isDigit(xpr[xpTail]) do
<span style="color: #008080;">elsif</span> <span style="color: #000000;">isDigit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
xpTail += 1
<span style="color: #008080;">while</span> <span style="color: #000000;">xpTail</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">isDigit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">xpTail</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if xpTail>xpHead then return xpr[xpHead..xpTail-1] end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">xpTail</span><span style="color: #0000FF;">></span><span style="color: #000000;">xpHead</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">xpr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">xpHead</span><span style="color: #0000FF;">..</span><span style="color: #000000;">xpTail</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if xpTail<=length(xpr) then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
throw("Invalid Char <%c>",{xpr[xpTail]})
<span style="color: #008080;">if</span> <span style="color: #000000;">xpTail</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Invalid Char &lt;%c&gt;"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">xpr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">xpTail</span><span style="color: #0000FF;">]})</span>
return ""
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function parse(string s)
bool expectingOP = false
<span style="color: #008080;">function</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
xpr = s
<span style="color: #004080;">bool</span> <span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
xpHead = 1
<span style="color: #000000;">xpr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
num = {}
<span style="color: #000000;">xpHead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
opr = {{CBkt,")",-1,NULL,NULL}} -- prevent evaluate null OP precedence.
<span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
while true do
<span style="color: #000000;">opr</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">CBkt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">")"</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">}}</span> <span style="color: #000080;font-style:italic;">-- prevent evaluate null OP precedence.</span>
token = nextToken()
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
if token="" then exit end if
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nextToken</span><span style="color: #0000FF;">()</span>
integer Type = max(find(token,opChar),Num)
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sequence tokenXP = {Type,token,xpHead,NULL,NULL}
<span style="color: #004080;">integer</span> <span style="color: #000000;">Type</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">,</span><span style="color: #000000;">opChar</span><span style="color: #0000FF;">),</span><span style="color: #000000;">Num</span><span style="color: #0000FF;">)</span>
if expectingOP then -- Process OP-alike tokenXP.
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tokenXP</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Type</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xpHead</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">}</span>
switch token
<span style="color: #008080;">if</span> <span style="color: #000000;">expectingOP</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- Process OP-alike tokenXP.</span>
case ")":
<span style="color: #008080;">switch</span> <span style="color: #000000;">token</span>
while opr[$][TYPE]!=OBkt do
<span style="color: #008080;">case</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">:</span>
joinXP(pop_opr())
<span style="color: #008080;">while</span> <span style="color: #000000;">opr</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">TYPE</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">OBkt</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
{} = pop_opr()
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
expectingOP = true
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">()</span>
case "+", "-", "*", "/":
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
while opPrec[tokenXP[TYPE]]<=opPrec[opr[$][TYPE]] do
<span style="color: #008080;">case</span> <span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"/"</span><span style="color: #0000FF;">:</span>
joinXP(pop_opr())
<span style="color: #008080;">while</span> <span style="color: #000000;">opPrec</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tokenXP</span><span style="color: #0000FF;">[</span><span style="color: #000000;">TYPE</span><span style="color: #0000FF;">]]<=</span><span style="color: #000000;">opPrec</span><span style="color: #0000FF;">[</span><span style="color: #000000;">opr</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">TYPE</span><span style="color: #0000FF;">]]</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
opr = append(opr,tokenXP)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
expectingOP = false
<span style="color: #000000;">opr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tokenXP</span><span style="color: #0000FF;">)</span>
default:
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
throw("Expecting Operator or ), not <%s>",{token})
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span>
end switch
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Expecting Operator or ), not &lt;%s&gt;"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">token</span><span style="color: #0000FF;">})</span>
else -- Process Num-alike tokenXP
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
switch token
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- Process Num-alike tokenXP</span>
case "+", "-", "*", "/", ")":
<span style="color: #008080;">switch</span> <span throw(style="Expectingcolor: Number or (, not <%s>#000000;",{>token})</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"/"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">:</span>
case "(":
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Expecting Number or (, not &lt;%s&gt;"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">token</span><span style="color: #0000FF;">})</span>
opr = append(opr,tokenXP)
<span style="color: #008080;">case</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">:</span>
expectingOP = false
<span style="color: #000000;">opr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tokenXP</span><span style="color: #0000FF;">)</span>
default: -- Number
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
num = append(num,tokenXP)
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">-- Number</span>
expectingOP = true
<span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tokenXP</span><span style="color: #0000FF;">)</span>
end switch
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
xpHead = xpTail
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #000000;">xpHead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xpTail</span>
while length(opr)>1 do // Join pending Op.
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
joinXP(pop_opr())
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opr</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// Join pending Op.</span>
end while
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
if length(num)!=1 then // Should be just the one (nested) node left.
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
throw("Parse Error...")
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// Should be just the one (nested) node left.</span>
end if
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Parse Error..."</span><span style="color: #0000FF;">)</span>
return num[1]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure visit(sequence node)
if level+1>length(Tree) then
<span style="color: #008080;">procedure</span> <span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">)</span>
Tree = append(Tree,"")
<span style="color: #008080;">if</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">Tree</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
string str = node[STR]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer Type = node[TYPE],
<span style="color: #004080;">string</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">STR</span><span style="color: #0000FF;">]</span>
p = node[POS],
<span style="color: #004080;">integer</span> <span style="color: #000000;">Type</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">TYPE</span><span style="color: #0000FF;">],</span>
e = p+length(str)-1
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">POS</span><span style="color: #0000FF;">],</span>
while length(Tree[level])<e do
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span>
Tree[level] &= ' '
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">])<</span><span style="color: #000000;">e</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">' '</span>
Tree[level][p..e] = str
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
level += 1
<span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">][</span><span style="color: #000000;">p</span><span style="color: #0000FF;">..</span><span style="color: #000000;">e</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str</span>
if Type=Num then
<span style="color: #000000;">level</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
resultStr &= str
<span style="color: #008080;">if</span> <span style="color: #000000;">Type</span><span style="color: #0000FF;">=</span><span style="color: #000000;">Num</span> <span style="color: #008080;">then</span>
result = to_integer(str)
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">str</span>
else
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span>
resultStr &= "("
<span style="color: #008080;">else</span>
visit(node[LHS])
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"("</span>
integer lhs = result
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">LHS</span><span style="color: #0000FF;">])</span>
resultStr &= str -- (same as &= opChar[Type])
<span style="color: #004080;">integer</span> <span style="color: #000000;">lhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">result</span>
visit(node[RHS])
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">str</span> <span style="color: #000080;font-style:italic;">-- (same as &= opChar[Type])</span>
resultStr &= ")"
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RHS</span><span style="color: #0000FF;">])</span>
switch Type
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">")"</span>
case Add: result = lhs+result
<span style="color: #008080;">switch</span> <span style="color: #000000;">Type</span>
case Sub: result = lhs-result
<span style="color: #008080;">case</span> <span style="color: #000000;">Add</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">+</span><span style="color: #000000;">result</span>
case Mul: result = lhs*result
<span style="color: #008080;">case</span> <span style="color: #000000;">Sub</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">-</span><span style="color: #000000;">result</span>
case Div: result = lhs/result
<span style="color: #008080;">case</span> <span style="color: #000000;">Mul</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">*</span><span style="color: #000000;">result</span>
default: throw("Invalid type")
<span style="color: #008080;">case</span> <span style="color: #000000;">Div</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">/</span><span style="color: #000000;">result</span>
end switch
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Invalid type"</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
level -= 1
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<span style="color: #000000;">level</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
procedure CalcVis(sequence ast, string expr)
result = 0
<span style="color: #008080;">procedure</span> <span style="color: #000000;">CalcVis</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">ast</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">expr</span><span style="color: #0000FF;">)</span>
level = 1
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
resultStr = ""
<span style="color: #000000;">level</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
Tree = {}
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
visit(ast)
<span style="color: #000000;">Tree</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
-- More fancy:
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ast</span><span style="color: #0000FF;">)</span>
for i=2 to length(Tree) do
<span style="color: #000080;font-style:italic;">-- More fancy:</span>
bool flipflop = false
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for j=1 to length(Tree[i]) do
<span style="color: #004080;">bool</span> <span style="color: #000000;">flipflop</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
while j>=length(Tree[i-1]) do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
Tree[i-1] &= " "
<span style="color: #008080;">while</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" "</span>
integer c1 = Tree[i][j],
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
c2 = Tree[i-1][j]
<span style="color: #004080;">integer</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span>
if flipflop and c1==' ' and c2==' ' then
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
Tree[i-1][j] = '.'
<span style="color: #008080;">if</span> <span style="color: #000000;">flipflop</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">==</span><span style="color: #008000;">' '</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c2</span><span style="color: #0000FF;">==</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'.'</span>
if c1!='.' and c1!=' '
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
and (j==1 or not isDigit(Tree[i][j-1])) then
<span style="color: #008080;">if</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">' '</span>
flipflop = not flipflop
<span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">==</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #008080;">not</span> <span style="color: #000000;">isDigit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]))</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">flipflop</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">flipflop</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"%s\n%s ==>\n%s = %d\n", {join(Tree,"\n"), expr, resultStr, result})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end procedure
<span style="color: #000080;font-style:italic;">--pp(Tree,{pp_Nest,9999})</span>
 
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n%s ==&gt;\n%s = %d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Tree</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">expr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">resultStr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">result</span><span style="color: #0000FF;">})</span>
constant expr = "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1"
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
try
sequence ast = parse(expr)
<span style="color: #008080;">constant</span> <span style="color: #000000;">expr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1"</span>
CalcVis(ast,expr)
<span style="color: #008080;">try</span>
catch e
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ast</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">parse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">)</span>
?e
<span style="color: #000080;font-style:italic;">-- pp(ast)</span>
end try</lang>
<span style="color: #000000;">CalcVis</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ast</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">catch</span> <span style="color: #000000;">e</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">e</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">try</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
{{out}}
<pre>
7,806

edits