from .tokens import Token from .utils import * 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].token 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 def __str__(self): return self.term.token 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: ( )? """ 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) def __str__(self): if self.op is not None: return f"({self.lhs}) {self.op} ({self.rhs})" else: return str(self.lhs)