summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Yin <fkfd@fkfd.me>2022-09-03 11:46:10 +0800
committerFrederick Yin <fkfd@fkfd.me>2022-09-03 11:46:10 +0800
commitdfb5ee45fb68aca09bd0ac9967c6b574f932d39f (patch)
treea137350c895d6d1a1ff1d9f7ae4db080e07ef877
parentb1794edb3d76db7c1a86fc14a60bc95b833bc7c7 (diff)
hackc: While statement
-rw-r--r--projects/hackc/classes.py16
-rw-r--r--projects/hackc/statements.py55
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' '(' <expression> ')' '{' <statement list> '}'
+ """
+ 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")