From dfb5ee45fb68aca09bd0ac9967c6b574f932d39f Mon Sep 17 00:00:00 2001 From: Frederick Yin Date: Sat, 3 Sep 2022 11:46:10 +0800 Subject: hackc: While statement --- projects/hackc/classes.py | 16 ++++--------- projects/hackc/statements.py | 55 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/projects/hackc/classes.py b/projects/hackc/classes.py index f1358f6..ed69810 100644 --- a/projects/hackc/classes.py +++ b/projects/hackc/classes.py @@ -1,4 +1,4 @@ -from .statements import Statement +from .statements import StatementList from .tokens import Token from .utils import * @@ -210,7 +210,7 @@ class Subroutine: name: Token, params: ParamList, variables: list, - statements: list, + statements: StatementList, ): self.category = category self.type = type @@ -266,13 +266,8 @@ class Subroutine: variables.append(variable) t += dt - statements = [] - while t < len(tokens): - statement, dt = Statement.from_tokens(tokens[t:]) - if statement is None: - break - statements.append(statement) - t += dt + statements, dt = StatementList.from_tokens(tokens[t:]) + t += dt body_close = tokens[t] if body_close != RIGHT_BRACE: @@ -289,6 +284,5 @@ class Subroutine: self.params.print_verbose() for variable in self.variables: variable.print_verbose() - for statement in self.statements: - statement.print_verbose() + self.statements.print_verbose() print(f"End of {self.category} {self.name}") diff --git a/projects/hackc/statements.py b/projects/hackc/statements.py index 0e257ed..458ba01 100644 --- a/projects/hackc/statements.py +++ b/projects/hackc/statements.py @@ -8,7 +8,13 @@ class Statement: @classmethod def from_tokens(cls, tokens: list) -> tuple: - for StatementClass in [LetStatement, DoStatement, ReturnStatement, IfStatement]: + for StatementClass in [ + LetStatement, + DoStatement, + ReturnStatement, + IfStatement, + WhileStatement, + ]: stmt, dt = StatementClass.from_tokens(tokens) if stmt is not None: return (stmt, dt) @@ -35,6 +41,8 @@ class StatementList: def print_verbose(self): for stmt in self.statements: stmt.print_verbose() + if not self.statements: + print("Do nothing") class LetStatement: @@ -190,3 +198,48 @@ class IfStatement: if self.else_then is not None: print("Else then:") self.else_then.print_verbose() + print("End if") + + +class WhileStatement: + def __init__(self, condition: Expression, do: StatementList): + self.condition = condition + self.do = do + + @classmethod + def from_tokens(cls, tokens: list) -> tuple: + """Construct while statement. + + Format: + 'while' '(' ')' '{' '}' + """ + if len(tokens) < 6 or tokens[0] != "while": + return (None, 0) + + if tokens[1] != LEFT_PAREN: + raise UnexpectedToken(LEFT_PAREN, tokens[1]) + + t = 2 + cond, dt = Expression.from_tokens(tokens[2:]) + if cond is None: + raise JackSyntaxError(f"Expected condition", tokens[2]) + t += dt + + if tokens[t] != RIGHT_PAREN: + raise UnexpectedToken(RIGHT_PAREN, tokens[t]) + if tokens[t + 1] != LEFT_BRACE: + raise UnexpectedToken(LEFT_BRACE, tokens[t + 1]) + t += 2 + + do, dt = StatementList.from_tokens(tokens[t:]) + t += dt + + if tokens[t] != RIGHT_BRACE: + raise UnexpectedToken(RIGHT_BRACE, tokens[t]) + + return (WhileStatement(cond, do), t + 1) + + def print_verbose(self): + print(f"While {self.condition} do:") + self.do.print_verbose() + print("End while") -- cgit v1.2.3