Exemple #1
0
def rpn_parse(text: str) -> List[expr.Expr]:
    """Parse text in reverse Polish notation
    into a list of expressions (exactly one if
    the expression is balanced).
    Example:
        rpn_parse("5 3 + 4 * 7")
          => [ Times(Plus(IntConst(5), IntConst(3)), IntConst(4)))),
               IntConst(7) ]
    May raise:  IndexError (imbalanced expression), lex.LexicalError.
    """
    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 in BINOPS:
            binop_class = BINOPS[tok.kind]
            right = stack.pop()
            left = stack.pop()
            stack.append(binop_class(left, right))
        elif tok.kind in UNOPS:
            unop_class = UNOPS[tok.kind]
            left = stack.pop()
            stack.append(unop_class(left))
        elif tok.kind == lex.TokenCat.ASSIGN:
            right = stack.pop()
            left = stack.pop()
            # Reverse left and right
            stack.append(expr.Assign(right, left))
        elif tok.kind == lex.TokenCat.VAR:
            stack.append(expr.Var(tok.value))
        else:
            print('oops')
    return stack
Exemple #2
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()}")
Exemple #3
0
def _primary(stream: TokenStream) -> expr.Expr:
    """Unary operations, Constants, Variables,
    input, and parenthesized expressions"""
    log.debug(f"Parsing primary with starting token {stream.peek()}")
    token = stream.take()
    if token.kind is TokenCat.INT:
        log.debug(f"Returning IntConst node from token {token}")
        return expr.IntConst(int(token.value))
    elif token.kind is TokenCat.VAR:
        log.debug(f"Variable {token.value}")
        return expr.Var(token.value)
    elif token.kind is TokenCat.READ:
        log.debug("Read")
        return expr.Read()
    elif token.kind is TokenCat.ABS:
        operand = _primary(stream)
        return expr.Abs(operand)
    elif token.kind is TokenCat.NEG:
        operand = _primary(stream)
        return expr.Neg(operand)
    elif token.kind is TokenCat.LPAREN:
        nested = _expr(stream)
        require(stream, TokenCat.RPAREN, consume=True)
        return nested
    else:
        raise InputError(f"Confused about {token} in expression")
Exemple #4
0
def rpn_parse(text: str) -> List[expr.Expr]:
    """Parse text in reverse Polish notation
    into a list of expressions (exactly one if
    the expression is balanced).
    Example:
        rpn_parse("5 3 + 4 * 7")
          => [ Times(Plus(IntConst(5), IntConst(3)), IntConst(4)))),
               IntConst(7) ]
    May raise:  IndexError (imbalanced expression), lex.LexicalError.
    """
    BINOPS = {
        lex.TokenCat.PLUS: expr.Plus,
        lex.TokenCat.TIMES: expr.Times,
        lex.TokenCat.DIV: expr.Div,
        lex.TokenCat.MINUS: expr.Minus
    }

    UNOPS = {lex.TokenCat.NEG: expr.Neg, lex.TokenCat.ABS: expr.Abs}

    tokens = lex.TokenStream(io.StringIO(text))
    # print (tokens)
    stack = []
    while tokens.has_more():
        tok = tokens.take()
        if tok.kind == lex.TokenCat.INT:
            stack.append(expr.IntConst(int(tok.value)))
            print("int", stack)
        elif tok.kind in BINOPS:
            binop_class = BINOPS[tok.kind]
            right = stack.pop()
            left = stack.pop()
            stack.append(binop_class(left, right))
            print("binop", stack)
        elif tok.kind in UNOPS:
            unop_class = UNOPS[tok.kind]
            left = stack.pop()
            stack.append(unop_class(left))
            print("unop", stack)
        elif tok.kind == lex.TokenCat.VAR:
            stack.append(expr.Var(str(tok.value)))
            print("var", stack)
        elif tok.kind == lex.TokenCat.ASSIGN:
            right = stack.pop()
            print("right", right)
            left = stack.pop()
            print("left", left)
            # Reverse left and right
            stack.append(expr.Assign(right, left))

    print(stack)
    return stack