-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.py
More file actions
323 lines (292 loc) · 12.1 KB
/
parser.py
File metadata and controls
323 lines (292 loc) · 12.1 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
"""Parser"""
import sys
from scanner import *
from constants import *
import random
class Parser():
def __init__(self, tokens):
"""
sets tokens returned from the tokenizer to tokens, it reverses them so that when we pop ,
we pop whats in the beggining of the tokens. Previous_token is empty and current_token is set
to the popped item from tokens.
"""
self.tokens = tokens
self.tokens.reverse()
self.previous_token = None
self.current_token = self.tokens.pop()
self.codes = []
self.symboltable = []
def print_tokens(self):
for i in self.tokens:
print i.name
def match(self, name, do_not_exit =False):
"""
Checks if the current_token is equal to name and if it is
it calls the function next_token.
"""
if(self.current_token.name == name):
#print "MATCH: successfully matched" , self.current_token.name
self.next_token()
return True
elif not do_not_exit:
print "MATCH: error, was expecting: " + name + " got : " + self.current_token.name
exit(0)
return False
def next_token(self):
"""
Checks if tokens are greater than zero and sets previous_token to the current_token and current_token
to the next item on the list
"""
if len(self.tokens) > 0:
self.previous_token = self.current_token
self.current_token = self.tokens.pop()
def parse(self):
self.program_statement()
#self.var_statement()
self.declarations()
self.begin_statement()
#print "finished begin statement"
self.match(symbols['.'])
#print "finished match ."
return self.codes
def program_statement(self):
"""
This function makes sure that program starts correctly
Example: program name;
"""
self.match(keywords['program'])
self.match('TK_IDENTIFIER')
self.match(symbols[';'])
def var_statement(self):
self.match(keywords['var'])
#self.match(keywords['TK_IDENTIFIER'])
while(self.match('TK_IDENTIFIER')):
self.symboltable.append(self.previous_token.value)
self.codes.append((opcodes['push'] , self.symboltable.index(self.previous_token.value)))
if self.match(symbols[','], do_not_exit =True):
#print "reached a comma"
continue
elif self.match(symbols[':']):
#print "got to colon"
break
if self.match(keywords['integer'], do_not_exit = True):
print "This var is an integer"
elif self.match(keywords['string'], do_not_exit = True):
print "This var is a string"
elif self.match(keywords['boolean'], do_not_exit = True):
print "this is a boolean"
elif self.match(keywords['real']):
print "This is a real"
else:
print "Did not match a valid Type"
def prod_E(self):
self.prod_T()
self.prod_E_prime()
def prod_E_prime(self):
if self.match(operators['+'], do_not_exit = True):
self.prod_T()
self.codes.append((opcodes['add'], None))
#print " got plus sign\n"
self.prod_E_prime()
elif self.match(operators['-'], do_not_exit = True):
self.prod_T()
self.codes.append((opcodes['sub'], None))
#print"got minus sign\n"
self.prod_E_prime()
def prod_T(self):
self.prod_F()
self.prod_T_prime()
def prod_T_prime(self):
if self.match(operators['*'], do_not_exit = True):
self.prod_F()
self.codes.append((opcodes['mult'] , None))
#print "got mult sign\n"
self.prod_T_prime()
elif self.match(operators['/'], do_not_exit = True):
self.prod_F()
self.codes.append((opcodes['div'] , None))
#print "got div sign\n"
self.prod_T_prime()
elif self.match(operators['and'], do_not_exit = True):
self.prod_F()
#print "got boolean and\n"
self.prod_T_prime()
elif self.match(operators['shl'], do_not_exit = True):
self.prod_F()
#print "got shift left\n"
self.prod_T_prime()
elif self.match(operators['shr'], do_not_exit = True):
self.prod_F()
#print "got shift right\r"
self.prod_T_prime()
def prod_F(self):
if self.match('TK_IDENTIFIER', do_not_exit = True):
lhs = self.previous_token
if self.previous_token.value not in self.symboltable:
print "UNDECLARED VARIABLE"
exit(0)
if self.match(operators[':='], do_not_exit = True):
self.assignment(lhs)
else:
#print "Previous token: " , self.previous_token.name, "value", self.previous_token.value
#print "Current token: " , self.current_token.name, "value", self.current_token.value
self.codes.append((opcodes['push'], self.symboltable.index(self.previous_token.value)))
elif self.match('TK_INTLIT', do_not_exit = True):
self.codes.append((opcodes['pushi'] , self.previous_token.value))
return type(self.previous_token.value)
elif self.match('TK_REALLIT' , do_not_exit = True):
self.codes.append((opcodes['pushi'], self.previous_token.value))
return type(self.previous_token.value)
elif self.match(symbols['('] , do_not_exit = True):
self.prod_L()
self.match(symbols[')'])
elif self.match(symbols[')'], do_not_exit = True):
print "reached right parenthesis"
elif self.match(keywords['write'],do_not_exit =True):
result = self.write_statement()
self.codes.append((opcodes['print'], result))
elif self.match(keywords['writeln'], do_not_exit = True):
result = self.write_statement()
self.codes.append((opcodes['println'], result))
elif self.match(operators['-'], do_not_exit = True):
self.prod_F()
#print "Got minus sign in prod_F\n"
else:
print self.current_token.name
print "Reached epsilon"
def prod_L(self):
self.prod_E()
self.prod_L_prime()
def prod_L_prime(self):
if self.match(operators['='], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['equ'], None))
elif self.match(operators['<>'], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['neq'] , None))
elif self.match(operators['>'], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['greater'] , None))
elif self.match(operators['<'], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['less'] , None))
elif self.match(operators['<='], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['leq'] , None))
elif self.match(operators['>='], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['geq'] , None))
elif self.match(operators['in'], do_not_exit = True):
self.prod_E()
self.codes.append((opcodes['in'] , None))
def declarations(self):
if self.current_token.name == keywords['var']:
self.var_statement()
self.match(symbols[';'])
self.declaration_tail()
def declaration_tail(self):
self.declarations()
def begin_statement(self):
"""
FOR NEXT TIME HAVE TO FINISH BEGIN_STATEMENT IF CLAUSE TO CONTINUE CORRECTLY
"""
self.match(keywords['begin'])
#print "successfully matched first begin\n"
if self.tokens and self.current_token.name != keywords['end']:
#print "matched end\n"
self.statement_list()
self.match(keywords['end'])
#print "successfully matched first end\n"
def write_statement(self):
self.match(symbols['('])
if self.match(symbols['"'], do_not_exit = True):
result = ''
while self.current_token.name != symbols['"']:
#print "this is value" , self.current_token.value
#print "this is name" , self.current_token.name
result += self.current_token.value + ' '
self.next_token()
self.match(symbols['"'])
self.match(symbols[')'])
return result
elif self.match('TK_IDENTIFIER') and self.previous_token.value in self.symboltable:
#print self.symboltable.index(self.previous_token.value)
self.codes.append((opcodes['print'] ,self.symboltable.index(self.previous_token.value)))
self.match(symbols[')'])
def statement_list(self):
"""
while there's tokens left and keyword is not end do statement() function
"""
while self.tokens and self.current_token.name != keywords['end']:
self.statement()
def statement(self):
if self.current_token.name == keywords['begin']:
self.begin_statement()
elif self.current_token.name == keywords['if']:
self.if_statement()
elif self.current_token.name == keywords['while']:
self.while_statement()
elif self.current_token.name == keywords['repeat']:
self.repeat_statement()
elif self.current_token.name == keywords['switch']:
self.switch_statement()
elif self.tokens and self.current_token.name != keywords['end']:
self.prod_E()
self.match(symbols[';'])
def if_statement(self):
self.if_stat()
def while_statement(self):
self.match(keywords['while'])
#print "matched while"
start_index = len(self.codes)
self.prod_L()
self.match(keywords['do'])
ran = random.random()
self.codes.append((opcodes['jfalse'], ran ))
self.statement()
self.codes.append((opcodes['pop'],None))
self.codes.append((opcodes['jmp'], start_index))
self.codes.append((opcodes['label'], ran))
def for_statement(self):
self.match(keywords['for'])
print "matched for"
def repeat_statement(self):
self.match(keywords['repeat'])
self.statement()
self.match(keywords['then'])
ran = random.random()
self.codes.append((opcodes['jfalse'], ran ))
self.prod_L()
self.codes.append((opcodes['label'], ran))
def switch_stat(self):
self.match(keywords['switch'])
print "matched switch"
def assignment(self, lhs):
rhs = self.prod_L()
#rhs = self.typematcher(self.previous_token.value, rhs)
self.codes.append((opcodes['pop'], self.symboltable.index(lhs.value)))
#self.codes.append((opcodes['pop'], self.previous_token.value))
def typematcher(self, lhs, rhs):
if type(lhs) == type(rhs):
return rhs
elif type(lhs) == int and type(rhs)== float:
return int(rhs)
elif type(lhs) == float and type(rhs) == int:
return float(rhs)
else:
print "Error not same type"
exit(0)
def if_stat(self):
self.match(keywords['if'])
self.prod_L()
self.match(keywords['then'])
ran = random.random()
self.codes.append((opcodes['jfalse'], ran ))
self.statement()
self.codes.append((opcodes['label'], ran))
if self.current_token.name == keywords['else']:
self.match(keywords['else'])
self.codes.append((opcodes['jtrue'], ran ))
self.statement()
self.codes.append((opcodes['label'], ran))
self.codes.append((opcodes['pop'],None))