1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
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:
<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)
def __str__(self):
if self.op is not None:
return f"({self.lhs}) {self.op} ({self.rhs})"
else:
return str(self.lhs)
|