How do you read an expression?
- Posted by David Cuny <HW1.DCUNY at HW1.CAHWNET.GOV> Dec 24, 1996
- 1604 views
*** 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