/
compilador.py
executable file
·424 lines (359 loc) · 12 KB
/
compilador.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
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
#! /usr/bin/env python
reserved = {
'if' : 'IF',
'then' : 'THEN',
'else' : 'ELSE',
'program' : 'PROGRAM',
'begin' : 'BEGIN',
'end' : 'END',
'procedure': 'PROCEDURE',
'while' : 'WHILE',
'do' : 'DO',
'var' : 'VAR',
'integer' : 'INTEGER',
'float' : 'FLOAT',
'write' : 'WRITE',
'read' : 'READ',
'function' : 'FUNCTION',
'procedure': 'PROCEDURE',
'div' : 'DIVIDE',
'var' : 'VAR',
'input' : 'INPUT',
'output' : 'OUTPUT',
'label' : 'LABEL',
'goto' : 'GOTO'
}
tokens = [
'NUMBER', 'CMD', 'FIM', 'DPONTOS', 'VIRG',
'PLUS','MINUS','TIMES','ATTRIB',
'LESS', 'LESS_EQ', 'MORE', 'MORE_EQ','EQUAL','DIFF',
'LPAREN','RPAREN','ID'
]+list(reserved.values())
# Tokens
t_FIM = r'.'
t_CMD = r'\;'
t_MORE = r'>'
t_LESS = r'<'
t_MORE_EQ = r'<='
t_LESS_EQ = r'>='
t_EQUAL = r'='
t_DIFF = r'!='
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
#t_DIVIDE = r'/'
t_ATTRIB = r'\:='
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_DPONTOS = r'\:'
t_VIRG = r','
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
t.type = reserved.get(t.value,'ID')
return t
def t_NUMBER(t):
r'\d+'
try:
t.value = int(t.value)
except ValueError:
print "Integer value too large", t.value
t.value = 0
return t
# Ignored characters
t_ignore = " \t"
contador=0
def t_newline(t):
r'\n+'
def t_error(t):
print "Illegal character '%s'" % t.value[0]
t.lexer.skip(1)
# Build the lexer
import sys
import ply.lex as lex
lex.lex()
import tabela
rotulo = tabela.Rotulo()
tipo = tabela.Tipo()
tabela = tabela.TabelaExtendida()
# Parsing rules
precedence = (
('left','LESS','MORE','LESS_EQ','MORE_EQ'),
('left','PLUS','MINUS'),
('left','TIMES','DIVIDE'),
('right','UMINUS'),
)
# dictionary of names
names = { }
def p_statement_init(t):
'''programa : program ID CMD bloco FIM
| program ID LPAREN lista_identificadores_programa RPAREN CMD bloco FIM'''
print "\tPARA"
def p_statement_lista_identificadores_programa(t):
'''lista_identificadores_programa : INPUT
| OUTPUT
| INPUT VIRG lista_identificadores_programa
| OUTPUT VIRG lista_identificadores_programa'''
def p_statement_program(t):
'program : PROGRAM'
print "\tINPP"
print "\tDSVS "+rotulo.nome()
rotulo.add()
def p_statement_bloco(t):
'''bloco : rotulos variaveis subrotinas comando_composto_inicial
| variaveis subrotinas comando_composto_inicial
| rotulos variaveis comando_composto_inicial
| variaveis comando_composto_inicial
| rotulos subrotinas comando_composto_inicial
| subrotinas comando_composto_inicial
| rotulos comando_composto_inicial
| comando_composto_inicial'''
print "\tDMEM "+str(tabela.getTam())
def p_statement_rotulos(t):
'rotulos : LABEL lista_numeros CMD'
def p_statement_lista_numeros(t):
'''lista_numeros : NUMBER
| NUMBER VIRG lista_numeros'''
rotulo.add()
tabela.addLabel(t[1],rotulo.nome())
rotulo.remove()
def p_statement_subrotinas(t):
'''subrotinas : funcao
| procedimento
| funcao subrotinas
| procedimento subrotinas'''
def p_statement_funcao(t):
'''funcao : function CMD DPONTOS tipo_retorno bloco CMD
| function LPAREN lista_identificadores_sub RPAREN DPONTOS tipo_retorno CMD bloco CMD'''
print "\tRTPR "+tabela.getNivel()
def p_statemente_function(t):
'function : FUNCTION ID'
print "\tDSVS "+rotulo.nome()
rotulo.add()
tabela.addFunc(t[2],rotulo.nome())
print rotulo.nome()+ "\tNADA"
rotulo.remove()
tabela.sobeNivel()
print "\tENPR "+tabela.getNivel()
rotulo.add()
tabela.resetParam()
def p_statement_tipo_retorno(t):
'''tipo_retorno : INTEGER
| FLOAT '''
tabela.funcao.setTipo(t[1])
def p_statement_procedimento(t):
'''procedimento : procedure CMD bloco CMD
| procedure LPAREN lista_identificadores_sub RPAREN CMD bloco CMD'''
print "\tRTPR "+tabela.getNivel()
tabela.desceNivel()
def p_statement_procedure(t):
'procedure : PROCEDURE ID'
print "\tDSVS "+rotulo.nome()
rotulo.add()
tabela.addFunc(t[2],rotulo.nome())
print rotulo.nome() + "\tNADA"
rotulo.remove()
tabela.sobeNivel()
print "\tENPR "+tabela.getNivel()
rotulo.add()
tabela.resetParam()
def p_statement_variaveis(t):
'variaveis : VAR declaracao_variaveis'
print "\tAMEM "+str(tabela.getTam())
def p_statement_declaracao_variaveis(t):
'''declaracao_variaveis : lista_identificadores_var DPONTOS tipo CMD
| lista_identificadores_var DPONTOS tipo CMD declaracao_variaveis'''
def p_statement_tipo(t):
'''tipo : INTEGER
| FLOAT '''
if t[1] == "integer":
tabela.setType("integer")
elif t[1]=="float" :
tabela.setType("float")
def p_statement_lista_identificadores_sub(t):
'''lista_identificadores_sub : parametro_formal
| parametro_formal CMD lista_identificadores_sub'''
#tabela.addParam(t[1],t[3])
def p_stamtement_parametro_formal(t):
'''parametro_formal : VAR ID DPONTOS INTEGER
| ID DPONTOS INTEGER
| ID DPONTOS FLOAT
| VAR ID DPONTOS FLOAT '''
if(t[1] == "var"):
tabela.addParam(t[2],t[4],True)
else:
tabela.addParam(t[1],t[3])
def p_statement_lista_identificadores_var(t):
'''lista_identificadores_var : ID
| ID VIRG lista_identificadores_var'''
tabela.addVar(t[1])
def p_statement_comando_composto_inicial(t):
'''comando_composto_inicial : begin comando END
| begin comando mais_comandos END'''
def p_statement_comando_begin(t):
'begin : BEGIN'
rotulo.remove()
print rotulo.nome()+"\tNADA"
def p_statement_comando_composto(t):
'''comando_composto : BEGIN comando END
| BEGIN comando mais_comandos END'''
def p_statement_mais_comandos(t):
'''mais_comandos : CMD comando
| CMD comando mais_comandos
| CMD '''
def p_statement_comando(t):
'''comando : NUMBER DPONTOS comando_sem_rotulo
| comando_sem_rotulo'''
if len(t) > 2:
label = tabela.getVar(t[1])
print label.getEnd() + "\tNADA"
print "\tENRT "+str(tabela.getNivel())+","+str(tabela.getLenTab())
def p_statement_comando_sem_rotulo(t):
'''comando_sem_rotulo : comando_composto
| atribuicao
| desvio
| chamada_subprograma
| comando_repetitivo
| comando_condicional'''
def p_statement_desvio(t):
' desvio : GOTO NUMBER'
label = tabela.getVar(t[2])
print "\tDSVR " + label.getEndGo(tabela.getNivel())
def p_statement_chamada_procedimento(t):
'''chamada_subprograma : id_sub
| WRITE LPAREN lista_identificadores_write RPAREN
| READ LPAREN lista_identificadores_read RPAREN
| id_sub LPAREN lista_expressoes_subprograma RPAREN '''
if t[1] != "write" and t[1] != "read":
print "\tCHPR " + tabela.getVar(t[1]).getRotulo()
def p_statement_id_sub(t):
'id_sub : ID'
tabela.setFunc(t[1])
tabela.resetParam()
t[0] = t[1]
def p_statement_lista_expressoes_subprograma(t):
'''lista_expressoes_subprograma : ID
| expression
| ID VIRG lista_expressoes_subprograma
| expression VIRG lista_expressoes_subprograma '''
elem = tabela.useParam()
if tabela.exists(t[1]):
ident = tabela.getVar(t[1])
if elem.referencia and not ident.referencia:
print "\tCREN "+ident.getEnd()
else:
print "\tCRVL "+ident.getEnd()
elif elem.referencia:
print "ERRO: expressao encontrada na passagem por referencia ",elem
raise SyntaxError
def p_statement_lista_identificadores_write(t):
'''lista_identificadores_write : ID
| ID VIRG lista_identificadores_write '''
ident = tabela.getVar(t[1])
print "\tCRVL " + ident.getEnd()
print "\tIMPR"
def p_statement_lista_identificadores_read(t):
'''lista_identificadores_read : ID
| ID VIRG lista_identificadores_read'''
print "\tLEIT"
ident = tabela.getVar(t[1])
print "\tARMZ " + ident.getEnd()
def p_statement_if(t):
'''comando_condicional : IF expression_if THEN comando
| IF expression_if THEN comando ELSE comando'''
print rotulo.nome() + "\tNADA"
rotulo.remove()
def p_statement_while_do(t):
'comando_repetitivo : while expression_while DO comando'
print rotulo.nome() + "\tNADA"
rotulo.remove()
def p_statement_while(t):
'while : WHILE'
print rotulo.nome() + "\tNADA"
def p_statement_atribuicao(t):
'atribuicao : ID ATTRIB expression'
if tabela.exists(t[1]):
ident = tabela.getVar(t[1])
if ident.eFuncao():
ident = ident.retorno
tabela.resetParam()
if ident.referencia:
print "\tARMI "+ident.getEnd()
else:
print "\tARMZ "+ident.getEnd()
tipo.add(ident.getTipo())
tipo.compara()
tipo.reset()
else:
sys.stderr.write("ERRO: variavel nao definida: "+t[1]+"\n")
raise SyntaxError
def p_statement_expr_if(t):
'expression_if : expression'
rotulo.add()
print "\tDSVF " + rotulo.nome()
def p_statement_expr_while(t):
'expression_while : expression'
rotulo.add()
print "\tDSVF " + rotulo.nome()
def p_expression_binop(t):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression
| expression LESS expression
| expression MORE expression
| expression LESS_EQ expression
| expression MORE_EQ expression
| expression EQUAL expression
'''
tipo.compara()
if t[2] == '+' : print "\tSOMA"
elif t[2] == '-' : print "\tSUBT"
elif t[2] == '*' : print "\tMULT"
elif t[2] == "div": print "\tDIVI"
elif t[2] == '>' : print "\tCMMA"
elif t[2] == '<' : print "\tCMME"
elif t[2] == '>=' : print "\tCMAG"
elif t[2] == '<=' : print "\tCMEG"
elif t[2] == '==' : print "\tCMDG"
elif t[2] == '<>' : print "\tCMNE"
def p_expression_function_exp(t):
'expression : id_sub LPAREN lista_expressoes_subprograma RPAREN'
if tabela.exists(t[1]):
ident = tabela.getVar(t[1])
print "\tCHPR " + ident.getRotulo()
def p_expression_uminus(t):
'expression : MINUS expression %prec UMINUS'
t[0] = -t[2]
def p_expression_group(t):
'expression : LPAREN expression RPAREN'
t[0] = t[2]
def p_expression_number(t):
'expression : NUMBER'
print "\tCRCT "+ str(t[1])
t[0] = t[1]
expression_tipo = "integer"
def p_expression_id(t):
'expression : ID'
if tabela.exists(t[1]) :
ident = tabela.getVar(t[1])
if ident.referencia:
print "\tCRVI " + ident.getEnd()
else:
print "\tCRVL " + ident.getEnd()
tipo.add(ident.getTipo())
else:
sys.stderr.write("ERRO: variavel nao definida:"+t[1]+"\n")
raise SyntaxError
def p_error(t):
print "Syntax error at '%s'" % t.value
import ply.yacc as yacc
yacc.yacc()
s = ""
while 1:
try:
s += raw_input() + " "
except EOFError:
break
#print s
yacc.parse(s)
#tabela.imprime()