-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLexicalAnalyzer.l
292 lines (252 loc) · 7.36 KB
/
LexicalAnalyzer.l
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
%{
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "y.tab.h"
FILE *yyin;
#define FLT_MAX 3.4028235E38
#define INT_MAX 32767
#define LEXEMA_SIZE 100
#define TSROWS 100000
int yylval;
struct TS {
char lexema[LEXEMA_SIZE]; /* CTE, ID */
char tipo[20]; /* En el nivel lexico el tipo es desconocido */
char valor[100]; /* En el nivel lexico, el valor se incluye solo si es constante */
};
struct TS tablaSimbolos[TSROWS];
int cantidadFilasTS = 0;
void validar_entero(char *enteroString);
void validar_real(char *realString);
void validar_string(char *string);
int guardar_en_TS(char *lexema, char *tipo, char *valor, int esCTE);
int buscar_en_TS(char *nombreDeSimbolo);
char* devolver_lexema(int);
char* devolver_tipo(int);
void guardar_TS_en_archivo();
int guardar_tipo_en_TS(char *lexema, char *tipo);
%}
%option noyywrap
%option yylineno
DIGITO [0-9]
LETRA [a-zA-Z]
CONST_STR \"({LETRA}|{DIGITO})*\"
CONST_REAL (({DIGITO}+"."{DIGITO}*)|({DIGITO}*"."{DIGITO}+))
CONST_INT {DIGITO}+
ID {LETRA}({LETRA}|{DIGITO}|_)*
COMENTARIO (("-/"({LETRA}|{DIGITO}|[ ])*"/-")|("-/"({LETRA}|{DIGITO}|[ ])*"-/"({LETRA}|{DIGITO}|[ ])*"/-"({LETRA}|{DIGITO}|[ ])*"/-"))
COMA ","
DOS_PUNTOS ":"
MENOR "<"
IGUAL_IGUAL "=="
MAYOR ">"
MENOR_IGUAL "<="
MAYOR_IGUAL ">="
DIFERENTE "!="
OP_CONCAT "++"
OP_SUMA "+"
OP_RESTA "-"
OP_MULT "*"
OP_DIV "/"
OP_ASIG ":="
OP_AND "and"
OP_OR "or"
OP_NOT "not"
COR_A "["
COR_C "]"
PAR_A "("
PAR_C ")"
PR_WRITE "WRITE"
PR_READ "READ"
PR_VAR "VAR"
PR_ENDVAR "ENDVAR"
PR_REAL "float"
PR_INTEGER "integer"
PR_STRING "string"
PR_IF "if"
PR_THEN "then"
PR_ELSE "else"
PR_ENDIF "endif"
PR_WHILE "while"
PR_DO "do"
PR_ENDWHILE "endwhile"
PR_IN "in"
%%
{PR_VAR} { return PR_VAR;}
{PR_ENDVAR} { return PR_ENDVAR;}
{PR_REAL} { return PR_REAL;}
{PR_INTEGER} { return PR_INTEGER;}
{PR_STRING} { return PR_STRING;}
{PR_IF} { return PR_IF;}
{PR_THEN} { return PR_THEN;}
{PR_ELSE} { return PR_ELSE;}
{PR_ENDIF} { return PR_ENDIF;}
{PR_WHILE} { return PR_WHILE;}
{PR_DO} { return PR_DO;}
{PR_ENDWHILE} { return PR_ENDWHILE;}
{PR_IN} { return PR_IN;}
{PR_WRITE} { return PR_WRITE;}
{PR_READ} { return PR_READ;}
{OP_ASIG} { return OP_ASIG;}
{OP_CONCAT} { return OP_CONCAT;}
{OP_SUMA} { return OP_SUMA;}
{OP_RESTA} { return OP_RESTA;}
{OP_MULT} { return OP_MULT;}
{OP_DIV} { return OP_DIV;}
{PAR_A} { return PAR_A;}
{PAR_C} { return PAR_C;}
{COR_A} { return COR_A;}
{COR_C} { return COR_C;}
{MAYOR} { return MAYOR;}
{MAYOR_IGUAL} { return MAYOR_IGUAL;}
{MENOR} { return MENOR;}
{MENOR_IGUAL} { return MENOR_IGUAL;}
{DIFERENTE} { return DIFERENTE;}
{IGUAL_IGUAL} { return IGUAL_IGUAL;}
{OP_AND} { return OP_AND;}
{OP_OR} { return OP_OR;}
{OP_NOT} { return OP_NOT;}
{ID} { yylval = guardar_en_TS(yytext, "", "", 0); return ID; }
{CONST_INT} { validar_entero(yytext); yylval = guardar_en_TS(yytext, "CONST_INT", yytext, 1); return CONST_INT; }
{CONST_STR} { validar_string(yytext); yylval = guardar_en_TS(yytext, "CONST_STR", yytext, 1); return CONST_STR; }
{CONST_REAL} { validar_real(yytext); yylval = guardar_en_TS(yytext, "CONST_REAL", yytext, 1); return CONST_REAL; }
{COMA} { return COMA;}
{DOS_PUNTOS} { return DOS_PUNTOS;}
{COMENTARIO} ;
[ \t\n] ;
. ;
%%
void validar_entero(char *enteroString) {
int valor;
valor = atoi(enteroString);
if(valor > INT_MAX) {
printf("\nConstante entera %s fuera de rango!", enteroString);
exit(1);
}
}
void validar_real(char *realString) {
double valor;
valor = atof(realString);
if(valor == 0) {
return;
}
if(valor > FLT_MAX) {
printf("\nConstante real %s fuera de rango!", realString);
exit(1);
}
}
void validar_string(char *string) {
int tamanio = strlen(string);
if(tamanio >= 32) {
printf("\nConstante string %s fuera de rango!", string);
exit(1);
}
}
/******************************************************************************************
**************************** FUNCIONES DE TABLA DE SIMBOLOS *******************************
******************************************************************************************/
/* Primero busca el lexema en TS.
Si lo encuentra: modifica los valores
Si no lo encuentra, lo agrega a la TS
En cualquiera de los dos casos, devuelve la posicion de TS donde lo agrego */
int guardar_en_TS(char *lexema, char *tipo, char *valor, int esCTE) {
int posicionEnTS = -1;
char valor_new[100];
char nuevoLexema[LEXEMA_SIZE + 1] = "";
/*Agrego el '_' al lexema */
if(esCTE == 1) {
nuevoLexema[0] = '_';
nuevoLexema[1] = '\0';
}
if(strcmp(tipo,"CONST_STR") == 0)
{
lexema++;
char *aux = lexema;
while(*lexema != '\0')
lexema++;
lexema--;
*lexema = '\0';
lexema = aux;
strcpy(valor_new,lexema);
}
strcat(nuevoLexema, lexema);
posicionEnTS = buscar_en_TS(nuevoLexema);
if(posicionEnTS != -1) {
/*Lo encontro! Actualiza!*/
if(strcmp(tablaSimbolos[posicionEnTS].tipo, tipo) != 0 && strcmp(tipo, "") != 0) {
printf("\n1 Variable %s de tipo %s no puede cambiar a tipo %s!!", lexema, tablaSimbolos[posicionEnTS].tipo, tipo);
exit(1);
}
} else {
/*No lo encontro! Agrega!*/
strcpy(tablaSimbolos[cantidadFilasTS].lexema, nuevoLexema);
strcpy(tablaSimbolos[cantidadFilasTS].tipo, tipo);
if(strcmp(tipo,"CONST_STR") == 0)
strcpy(tablaSimbolos[cantidadFilasTS].valor, valor_new);
else
strcpy(tablaSimbolos[cantidadFilasTS].valor, valor);
cantidadFilasTS++;
posicionEnTS = cantidadFilasTS -1;
}
return posicionEnTS;
}
/* USAR SOLO EN LEXICO
Busca un simbolo en la TS devolviendo su posicion en la misma.
Si no lo encuentra devuelve -1 */
int buscar_en_TS(char *nombreDeSimbolo) {
int i = 0;
for(i = 0 ; i < cantidadFilasTS ; i++) {
if(strcmp(nombreDeSimbolo, tablaSimbolos[i].lexema) == 0) {
return i;
}
}
return -1;
}
void guardar_TS_en_archivo() {
int i = 0;
FILE *tosFP;
tosFP = fopen("ts.txt", "w+");
if(tosFP == NULL) {
printf("\nIMPOSIBLE GUARDAR TS EN ARCHIVO!");
exit(1);
}
fprintf(tosFP, "NOMBRE \t\t\t TIPO \t\t\t VALOR");
for(i = 0 ; i < cantidadFilasTS ; i++) {
fprintf(tosFP, "\n%s \t\t\t %s \t\t\t %s", tablaSimbolos[i].lexema, tablaSimbolos[i].tipo, tablaSimbolos[i].valor);
}
fclose(tosFP);
}
int guardar_tipo_en_TS(char *lexema, char *tipo) {
int posicionEnTS = -1;
posicionEnTS = buscar_en_TS(lexema);
if(posicionEnTS != -1) {
/*Lo encontro! Actualiza!*/
if(strcmp(tablaSimbolos[posicionEnTS].tipo, "") == 0) {
strcpy(tablaSimbolos[posicionEnTS].tipo, tipo);
} else {
/* Lo encontro e intenta actualizar pero es de tipo diferente!*/
if(strcmp(tablaSimbolos[posicionEnTS].tipo, tipo) != 0) {
printf("\nVariable %s de tipo %s no puede cambiar a tipo %s!!", lexema, tablaSimbolos[posicionEnTS].tipo, tipo);
exit(1);
}
}
} else {
/*No lo encontro! Es un error porque debería encontrarlo!*/
printf("Error: No encontró la lexema solicitada: %s\n", lexema);
exit(1);
}
return posicionEnTS;
}
char* devolver_lexema(int pos)
{
return tablaSimbolos[pos].lexema;
}
char* devolver_tipo(int pos)
{
return tablaSimbolos[pos].tipo;
}
int devolver_indice()
{
return cantidadFilasTS;
}