Arithmetic evaluation/Phix: Difference between revisions

From Rosetta Code
Content added Content deleted
(Created page with "=={{header|Phix}}== {{trans|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 re...")
 
(→‎{{header|Phix}}: removed header as it was making the completed task count for Phix wrong.)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
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...
=={{header|Phix}}==
<!--<lang Phix>(phixonline)-->
{{trans|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, plus 221 lines -> 166 lines, should you wrongly care about that, I know I shouldn't...)
<lang Phix>-- demo\rosetta\Arithmetic_evaluationD.exw
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Arithmetic_evaluationD.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
enum Num, OBkt, CBkt, Add, Sub, Mul, Div
<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>
constant opChar = {"#", "(", ")", "+", "-", "*", "/"},
<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>
opPrec = {0, -9, -9, 1, 1, 2, 2}
<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>
enum TYPE,STR,POS,LHS,RHS -- (for nodes in opr and 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>
sequence opr, num
<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()
<span style="color: #008080;">function</span> <span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">()</span>
sequence res = opr[$]; opr = opr[1..-2]
<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>
return res
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

procedure joinXP(sequence x)
<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[RHS] = num[$]; num = num[1..-2]
<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>
x[LHS] = num[$]
<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>
num[$] = x
<span style="color: #000000;">num</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>

function isDigit(integer ch)
<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>
return ch>='0' and ch<='9'
<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>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

string xpr, token, resultStr
<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>
integer xpHead, xpTail, result, level
<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>
sequence Tree
<span style="color: #004080;">sequence</span> <span style="color: #000000;">Tree</span>

function nextToken()
<span style="color: #008080;">function</span> <span style="color: #000000;">nextToken</span><span style="color: #0000FF;">()</span>
while xpHead<=length(xpr) and xpr[xpHead]==' ' do
<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>
xpHead += 1 -- Skip spaces
<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>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
xpTail = xpHead
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xpHead</span>
if xpHead<=length(xpr) then
<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>
integer ch = xpr[xpHead]
<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>
if find(ch,"()+-*/") then -- valid non-number
<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>
xpTail += 1
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
elsif isDigit(ch) then
<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>
while xpTail<=length(xpr) and isDigit(xpr[xpTail]) do
<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>
xpTail += 1
<span style="color: #000000;">xpTail</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if xpTail>xpHead then return xpr[xpHead..xpTail-1] 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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if xpTail<=length(xpr) then
<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>
throw("Invalid Char <%c>",{xpr[xpTail]})
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return ""
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

function parse(string s)
<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>
bool expectingOP = false
<span style="color: #004080;">bool</span> <span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
xpr = s
<span style="color: #000000;">xpr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
xpHead = 1
<span style="color: #000000;">xpHead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
num = {}
<span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
opr = {{CBkt,")",-1,NULL,NULL}} -- prevent evaluate null OP precedence.
<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>
while true do
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
token = nextToken()
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nextToken</span><span style="color: #0000FF;">()</span>
if token="" then exit end if
<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>
integer Type = max(find(token,opChar),Num)
<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>
sequence tokenXP = {Type,token,xpHead,NULL,NULL}
<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>
if expectingOP then -- Process OP-alike tokenXP.
<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>
switch token
<span style="color: #008080;">switch</span> <span style="color: #000000;">token</span>
case ")":
<span style="color: #008080;">case</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">:</span>
while opr[$][TYPE]!=OBkt do
<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>
joinXP(pop_opr())
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
end while
{} = pop_opr()
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">()</span>
expectingOP = true
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
case "+", "-", "*", "/":
<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>
while tokenXP[TYPE]<=opr[$][TYPE] do
<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>
joinXP(pop_opr())
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
end while
opr = append(opr,tokenXP)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<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>
expectingOP = false
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
default:
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span>
throw("Expecting Operator or ), not <%s>",{token})
<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>
end switch
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
else -- Process Num-alike tokenXP
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- Process Num-alike tokenXP</span>
switch token
case "+", "-", "*", "/", ")":
<span style="color: #008080;">switch</span> <span style="color: #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>
throw("Expecting Number or (, not <%s>",{token})
<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>
case "(":
<span style="color: #008080;">case</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">:</span>
opr = append(opr,tokenXP)
<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>
expectingOP = false
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
default: -- Number
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">-- Number</span>
num = append(num,tokenXP)
<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>
expectingOP = true
<span style="color: #000000;">expectingOP</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
end switch
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
xpHead = xpTail
<span style="color: #000000;">xpHead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xpTail</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
while length(opr)>1 do // Join pending Op.
<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>
joinXP(pop_opr())
<span style="color: #000000;">joinXP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pop_opr</span><span style="color: #0000FF;">())</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if length(num)!=1 then // Should be just the one (nested) node left.
<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>
throw("Parse Error...")
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Parse Error..."</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return num[1]
<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>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

procedure visit(sequence node)
<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>
if level+1>length(Tree) then
<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>
Tree = append(Tree,"")
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
string str = node[STR]
<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>
integer Type = node[TYPE],
<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>
p = node[POS],
<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>
e = p+length(str)-1
<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>
while length(Tree[level])<e do
<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>
Tree[level] &= ' '
<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>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
Tree[level][p..e] = str
<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>
level += 1
<span style="color: #000000;">level</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if Type=Num then
<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>
resultStr &= str
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">str</span>
result = to_integer(str)
<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>
else
<span style="color: #008080;">else</span>
resultStr &= "("
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"("</span>
visit(node[LHS])
<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>
integer lhs = result
<span style="color: #004080;">integer</span> <span style="color: #000000;">lhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">result</span>
resultStr &= str -- (same as &= opChar[Type])
<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>
visit(node[RHS])
<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>
resultStr &= ")"
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">")"</span>
switch Type
<span style="color: #008080;">switch</span> <span style="color: #000000;">Type</span>
case Add: 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 Sub: 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 Mul: 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>
case Div: result = lhs/result
<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>
default: throw("Invalid type")
<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 switch
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
level -= 1
<span style="color: #000000;">level</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>

procedure CalcVis(sequence ast, string expr)
<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>
result = 0
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
level = 1
<span style="color: #000000;">level</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
resultStr = ""
<span style="color: #000000;">resultStr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
Tree = {}
<span style="color: #000000;">Tree</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
visit(ast)
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ast</span><span style="color: #0000FF;">)</span>
-- More fancy:
<span style="color: #000080;font-style:italic;">-- More fancy:</span>
for i=2 to length(Tree) do
<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>
bool flipflop = false
<span style="color: #004080;">bool</span> <span style="color: #000000;">flipflop</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
for j=1 to length(Tree[i]) 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>
while j>=length(Tree[i-1]) do
<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>
Tree[i-1] &= " "
<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>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer c1 = Tree[i][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>
c2 = Tree[i-1][j]
<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>
if flipflop and c1==' ' and c2==' ' then
<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>
Tree[i-1][j] = '.'
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if c1!='.' and c1!=' '
<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>
and (j==1 or not isDigit(Tree[i][j-1])) then
<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>
flipflop = not flipflop
<span style="color: #000000;">flipflop</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">flipflop</span>
end if
<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>
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: #000080;font-style:italic;">--pp(Tree,{pp_Nest,9999})</span>
end procedure
<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>

<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
constant expr = "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1"
try
<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>
sequence ast = parse(expr)
<span style="color: #008080;">try</span>
CalcVis(ast,expr)
<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>
catch e
<span style="color: #000080;font-style:italic;">-- pp(ast)</span>
?e
<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>
end try</lang>
<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}}
{{out}}
<pre>
<pre>

Latest revision as of 10:15, 13 December 2021

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 visit(ast) and visit(node[LHS/RHS]) do exactly what it says on the tin, whereas a.root.accept(c) and xp.LHS/RHS.accept(this) do not. Plus, 221 lines -> 166 lines, should you wrongly care about that, I know I shouldn't...

-- demo\rosetta\Arithmetic_evaluationD.exw
with javascript_semantics
enum               Num, OBkt, CBkt, Add, Sub, Mul, Div
constant opChar = {"#", "(",  ")",  "+", "-", "*", "/"},
         opPrec = {0,  -9,   -9,      1,   1,   2,   2}
enum TYPE,STR,POS,LHS,RHS -- (for nodes in opr and num)
sequence opr, num

function pop_opr()
    sequence res = opr[$];  opr = opr[1..-2]
    return res
end function

procedure joinXP(sequence x)
    x[RHS] = num[$];  num = num[1..-2]
    x[LHS] = num[$]
    num[$] = x
end procedure

function isDigit(integer ch)
    return ch>='0' and ch<='9'
end function

string xpr, token, resultStr
integer xpHead, xpTail, result, level
sequence Tree

function nextToken()
    while xpHead<=length(xpr) and xpr[xpHead]==' ' do
        xpHead += 1 -- Skip spaces
    end while
    xpTail = xpHead
    if xpHead<=length(xpr) then
        integer ch = xpr[xpHead]
        if find(ch,"()+-*/") then -- valid non-number
            xpTail += 1
        elsif isDigit(ch) then
            while xpTail<=length(xpr) and isDigit(xpr[xpTail]) do
                xpTail += 1
            end while
        end if
        if xpTail>xpHead then return xpr[xpHead..xpTail-1] end if
    end if
    if xpTail<=length(xpr) then
        throw("Invalid Char <%c>",{xpr[xpTail]})
    end if
    return ""
end function

function parse(string s)
    bool expectingOP = false
    xpr = s
    xpHead = 1
    num = {}
    opr = {{CBkt,")",-1,NULL,NULL}} -- prevent evaluate null OP precedence.
    while true do
        token = nextToken()
        if token="" then exit end if
        integer Type = max(find(token,opChar),Num)
        sequence tokenXP = {Type,token,xpHead,NULL,NULL}
        if expectingOP then     -- Process OP-alike tokenXP.
            switch token
                case ")":
                    while opr[$][TYPE]!=OBkt do
                        joinXP(pop_opr())
                    end while
                    {} = pop_opr()
                    expectingOP = true
                case "+", "-", "*", "/":
                    while opPrec[tokenXP[TYPE]]<=opPrec[opr[$][TYPE]] do
                        joinXP(pop_opr())
                    end while
                    opr = append(opr,tokenXP)
                    expectingOP = false
                default:
                    throw("Expecting Operator or ), not <%s>",{token})
            end switch
        else                    -- Process Num-alike tokenXP
            switch token
                case "+", "-", "*", "/", ")":
                    throw("Expecting Number or (, not <%s>",{token})
                case "(":
                    opr = append(opr,tokenXP)
                    expectingOP = false
                default: -- Number
                    num = append(num,tokenXP)
                    expectingOP = true
            end switch
        end if
        xpHead = xpTail
    end while
    while length(opr)>1 do // Join pending Op.
        joinXP(pop_opr())
    end while
    if length(num)!=1 then // Should be just the one (nested) node left.
        throw("Parse Error...")
    end if
    return num[1]
end function

procedure visit(sequence node)
    if level+1>length(Tree) then
        Tree = append(Tree,"")
    end if
    string str = node[STR]
    integer Type = node[TYPE],
            p = node[POS],
            e = p+length(str)-1
    while length(Tree[level])<e do
        Tree[level] &= ' '
    end while
    Tree[level][p..e] = str
    level += 1
    if Type=Num then
        resultStr &= str
        result = to_integer(str)
    else
        resultStr &= "("
        visit(node[LHS])
        integer lhs = result
        resultStr &= str -- (same as &= opChar[Type])
        visit(node[RHS])
        resultStr &= ")"
        switch Type
            case Add: result = lhs+result
            case Sub: result = lhs-result
            case Mul: result = lhs*result
            case Div: result = lhs/result
            default: throw("Invalid type")
        end switch
    end if
    level -= 1
end procedure

procedure CalcVis(sequence ast, string expr)
    result = 0
    level = 1
    resultStr = ""
    Tree = {}
    visit(ast)
    -- More fancy:
    for i=2 to length(Tree) do
        bool flipflop = false
        for j=1 to length(Tree[i]) do
            while j>=length(Tree[i-1]) do
                Tree[i-1] &= " "
            end while
            integer c1 = Tree[i][j],
                    c2 = Tree[i-1][j]
            if flipflop and c1==' ' and c2==' ' then
                Tree[i-1][j] = '.'
            end if
            if c1!='.' and c1!=' '
            and (j==1 or not isDigit(Tree[i][j-1])) then
                flipflop = not flipflop
            end if
        end for
    end for
--pp(Tree,{pp_Nest,9999})
    printf(1,"%s\n%s ==>\n%s = %d\n", {join(Tree,"\n"), expr, resultStr, result})
end procedure

constant expr = "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1"
try
    sequence ast = parse(expr)
--  pp(ast)
    CalcVis(ast,expr)
catch e
    ?e
end try
?"done"
{} = wait_key()
Output:
   ........................................................+.
 .+..                                                        1
1    *...
    2   .-..........
       3     .......*................................
            *...                 ....................-.
           2   .-.            ..-...                   1
              3   2       ...*      /...
                        .-.   5   22   .+..
                       2   4          7    *...
                                          2   .-.
                                             3   1

1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1 ==>
((1+(2*(3-((2*(3-2))*((((2-4)*5)-(22/(7+(2*(3-1)))))-1)))))+1) = 60