next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Uso de Yacc Sup: La Gramática de yapp Ant: La Cola: Diferencias entre Err: Si hallas una errata ...


El Análisis Léxico en yacc: flex

El analizador léxico para yacc desarrollado en las secciones anteriores ha sido escrito usando la variante flex del lenguaje LEX. Un programa flex tiene una estructura similar a la de un program yacc con tres partes: cabeza, cuerpo y cola separados por %%. Veamos como ejemplo de manejo de flex, los contenidos del fichero flex inherited1.l utilizado en las secciones anteriores:

 1   %{
 2   #include <string.h>
 3   #include "y.tab.h"
 4   %}
 5   id [A-Za-z_][A-Za-z_0-9]*
 6   white [ \t\n]+
 7   %%
 8   global    {  return GLOBAL; }
 9   local     {  return LOCAL; }
10   float     {  return FLOAT; }
11   int       {  return INTEGER; }
12   {id}      {  yylval.s = strdup(yytext); return NAME; }
13   {white}   { ; }
14   ,         { return yytext[0]; }
15   .         { fprintf(stderr,"Error. carácter inesperado.\n"); }
16   %%
17   int yywrap() { return 1; }
La cabeza contiene declaraciones C asi como definiciones regulares. El fichero y.tab.h que es incluído en la línea 3, fué generado por yacc y contiene, entre otras cosas, la información recolectada por yacc sobre los tipos de los atributos (declaración %union) y la enumeración de los terminales. Es, por tanto, necesario que la compilación con yacc preceda a la compilación con flex. La información en y.tab.h es usada por el analizador léxico para ``sincronizarse'' con el analizador sintáctico. Se definen en las líneas 5 y 6 las macros para el reconocimiento de identificadores (id) y blancos (white). Estas macros son llamadas en el cuerpo en las líneas 12 y 13. La estructura del cuerpo consiste en parejas formadas por una definición regular seguidas de una acción. La variable yylval contiene el atributo asociado con el terminal actual. Puesto que el token NAME fué declarado del tipo cadena (véase 7.19.2), se usa el correspondiente nombre de campo yylval.s. La cadena que acaba de casar queda guardada en la variable yytext, y su longitud queda en la variable entera global yyleng.

Una vez compilado con flex el fuente, obtenemos un fichero denominado lex.yy.c. Este fichero contiene la rutina yylex() que realiza el análisis léxico del lenguaje descrito.

La función yylex() analiza las entradas, buscando la secuencia mas larga que casa con alguna de las expresiones regulares y ejecuta la correspondiente acción. Si no se encuentra ningun emparejamiento se ejecuta la regla ``por defecto'', que es:

(.|\n) { printf("%s",yytext); }

Si encuentran dos expresiones regulares con las que la cadena mas larga casa, elige la que figura primera en el programa flex.

Una vez que se ha ejecutado la correspondiente acción, yylex() continúa con el resto de la entrada, buscando por subsiguientes emparejamientos. Asi continúa hasta encontrar un final de fichero en cuyo caso termina, retornando un cero o bien hasta que una de las acciones explicitamente ejecuta una sentencia return.

Cuando el analizador léxico alcanza el final del fichero, el comportamiento en las subsiguientes llamadas a yylex resulta indefinido. En el momento en que yylex alcanza el final del fichero llama a la función yywrap, la cual retorna un valor de 0 o 1 según haya mas entrada o no. Si el valor es 0, la función yylex asume que la propia yywrap se ha encargado de abrir el nuevo fichero y asignarselo a yyin.


next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Uso de Yacc Sup: La Gramática de yapp Ant: La Cola: Diferencias entre Err: Si hallas una errata ...
Casiano Rodríguez León
2013-03-05