fix(parser): ignore newlines instead of using them as statement terminators
This commit is contained in:
@@ -12,7 +12,7 @@ from src.token import Token, TokenType
|
|||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
IGNORE: set[TokenType] = {
|
IGNORE: set[TokenType] = {
|
||||||
TokenType.WHITESPACE, TokenType.COMMENT
|
TokenType.WHITESPACE, TokenType.COMMENT, TokenType.NEWLINE
|
||||||
}
|
}
|
||||||
|
|
||||||
STATEMENT_BOUNDARY: set[TokenType] = {
|
STATEMENT_BOUNDARY: set[TokenType] = {
|
||||||
@@ -31,16 +31,10 @@ class Parser:
|
|||||||
|
|
||||||
def parse(self) -> list[Stmt]:
|
def parse(self) -> list[Stmt]:
|
||||||
statements: list[Stmt] = []
|
statements: list[Stmt] = []
|
||||||
self.skip_newlines()
|
|
||||||
while not self.is_at_end():
|
while not self.is_at_end():
|
||||||
statements.append(self.declaration())
|
statements.append(self.declaration())
|
||||||
self.skip_newlines()
|
|
||||||
return statements
|
return statements
|
||||||
|
|
||||||
def skip_newlines(self):
|
|
||||||
while self.check(TokenType.NEWLINE):
|
|
||||||
self.advance()
|
|
||||||
|
|
||||||
def is_at_end(self) -> bool:
|
def is_at_end(self) -> bool:
|
||||||
return self.peek().type == TokenType.EOF
|
return self.peek().type == TokenType.EOF
|
||||||
|
|
||||||
@@ -122,7 +116,6 @@ class Parser:
|
|||||||
initializer: Optional[Expr] = None
|
initializer: Optional[Expr] = None
|
||||||
if self.match(TokenType.EQUAL):
|
if self.match(TokenType.EQUAL):
|
||||||
initializer = self.expression()
|
initializer = self.expression()
|
||||||
self.expect_eol("Expected end of line after variable initialization")
|
|
||||||
return LetStmt(name, initializer)
|
return LetStmt(name, initializer)
|
||||||
|
|
||||||
def statement(self) -> Stmt:
|
def statement(self) -> Stmt:
|
||||||
@@ -208,19 +201,22 @@ class Parser:
|
|||||||
def return_stmt(self) -> Stmt:
|
def return_stmt(self) -> Stmt:
|
||||||
keyword: Token = self.previous()
|
keyword: Token = self.previous()
|
||||||
value: Optional[Expr] = None
|
value: Optional[Expr] = None
|
||||||
if not self.check(TokenType.NEWLINE) and not self.is_at_end():
|
if not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end():
|
||||||
value = self.expression()
|
value = self.expression()
|
||||||
self.expect_eol("Expected end of line after return statement.")
|
if not self.is_at_end() and not self.check(TokenType.RIGHT_BRACE):
|
||||||
|
self.error(keyword, "Return must be the last statement in a function.")
|
||||||
return ReturnStmt(keyword, value)
|
return ReturnStmt(keyword, value)
|
||||||
|
|
||||||
def break_stmt(self) -> Stmt:
|
def break_stmt(self) -> Stmt:
|
||||||
keyword: Token = self.previous()
|
keyword: Token = self.previous()
|
||||||
self.expect_eol("Expected end of line after break statement.")
|
if not self.is_at_end() and not self.check(TokenType.RIGHT_BRACE):
|
||||||
|
self.error(keyword, "Break must be the last statement in a block.")
|
||||||
return BreakStmt(keyword)
|
return BreakStmt(keyword)
|
||||||
|
|
||||||
def continue_stmt(self) -> Stmt:
|
def continue_stmt(self) -> Stmt:
|
||||||
keyword: Token = self.previous()
|
keyword: Token = self.previous()
|
||||||
self.expect_eol("Expected end of line after continue statement.")
|
if not self.is_at_end() and not self.check(TokenType.RIGHT_BRACE):
|
||||||
|
self.error(keyword, "Continue must be the last statement in a block.")
|
||||||
return ContinueStmt(keyword)
|
return ContinueStmt(keyword)
|
||||||
|
|
||||||
def while_stmt(self) -> Stmt:
|
def while_stmt(self) -> Stmt:
|
||||||
@@ -230,9 +226,7 @@ class Parser:
|
|||||||
|
|
||||||
def block_stmt(self) -> list[Stmt]:
|
def block_stmt(self) -> list[Stmt]:
|
||||||
statements: list[Stmt] = []
|
statements: list[Stmt] = []
|
||||||
self.skip_newlines()
|
|
||||||
while not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end():
|
while not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end():
|
||||||
self.skip_newlines()
|
|
||||||
statements.append(self.declaration())
|
statements.append(self.declaration())
|
||||||
|
|
||||||
self.consume(TokenType.RIGHT_BRACE, "Expected '}' after block.")
|
self.consume(TokenType.RIGHT_BRACE, "Expected '}' after block.")
|
||||||
@@ -240,7 +234,6 @@ class Parser:
|
|||||||
|
|
||||||
def expression_stmt(self) -> Stmt:
|
def expression_stmt(self) -> Stmt:
|
||||||
value: Expr = self.expression()
|
value: Expr = self.expression()
|
||||||
self.expect_eol("Expected end of line after expression")
|
|
||||||
return ExpressionStmt(value)
|
return ExpressionStmt(value)
|
||||||
|
|
||||||
def expression(self) -> Expr:
|
def expression(self) -> Expr:
|
||||||
|
|||||||
Reference in New Issue
Block a user