-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.py
72 lines (57 loc) · 1.87 KB
/
parser.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
62
63
64
65
66
67
68
69
70
71
72
import re
import inspect
from sys import argv
from os import stat
from tokenizer import parseExpression
from stack import Stack
# No idea what to call this, so Interpreter it is
class Interpreter:
def __init__(self, filename):
self.memory = {
# Predefined Functions
"AND": lambda i1, i2: i1 & i2,
"OR": lambda i1, i2: i1 | i2,
"XOR": lambda i1, i2: i1 ^ i2,
"NOT": lambda i1: i1 ^ -1,
"OUT": lambda i: print(i),
"OUTBIN": lambda i: print(bin(i)),
"=": lambda key, value: self.addVariableToMemory(key, value),
}
# TODO: Update operators dynamically & at runtime
self.operators = ["AND", "OR", "XOR", "NOT", "OUT", "OUTBIN"]
expressions = self.retrieveFileContents(filename)
for expression in expressions:
self.evaluateExpression(expression)
def evaluateExpression(self, expression):
stack = Stack()
postfix = parseExpression(expression, self.operators)
for token in postfix:
if not self.isTokenFunction(token):
stack.push(token)
else:
argumentCount = self.getArguments(token)
arguments = [stack.pop() for _ in range(argumentCount)]
arguments = [self.memory.get(a, a) for a in arguments]
result = self.memory[token](*arguments)
stack.push(result)
def addVariableToMemory(self, value, key):
try:
self.memory[key] = eval(value)
except TypeError:
self.memory[key] = value
def isTokenFunction(self, token):
if token not in self.memory:
return False
return inspect.isfunction(self.memory[token])
@staticmethod
def retrieveFileContents(filename):
with open(filename, "r") as file:
# Support lines ending in .
return [re.sub('\.$', '', l) for l in file if not re.match("^\s*\/\/.*$", l)]
def getArguments(self, token):
function = self.memory[token]
args = inspect.getfullargspec(function)[0]
return len(args)
if __name__ == "__main__":
codeToRun = argv[1] or "code3.txt"
Interpreter(codeToRun)