ThatNinja
ThatNinja

Reputation: 29

What is "trace" parameter to evaluate function?

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

Answers (1)

viraptor
viraptor

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

Related Questions