-
Notifications
You must be signed in to change notification settings - Fork 0
/
Machine.py
101 lines (86 loc) · 3.5 KB
/
Machine.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from types import *
class MachineError(Exception):
def __init__(self):
self.message = 'The machine encountered a problem'
class Machine:
def __init__(self):
self.operators = {}
self.stack = []
self.errorMessage = ""
def clearError(self):
self.errorMessage = ""
self.stack = []
def addOperator(self, processor):
try:
if type( processor.symbol ) is not StringType:
raise AttributeError('symbol not defined')
if type( processor.minArgs ) is not IntType:
raise AttributeError('minArgs not defined')
if type( processor.maxArgs ) is not IntType:
raise AttributeError('maxArgs not defined')
if type( processor.process ) is not MethodType:
raise AttributeError('process not defined')
if type( processor.description ) is not StringType:
raise AttributeError('description not defined')
if processor.minArgs < 0:
raise AttributeError('minArgs < 0')
if processor.maxArgs >=0 and processor.minArgs > processor.maxArgs:
raise AttributeError('minArgs > maxArgs')
except AttributeError as err:
self.error("The operator is malformed: "+err.message+"\n received: "+str(processor.__dict__))
self.operators[ processor.symbol ] = processor
def describeOperator(self, operator):
if operator in self.operators:
print( self.operators[operator].description )
else:
self.error('operator "'+operator+'" not defined ')
def error(self, message):
self.errorMessage = 'error: '+str(message)
raise MachineError()
def parse(self, text):
self.stack.append( text )
parts = text.split('(',1);
operator = parts[0]
if operator not in self.operators:
try:
value = float(operator)
self.stack.pop()
return value
except Exception as e:
self.error('operator "'+operator+'" not found: '+str(e))
if len(parts) != 2:
self.error('expected ( to follow operator')
if parts[1][-1] != ')':
self.error('unclosed parentheses: '+parts[1])
args = parts[1][:-1]
openCount=0
index = 0
parts = []
for i in range(0,len(args)):
if args[i] == '(':
openCount += 1
elif args[i] == ')':
openCount -= 1
elif openCount == 0 and args[i] == ',':
parts += [args[index:i]]
index = i+1
if openCount != 0:
self.error('The number of opening and closing brackets '+
'do not matching the arguments to processing "'+operator+'"')
parts += [args[index:]]
if len(parts) == 1:
if len(parts[0]) == 0:
parts = []
processor = self.operators[operator]
numArgs = len(parts)
if numArgs < processor.minArgs:
self.error('"'+operator+'" takes at least '+
str(processor.minArgs)+
' arguments but found '+str(numArgs))
elif processor.maxArgs >=0 and numArgs > processor.maxArgs:
self.error('"'+operator+'" takes at most '+
str(processor.maxArgs)+
' arguments but found '+str(numArgs))
result = processor.process(parts, self)
self.stack.pop()
return result