next up previous contents
Next: Un pequeño ejemplo Up: 5.3 El comportamiento no Previous: 5.3.1 El comportamiento determinista

5.3.2 La incorporación del no determinismo a los reconocedores Flex

Puesto que la carencia del no determinismo en los reconocedores generados por Flex vienen dada porque no se almacena información global sobre el texto reconocido, la solución consiste en encontrar algún método de incorporar a los reconocedores tal información. A priori, ésta puede parecer una tarea desbordante, ya que la consecución de no determinismo en todas las condiciones de arranque significaría tener que guardar una estructura arborescente, puesto que habría múltiples caminos mediante los cuales reconocer una palabra.

Sin embargo, si enfocamos bien el problema, se puede observar que éste radica en la iteración continuada en las reglas iniciales. Por lo tanto, de lo que se trata es de buscar un mecanismo que indique al reconocedor que un patrón ya ha sido reconocido para evitar que vuelva a lanzar la regla correspondiente.

De este modo, mediante la combinación de yyless(0); BEGIN(INITIAL) y esa información del matching de los patrones se puede conseguir un comportamiento no determinista del autómata reconocedor.

La solución adoptada se ha mostrado simple y eficiente, pues tan sólo es necesario mantener las dos variables siguientes:

Inicialmente ambas variables establecen sus valores a 0. Cuando se reconoce un patrón para una palabra, se incrementa en 1 el valor de match_no y si el valor de semaphore es 0, se iguala el valor de ésta al de match_no. Cuando se termine de reconocer esa palabra o se deseche por ser errónea, se llama a yyless(0) y BEGIN(INITIAL), con lo cual el analizador léxico intentará reconocer la palabra otra vez desde el principio.

El reconocedor intentará entrar otra vez por el mismo patrón de antes, pero esta vez semaphore tendrá un valor distinto de 0 (concretamente tendrá valor 1), lo que indica que no debemos escoger ese patrón, sino otro que es la siguiente mejor elección. Se decrementa su valor en 1 y se hace un REJECT, con lo cual se busca precisamente la siguiente mejor elección.

El siguiente patrón reconocido será el corecto puesto que semaphore tendrá valor 0. Se incrementa el valor de match_no y se prosigue con el proceso.

Se debe de contemplar la posibilidad de una salida para el caso de que ya no haya más patrones correctos para la palabra examinada. Para ello se llama a yymore() y a BEGIN S desde una regla con el punto como patrón. La condición de arranque S contiene la regla siguiente:

/* Success condition */
<S>{nosep}*/{sep} {
                   BEGIN 0;
                   return (1);
                  }

La acción BEGIN 0 es equivalente a BEGIN(INITIAL). Esta regla es la única en la que se realiza un return, por lo que una vez que se llama a la función yylex desde el analizador sintáctico, no se devuelve el control hasta que se llega a la condición S, hecho que se da cuando ya se han examinado todos los posibles componentes léxicos válidos para una palabra.

Existe también una condición de error, llamada E, a la que se manda el reconocedor cuando una palabra no puede ser construida mediante el camino examinado:

/* Error condition */
<E>{nosep}*/{sep}  {
                    yyless(0);
                    BEGIN(INITIAL);
                   }

Es igual que la regla con <S> excepto que ésta no devuelve el control al analizador sintáctico, sino que intentará encontrar otro camino para reconocer la palabra.


next up previous contents
Next: Un pequeño ejemplo Up: 5.3 El comportamiento no Previous: 5.3.1 El comportamiento determinista

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