How do you read an expression?
*** Reply to note of 12/23/96 21:18
*** WARNING: a lot of code to follow ***
this will read an expression. there are a number of things that it will
*not* do, such as double unary signs (--3) and operator precedence. on the
other hand, it *will* handle the expressions you've got, as long as you
use parenthesis.
this code is *not* extensively tested. it does a parse-on-the-fly, rather
than a robust tokenize/parse/execute. on the other hand, it is fairly
small, and almost readable.
if this is too large of a post, let me know, and i will avoid such in the
future. *please* no flames, etc. there are no guarantees to the fitness
of the code; etc. etc. etc. i put it together fairly rapidly.
--- CODE STARTS HERE ---
global atom x -- your "x" variable
global integer p -- current character being parsed in string
function math( atom a, integer op, atom b )
-- perform operation OP with A and B
if op = '+' then
return a + b
elsif op = '-' then
return a - b
elsif op = '*' then
return a * b
elsif op = '/' then
if b = 0 then
-- your error handler here. division by zero.
return 0
else
return a / b
end if
elsif op = '^' then
return power( a, b )
elsif op = '=' then
return b
elsif op = 0 then
return a
else
-- your error handler here.
-- op was not recognized
return 1
end if
end function
function isNumber( integer i )
-- return true if character is part of a number
if i = '.' then
return -1 -- decimal place
else
return i >= '0' and i <= '9' -- true if ranges from '0' to '9'
end if
end function
function isOp( integer i )
-- return true if character is an operand
return i = '+' or i = '-' or i = '*' or i = '/' or i = '^'
end function
function parse1( sequence s )
integer op, decimal, sign
atom accum, num
op = '=' -- first operation is assignment to accumulator
accum = 0 -- initialize accumulator
sign = 1 -- unary minus
while p <= length(s) do -- scan
if s[p] = '(' then -- left paren
p = p + 1 -- move past the paren
num = parse1( s ) -- recurse
accum = math( accum, op, num ) -- accumulate
elsif s[p] = ')' then
return accum -- return parsed expression
elsif s[p] = '-' then
-- handle unary minus
if p = 1 then -- first character in string
sign = -1 -- unary minus
elsif isOp( s[p-1] ) then -- prior character was op
sign = -1 -- unary minus
else
op = s[p] -- operand
end if
elsif isOp( s[p] ) then
op = s[p] -- assign operand to pending operation
elsif s[p] = 'x' then
accum = math( accum, op, x * sign ) -- variable
sign = 1 -- clear the sign
elsif isNumber( s[p] ) then -- number
num = 0 -- clear accumulator
decimal = 0 -- no decimal place
while isNumber( s[p] ) do -- while it's a number
if s[p] = '.' then
decimal = 1
else
num = ( num * 10 ) + ( s[p] - '0' ) -- accumulate
decimal = decimal * 10 -- decimal place
end if
p = p + 1 -- increment pointer
end while
if decimal > 0 then -- was there a decimal place?
num = num / decimal -- divide by the decimal amount
end if
p = p - 1 -- back up one character (we went too far)
num = num * sign -- add sign
sign = 1 -- clear sign
if s[p+1] = 'x' then -- handle stuff like 3x
p = p + 1 -- move past x
accum = math( accum, op, num * x ) -- include in operation
else
accum = math( accum, op, num ) -- perform pending operation
end if
else
-- your error handler here.
-- there is an error in the expression
end if
p = p + 1 -- increment to the next character
end while
return accum
end function
function parse( sequence s )
-- main parsing function call
p = 1 -- set pointer to first character
return parse1( s ) -- parse expression
end function
-- test it
sequence expression
atom result
x = 22 -- put value in x
expression = "" -- initialize
while compare( expression, "\n" ) do -- until a blank line is entered
puts( 1, "\n Give me an expression >" ) -- prompt
expression = gets(0) -- get expression
result = parse( expression )-- parse it
printf( 1, "\nThe result is: %g", result ) -- print results
end while
--- CODE ENDS HERE
merry christmas, all.
-- David Cuny
|
Not Categorized, Please Help
|
|