Post by tsh73 on Oct 11, 2018 10:30:37 GMT
As you probably know JB lacks EVAL function
but the hardly stops anyone
Here three (old) attempts at evaluating math expression from string, two mine, one from old forum - original author is Balaji
If you have better one just add.
1. Really naïve attempt at evaluating.
Find innermost expression - evaluate - substitute back - continue until done.
At JB Files archive.
jbfilesarchive.com/phpBB3/viewtopic.php?f=5&t=1230
2. one with lot's of stacks - likely shunting yard related.
a program which parses and evaluates arithmetic expressions with An abstract-syntax tree (AST)
on Rosetta code
rosettacode.org/wiki/Arithmetic_evaluation#Liberty_BASIC
3. FreeCalc by Balaji
I think this one uses recursive descent approach
last version I have stored commented
'v.2.01 - modif by Stefan Pendl'v.2.01 - modif by Stefan Pendl
global inp$, pos, char$, error$, count, useDegrees
dim var$(100), value(100)
' default for angular units is radians
useDegrees = 0
print "FreeCalc 2.0"
print "Welcome. Enter 'help' to view FreeCalc Help. Enter 'exit' to close FreeCalc"
print
print "Trigonometric Functions use Radians!"
print
[input]
input inp$
if inp$="" then [input]
inp$=lower$(inp$)
gosub [command]
if command then [input]
ans$=JBeval$()
if error$<>"" then print:ans$="ERROR: ";error$
print ans$
if error$<>"" then print
goto [input]
[command]
command=1
select case inp$
case "exit"
print "Thank You for using FreeCalc"
END
case "help"
print "FreeCalc Help"
print " FreeCalc is an expression evaluator. It supports variables and can store values."
print "Integers, floating point & scientific notation numbers are accepted.."
print: print "Operators(In evaluation order):"
print "- -> Negative"
print "() -> Parenthesis"
print "*/ -> Multiplication, Division"
print "+- -> Addition, Subtraction"
print: print "Expressions can be entered directly. Assignment statements must start with ':'"
print "Variables names must consist of one or more alphabets. No digits are allowed."
print: print "Examples:"
print "?12*15"
print "?:side=5.1e2/2"
print "?:area=pow(side,2)"
print: print "Predefined functions:"
print "pi(), sin(n), cos(n), tan(n), asin(n), acos(n), atan(n), log(n), exp(n), sqrt(n), pow(n, p)"
print: print "Commands:"
print "about -> Displays information about FreeCalc"
print "clear -> Clears the screen"
print "exit -> Exit FreeCalc"
print "help -> FreeCalc help"
print "var -> Displays currently used variables and their values"
print "degrees -> Values for trigonometric functions are degrees"
print "radians -> Values for trigonometric functions are radians (the default)"
print "Commands and variable names are not case sensitive": print
case "clear"
cls
case "var"
print "Total ";count;" variables stored in memory"
for i=1 to count
print var$(i);"=";value(i)
next i
case "degrees"
print:print "Trigonometric Functions use Degrees!":print
useDegrees = 1
case "radians"
print:print "Trigonometric Functions use Radians!":print
useDegrees = 0
case "about"
print "FreeCalc"
print "Version 2.0"
print "Written by Balaji": print
case else
command=0
end select
return
function JBeval$()
pos=0: error$=""
call nextChar
if char$=":" then
JBeval$=assignment$()
else
JBeval$=str$(expression())
end if
if pos<=len(inp$) and error$="" then error$="Unknown Command: "; inp$
end function
function assignment$()
call nextChar
var$=getID$()
if error$<>"" then exit function
index=getIndex(var$)
if match("=")=0 then exit function
value=expression()
value(index)=value
assignment$=var$(index);"=";value(index)
end function
function expression()
expression=addTerm()
if error$<>"" then exit function
end function
function addTerm()
ans=multTerm()
do while instr("+-", char$)>0
op$=char$
call nextChar
temp=multTerm()
if error$<>"" then exit function
if op$="+" then ans=ans+temp else ans=ans-temp
loop
addTerm=ans
end function
function multTerm()
ans=factor()
do while instr("*/", char$)>0
op$=char$
call nextChar
temp=factor()
if error$<>"" then exit function
if op$="*" then
ans=ans*temp
else
if temp=0 then
error$="Division by zero"
exit function
end if
ans=ans/temp
end if
loop
multTerm=ans
end function
function factor()
if isAlpha() then
id$=getID$()
if char$="(" then
factor=getFunction(id$)
else
factor=getValue(id$)
end if
exit function
end if
select case char$
case "("
call nextChar
factor=expression()
if error$<>"" then exit function
if match(")")=0 then exit function
case "-"
call nextChar
factor=-1*factor()
case else
factor=getNum()
end select
end function
function getValue(var$)
i=getIndex(var$)
getValue=value(i)
end function
function getIndex(var$)
for i=1 to count
if var$(i)=var$ then
getIndex=i
exit function
end if
next i
count=count+1
var$(count)=var$
getIndex=count
end function
function getID$()
do while isAlpha()
getID$=getID$;char$
call nextChar
loop
if getID$="" then error$="Expected variable"
end function
function getNum()
do while isDigit()
n$=n$;char$
call nextChar
loop
if n$="" then error$="Expected Number"
if char$="." then
n$=n$;"."
call nextChar
do while isDigit()
n$=n$;char$
call nextChar
loop
end if
if char$="e" then
n$=n$;"e"
call nextChar
do while isDigit()
n$=n$;char$
call nextChar
loop
end if
getNum=val(n$)
end function
function getFunction(fname$)
if match("(")=0 then exit function
if instr(" pi ", " ";fname$;" ") then call param0
if instr(" sin cos tan asin acos atan sqrt exp log ", " ";fname$;" ") then call param1 n
if instr(" sin cos tan ", " ";fname$;" ") and (useDegrees = 1) then n = asn(1) / 90 * n
if instr(" pow ", " ";fname$;" ") then call param2 n1, n2
if error$<>"" then exit function
select case fname$
case "pi"
ans=asn(1)*2
case "sin"
ans=sin(n)
case "cos"
ans=cos(n)
case "tan"
ans=tan(n)
case "asin"
ans=asn(n)
case "acos"
ans=acs(n)
case "atan"
ans=atn(n)
case "sqrt"
ans=sqr(n)
case "exp"
ans=exp(n)
case "log"
ans=log(n)
case "pow"
ans=n1 ^ n2
case else
error$="Unknown function: "; fname$
end select
if instr(" asin acos atan ", " ";fname$;" ") and (useDegrees = 1) then ans = 90 / asn(1) * ans
getFunction=ans
end function
sub param0
if match(")")=0 then exit sub
end sub
sub param1 BYREF num
num=expression()
if error$<>"" then exit sub
if match(")")=0 then exit sub
end sub
sub param2 BYREF num1, BYREF num2
num1=expression()
if error$<>"" then exit sub
if match(",")=0 then exit sub
num2=expression()
if error$<>"" then exit sub
if match(")")=0 then exit sub
end sub
function isDigit()
isDigit=(char$>="0" and char$<="9")
end function
function isAlpha()
isAlpha=(char$>="a" and char$<="z")
end function
function match(c$)
if char$=c$ then
match=1
call nextChar
else
error$="Expected ";c$
end if
end function
sub nextChar
pos=pos+1
char$=mid$(inp$, pos, 1)
end sub