Esempio n. 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
Esempio n. 2
0
def _stmt(stream: TokenStream) -> expr.Expr:
    """
    #  stmt ::=  assign | loop | ifstmt | printstmt
    assignment ::= IDENT '=' expression ';'
    """
    if stream.peek().kind is TokenCat.WHILE:
        return _while(stream)
    if stream.peek().kind is TokenCat.IF:
        return _if(stream)
    if stream.peek().kind is TokenCat.PRINT:
        return _print(stream)
    if stream.peek().kind is not TokenCat.VAR:
        raise InputError(
            f"Expecting identifier at beginning of assignment, got {stream.peek()}"
        )
    target = expr.Var(stream.take().value)
    if stream.peek().kind is not TokenCat.ASSIGN:
        raise InputError(f"Expecting assignment symbol, got {stream.peek()}")
    stream.take()  # Discard token
    value = _expr(stream)
    if stream.peek().kind is not TokenCat.SEMI:
        raise InputError(
            f"Expecting semicolon after assignment, got {stream.peek()}")
    stream.take()  # Discard token
    return expr.Assign(target, value)
Esempio n. 3
0
 def _assignment(self) -> ex.Expr:
     expr = self._ternary()
     if self._match(TokenType.EQUAL):
         equals = self._previous
         value = self._assignment()
         if isinstance(expr, ex.Variable):
             name = expr.name
             return ex.Assign(name, value)
         if isinstance(expr, ex.Get):
             return ex.Set(expr.object, expr.name, value)
         self._error(equals, 'Invalid assignment target.')
     return expr
Esempio n. 4
0
def _stmt(stream: TokenStream) -> expr.Expr:
    """
    stmt ::= exp ['=' exp]
    """
    left = _expr(stream)
    if stream.peek().kind is TokenCat.ASSIGN:
        if not isinstance(left, expr.Var):
            raise InputError("Can only assign to a variable")
        stream.take()
        right = _expr(stream)
        return expr.Assign(left, right)
    else:
        return left
Esempio n. 5
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
Esempio n. 6
0
    def assignment(self):
        expr = self._or()

        if self.match(TokenType.EQUAL):
            equals = self.previous()
            value = self.assignment()

            if isinstance(expr, Expr.Variable):
                name = expr.name
                return Expr.Assign(name, value)

            self.error(equals, "Invalid assignment target.")

        return expr
Esempio n. 7
0
    def assignment(self) -> e.Expr:
        expr: e.Expr = self._or()

        if self.match(TokenType.EQUAL):
            equals: Token = self.previous()
            value: e.Expr = self.assignment()

            if isinstance(expr, e.Variable):
                name: Token = expr.name
                return e.Assign(name, value)
            elif isinstance(expr, e.Get):
                get: e.Get = expr
                return e.Set(get.object, get.name, value)

            self.error(equals, "Invalid assignment target.")

        return expr