Descripción del lenguaje Lenguaje flex Descripción del lenguaje Dr. Julio J. Águila G. miércoles 19 de agosto de 2014
Objetivo Presentar una herramienta computacional para construir analizadores léxicos utilizando la teoría de autómatas y lenguajes formales. administrador de la tabla de símbolos manejador de errores analizador sintáctico léxico obtén el siguiente componente léxico componente léxico
administrador de la tabla de símbolos manejador de errores analizador sintáctico léxico obtén el siguiente componente léxico componente léxico
Funcionamiento Sea un archivo de especificaciones flex llamado file.flex. lex.yy.c a.out compilador de flex de C Programa fuente en flex file.flex Archivo de entrada Secuencia de Componentes Léxicos
Estructura del archivo fuente Un programa de especificaciones flex consta de tres partes: Declaraciones %% Especificaciones regulares y reglas de traducción Procedimientos auxiliares
Expresiones regulares Expresión Empareja con Ejemplo c cualquier carácter c que no sea operador a \c el carácter c literalmente \* “s” la cadena s literalmente “**” . cualquier carácter excepto de nueva línea a.*b ^ el comienzo de línea ^abc $ el fin de línea abc$ [s] cualquier carácter en s [abc] [^s] cualquier carácter que no esté en s [^abc] r* cero o más r a* r+ una o más r a+ r? cero o una r a? r{m,n} m a n casos de r a{1,5} r1r2 r1 y entonces r2 ab r1|r2 r1 o r2 a|b (r) r (a b) r1/r2 r1 cuando va seguida de r2 abc/123
Operadores Se debe eliminar el significado especial de los símbolos de los operadores si el símbolo de operador se utiliza como carácter de emparejamiento, los operadores son: \ “ . ^ $ [ ] * + ? { } | / Esto se puede hacer encerrando entre comillas el carácter, o anteponiendo \ al carácter. Por ejemplo “*” o \* quita el significado de la cerradura de Kleene al operador *.
Ejemplo: archivo tolower.flex %{ /* * remove upper case letters */ %} %% [A-Z]+
Compilación tolower.flex Generamos el analizador léxico con el compilador flex: flex tolower.flex Se crea un archivo lex.yy.c a partir del cual generamos un ejecutable con gcc: gcc -o tolower lex.yy.c -ll Probamos con: ./tolower < tolower.flex
Ejemplo: archivo tolower.flex %{ /* * remove upper case letters */ %} %% [A-Z]+ Declaraciones Especificaciones regulares y reglas de traducción
Expresiones regulares Expresión Empareja con Ejemplo c cualquier carácter c que no sea operador a \c el carácter c literalmente \* “s” la cadena s literalmente “**” . cualquier carácter excepto de nueva línea a.*b ^ el comienzo de línea ^abc $ el fin de línea abc$ [s] cualquier carácter en s [abc] [^s] cualquier carácter que no esté en s [^abc] r* cero o más r a* r+ una o más r a+ r? cero o una r a? r{m,n} m a n casos de r a{1,5} r1r2 r1 y entonces r2 ab r1|r2 r1 o r2 a|b (r) r (a b) r1/r2 r1 cuando va seguida de r2 abc/123
Ejemplo: archivo line_numbering.flex %{ /* * line numbering */ %} %% \n ECHO; ^.*$ printf("%d\t%s", yylineno++, yytext); Especificaciones regulares y reglas de traducción
Reglas de traducción Las reglas de traducción de un archivo flex son proposiciones de la forma: p1 { acción1 } p2 { acción2 } ... ... pn { acciónn } Donde pi es una expresión regular y cada accióni es un fragmento de programa que describe la acción del analizador léxico cuando el patrón pi coincide con un lexema.
Compilación line_numbering.flex Generamos el analizador léxico con el compilador flex: flex line_numbering.flex Se crea un archivo lex.yy.c a partir del cual generamos un ejecutable con gcc: gcc –o line_numbering lex.yy.c -ll Probamos con: ./line_numbering < tolower.flex
Ejemplo: archivo line_numbering.flex (2da versión) %{ /* * line numbering */ %} %% ^.*\n printf("%d\t%s", yylineno++, yytext);
Expresiones regulares Expresión Empareja con Ejemplo c cualquier carácter c que no sea operador a \c el carácter c literalmente \* “s” la cadena s literalmente “**” . cualquier carácter excepto de nueva línea a.*b ^ el comienzo de línea ^abc $ el fin de línea abc$ [s] cualquier carácter en s [abc] [^s] cualquier carácter que no esté en s [^abc] r* cero o más r a* r+ una o más r a+ r? cero o una r a? r{m,n} m a n casos de r a{1,5} r1r2 r1 y entonces r2 ab r1|r2 r1 o r2 a|b (r) r (a b) r1/r2 r1 cuando va seguida de r2 abc/123
Ejemplo: archivo wc.flex %{ /* * word count */ int nchar = 0; int nword = 0; int nline = 0; %} Declaraciones
Ejemplo: archivo wc.flex %% \n ++nchar, ++nline; [^ \t\n]+ ++nword, nchar+= yyleng; . ++nchar; Especificaciones regulares y reglas de traducción
Ejemplo: archivo wc.flex #include <stdio.h> int main ( void ) { yylex(); printf("%d %d %d\n", nchar, nword, nline); return 0; } Procedimientos Auxiliares
Compilación wc.flex Generamos el analizador léxico con el compilador flex: flex wc.flex Se crea un archivo lex.yy.c a partir del cual generamos un ejecutable con gcc: gcc –o wc lex.yy.c -ll Probamos con: ./wc < tolower.flex
Declaraciones La sección de declaraciones incluye declaraciones de headers, constantes simbólicas, variables, funciones auxiliares, etc. Por ejemplo: %{ /* * word count */ int nchar = 0; int nword = 0; int nline = 0; %}
Procedimientos auxiliares La tercera sección contiene todos los procedimientos auxiliares que puedan necesitar las acciones. A veces estos procedimientos se pueden compilar por separado y cargar con el analizador léxico.
Ejemplo: archivo wc.flex #include <stdio.h> int main ( void ) { yylex(); printf("%d %d %d\n", nchar, nword, nline); return 0; }
Archivo lex.yy.c Es el archivo que contiene al analizador léxico llamado yylex. Dentro de él también están declaradas las variables yyin e yytext: 166 extern FILE *yyin, *yyout; 353 extern char *yytext; 637 extern int yylex (void); Obs.: Los valores de línea sólo son referenciales.
Manuales sobre flex UBUNTU tiene un manual en línea: man flex En Internet también se puede buscar y descargar un manual.
Gracias por su atención.