Arithmetic evaluation: Difference between revisions

Content added Content deleted
(Added XPL0 example.)
Line 3,763: Line 3,763:
</syntaxhighlight>
</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">
<syntaxhighlight lang="m2000 interpreter">
Module CheckAst {
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
until len(in$)=0
=stack(Ast, op)
="("+ast$+")"
}
}
Function Ast1$ (&in$) {
Function Ast1(&in$) {
object Ast=stack, op=stack
Def ast$, oper$
Do
Do {
Ast$+=.Ast2$(&in$)
stack Ast {stack .Ast2(&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
if len(oper$)>0 then stack op {push oper$}
ast$+=oper$
in$=Mid$(in$, 2)
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$=Trim$(in$)
in$=Mid$(in$, 2)
=.Ast(&in$)
if Asc(in$)<>40 then =.Number$(&in$) : exit
in$=Mid$(in$, 2)
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
CheckAst
</syntaxhighlight>
</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}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==