RosettaCodeData/Task/Arithmetic-evaluation/M2000-Interpreter/arithmetic-evaluation-2.m2000

86 lines
1.7 KiB
Plaintext

Module CheckAst {
class EvalAst {
private:
Function Ast(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast1(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("+-", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op} // dump op to end of stack Ast
=Ast
}
Function Ast1(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast2(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("*/", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op}
=Ast
}
Function Ast2(&in$) {
in$=Trim$(in$)
if Asc(in$)<>40 then =.GetNumber(&in$) : exit
in$=Mid$(in$, 2)
=.Ast(&in$)
in$=Mid$(in$, 2)
}
Function GetNumber (&in$) {
Def ch$, num$
Do
ch$=left$(in$,1)
if instr("0123456789", ch$)>0 else exit
num$+=ch$
in$=Mid$(in$, 2)
until len(in$)=0
=stack:=val(num$)
}
public:
value () {
=.Ast(![])
}
}
Ast=EvalAst()
Expr$ = "1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
// 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