next up previous contents
Next: 5.3 El comportamiento no Up: 5.2 Las reglas léxicas Previous: 5.2.3 Implementación de las

A.1.2 Un ejemplo sencillo

Para que se pueda comprender mejor la implementación de las reglas léxicas, vamos a mostrar un pequeño ejemplo. Se trata de reconocer los sustantivos que forman el género mediante G1 y el número mediante N1.

Lo primero que debemos hacer es definir las condiciones de arranque en la sección inicial de declaraciones del programa Flex. Para nuestro ejemplo, es suficiente con definir G1, N1 y E. esta última constituye la condición de error a la cual se enviará el autómata del reconocedor siempre que una palabra no puede ser reconocida. Esto se traduce en código de la siguiente maneragif:

/* Error */
%x E

/* gender */
%x G1

/* Number */
%x N1

Después definimos los dos patrones siguientes:

En las siguientes línea de código se definen estos dos patronesgif:

/* Separator characters */
sep   [" "\t,;:\.\n]

/* Non-separator characters */
nosep [^" "\t,;:\.\n]]

Con esto ya podemos comenzar a definir reglas en la sección de reglas del programa Flex. Como ejemplo vamos a mostrar cómo se reconocen las palabras cuyos lemas son perro y gato.

Los lexemas de estas palabra son perr y gat, respectivamente. Como dijimos anteriormente, deberán ser utilizados como patrones en la parte izquierda de una regla sin condición de arranque, como se muestra a continuación:

gat    |
perr   {yymore();
        BEGIN G1;
       }

Mediante la llamada a la función yymore indicamos a Flex que queremos seguir añadiendo en yytextgif los caracteres que sean reconocidos a continuación.

Ahora es preciso definir la reglas mediante las cuales se reconoce el género de las palabras incluidas en el grupo G1. Estas palabras forman el masculino añadiendo una o al lexema y el femenino añadiendo una a. En el siguiente código se muestra la definición de tales reglas:

/* Terminations for gender: Case 1 */
<G1>o          {/* Masculine */
                printf(" masculine");
                yymore();
                BEGIN N1:
               }
<G1>a          {/* Feminine */
                printf(" feminine");
                yymore();
                BEGIN N1;
               }

El prefijo <G1> antes de los patrones o y a indica que ambas reglas sólo se activarán cuando la condición de arranque G1 haya sido activada mediante BEGIN G1. Como G1 ha sido definida en modo exclusivo, después de BEGIN G1 únicamente estas dos reglas estarán activas.

Como todas las palabras que forman el género en G1 forman el número en N1, ambas reglas utilizan BEGIN N1 para activar la condición de arranque N1.

Las reglas para el reconocimiento del número son la siguientes:

/* Terminations for number: Case 1 */
<N1>s/{sep}    {/* Plural */
                printf(", plural --> %s",yytext);
                BEGIN(INITIAL)
               }
<N1>""/{sep}   {/* Singular */
                printf(", singular --> %s", yytext);
                BEGIN(INITIAL);
               }
<N1>.          {/* Bad word. Error. */
                yymore();
                BEGIN E;
               }

La terminación /{sep} constituye un contexto de colagif. Se utiliza para indicar que el patrón de esa regla deberá estar segido por un separador, pero el carácter separador no es incluido en yytext y será reconocido en patrones de reglas posteriores, pero no en la actual. Se utiliza en estos patrones para evitar reconocer una palabra incompleta.

La expresión "" se utiliza para indicar un carácter vacío, puesto que las palabras de N1 no añaden ningún carácter para formar el plural.

El patrón . empareja con cualquier carácter excepto con un avance de línea. Se utiliza para detectar palabras erróneas o aquellas que no han sido incluidas en el lexical. En las acciones de esta regla se utiliza yymore para que al activar el modo pánico, en yytext se almacene todo el texto no reconocido como válido. La regla del error es la siguiente:

<E>{nosep}*/{sep} {/* Panic mode. Recognise every character 
                    * until the next separator.              */
                   printf(", ERROR --> %s", yytext);
                   BEGIN(INITIAL);
                  }

La acción BEGIN(INITIAL) hace que el reconocedor vuelva a las reglas que no tienen condición de arranquegif.

Por último las siguientes reglas permiten tratar los separadores.

""        |
\t        |
\n        {/* separator non significatives */
           ;
          }
","     |
";"     |
":"     |
"."     {/* Puntuation marks */
           printf(" Puntuation mark -> %s", yytext);
           BEGIN(INITIAL);
          }

Los espacios, tabuladores y caracteres de nueva línea se ignoran, pero las marcas de puntuación se reconocen como un componente léxico, ya que son significativas en el proceso de análisis sintáctico para detectar los límites de las oraciones.

En este ejemplo sólo se muestra por pantalla el género y el número. En el analizador real, se almacenan los datos en una estructura que se pasa al analizador sintáctico. El modo en que se enlazan los analizadores léxico y sintáctico se muestra en el capítulo 6.

Un aspecto importante que hay que tener en cuenta es el de la definición de yytext. La variable yytext está definida por defecto en Flex como un puntero a char. La ventaja de usar esta definción es que no se producirán overflows en el buffer cuando se reconozcan componentes léxicos muy largosgif, ya que Flex va asignando memoria a yytext dinámicamentegif. La desventaja es que no se puede modificar el contenido de yytext, ya que los resultados que se obtendrían serían impredecibles. Esto último implica que no se pueden utilizar funciones como input y unput.

Se puede definir la variables yytext como un array mediante la utilización de %array en la sección de declaraciones del programa Flex. El tamaño viene determinado por el valor de YYLMAX, originalmente 8 Kilobytes. Utilizando esta definicón se puede modificar el valor de yytext sin problemas. El único inconveniente que podría surgir sería el derivado del límite de tamaño impuesto por el array. En nuestro caso no es ningún problema, ya que no existen palabras de miles de caracteresgif.


next up previous contents
Next: 5.3 El comportamiento no Up: 5.2 Las reglas léxicas Previous: 5.2.3 Implementación de las

Miguel A. Alonso Pardo
Thu Nov 20 16:47:01 CET 1997