Arithmetic evaluation: Difference between revisions

(Added XPL0 example.)
Line 3,763:
</syntaxhighlight>
 
New version of the task program. Based on BBC Basic. Exclude the final use of Eval() function (we use it for test only)
From BBC BASIC. In M2000 we can't call a user function which isn't a child function, so here we make all functions as members of same group, so now they call each other. A function as a member in a group can use other members, using a dot or This and a dot, so .Ast$() is same as This.Ast$().
The Ast is a stack object which have strings and numbers. String are operators. This stack has all members in a RPN form. So it is easy to extract numbers and push them to reg (a stack also), and process the operators as they pop from the stack. There is no unary operator.
 
So the Ast isn't a tree here, it is a flat list.
 
<syntaxhighlight lang="m2000 interpreter">
Module CheckAst {
class EvalAst {
Group Eval {
private:
Function Ast$ (&in$) {
Function Ast(&in$) {
Def ast$, oper$
object Ast=stack, op=stack
Do {
Do
Ast$+=.Ast1$(&in$)
stack Ast {stack .Ast1(&in$)}
in$=Trim$(in$)
in$=Trim$(in$)
oper$=left$(in$,1)
oper$=left$(in$,1)
if Instr("+-", oper$)>0 then {
if Instr("+-", oper$)>0 else exit
ast$+=oper$
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
in$=Mid$(in$, 2)
} else exit
} until len(in$)=0
=stack(Ast, op)
="("+ast$+")"
}
}
Function Ast1$ (&in$) {
object Ast=stack, op=stack
Def ast$, oper$
Do
Do {
stack Ast {stack Ast$+=.Ast2$(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("*/", oper$)>0 thenelse {exit
if len(oper$)>0 then stack op {push oper$}
ast$+=oper$
in$=Mid$(in$, 2)
until len(in$)=0
} else exit
=stack(Ast, op)
} until len(in$)=0
}
="("+ast$+")"
Function Ast2(&in$) {
}
in$=Trim$(in$)
Function Ast2$ (&in$) {
if Asc(in$)<>40 then =.GetNumber(&in$) : exit
Def ast$, oper$
in$=TrimMid$(in$, 2)
=.Ast(&in$)
if Asc(in$)<>40 then =.Number$(&in$) : exit
in$=Mid$(in$, 2)
}
ast$=.Ast$(&in$)
Function GetNumber (&in$) {
in$=Mid$(in$, 2)
Def ch$, num$
=ast$
Do
}
ch$=left$(in$,1)
Function Number$ (&in$) {
if instr("0123456789", ch$)>0 else exit
Def ch$, num$
num$+=ch$
Do {
in$=Mid$(in$, 2)
ch$=left$(in$,1)
until len(in$)=0
if instr("0123456789", ch$)>0 Then {
=stack:=val(num$)
num$+=ch$
}
in$=Mid$(in$, 2)
public:
} Else Exit
value () {
} until len(in$)=0
=.Ast(![])
=num$
}
}
}
}
Ast=EvalAst()
Expr$ = "1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
Expr$ = "1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
Print Eval(Eval.Ast$(&Expr$))=71
// Expr$="1/2+(4-3)/2+1/2"
print "Result through eval$:";eval(Expr$)
print "Expr :";Expr$
mres=Ast(&Expr$)
print "RPN :";array(stack(mres))#str$()
reg=stack
stack mres {
while not empty
if islet then
read op$
stack reg {
select case op$
case "+"
push number+number
case "-"
shift 2:push number-number
case "*"
push number*number
case "/"
shift 2:push number/number // shif 2 swap top 2 values
end select
}
else
read v
stack reg {push v}
end if
end while
}
if len(reg)<>1 then Error "Wrong Evaluation"
print "Result :";stackitem(reg)
}
CheckAst
</syntaxhighlight>
 
{{out}}
<pre>
Result through eval$:71
Expr : 1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10
RPN : 1 2 3 4 5 * 6 7 8 * * + 9 - + 10 / * +
Result :71
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
404

edits