Reputation: 29
So we started learning python in one of my classes, and now we are messing around with postfix/prefix notations. I looked around the web for some examples, and found this code, but i don't fully understand it. My question is regarding evaluate and parse functions. What is the deal with "trace" Why is it there, what does it do(if trace blocks)?
import operator
import string
import operator
import string
class EvaluationError(Exception):
pass
class InvalidParse(Exception):
pass
class InvalidNumber(Exception):
pass
class InvalidOperator(Exception):
pass
class UnbalancedParens(Exception):
pass
def cast(value):
if isinstance(value, (int, float)):
return value
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
raise InvalidNumber(value)
class Operator(object):
def __init__(self, op, precedence):
self._op = op
self._prec = precedence
def __call__(self, *args):
return self._op(*args)
def __lt__(self, op):
return self._prec < op._prec
def __gt__(self, op):
return self._prec > op._prec
def __eq__(self, op):
return self._prec == op._prec
def __repr__(self):
return repr(self._op)
def __str__(self):
return str(self._op)
class Calculator(object):
operators = {
'+' : Operator(operator.add, 1),
'-' : Operator(operator.sub, 1),
'*' : Operator(operator.mul, 2),
'/' : Operator(operator.div, 2),
'^' : Operator(operator.pow, 3),
}
def __init__(self):
pass
def calculate(self, expr):
tokens = self.parse(expr)
result = self.evaluate(tokens)
return result
def evaluate(self, tokens, trace=False):
stack = []
for item in tokens:
if isinstance(item, Operator):
if trace:
print stack
b, a = cast(stack.pop()), cast(stack.pop())
result = item(a, b)
stack.append(result)
if trace:
print stack
else:
if item.endswith('.'):
raise InvalidNumber(item)
stack.append(item)
if len(stack) > 1:
raise EvaluationError(str(stack))
return stack[0]
def parse(self, expr, trace=False):
tokens = []
op_stack = []
last = None
for c in expr:
if c in string.whitespace:
last = c
elif c in string.digits:
value = str(c)
if last and last in string.digits:
value = tokens.pop() + value
last = c
tokens.append(value)
elif c == '.':
if last and last in string.digits:
tokens.append(tokens.pop() + ".")
else:
raise InvalidParse()
elif c == '(':
op_stack.append('(')
elif c == ')':
if not op_stack:
raise UnbalancedParens(c)
while op_stack:
curr = op_stack.pop()
if curr is '(':
break
else:
tokens.append(curr)
else:
op = self.operators.get(c, None)
if op is None:
raise InvalidOperator(c)
while op_stack:
curr = op_stack[-1]
if curr is '(':
break
elif curr < op:
break
tokens.append(op_stack.pop())
op_stack.append(op)
last = c
if trace:
print "----"
print tokens
print op_stack
print "----"
while op_stack:
op = op_stack.pop()
if op is '(':
raise UnbalancedParens()
tokens.append(op)
if trace:
print "----"
print tokens
print op_stack
print "----"
return tokens
if __name__ == '__main__':
import sys
calc = Calculator()
print calc.calculate("12^2.5-10")
Upvotes: 0
Views: 49
Reputation: 34145
Literally what it says in the code. If trace
is set to True
, you'll get the stack printed out at various point of execution. This seems to exist for debugging / presentation purposes.
Upvotes: 1