-
Notifications
You must be signed in to change notification settings - Fork 0
/
interpreter.py
61 lines (47 loc) · 1.74 KB
/
interpreter.py
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
from tokens import Token, Tokens
class NodeVisitor:
def visit(self, node):
method_name = 'visit_' + type(node).__name__
visitor = getattr(self, method_name, self.generic_visit)
return visitor(node)
def generic_visit(self, node):
raise Exception('No visit_{} method'.format(type(node).__name__))
class Interpreter(NodeVisitor):
GLOBAL_SCOPE = {}
def __init__(self, parser):
self.parser = parser
def visit_BinOp(self, node):
if node.op.type == Tokens.PLUS:
return self.visit(node.left) + self.visit(node.right)
elif node.op.type == Tokens.MINUS:
return self.visit(node.left) - self.visit(node.right)
elif node.op.type == Tokens.MUL:
return self.visit(node.left) * self.visit(node.right)
elif node.op.type == Tokens.DIV:
return self.visit(node.left) / self.visit(node.right)
def visit_UnaryOp(self, node):
op = node.op.type
if op == Tokens.PLUS:
return +self.visit(node.expr)
elif op == Tokens.MINUS:
return - self.visit(node.expr)
def visit_Num(self, node):
return node.value
def visit_Compound(self, node):
for child in node.children:
self.visit(child)
def visit_NoOp(self, node):
pass
def visit_Assign(self, node):
var_name = node.left.value
self.GLOBAL_SCOPE[var_name] = self.visit(node.right)
def visit_Var(self, node):
var_name = node.value
val = self.GLOBAL_SCOPE.get(var_name)
if val is None:
raise NameError(repr(var_name))
else:
return val
def interpret(self):
tree = self.parser.parse()
return self.visit(tree)