example input
5!
-2^2
a$ = " "
WHILE a$ <> ""
LINE INPUT "? "; a$
result# = eval(a$)
PRINT result#
WEND
END
FUNCTION eval# (ee AS STRING)
DIM i AS INTEGER
DIM id AS INTEGER
DIM l AS INTEGER
DIM fn AS INTEGER
DIM aa AS STRING
DIM d2 AS STRING
DIM e2 AS STRING
DIM s2 AS STRING
DIM ch2 AS STRING
DIM g AS _FLOAT
DIM x AS _FLOAT
DIM fc AS DOUBLE
DIM v##(20)
e2 = UCASE$(ee)
IF LEN(e2) = 0 THEN e2 = "0"
i = 1: id = 0: l = LEN(e2): s2 = "": fn = 0
GOSUB scan
GOSUB expr
IF ch2 <> " " OR id > 1 THEN
PRINT
PRINT "Syntax Error"
PRINT
END IF
eval# = v##(0)
EXIT FUNCTION
'================================
scan:
IF i > l THEN
ch2 = " "
RETURN
END IF
ch2 = MID$(e2, i, 1)
i = i + 1
IF ch2 = " " THEN GOSUB scan
RETURN
unary:
IF ch2 = "-" OR ch2 = "+" THEN
s2 = s2 + ch2
GOSUB scan
GOSUB term
aa = RIGHT$(s2, 1)
s2 = LEFT$(s2, LEN(s2) - 1)
IF aa <> "-" THEN RETURN
v##(id - 1) = -v##(id - 1)
RETURN
END IF
GOSUB factor
RETURN
gamma:
GOSUB unary
WHILE ch2 = "!"
x = v##(id - 1)
GOSUB factorial
v##(id - 1) = g
GOSUB scan
WEND
RETURN
expon:
GOSUB gamma
WHILE ch2 = "^"
GOSUB scan
GOSUB gamma
id = id - 1
v##(id - 1) = v##(id - 1) ^ v##(id)
WEND
RETURN
term:
GOSUB expon
WHILE (ch2 = "*" OR ch2 = "/")
s2 = s2 + ch2
GOSUB scan
GOSUB expon
aa = RIGHT$(s2, 1)
s2 = LEFT$(s2, LEN(s2) - 1)
IF aa = "*" THEN
id = id - 1
v##(id - 1) = v##(id - 1) * v##(id)
END IF
IF aa = "/" THEN
id = id - 1
v##(id - 1) = v##(id - 1) / v##(id)
END IF
WEND
RETURN
expr:
GOSUB term
WHILE (ch2 = "-" OR ch2 = "+")
s2 = s2 + ch2
GOSUB scan
GOSUB term
aa = RIGHT$(s2, 1)
s2 = LEFT$(s2, LEN(s2) - 1)
IF aa = "-" THEN
id = id - 1
v##(id - 1) = v##(id - 1) - v##(id)
END IF
IF aa = "+" THEN
id = id - 1
v##(id - 1) = v##(id - 1) + v##(id)
END IF
WEND
RETURN
factor:
IF ch2 = "E" THEN
IF MID$(e2, i - 1, 2) <> "EX" THEN
v##(id) = 2.71828182845904523536##
id = id + 1
GOSUB scan
RETURN
END IF
END IF
IF ch2 = "P" AND MID$(e2, i - 1, 2) = "PI" THEN
v##(id) = 3.14159265358979323846##
id = id + 1
i = i + 1
GOSUB scan
RETURN
END IF
IF INSTR(".0123456789", ch2) THEN
d2 = ""
WHILE INSTR("DE.0123456789", ch2)
d2 = d2 + ch2
GOSUB scan
WEND
v##(id) = VAL(d2)
id = id + 1
RETURN
END IF
IF ch2 = "(" THEN
GOSUB scan
GOSUB expr
IF ch2 = "," THEN
GOSUB scan
GOSUB expr
END IF
IF ch2 <> ")" THEN
PRINT
PRINT "Missing ')'"
END IF
'IF fn = 0 THEN
GOSUB scan
'END IF
RETURN
END IF
IF ch2 = "A" THEN
IF MID$(e2, i - 1, 4) = "ABS(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = ABS(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "ACOS(" THEN
i = i + 3 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _ACOS(v##(id - 1))
ELSEIF MID$(e2, i - 1, 6) = "ACOSH(" THEN
i = i + 4
GOSUB scan
GOSUB factor
v##(id - 1) = _ACOSH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 7) = "ARCCOT(" THEN
i = i + 5
GOSUB scan
GOSUB factor
v##(id - 1) = _ARCCOT(v##(id - 1))
ELSEIF MID$(e2, i - 1, 7) = "ARCCSC(" THEN
i = i + 5
GOSUB scan
GOSUB factor
v##(id - 1) = _ARCCSC(v##(id - 1))
ELSEIF MID$(e2, i - 1, 7) = "ARCSEC(" THEN
i = i + 5
GOSUB scan
GOSUB factor
v##(id - 1) = _ARCSEC(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "ASIN(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _ASIN(v##(id - 1))
ELSEIF MID$(e2, i - 1, 6) = "ASINH(" THEN
i = i + 4
GOSUB scan
GOSUB factor
v##(id - 1) = _ASINH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "ATN(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = ATN(v##(id - 1))
ELSEIF MID$(e2, i - 1, 6) = "ATAN2(" THEN
i = i + 4
GOSUB scan
GOSUB factor
id = id - 1
v##(id - 1) = _ATAN2(v##(id - 1), v##(id))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function A" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "C" THEN
IF MID$(e2, i - 1, 4) = "COS(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = COS(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "COSH(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _COSH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "COT(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = _COT(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "COTH(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _COTH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "CSC(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _CSC(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "CSCH(" THEN
i = i + 3 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _CSCH(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function C" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "D" THEN
IF MID$(e2, i - 1, 4) = "D2G(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _D2G(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "D2R(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = _D2R(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function D" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "E" THEN
IF MID$(e2, i - 1, 4) = "EXP(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = EXP(v##(id - 1))
ELSEIF MID$(e2, i - 1, 6) = "EXP10(" THEN
i = i + 4 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = EXP(v##(id - 1) * 2.3025850929940456840##)
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function E" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "G" THEN
IF MID$(e2, i - 1, 4) = "G2D(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _G2D(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "G2R(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = _G2R(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function G" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "H" THEN
IF MID$(e2, i - 1, 6) = "HYPOT(" THEN
i = i + 4 'advance pointer to just before "("
GOSUB scan
GOSUB factor
id = id - 1
v##(id - 1) = _HYPOT(v##(id - 1), v##(id))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function H" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "I" THEN
IF MID$(e2, i - 1, 4) = "INT(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = INT(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function I" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "L" THEN
IF MID$(e2, i - 1, 4) = "LOG(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = LOG(v##(id - 1))
ELSEIF MID$(e2, i - 1, 6) = "LOG10(" THEN
i = i + 4 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = LOG(v##(id - 1)) * 0.43429448190325182765##
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function L" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "R" THEN
IF MID$(e2, i - 1, 4) = "R2D(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = _R2D(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "R2G(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = _R2G(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function R" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "S" THEN
IF MID$(e2, i - 1, 4) = "SIN(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = SIN(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "SINH(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _SINH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "SEC(" THEN
i = i + 2
GOSUB scan
GOSUB factor
v##(id - 1) = _SEC(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "SECH(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _SECH(v##(id - 1))
ELSEIF MID$(e2, i - 1, 4) = "SQR(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = SQR(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function S" + MID$(e2, i, k% - i)
END IF
ELSEIF ch2 = "T" THEN
IF MID$(e2, i - 1, 4) = "TAN(" THEN
i = i + 2 'advance pointer to just before "("
GOSUB scan
GOSUB factor
v##(id - 1) = TAN(v##(id - 1))
ELSEIF MID$(e2, i - 1, 5) = "TANH(" THEN
i = i + 3
GOSUB scan
GOSUB factor
v##(id - 1) = _TANH(v##(id - 1))
ELSE
k% = INSTR(i, e2, "(")
PRINT "unknown function T" + MID$(e2, i, k% - i)
END IF
END IF
RETURN
factorial:
g = 1##
FOR fc = 1 TO x
g = g * fc
NEXT fc
RETURN
END FUNCTION
bug fixed, should be OK now, the only funny thing is that because I wanted to support the atan2 function which takes 2 values is that it won't complain if you enter "(1, 2)" for example
but as long as you enter a valid math expression it should give a reasonably correct answer