summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--projects/hackc/classes.py3
-rw-r--r--projects/hackc/expressions.py62
-rw-r--r--projects/hackc/utils.py2
3 files changed, 62 insertions, 5 deletions
diff --git a/projects/hackc/classes.py b/projects/hackc/classes.py
index b300d98..bd83cc4 100644
--- a/projects/hackc/classes.py
+++ b/projects/hackc/classes.py
@@ -180,7 +180,7 @@ class ParamList:
if tokens[0] == RIGHT_PAREN:
# empty param list, i.e. '(' ')'
- return (ParamList([]), 2)
+ return (ParamList([]), 0)
t = 0
params = []
@@ -313,3 +313,4 @@ class Subroutine:
variable.print_verbose()
for statement in self.statements:
statement.print_verbose()
+ print(f"End of {self.category} {self.name}")
diff --git a/projects/hackc/expressions.py b/projects/hackc/expressions.py
index 3bc83d2..f4623da 100644
--- a/projects/hackc/expressions.py
+++ b/projects/hackc/expressions.py
@@ -17,8 +17,26 @@ class Term:
if tokens[0].type in ["integer", "string"] or tokens[0] in CONSTANTS:
return (ConstantTerm(tokens[0]), 1)
if tokens[0].token in UNARY_OPS:
+ """Format: <unary op> <term>"""
term, dt = Term.from_tokens(tokens[1:])
return (UnaryTerm(tokens[0], term), dt + 1)
+ if tokens[0] == LEFT_PAREN:
+ """Format: '(' <expression> ')'"""
+ expr, dt = Expression.from_tokens(tokens[1:])
+ if tokens[dt + 1] != RIGHT_PAREN:
+ raise JackSyntaxError(
+ f"Expected `{RIGHT_PAREN}`, got `{tokens[dt]}` instead", tokens[dt]
+ )
+ return (expr, dt + 2)
+ if tokens[0].type == "identifier":
+ if tokens[1] in [LEFT_PAREN, "."]:
+ # subroutine(...) or Class.subroutine(...)
+ return SubroutineCall.from_tokens(tokens)
+ if tokens[1] == LEFT_BRACKET:
+ # array[index]
+ return SubscriptTerm.from_tokens(tokens)
+ return (VarTerm(tokens[0]), 1)
+ return (None, 0)
class ConstantTerm:
@@ -29,17 +47,53 @@ class ConstantTerm:
return self.term.token
-class VarTerm:
- def __init__(self, var: Token, subscript=None):
+class SubscriptTerm:
+ def __init__(self, var: Token, subscript: Token):
self.var = var
self.subscript = subscript
+ @classmethod
+ def from_tokens(cls, tokens: list) -> tuple:
+ """Construct a subscripted array term.
+
+ Format:
+ <var> '[' <subscript> ']'
+ """
+ if tokens[0].type != "identifier" or tokens[1] != LEFT_BRACKET:
+ return (None, 0)
+
+ var = tokens[0]
+ t = 2
+ sub, dt = Expression.from_tokens(tokens[2:])
+ if sub is None:
+ raise JackSyntaxError(f"Expected subscript", tokens[2])
+ t += dt
+ if tokens[t] != RIGHT_BRACKET:
+ raise JackSyntaxError(
+ f"Expected `{RIGHT_BRACKET}`, got `{tokens[t]}` instead", tokens[t]
+ )
+ return (SubscriptTerm(var, sub), t + 1)
+
+ def __str__(self):
+ return f"{self.var}[{self.subscript}]"
+
+
+class VarTerm:
+ def __init__(self, var: Token):
+ self.var = var
+
+ def __str__(self):
+ return self.var.token
+
class UnaryTerm:
def __init__(self, op: Token, term: Term):
self.op = op
self.term = term
+ def __str__(self):
+ return f"({self.op}{self.term})"
+
class SubroutineCall:
def __init__(self, name: Token, exprs: list):
@@ -72,7 +126,7 @@ class Expression:
return (Expression(lhs), t)
t += 1
- rhs, dt = Term.from_tokens(tokens[t])
+ rhs, dt = Term.from_tokens(tokens[t:])
if rhs is None:
raise JSE(f"Expected other term, got `{rhs}` instead", rhs)
t += dt
@@ -81,6 +135,6 @@ class Expression:
def __str__(self):
if self.op is not None:
- return f"({self.lhs}) {self.op} ({self.rhs})"
+ return f"({self.lhs} {self.op} {self.rhs})"
else:
return str(self.lhs)
diff --git a/projects/hackc/utils.py b/projects/hackc/utils.py
index 58888ac..d375953 100644
--- a/projects/hackc/utils.py
+++ b/projects/hackc/utils.py
@@ -8,6 +8,8 @@ EXIT_CODE_EOF = 7
# vim autoindent misbehaves if I type these verbatim in strings
LEFT_BRACE = "{"
RIGHT_BRACE = "}"
+LEFT_BRACKET = "["
+RIGHT_BRACKET = "]"
LEFT_PAREN = "("
RIGHT_PAREN = ")"