def return_statement(self): keyword = self._previous value = None if not self._check(TokenType.SEMICOLON): value = self.expression() self._consume(TokenType.SEMICOLON, "Expect ';' after return value.") return Stmt.Return(keyword, value)
def if_statement(self): self._consume(TokenType.LEFT_PAREN, "Expect '(' after 'if'.") condition = self.expression() self._consume(TokenType.RIGHT_PAREN, "Expect ')' after if condition.") then_branch = self.statement() else_branch = None if self._match([TokenType.ELSE]): else_branch = self.statement() return Stmt.If(condition, then_branch, else_branch)
def for_statement(self): self._consume(TokenType.LEFT_PAREN, "Expect '(' after 'for'.") if self._match([TokenType.SEMICOLON]): initializer = None elif self._match([TokenType.VAR]): initializer = self.var_declaration() else: initializer = self.expression() condition = Expr.Literal(True) if not self._check(TokenType.SEMICOLON): condition = self.expression() self._consume(TokenType.SEMICOLON, "Expect ';' after loop condition.") incrementor = None if not self._check(TokenType.RIGHT_PAREN): incrementor = self.expression() self._consume(TokenType.RIGHT_PAREN, "Expect ') after for clauses.") body = self.statement() # Lox Code - `for (var a = 0; a < 3; a = a + 1) print a;` # is ~transalated~ desugared into: # { // This additional Block limits the scope # var a = 0; # while (a < 3){ # print a; # a = a + 1; # } # } if incrementor != None: body = Stmt.Block([body, incrementor]) body = Stmt.While(condition, body) if initializer != None: body = Stmt.Block([initializer, body]) return body
def statement(self): if self._match([TokenType.FOR]): return self.for_statement() if self._match([TokenType.IF]): return self.if_statement() if self._match([TokenType.PRINT]): return self.print_statement() if self._match([TokenType.RETURN]): return self.return_statement() if self._match([TokenType.WHILE]): return self.while_statement() if self._match([TokenType.LEFT_BRACE]): return Stmt.Block(self.block()) return self.expression_statement()
def function_declaration(self, kind): '''We reuse this method for both function and method declaration. `kind` is used to distinguish between the two. ''' name = self._consume(TokenType.IDENTIFIER, f"Expect {kind} name.") self._consume(TokenType.LEFT_PAREN, f"Expect '(' after {kind} name.") parameters = [] if not self._check(TokenType.RIGHT_PAREN): parameters.append( self._consume(TokenType.IDENTIFIER, "Expect parameter name.")) while self._match([TokenType.COMMA]): parameters.append( self._consume(TokenType.IDENTIFIER, "Expect parameter name.")) if len(parameters) > 255: self._error(self._peek(), "Cannot have more than 255 parameters.") self._consume(TokenType.RIGHT_PAREN, "Expect ')'after parameters.") self._consume(TokenType.LEFT_BRACE, "Expect '{' before" + kind + "body.") body = self.block() return Stmt.Function(name, parameters, body)
def var_declaration(self): name = self._consume(TokenType.IDENTIFIER, "Expect variable name.") value = self.expression() if self._match([TokenType.EQUAL]) else None self._consume(TokenType.SEMICOLON, "Expect ';' after variable declaration.") return Stmt.Var(name, value)
def expression_statement(self): expression = self.expression() self._consume(TokenType.SEMICOLON, "Expected ';' after expression.") return Stmt.Expression(expression)
def print_statement(self): value = self.expression() self._consume(TokenType.SEMICOLON, "Expected ';' after expression.") return Stmt.Print(value)
def while_statement(self): self._consume(TokenType.LEFT_PAREN, "Expect ')' after while.") condition = self.expression() self._consume(TokenType.RIGHT_PAREN, "Expect ')' after condition.") body = self.statement() return Stmt.While(condition, body)