summaryrefslogtreecommitdiff
path: root/projects/hackc/expressions.py
diff options
context:
space:
mode:
Diffstat (limited to 'projects/hackc/expressions.py')
-rw-r--r--projects/hackc/expressions.py76
1 files changed, 76 insertions, 0 deletions
diff --git a/projects/hackc/expressions.py b/projects/hackc/expressions.py
new file mode 100644
index 0000000..de58528
--- /dev/null
+++ b/projects/hackc/expressions.py
@@ -0,0 +1,76 @@
+from .tokens import Token
+
+OPS = "+-*/&|<>="
+UNARY_OPS = "-~"
+CONSTANTS = ["true", "false", "null", "this"]
+
+
+class Term:
+ def __init__(self):
+ pass
+
+ @classmethod
+ def from_tokens(cls, tokens: list) -> tuple:
+ if not tokens:
+ return (None, 0)
+ if tokens[0].type in ["integer", "string"] or tokens[0] in CONSTANTS:
+ return (ConstantTerm(tokens[0]), 1)
+ if tokens[0] in UNARY_OPS:
+ term, dt = Term.from_tokens(tokens[1:])
+ return (UnaryTerm(tokens[0], term), dt + 1)
+
+
+class ConstantTerm:
+ def __init__(self, term: Token):
+ self.term = term
+
+
+class VarTerm:
+ def __init__(self, var: Token, subscript=None):
+ self.var = var
+ self.subscript = subscript
+
+
+class UnaryTerm:
+ def __init__(self, op: Token, term: Term):
+ self.op = op
+ self.term = term
+
+
+class SubroutineCall:
+ def __init__(self, name: Token, exprs: list):
+ self.name = name
+ self.exprs = exprs
+
+ @classmethod
+ def from_tokens(cls, tokens: list) -> tuple:
+ pass
+
+
+class Expression:
+ def __init__(self, lhs: Term, op=None, rhs=None):
+ self.lhs = lhs
+ self.op = op
+ self.rhs = rhs
+
+ @classmethod
+ def from_tokens(cls, tokens: list) -> tuple:
+ """Construct expression.
+
+ Format:
+ <term> (<op> <term>)?
+ """
+ lhs, dt = Term.from_tokens(tokens)
+ t = dt
+
+ op = tokens[t]
+ if op.token not in OPS:
+ return (Expression(lhs), t)
+
+ t += 1
+ rhs, dt = Term.from_tokens(tokens[t])
+ if rhs is None:
+ raise JSE(f"Expected other term, got `{rhs}` instead", rhs)
+ t += dt
+
+ return (Expression(lhs, op, rhs), t)