Here you go. The function is completely self-contained.
It treats everything as float though.
;examples:
Print eval("3/4")
Print eval("2^(3+2)")
Print eval("5>1 And 5<100")
WaitKey
End
;All values are considered float
;The string must be less than 256 characters long
Function eval#(s$)
Local lens
s=Lower(s)
s=Replace(s,"and","&")
s=Replace(s,"xor","@")
s=Replace(s,"or","|")
s=Replace(s,"mod","%")
lens=Len(s)
Local value=CreateBank((lens+1)*4)
Local claimed=CreateBank(lens+1)
Local m$,i,oldi,gotpoint,nest
Local cmdpri$,cmdsi$;strings, so numbers can be easily inserted
Local ci,pri
For i=1 To lens
m=Mid(s,i,1)
pri=0
Select m
Case "&","|","@"
pri=1
Case "=","<",">"
pri=2
Case "+","-"
pri=3
Case "*","/","%"
pri=4
Case "^"
pri=5
Case "("
nest=nest+1
Case ")"
nest=nest-1
If nest<0 Then RuntimeError "too many ')'"
Default
If Int(m)<>0 Or m="0" Or m="." Then
;get number into value bank
oldi=i
gotpoint=(m=".")
Repeat
i=i+1
m=Mid(s,i,1)
If m="." Then
If gotpoint=1 Then RuntimeError "2 decimal points!"
gotpoint=1
Else
If Int(m)=0 And m<>"0" Then Exit
EndIf
PokeByte claimed,i,oldi
Forever
PokeFloat value,oldi*4,Float(Mid(s,oldi,i-oldi))
i=i-1
Else
If m<>" " Then RuntimeError "what is '"+m+"' ?"
EndIf
End Select
If pri>0 Then
;insert operators into list by highest priority to lowest
pri=pri+5*nest
For ci=1 To Len(cmdpri)
If pri>Asc(Mid(cmdpri,ci,1)) Then
Exit
EndIf
Next
cmdpri=Left(cmdpri,ci-1)+Chr(pri)+Mid(cmdpri,ci)
cmdsi =Left(cmdsi ,ci-1)+Chr(i )+Mid(cmdsi ,ci)
EndIf
Next
If nest>0 Then RuntimeError "too many '('"
Local lenc
lenc=Len(cmdsi)
Local mi,ii,ii2,add
Local lv#,rv#,ans#
For i=1 To lenc
mi=Asc(Mid(cmdsi,i,1))
;find values to the right and left of operator
For add=-1 To +1 Step 2
ii=mi+add
;skip over spaces and parens
Repeat
m=Mid(s,ii,1)
If m<>" " And m<>"(" And m<>")" Then Exit
ii=ii+add
Forever
;magical code that makes sure it uses the correct order of the priorities
Repeat
ii2=PeekByte(claimed,ii)
If ii2=0 Then Exit
ii=ii2
Forever
PokeByte claimed,ii,mi
If add=-1 Then
lv=PeekFloat(value,ii*4)
Else
rv=PeekFloat(value,ii*4)
EndIf
Next
;do the math and put result in the value bank a the spot of the operator
Select Mid(s,mi,1)
Case "+" ans=lv+rv
Case "-" ans=lv-rv
Case "*" ans=lv*rv
Case "/" ans=lv/rv
Case "=" ans=lv=rv
Case "<" ans=lv<rv
Case ">" ans=lv>rv
Case "&" ans=lv And rv
Case "|" ans=lv Or rv
Case "%" ans=lv Mod rv
Case "^" ans=lv^rv
Case "@" ans=lv Xor rv
Default RuntimeError Mid(s,mi,1)
End Select
PokeFloat value,mi*4,ans
Next
FreeBank value
FreeBank claimed
Return ans
End Function
|