Ejercicio para el curso de compiladores, es un buen ejemplo de un “hola mundo” para lex, generador de analizadores léxicos. Si tenemos un archivo en C sin indentación, por ejemplo
int main() { for(;;;){ if (1) { printf("T"); } else { printf("F"); printf(" error"); } } return 0; }
queremos que lo convierta en
int main() { for(;;;){ if (1) { printf("T"); } else { printf("F"); printf(" error"); } } return 0; }
Compilar primero con ‘flex prueba.lex’ y luego con ‘gcc lex.yy.c -lfl -o formato’. Ejecutar con ‘$ ./formato < prueba.c’.
El primer bloque del archivo .lex declara variables tal como se declaran en C.
%{
int profundidad = 0;
int i = 0;
%}
A continuación van las reglas. Primero se pone la expresión regular que se quiere atrapar, después va el código en C que se va a ejecutar cuando se encuentre la expresión.
Si se encuentra una llave que abre hay que indicar que se quiere aumentar la profundidad de indentación; si se encuentra una que cierra, que se reduce. Como queremos conservar las llaves (son, al mismo tiempo, “instrucciones” y datos que hay que mostrar) indicamos que se impriman. La variable ‘yytext’ contiene el texto de la expresión regular atrapada, en este caso solamente la llave.
%%
"{" {
++profundidad;
printf("%s", yytext);
}
"}" {
profundidad -= 1;
printf("%s", yytext);
}
Luego sigue una parte que al principio es fácil ignorar; sin esta parte va a funcionar casi bien; el archivo de prueba será indentado como
int main() { for(;;;){ if (1) { printf("T"); } else { printf("F"); printf(" error"); } } /* <----- MAL! */ return 0; }
Si encontramos una llave que cierra al principio de la línea no va a haber tiempo para alinearla con los espacios como se indica en la expresión de más abajo; entonces indicamos aquí que queremos que se comporte de forma especial, reduciendo la profundidad antes de poner la indentación.
\n[ \t]*"}" {
profundidad -= 1;
printf("\n");
for (i = 0; i < profundidad; ++i) {
printf(" ");
}
printf("}");
}
Por último, para agregar indentación en cualquier otro caso lo que hace falta es poner en un ciclo un número de espacios proporcional a la profundidad. Eso se puede hacer después de encontrar un \n:
\n {
printf("%s", yytext);
for (i = 0; i %lt; profundidad; ++i) {
printf(" ");
}
}
%%
Relacionados:
No user responded in this post
Leave A Reply
Nota: La moderación de comentarios está activada; no hace falta volver a enviar los comentarios.