Example #1
0
def calc(text: str):
    """Read and evaluate a single line formula."""
    try:
        tokens = lex.TokenStream(io.StringIO(text))
        stack = []
        while tokens.has_more():
            tok = tokens.take()
            if tok.kind == lex.TokenCat.INT:
                stack.append(expr.IntConst(int(tok.value)))
            elif tok.kind == lex.TokenCat.PLUS:
                right = stack.pop()
                left = stack.pop()
                stack.append(expr.Plus(left, right))
    except lex.LexicalError as e:
        print(f"*** Lexical error {e}")
        return
    except IndexError:
        # Stack underflow means the expression was imbalanced
        print(f"*** Imbalanced RPN expression, missing operand at {tok.value}")
        return
    if len(stack) == 0:
        print("(No expression)")
    else:
        # For a balanced expression there will be one Expr object
        # on the stack, but if there are more we'll just print
        # each of them
        for exp in stack:
            print(f"{exp} => {exp.eval()}")
Example #2
0
    def expr(self, node) -> expr.Expr:
        #        if node is None:
        #            return expr.UnspecifiedExpr()
        #        else:
        #            #print('NODE', node, self.datum(node))
        #            return self.datum(node).expr(self, node)

        #HACK Should do this by inheritance, but it's pretty readable
        #having it all here.
        if self.is_of_class(node, 'Plus'):
            return expr.Plus(*(self.expr(rand)
                               for rand in self.neighbors(node, 'operands')))
        elif self.is_of_class(node, 'Minus'):
            return expr.Minus(self.neighbor(node, 'minuend'),
                              self.neighbor(node, 'subtrahend'))
        elif self.is_of_class(node, 'Times'):
            return expr.Times(*(self.expr(rand)
                                for rand in self.neighbors(node, 'operands')))
        #TODO Div
        elif self.is_of_class(node, 'Block'):
            return self.expr(self.neighbor(node, 'source'))
        elif self.is_of_class(node, 'Number'):
            return expr.Number(self.value_of(node))
        else:
            return expr.UnspecifiedExpr()