-
Notifications
You must be signed in to change notification settings - Fork 0
/
GRAMATICA.y
300 lines (239 loc) · 13.9 KB
/
GRAMATICA.y
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
%token IF THEN ELSE ENDIF PRINT INT BEGIN END FLOAT GLOBAL LOOP UNTIL TOFLOAT ID CTE MENORIGUAL MAYORIGUAL IGUALIGUAL DISTINTO CADENA
%right THEN ELSE IF
%left '+' '-'
%left '*' '/'
%%
programa : parte_declarativa parte_ejecutable
| parte_ejecutable
;
parte_declarativa : parte_declarativa sentencia_declarativa
| sentencia_declarativa
;
parte_ejecutable : parte_ejecutable sentencia_ejecutable
| parte_ejecutable ambito
| sentencia_ejecutable
| ambito
|error ';' {notificar("Sentencia invalida");}
;
parte_ejecutable_bloque : parte_ejecutable_bloque sentencia_ejecutable
| sentencia_ejecutable
;
sentencia_declarativa : tipo lista_var ';' {addRegla("una declaracion de variable");}
| tipo error ';' {notificar("Se esperaba un identificador (o una lista de identificadores)");}
| tipo lista_var error ';' {notificar("Error luego de la lista de identificadores");}
;
tipo : FLOAT {tipo="FLOAT";}
| INT {tipo="INT";}
;
lista_var : lista_var ',' ID {declararVariable($3, tipo);}
| ID {declararVariable($1, tipo);}
| error ',' ID {notificar ("Error en la lista de identificadores");}
;
lista_var_g : lista_var_g ',' ID {hacerGlobal($3);}
| ID {hacerGlobal($1);}
| error ',' ID {notificar ("Error en la lista de identificadores");}
;
sentencia_ejecutable : seleccion
| iteracion ';'
| iteracion {notificar("Falta ';' para cerrar la iteracion");}
| salida_mensajes ';'
| salida_mensajes {notificar("Falta ';' para cerrar la sentencia PRINT");}
| asignacion
;
seleccion : IF condicion_if THEN bloque_de_sentencias { int incompleto = codGen->desapilar();
codGen->completarTerceto(incompleto, "["+QString::number(codGen->ultimoTerceto()+1)+"]", 3);
addRegla("el cierre de una sentencia de seleccion (IF-THEN)");
codGen->crearTerceto("Label", QString::number(codGen->ultimoTerceto()+1), "null");
}
| IF condicion_if THEN bloque_de_sentencias else bloque_de_sentencias { int incompleto = codGen->desapilar();
codGen->completarTerceto(incompleto, "["+QString::number(codGen->ultimoTerceto()+1)+"]", 2);
addRegla("el cierre de una sentencia de seleccion (IF-THEN-ELSE)");
codGen->crearTerceto("Label", QString::number(codGen->ultimoTerceto()+1), "null");
}
| IF condicion_if bloque_de_sentencias {notificar("Se encontro el cierre de una sentencia de seleccion a la que le falta la palabra reservada THEN");}
| IF condicion_if bloque_de_sentencias ELSE bloque_de_sentencias {notificar("Se encontro el cierre de una sentencia de seleccion a la que le falta la palabra reservada THEN");}
;
condicion_if : '(' condicion ')' { int nroTerceto = codGen->crearTerceto("BF", "[" +QString::number(codGen->ultimoTerceto())+"]", "");
codGen->apilar(nroTerceto);
}
| '(' condicion {notificar("Se esperaba ')'");}
| condicion ')' {notificar("Se esperaba '('");}
| condicion {notificar("Se esperaban parentesis alrededor de la condicion");}
;
else : ELSE { int incompleto = codGen->desapilar();
codGen->completarTerceto(incompleto, "["+QString::number(codGen->ultimoTerceto()+2)+"]", 3);
int nroTerceto = codGen->crearTerceto("BI", "", "null");
codGen->crearTerceto("Label", QString::number(codGen->ultimoTerceto()+1), "null");
codGen->apilar(nroTerceto);
}
;
condicion_until : '(' condicion ')' { int nroInicio = codGen->desapilar();
int ultimoTerceto = codGen->ultimoTerceto();
codGen->crearTerceto("BF", "["+QString::number(ultimoTerceto)+"]", "["+QString::number(nroInicio)+"]");
}
| '(' condicion {notificar("Se esperaba ')'");}
| condicion ')' {notificar("Se esperaba '('");}
| condicion {notificar("Se esperaban parentesis alrededor de la condicion");}
;
condicion : expresion comparador expresion { addRegla("una condicion");
QString tipo1, tipo2;
if (!tiposArrojados.empty())
tipo1 = tiposArrojados.pop();
if (!tiposArrojados.empty())
tipo2 = tiposArrojados.pop();
if (tipo1!=tipo2)
notificar("Tipos incompatibles en la comparacion");
else
codGen->crearTerceto($2, $1, $3, codGen->obtenerTipo($1));
}
| expresion comparador error {notificar("Se esperaba una expresion en el lado derecho de la condicion");};
| error comparador expresion {notificar("Se esperaba una expresion en el lado izquierdo de la condicion");};
| expresion error expresion {notificar("Se esperaba un comparador entre las expresiones de la condicion");};
| error comparador error {notificar("Se esperaban expresiones alrededor del comparador");}
| error {notificar("Se esperaba una condicion");};
;
asignacion : ID '=' expresion ';' {addRegla("una sentencia de asignacion");
QString old = $1;
$1 = mangle($1);
tabladeSimbolos->eliminar(old);
if ($1 != "") {
if (!tiposArrojados.empty()) {
QString tipoExpr = tiposArrojados.pop();
QString tipoId = tabladeSimbolos->obtenerTipo($1);
if (tipoExpr!=tipoId)
notificar("Se esta intentando asignar una expresion de tipo " + tipoExpr + " a una variable de tipo " + tipoId);
else
codGen->crearTerceto("=", $1, $3, tipoExpr);
}
}
}
| ID '=' expresion {addRegla("una sentencia de asignacion"); notificar("Falta ';' para cerrar la asignacion");}
| ID '=' error ';' {notificar("Se esperaba una expresion");}
| ID '=' expresion error ';' {notificar("Error en la asignacion");}
| ID error ';'{notificar("Se esperaba el operador de asignacion '='");}
;
expresion : expresion '+' expresion { $$ = "["+QString::number(codGen->crearTerceto("+", $1, $3, codGen->obtenerTipo($1)))+"]";
QString tipo1, tipo2;
if (!tiposArrojados.empty())
tipo1 = tiposArrojados.pop();
if (!tiposArrojados.empty())
tipo2 = tiposArrojados.pop();
if (tipo1!=tipo2)
notificar("Tipos incompatibles en la suma");
else
tiposArrojados.push(tipo1);
}
| expresion '-' expresion { $$ = "["+QString::number(codGen->crearTerceto("-", $1, $3, codGen->obtenerTipo($1)))+"]";
QString tipo1, tipo2;
if (!tiposArrojados.empty())
tipo1 = tiposArrojados.pop();
if (!tiposArrojados.empty())
tipo2 = tiposArrojados.pop();
if (tipo1!=tipo2)
notificar("Tipos incompatibles en la resta");
else
tiposArrojados.push(tipo1);
}
| TOFLOAT '(' expresion ')' { tiposArrojados.pop();
tiposArrojados.push("FLOAT");
$$ = "["+QString::number(codGen->crearTerceto("TOFLOAT", $3, "null","FLOAT"))+"]";
}
| expresion '*' expresion { $$ = "["+QString::number(codGen->crearTerceto("*", $1, $3, codGen->obtenerTipo($1)))+"]";
QString tipo1, tipo2;
if (!tiposArrojados.empty())
tipo1 = tiposArrojados.pop();
if (!tiposArrojados.empty())
tipo2 = tiposArrojados.pop();
if (tipo1!=tipo2) {
notificar("Tipos incompatibles en la multiplicacion");
tiposArrojados.push("Indefinido");
}
else
tiposArrojados.push(tipo1);
}
| expresion '/' expresion { $$ = "["+QString::number(codGen->crearTerceto("/", $1, $3, codGen->obtenerTipo($1)))+"]";
QString tipo1, tipo2;
if (!tiposArrojados.empty())
tipo1 = tiposArrojados.pop();
if (!tiposArrojados.empty())
tipo2 = tiposArrojados.pop();
if (tipo1!=tipo2) {
notificar("Tipos incompatibles en la division");
tiposArrojados.push("Indefinido");
}
else
tiposArrojados.push(tipo1);
}
| ID {
QString old = $1;
$1 = mangle($1);
$$=$1;
tabladeSimbolos->eliminar(old);
if ($1 != "")
tiposArrojados.push(tabladeSimbolos->obtenerTipo($1));
}
| CTE { if (!rangoValido($1, false)) {
notificar("Constante entera fuera de rango");
tiposArrojados.push("INT");
} else {
$$=$1;
marcarUsada($1);
tiposArrojados.push(tabladeSimbolos->obtenerTipo($1));
}
}
| '-' CTE %prec '*' { if (rangoValido($2, true)) {
$2 = negativo($2);
$$=$2;
tiposArrojados.push(tabladeSimbolos->obtenerTipo($2));
} else {
notificar("Constante entera fuera de rango");
tiposArrojados.push("INT");
}
}
;
comparador : '>' {$$ = ">";}
| '<' {$$ = "<";}
| MAYORIGUAL {$$ = ">=";}
| MENORIGUAL {$$ = "<=";}
| DISTINTO {$$ = "<>";}
| IGUALIGUAL {$$ = "==";}
;
bloque_de_sentencias : sentencia_ejecutable
| BEGIN parte_ejecutable_bloque END ';' {addRegla("el cierre de un bloque BEGIN-END");}
| BEGIN parte_ejecutable_bloque END {notificar("Falta ';' para cerrar el bloque BEGIN-END");}
;
iteracion : loop bloque_de_sentencias UNTIL condicion_until {addRegla("una sentencia de iteracion");}
;
loop : LOOP { int inicioLoop = codGen->ultimoTerceto()+1;
codGen->apilar(inicioLoop);
codGen->crearTerceto("Label", QString::number(inicioLoop), "null");
}
salida_mensajes : PRINT '(' CADENA ')' {codGen->crearTerceto("PRINT", $3, "null"); addRegla("una sentencia de impresion por pantalla");}
| PRINT '(' CADENA {notificar("Falta ')'");}
| PRINT CADENA ')' {notificar("Falta '('");}
| PRINT CADENA {notificar ("Faltan parentesis alrededor de la cadena");}
| PRINT '(' error ')' {notificar("Se esperaba una cadena");}
;
ambito : abre_ambito parte_declara_ambito parte_ejecutable cierra_ambito {addRegla("el cierre de una declaracion de ambito");}
| abre_ambito parte_ejecutable cierra_ambito {addRegla("el cierre de una declaracion de ambito");}
| abre_ambito parte_declara_ambito cierra_ambito {notificar("El ambito debe tener sentencias ejecutables");}
| abre_ambito parte_ejecutable parte_declara_ambito cierra_ambito {notificar("Las sentencias declarativas del ambito deben estar antes que las ejecutables");}
| abre_ambito error cierra_ambito {notificar("Error de sintaxis en el ambito");}
;
abre_ambito : '{' { int aux =ambitos.value(sufijo);
aux++;
ambitos.remove(sufijo);
ambitos.insert(sufijo, aux);
sufijo+= "_";
sufijo+= QString::number(aux);
ambitos.insert(sufijo, 0);
}
;
cierra_ambito : '}' { sufijo = sufijoPadre(sufijo);}
;
parte_declara_ambito : parte_declara_ambito sent_declara_ambito
| sent_declara_ambito
;
sent_declara_ambito : sentencia_declarativa
| GLOBAL lista_var_g ';' {addRegla("una declaracion de variable global");}
;