Κυριακή 5 Μαρτίου 2023

Revision 19 Version 12 (Udpate2)

Update2: More compact code! Removed class, and we have only one function AST() which have two subroutines. Subs in M2000 may change the stack of values, which is the same as the one in the module/function from where we call it. A stack Op { } block put temporary the Op object as current stack and after the exit from the block we get the old untouched stack. (the "original" stack of function never exposed as a pointer to get it as stack object. There is th [] read only variable which get the pointer of current stack and leave an empty stack. So to get the current stack as object we have to swap it with an empty one. so k=[] get the current object to K, and stack K move all items to current stack at the end, so K now is a pointer to an empty stack. Stack New { } is a block which pass an empty stack as current stack, and hold old one, without using variable, and at the exit the old one released as current stack.

Update1: Now Evaluator works fine (will be update in INFO on revision 20). Expressions like 2*-(3) (unary sign after mul/div and then parenthesis).


Evaluator for expressions now use the unary + (identity). Also fixed the error (-2)^2 which now return 4 (not -4). Also some commands like Open, Input, Clipboard can work with string variables without suffix $/ (I am working to fix all the commands)

I add the Evaluator module (the code is bellow). I make this tool to adjust the M2000 evaluator (which is way different from this). So this evaluator get an expression and produce a list of numbers and symbols as RPN (Reverse Polish Notation), using unary - +, and ^, *, /, +, - and parenthesis ( ), and numbers (could be floating point too). The list is a stack object which have fields for numbers and strings (stack objects can hold anything including objects, they have a Vb6 collection object inside). We can process that list to calculate the result. Also there is a function which get the string representation of stack item (we can do that making a copy and then use that copy to produce an array, and that array can be stringify  using #str$() function - see code bellow).

This is the output of the program:





Need version 12 revision 19


form 96, 82
Module CheckEvaluator (Expr$) {
function rpn_to_infix$(a$) {
def m=0
inventory precedence="-":=2,"+":=2,"*":=3,"/":=3,"u-":=4, "u+":=4, "^":=5
dim token$()
token$()=piece$(a$," ")
l=len(token$())
dim type(l)=0, right(l)=0, infix$(l)
infix=-1
for i=0 to l-1
if exist(precedence, token$(i)) then
type(i)=precedence(token$(i))
if type(i)>=4 then right(i)=-1
end if
if type(i)=0 then
infix++
infix$(infix)=token$(i)
type(infix)=100
else
if right(i) then
if type(i)=5 then
if type(infix)<type(i) then infix$(infix)="("+infix$(infix)+")"
if type(infix-1)<100 then infix$(infix-1)="("+infix$(infix-1)+")"
infix$(infix-1)=infix$(infix-1)+token$(i)+infix$(infix)
else.if token$(i)="u-" then
infix$(infix)="-"+infix$(infix)
infix++
else
infix$(infix)="+"+infix$(infix)
infix++
end if
else
if type(infix)<type(i) then infix$(infix)="("+infix$(infix)+")"
if type(infix-1)<type(i) then
infix$(infix-1)="("+infix$(infix-1)+")"+token$(i)+infix$(infix)
else
infix$(infix-1)=infix$(infix-1)+token$(i)+infix$(infix)
end if
end if
type(infix-1)=type(i)
infix--
end if
next i
=infix$(0)
}
Function Ast(&in$) {
flush
Ast()
=[]

sub Ast()
Local op=stack
do
Ast1()
do
in$=Ltrim$(in$)
oper$=left$(in$,1)
if oper$="*" then
in$=Mid$(in$, 2)
Ast1()
data "*"
else.if oper$="/" then
in$=Mid$(in$, 2)
Ast1()
data "/"
else
exit
end if
until len(in$)=0
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("+-", oper$)>0 else exit
stack op
if len(oper$)>0 then stack op {data oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack op
End sub
Sub Ast1()
local object op1=stack
local integer m
do
do
in$=Trim$(in$)
oper$=left$(in$,1)
if oper$="-" then
in$=Mid$(in$, 2)
stack op1 {push "u-"}
else.if oper$="+" then
in$=Mid$(in$, 2)
stack op1 {push "u+"}
else
exit
end if
always
in$=Trim$(in$)
if Asc(in$)<>40 then
string ch="", num=""
boolean once=false
do
ch=left$(in$,1)
if once then
if instr("0123456789", ch)>0 else exit
else
if instr(".0123456789", ch)>0 else exit
if ch="." then once=true
end if
num+=ch
in$=Mid$(in$, 2)
until len(in$)=0
if num="." then Error "missing number"
if len(num)=0 then =stack: exit
data val(num)
else
in$=Mid$(in$, 2)
Ast()
in$=Mid$(in$, 2)
end if


m++
in$=Trim$(in$)
oper$=left$(in$,1)
if m>1 then
data "^"
if oper$<>"^" then stack op1
end if
if oper$="^" else exit
in$=ltrim$(Mid$(in$, 2))
oper$=left$(in$,1)
if Instr("-+", oper$)>0 then
Ast1()
data "^"
   exit
end if
until len(in$)=0
stack op1
end sub
}
Pen 15 {
Pen 12 {print "input expression:";}
Pen 14 {print Expr$}
print "Result through eval$:";
pen 10 {print eval(Expr$)}
mres=Ast(&Expr$)
print "computed RPN    :";array(stack(mres))#str$()
MM$=rpn_to_infix$(array(stack(mres))#str$())
print "cumputed INFIX  :";rpn_to_infix$(array(stack(mres))#str$())
print "Using Eval$() on infix:";eval(MM$)
pen 11 {
Print "Compute RPN value:";
}
reg=stack
mm=each(mres)
while mm
if stacktype$(mm)="String" then
stack reg {
select case stackitem$(mm)
case "+"
push number+number
case "-"
shift 2:push number-number
case "*"
push number*number
case "/"
shift 2: push number/number // shift 2 swap top 2 values
case "^"
shift 2:push number**number
case "u-"
push -number
end select
}
else
stack reg {push stackitem(mm)}
end if
end while
if len(reg)<>1 then Error "Wrong Evaluation" else pen 10 { print stackitem(reg)}
}
}
cls
Report{INFIX to RPN to INFIX example - Compute value for RPN through flat list (as stack object)
Symbols: + - * / ^  ( ) 0 1 2 3 4 5 6 7 8 9 .
Precedence (high to low): Exponentiation (^), unary identity (+) and  negation (-), Multiplication (*)and Division (/), Addition (+) and Subtraction (-)
}
CheckEvaluator "-2^+3^-4"
CheckEvaluator "-2^-3^-4"
CheckEvaluator "-2^(-3)^-4"
CheckEvaluator "-2^2-2^2"
CheckEvaluator "-2^3-2^3"
CheckEvaluator "(-2.5)^2"
CheckEvaluator "(-2)^3"
CheckEvaluator "(-(2))^3"
CheckEvaluator "--++--3.45"
CheckEvaluator "1+2 * (3 + ( 2 ^ 2 * 5 + 6 * 7 * 2^3) - 9) / 10"
CheckEvaluator "2/3/4"
CheckEvaluator "2*-(3)/-4*(-5)+--3"


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.