Exemple #1
0
    def primary(self) -> Expr.Expr:
        if self.match(Token.TokenType.FALSE):
            return Expr.Literal(False)
        if self.match(Token.TokenType.TRUE):
            return Expr.Literal(True)
        if self.match(Token.TokenType.NIL):
            return Expr.Literal(None)

        if self.match(Token.TokenType.NUMBER, Token.TokenType.STRING):
            return Expr.Literal(self.previous().literal)

        if self.match(Token.TokenType.SUPER):
            keyword = self.previous()

            self.consume(Token.TokenType.DOT, "Expect '.' after 'super'.")
            method = self.consume(Token.TokenType.IDENTIFIER,
                                  "Expect superclass method name.")
            return Expr.Super(keyword, method)

        if self.match(Token.TokenType.THIS):
            return Expr.This(self.previous())

        if (self.match(Token.TokenType.IDENTIFIER)):
            return Expr.Variable(self.previous())

        if self.match(Token.TokenType.LEFT_PAREN):
            expression = self.expression()
            self.consume(Token.TokenType.RIGHT_PAREN,
                         "Expect ')' after expression.")
            return Expr.Grouping(expression)

        raise self.error(self.peek(), "Expect expression.")
Exemple #2
0
    def primary(self):
        '''
        We've reached the end with terminal conditions. This is how we stop the recursive descent
        Terminals include -> Bools, Null, Numbers, Strings, Parenthetical groups (which as expected
        have their nested expression start the whole process back up from the top. 
        '''
        if self.match(TokenType.THIS): return Expr.This(self.previous())
        if self.match(TokenType.FALSE): return Expr.Literal(False)
        if self.match(TokenType.TRUE): return Expr.Literal(True)
        if self.match(TokenType.NIL): return Expr.Literal(None)
        if self.match(TokenType.NUMBER, TokenType.STRING):
            return Expr.Literal(self.previous().literal)

        if self.match(TokenType.SUPER):
            keyword = self.previous()
            self.consume(TokenType.DOT, "Expect '.' after 'super'.")
            method = self.consume(TokenType.IDENTIFIER,
                                  "Expect superclass method name")
            return Expr.Super(keyword, method)

        if self.match(TokenType.IDENTIFIER):
            return Expr.Variable(self.previous())

        if self.match(TokenType.LEFT_PAREN):
            expr = self.expression()
            self.consume(
                TokenType.RIGHT_PAREN, "Expect ')' after expression"
            )  ## need to find a match otherwise must record as error
            return Expr.Grouping(expr)
        self.error(self.peek(), "Expect expression"
                   )  ## indicates we reached a token that can't start an expr
Exemple #3
0
def main():
    astPrinter = AstPrinter()
    expression = Expr.Binary(
        Expr.Unary(Token(TokenType.MINUS, '-', None, 1), Expr.Literal(123)),
        Token(TokenType.STAR, '*', None, 1),
        Expr.Grouping(Expr.Literal(45.67)))

    print(astPrinter.print(expression))
Exemple #4
0
    def primary(self) -> Expr.Expr:
        if self.match(IDENTIFIER):
            # IDENTIFIER token contains a word, make it into an Expr
            return Expr.Variable(self.previous())
        # handle the keyword values
        if self.match(FALSE): return Expr.Literal(False)
        if self.match(TRUE): return Expr.Literal(True)
        if self.match(NIL): return Expr.Literal(None)
        if self.match(THIS): return Expr.This(self.previous())
        if self.match(SUPER):
            keyword = self.previous()  # save "super" token
            self.consume(DOT, "Expect '.' after 'super'")
            method_name = self.consume(IDENTIFIER,
                                       "Expect superclass method name.")
            return Expr.Super(keyword, method_name)
        # handle literal values
        if self.match(NUMBER, STRING):
            return Expr.Literal(self.previous().literal)
        '''
        The only remaining legitimate option is a left paren, which will
        contain an expression and must be followed by a right paren.

        What would this code do, one asks, given input of "()"? As Nystrom
        wrote it (through Chapter 8, maybe it gets improved later?) it will
        look at the token list of [LEFT_PAREN,RIGHT_PAREN,...]; it will call
        self.expression to process the list [RIGHT_PAREN,...], and will fall
        through to be an error below. Thus Lox doesn't support the null
        expression.

        I am changing this to recognize "()" and return "(nil)".

        '''
        if self.match(LEFT_PAREN):
            if self.peek().type == RIGHT_PAREN:
                grouped_expr = Expr.Literal(None)
            else:
                grouped_expr = self.expression()
            self.consume(RIGHT_PAREN, "Expected ')' after expression")
            return Expr.Grouping(grouped_expr)
        '''
        This is the basement of the recursive ladder. It only returns a value
        when there is a match to one of the ttypes it checks for. Ergo all
        possible Expression token types must be checked-for here, or above
        here. A token type not explicitly checked-for ends up at this error.

        This is also where we end up, if there is a binary operator without a
        left argument, e.g. /5 or (!=3). Per challenge 3, detect that. Note
        that BANG and MINUS have been dealt with in unary() above. If one of
        those is not followed by a valid rhs, it is the following character
        that drops through to here.
        '''
        bad_token = self.peek()
        if bad_token.type in (PLUS, SLASH, STAR, EQUAL, GREATER, LESS):
            self.error(bad_token, 'operator requires a left operand')
        '''
        Finally we just don't know what's going on.
        '''
        self.error(bad_token, 'Unanticipated input')
Exemple #5
0
def run_main():
    exp = Expr.Binary(
        Expr.Unary(
            Token(TokenType.MINUS, "-", null, 1),
            Expr.Litaral(123)),
        Toke(TokenType.Star, "*", null, 1),
        Expr.Grouping(
            Expr.Literal(45.67)))

    print(AstPrinter.print(exp))
Exemple #6
0
    def _literal(self):
        if self._match(TokenType.ALPHA):
            return Expr.Literal(self._previous().value)

        if self._match(TokenType.LEFT_PARAN):
            expr = self._expression()
            if self._match(TokenType.RIGHT_PARAN):
                return Expr.Grouping(expr)
            else:
                self.__error("Closing Paranthesis not found")

        self.__error("Unexpected Token")
Exemple #7
0
 def primary(self):
     if self.identifier(exp=None):
         return Expr.Identifier(self.lastToken())
     elif self.match(TokenType.NUMBER, TokenType.STRING, TokenType.TRUE,
                     TokenType.FALSE, TokenType.NIL):
         return Expr.Literal(self.nextToken())
     elif self.consume(TokenType.LEFT_PAREN):
         ast = self.expression()
         self.consume(TokenType.RIGHT_PAREN, exp=')')
         return Expr.Grouping(ast)
     elif self.consume(TokenType.LAMBDA):
         return self.funExpr()
     else:
         raise self.errUnexpToken("primary expr")
Exemple #8
0
    def primary(self):
        if self.match(TokenType.FALSE):
            return Expr.Literal(False)
        if self.match(TokenType.TRUE):
            return Expr.Literal(True)
        if self.match(TokenType.NIL):
            return Expr.Literal(None)

        if self.match(TokenType.NUMBER, TokenType.STRING):
            return Expr.Literal(self.previous().literal)

        if self.match(TokenType.LEFT_PAREN):
            expr = self.expression()
            self.consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.")
            return Expr.Grouping(expr)

        self.consume(None, "Unexpected token")
Exemple #9
0
 def primary(self) -> Expr.Expr:
     """ Parses a primary expression """
     if self.match(TokenType.TRUE):
         return Expr.Literal(True)
     elif self.match(TokenType.FALSE):
         return Expr.Literal(False)
     elif self.match(TokenType.NIL):
         return Expr.Literal(None)
     elif self.match(TokenType.INT, TokenType.FLOAT, TokenType.STRING):
         return Expr.Literal(self.previous().literal)
     elif self.match(TokenType.LEFT_PAREN):
         expr = self.expression()
         self.consume(TokenType.RIGHT_PAREN,
                      "Expected closing ')' after expression")
         return Expr.Grouping(expr)
     elif self.match(TokenType.IDENTIFIER):
         return Expr.Variable(self.previous())
     else:
         raise self.error(self.peek(), "Expected expression")
Exemple #10
0
        return self.parenthesize(expr.operator.lexeme, expr.left, expr.right) 

    def visit_Grouping(self, expr):
        assert isinstance(expr, Expr.Grouping), "Must be Grouping Expression otherwise cannot print its AST" 
        return self.parenthesize("group", expr.expression) 

    def visit_Literal(self, expr):
        assert isinstance(expr, Expr.Literal), "Must be Literal Expression otherwise cannot print its AST" 
        return str(expr.value)

    def visit_Unary(self, expr):
        assert isinstance(expr, Expr.Unary), "Must be Unary Expression otherwise cannot print its AST"
        return self.parenthesize(expr.operator.lexeme, expr.right) 

    def parenthesize(self, name, *exprs):
        builder = ["(", name] 
        for expr in exprs:
            builder.append(expr.accept(self)) 
        builder.append(")") 
        return " ".join(builder) 

if __name__ == "__main__":
    ## Test Expression below 
    left_expression = Expr.Unary(Token(TokenType.MINUS, "-", 1, None), Expr.Literal(123)) 
    operator = Token(TokenType.STAR, "*", 1, None) 
    right_expression = Expr.Grouping(Expr.Literal(45.67)) 
    main_expression = Expr.Binary(left_expression, operator, right_expression) 
    print(ASTPrinter().print_ast(main_expression))


Exemple #11
0
    def visit_binary_expr(self, expr: Expr.Binary):
        return self.parenthesize(expr.operator.lexeme, expr.left, expr.right)

    def visit_grouping_expr(self, expr: Expr.Grouping):
        return self.parenthesize("group", expr.expression)

    def visit_literal_expr(self, expr: Expr.Literal):
        return str(expr.value) if expr.value != None else "nil"

    def visit_unary_expr(self, expr: Expr.Unary):
        return self.parenthesize(expr.operator.lexeme, expr.right)

    def parenthesize(self, name: str, *expressions):
        res = "(" + name

        for expression in expressions:
            res += " " + expression.accept(self)

        res += ")"

        return res


if __name__ == "__main__":
    expression = Expr.Binary(
        Expr.Unary(Token.Token(Token.TokenType.MINUS, "-", None, 1),
                   Expr.Literal(123)),
        Token.Token(Token.TokenType.STAR, "*", None, 1),
        Expr.Grouping(Expr.Literal(45.67)))

    print(AstPrinter().print_ast(expression))
Exemple #12
0
def _test():
    ast = Expr.Binary(
        Expr.Unary(Token(TokenType.MINUS, "-", None, 1), Expr.Literal(123)),
        Token(TokenType.STAR, "*", None, 1),
        Expr.Grouping(Expr.Literal(45.67)))
    print(LispPrinter().visit(ast))