Documente Academic
Documente Profesional
Documente Cultură
to “"”
Podemos considerar que, mientras los caracteres son las unidades de entrada
para el analizador léxico (que los une formando unidades lógicas llamadas to-
kens), los tokens son las unidades de entrada (símbolos terminales) para el anal-
izador sintáctico, que los une formando otras unidades lógicas llamadas símbolos
no terminales (véase en el tema siguiente la descripción de gramáticas formales
así como símbolos terminales y no terminales). Los lexemas que cuadran con el
patrón constituyen cadenas de caracteres del programa fuente y serán tratados
conjuntamente, por el analizador sintáctico, como una unidad léxica.
La mayoría de los lenguajes de programación reconocen los siguientes tokens:
palabras clave, diversas clases de operadores, identificadores, constantes numéri-
cas, strings literales, y símbolos de puntuación (tales como paréntesis, comas y
puntos y comas). En el ejemplo anterior, cuando el analizador léxico lee “pi”
devuelve al analizador sintáctico un token ID representando un identificador.
Cuando decimos que devuelve un token, lo que suele ocurrir es que devuelve un
entero que hemos asociado con dicho token. Es decir, en algún lugar del com-
pilador habrá una línea como esta: “#define ID 300”. Es a este entero al que
llamamos ID en el ejemplo.
Un patrón es una regla para reconocer el conjunto de lexemas que representan
un mismo token en el lenguaje fuente. Por ejemplo, el modelo para el token CONST
es, justamente, las letras “c”, “o”, “n”, “s”, “t” seguidas. El modelo para el token
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
28 Análisis léxico
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.3 Descripciones declarativas de los tokens: Expresiones regulares 29
scribirlos con lápiz y papel) y las expresiones regulares (en el caso de usar una
máquina de escribir). Vamos a definir algunos de los términos utilizados en el
análisis y en la descripción de tokens.
- Definimos s0 como ε.
- Para i > 0 d e f i n i m o s E s decir: s 1 = s, s2 = ss, s3 = sss,
...etc.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
30 Análisis léxico
Concatenación de L y M LM = {st | s ∈ L y t ∈ M}
U n i ó n de L y M
Clausura (reflexi-
va) de Kleene de L
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Clausura positiva
(transitiva) de L
{letra}({letra}|{dígito})*
La barra vertical significa OR. Los paréntesis se utilizan para agrupar expresiones.
El asterisco significa 0 o más instancias de la expresión entre paréntesis. Las
llaves las utilizaremos con dos significados diferentes: para indicar el conjunto
compuesto por los strings del interior, y otras veces para indicar que lo que hay
dentro no hay que tomarlo textualmente. El significado que utilicemos estará claro
por el contexto. Así {letra} indica un carácter alfabético y no la palabra “letra”.
La yuxtaposición indica concatenación.
Según todo esto la expresión regular anterior puede leerse: Una letra seguida
de 0 o más instancias de letras o dígitos.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.3 Descripciones declarativas de los tokens: Expresiones regulares 31
3. Supongamos que r y s son dos expresiones regulares que denotan los lengua-
jes L(r) y L(s). Entonces:
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
32 Análisis léxico
4. La expresión (a|b)* denota el conjunto formado por todos los strings con-
stituidos por cero o más instancias de a o de b. Es decir, el conjunto de
todos los strings formados con las letras a y b. Otra forma de describir este
conjunto es como (a *b*)*.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.3 Descripciones declarativas de los tokens: Expresiones regulares 33
dígito 0|1|2|3|4|5|6|7|8|9
entero {dígito}+
fracción "."{entero}
exponente e("+"|"-")?{entero}
flotante {entero}{fracción}?{exponente}?
dígito 0|1|2|3|4|5|6|7|8|9
entero {dígito}+
fracción "."{entero}
exponente e("+"|"-")?{entero}
flotante {entero}{fracción}?{exponente}?
Utilizamos las comillas "" para encerrar aquellos caracteres que pueden tener
un significado de metacaracter. Por ejemplo, “(+” podría ser interpretado co-
mo 1 o más ocurrencias del paréntesis que abre. Si lo que queremos es indicar
el carácter “+” lo encerramos entre comillas así: “("+"”. También utilizamos
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
los paréntesis cuadrados y el guión para abreviar una clase de caracteres. Por
ejemplo 0|1|2|3|4|...|9se puede abreviar por [0-9]. Mientras que [a-z] rep-
resenta la clase de todas las letras minúsculas y constituye una abreviatura para
a|b|c|...|z.
no puede ser descrito por ninguna Definición regular, pero tampoco puede ser
descrito por ninguna gramática libre de contexto.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
34 Análisis léxico
- El resto de los caracteres son tomados como tokens formados por un único
carácter, y se les hace corresponder su valor numérico según el código
ASCII.
El programa resultante consta de tres archivos diferentes:léxico.l fuente
que al compilarlo con FLEX generará la función ‘‘int yylex(void)’’ que im-
plementa el analizador léxico; cabecera.h con el valor numérico de los tokens; y
main. c con el programa principal que llama repetidamente al analizador léxico.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.3 Descripciones declarativas de los tokens: Expresiones regulares 35
2 #include”cabecera.h”
3
4 %}
5
6 %option noyywrap
7 %option yylineno
8
9 id [a-zA-Z][0-9a-zA-Z]*
10
11 %%
12
13 [ \n\t]+ ;
14
15 ”for” return FOR;
16 ” if” return IF;
17 ”then” return THEN;
18 ”else” return ELSE;
19 ”int” return INT;
20 ”while” return WHILE;
21
22 [0-9]+ return NUM;
23 {id} return ID;
24
25 . return *yytext;
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
8 #include”cabecera.h”
9
10 extern char* yytext;
11 extern int yyleng;
12 extern int yylineno;
13
14 int yylex(void) ;
15
16 int main() {
17 Token t;
18 cout < < ”comienza„elprograma” < < endl;
19 while((t = Token(yylex())) != FIN)
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
36 Análisis Léxi
switch(t) {
case NUM : cout « ” Número ’” « yytext « ”’ de ” « yyleng
« ” dígitos en l a l i n e a ” « yylineno « endl;
break;
case ID : cout « ”Id ’” « yytext « ”’ de ” « yyleng
« ” caracteres en l a l i n e a ” « yylineno
« endl;
break;
case FOR :
case IF :
case THEN :
case ELSE :
case INT :
case WHILE : cout « ”pal r e s ’” « yytext « ”’ de ” « yyleng
« ” caracteres en la linea ” « yylineno
« endl;
break;
default : cout « ” Es e l caracter ’” « char(t) « ”’” « endl;
break;
} /* fin del switch y del while */
return EXIT.SUCCESS;
} /* fin de main() */
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.3 Descripciones declarativas de los tokens: Expresiones regulares 37
La idea es recorrer los diagramas de todas las maneras posibles siguiendo las
flechas. En cada recorrido vamos juntando los caracteres que encontramos y esto
nos dará diferentes cadenas pertenecientes a nuestro lenguaje.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
38 Análisis léxico
2.4. M é t o d o r á p i d o y sucio de i m p l e m e n t a r u n
analizador léxico a m a n o
A menudo se considera que la implementación de un analizador léxico es una
tarea muy simple que no necesita de técnicas especiales. Basta con poner manos
a la obra e implementar directamente el programa correspondiente.
Se suele decir que utilizar la herramienta FLEX para implementar anal-
izadores léxicos tiene sus ventajas y sus inconvenientes. Así se considera que
los analizadores realizados con la herramienta FLEX son lentos (realmente no
existe ningún estudio serio que confirme esta opinión) aunque flexibles y que se
pueden modificar fácilmente así como depurar. Estos métodos están basados en
simular autómatas finitos (que se explicarán más adelante) y se prestan bien a
ser generados por herramientas automáticas (como FLEX) ya que existen algo-
ritmos que a partir de una expresión regular obtienen, de forma automática, un
autómata finito equivalente. Por otra parte la codificación directa, en lenguaje
C, del analizador léxico suele ser de ejecución rápida y de implementación más o
menos sencilla, aunque suele ser más complicada que la generación automática.
Como ejemplo de lo que pueden ser los analizadores hechos a mano (método
rápido y sucio) se muestra, a continuación, el código C de un analizador léxico
algoritmo esquematizado así:
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
- Si el último carácter leído c es una letra, entonces se puede tratar del inicio
de un identificador o de una palabra reservada. Se ejecuta un bucle en que
se van leyendo todas las letras y dígitos que le siguen hasta encontrar un
último carácter distinto de letra y de dígito. Este último carácter marca
el final del lexema actual pero forma parte del token siguiente, así que se
devuelve a la entrada.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.4 Método rápido y sucio de implementar un analizador léxico a mano 39
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 e n u m {FIN=0, ID=256, NUM, FOR, IF, THEN, ELSE, INT, WHILE};
7
8 char buffer[500];
9 char* yytext;
10 char* p;
11 intyyleng;
12
13 # d e f i n e MAXIMO 6
14 s t r u c t {char* nombre; int token;} tabla[MAXIMO] =
{”for”,FOR, ”if”,IF, ”then”,THEN,
”else”,ELSE, ”int”,INT, ”while”, WHILE};
17
18 int yylex(void) ;
19
20 int main() {
21 int t;
22 printf (” comienza e l programa\n”);
23 while((t = yylex()) != FIN)
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
40 Análisis léxico
switch(t) {
case NUM : printf(”Numero ’ %s’ de %d digitos\n” ,
yytext, yyleng); break;
case I D : printf (” Id ’%s’ de %d caracteres\n” ,
yytext, yyleng); break;
case FOR :
30 case IF :
case THEN :
case ELSE :
case INT :
case WHILE : printf(” pal r e s ’ %s’ de %d chars\n”,
yytext, yyleng); break;
default : printf(”Es e lcaracter ’%c’\n”, t);
break;
} /* fin del switch y del while */
39 return EXIT.SUCCESS;
40 } /* fin de main() */
41
42 int yylex(void) {
43 int c;
44 while ((c = getchar()) = = ’ ’ || c = = ’\n’ || c = = ’\t’) ;
if (c = = EOF) return FIN;
46 yytext = buffer;
47 p = buffer;
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
if (isdigit(c)) {
49 do {
*p = c;
p++;
c = getchar();
} while (isdigit(c)) ;
if (c != EOF) ungetc(c, stdin);
*p = 0;
yyleng = p - yytext;
return NUM;
58 }
59 else if (isalpha(c)) {
60 int i;
61 do {
*p = c;
p++;
c = getchar();
} while (isalnum(c)) ;
if (c != EOF) ungetc(c, stdin);
*p = 0;
yyleng = p - yytext;
for (i = 0; i < MAXIMO ; i++)
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 41
if (strcmp(tabla[i].nombre, yytext) = = 0)
r e t u r n tabla[i].token;
return ID;
}
else r e t u r n c;
} /* fin de yylex() */
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
42 Análisis léxico
1. Un conjunto de estados S.
U n a u t ó m a t a finito e s u n a m á q u i n a i d e a l c u y o f u n c i o n a m i e n t o e s c o m o
s i g u e : Se empieza en el estado inicial y se van leyendo caracteres de entrada
de una cierta cadena S, realizando las correspondientes transiciones entre es-
tados según sean los caracteres leídos. Si al acabar la cadena de entrada nos
encontramos en alguno de los estados de aceptación, entonces decimos que el
a u t ó m a t a acepta la cadena S de la entrada. Por el contrario, si terminamos en
alguno de los estados que no son de aceptación, o bien nos encontramos que
p a r a el carácter actual de la entrada no existe transición desde el estado actual,
entonces decimos que el a u t ó m a t a no acepta el string S.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 43
Por ahora, vamos a suponer que los diagramas son deterministas, es decir,
de un mismo estado no pueden salir dos vértices diferentes con el mismo
carácter como etiqueta ni existe ningún vértice etiquetado con el string nulo
ε.
- Existe un estado especial, llamado el estado inicial y marcado con una flecha
a partir del cual comenzamos a reconocer los tokens.
- Algunos estados pueden tener acciones que debemos realizar cuando los
alcanza el flujo de control.
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Como ejemplo mostramos, en las figuras 2.2 y 2.3, los diagramas de transi-
ción de los autómatas finitos (no determinista y determinista), que reconocen la
cadena (a|b)*abb:
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
44 Análisis léxico
El estado 3 es el de aceptación
El estado 3 es el de aceptación
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 45
Tener en cuenta que esto no quiere decir que todas las cadenas que re-
conozca un AFD tengan que ser de la forma uviw (con una parte que se repita).
Por ejemplo, tomemos el lenguaje denotado por la expresión regular (a | b) que
está formado por cadenas cualesquiera de a’s y b’s en cualquier orden. Podemos
generar una cadena que pertenezca al lenguaje de la longitud m que queramos
siguiendo el siguiente proceso: Lanzamos una moneda m veces y apuntamos a si
sale cara o b si sale cruz. Si el proceso es realmente aleatorio vamos a obtener
cadenas que pertenecen al lenguaje y que no tienen patrones que se repitan.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
46 Análisis léxico
Lo que afirma el lema de bombeo es que, si tenemos una cadena que pertenece
al lenguaje, entonces pueden generarse otras cadenas que también pertenecen al
lenguaje y que, esta vez si que, tienen patrones que se repiten.
( ( ( (...( )...) ) ) )
In In
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 47
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
48 Análisis léxico
Ahora enumeramos las reglas de los pasos inductivos. Hay que tener siempre
presentes las hipótesis de inducción mencionadas anteriormente. Para ello vamos
a suponer que las sub-expresiones regulares r y s tienen los siguientes autómatas
finitos:
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 49
Con el algoritmo inductivo anterior se puede obtener un AFN que sea equiv-
alente que cualquier expresión regular dada (es decir, que reconozca el mismo
lenguaje). Hay que tener en cuenta que cada vez que se construye un nuevo es-
tado, se le da un nombre distinto, de tal forma que no pueda haber dos estados
de un AFN con el mismo nombre.
Todos los AFN intermedios producidos corresponden a subexpresiones de la
expresión regular original y tienen varias propiedades importantes:
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
50 Análisis léxico
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 51
del conjunto P o desde alguno que, a su vez, sea accesible mediante transiciones
épsilon.
D E F I N I C I O N 2 . 7 ( F u n c i ó n s a l t o a p l i c a d a a u n s u b c o n j u n t o ) Dado un
Autómata Finito M = {S, Σ, δ, S0, F}, y un subconjunto P ⊆ S P =
{p1,p2,... ,pm} de estados pertenecientes a S, y un carácter a ∈ Σ, Definimos
la función s a l t o ( P , a ) o δ(P,a) así: δ({p1,p2,... ,pm}, a) = {q i ∈ S | p j ∈
P, q i ∈ δ ( p j , a ) } .
- Los estados de aceptación de M' son aquellos que posean algún estado de
aceptación del autómata original. Es decir, dado un estado S'i ∈ M',
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
52 Análisis léxico
siendo S'i = {Sa, Sb,... , Sk} ⊆ S, S'i ∈ F' St ∈S'i tal que St ∈
F.
- A partir de cualquier estado S'i ∈ M', y de cualquier carácter a G
Σ, podemos obtener otros estados S'j de M' (y las correspondientes
transiciones entre ellos) así:
S'j = c i e r r e ε ( δ ( S ' i , a)), y δ'(S'i, a) = S'j.
E J E M P L O 2.3 ( C o n v e r s i o n d e A F N a A F D p o r la subset construction)
Volviendo a nuestro AFN del anterior ejemplo 2.1 de la página 49, el autómata
finito determinista (AFD) que resultaría de aplicar el algoritmo anterior sería:
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 H a c i a la generación a u t o m á t i c a de analizadores léxicos 53
{S', Σ, δ', S0, F'}) tal que sea equivalente 2 a M pero que tenga el menor número
de estados posible.
Un resultado teórico básico es que el A F D mínimo siempre existe y que es
único (salvo la posibilidad de renombrar los estados).
El algoritmo p a r a minimizar dicho A F D M está basado en la Definición de u n a
relación de equivalencia (≡) en su conjunto de estados S tal que nos parte este
conjunto de estados S en clases de equivalencia disjuntas. Por último construimos
el A F D M' de forma que los estados de M' están formados por las clases de
equivalencia de M.
C o n s t r u i m o s u n a r e l a c i ó n d e e q u i v a l e n c i a ( ≡ ) e n S de la siguiente man
era:
p,q∈S, q≡p sii x ∈Σ*, δ ( p , x ) ∈ F δ ( q , x ) ∈ F
- δ'([q],a) = [δ(q,a)]
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
• S'0
A L G O R I T M O 2.2 ( M i n i m i z a c i ó n d e a u t ó m a t a s finitos d e t e r m i n i s t a s )
Dado un AFD que llamaremos M = {S, Σ, δ, S0, F}, por este método construire-
mos otro AFD, que llamaremos M' = {S', Σ, δ', S'0, F'}. equivalente al anterior
y en el que, al igual que ocurría en la subset construction, cada uno de los esta-
dos de M' está constituido por un subconjunto de estados del autómata original
M.
El algoritmo es iterativo sobre las versiones del conjunto de estados v e r s i o n i S':
estado de fallo. A menudo no nos tomamos el trabajo de describir así el AFD puesto que puede
considerarse que el estado de fallo está siempre implícito
2
Dos autómatas son equivalentes si reconocen el mismo lenguaje
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
54 Análisis léxico
Adviértase que el estado fallo está siempre implícito (las transiciones vacías
en la tabla de transición equivalen a una transición implícita al estado de
fallo) y ahora hacemos explícitas esas transiciones.
Adviértase, también, que algunos de los estado de aceptación' o de no.acep-
tación', puede ser vacío. Es decir, podría ocurrir que el autómata original
solo contuviese estados de aceptación o de no aceptación.
• versioniSj' ∈ versioniS' .
Recordemos que cada estado de versioniS' está constituido por un sub-
conjunto de estados del autómata original M, deforma que tendremos
que: v e r s i o n i S j = { S j 1 ,Sj2,... , Sjm } ⊆ S.
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
• a∈Σ
Construimos la relación de equivalencia en versioni Sj así:
S j k , S j m ∈ versioniSj' , S j k ≡ Sjm versioni [ δ ( S j k , a)] =
versioni[δ(Sjm,a)].
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 55
0 1
A B – aceptación
B C D
C B – aceptación
D C D
J u n t a n d o los estados de aceptación y no aceptación tenemos nuestra versión
inicial del nuevo conjunto de estados:
Versión 0 0 1
A B fallo
C B fallo aceptación
B C D
D C D no aceptación
fallo fallo fallo
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
"Λ~ΛC A, C ))
^ ¾ = = ^ 0
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
56 Análisis léxico
- Cada estado nos va a generar un trozo de código así que la longitud del pro-
grama final va a ser proporcional al número de estados. Ahora realizaremos
un bucle en que se genera el código siguiente para cada estado:
• Si el estado actual pa tiene alguna acción asignada, la realizamos.
• Si hemos llegado al final de la cadena (ca = EOF), finaliza el bucle.
• Si el estado actual pa tiene transiciones de salida, entonces se avanza
el puntero c a de los caracteres de entrada (se lee el siguiente carácter
de la entrada).
• El siguiente estado p'a es el que indique la tabla de transición en la fila
pa y columna ca: p'a = tabla[pa][ca].
• Si no existe la transición anterior (es decir, la celda tabla[pa] [ca] está va-
cía), entonces finaliza el bucle y el programa indicando que la cadena
de entrada NO pertenece al lenguaje denotado por el AFD.
- Al finalizar el bucle anterior miramos cual es el estado actual pa:
• Si el estado actual es de aceptación, finaliza el programa indicando que
la cadena de entrada SI pertenece al lenguaje denotado por el AFD.
Es decir, que el autómata acepta la cadena.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 57
# i n c l u d e <stdio.h>
# i n c l u d e <ctype.h>
# i n c l u d e <stdlib.h>
# d e f i n e DEBUG
e n u m {A, B, C, D, E, F} ;
int yylex(void) {
intc;
int estado = A;
while(1) {
#ifdef DEBUG
printf (” estado = %d ” ,estado);
fflush(stdout);
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
58 Análisis léxico
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 59
#endif
switch(estado) {
case A: c = getchar();
if (c = = ’0’) estado = B;
else if (isdigit (c)) estado = F;
25 else return 0;
break;
case B: c = getchar();
if (c = = ’x’ || c = = ’X’) estado = C;
else if (isdigit (c)) estado = E;
else if (c = = EOF) return 1;
31 else return 0;
break;
case C: c = getchar();
if (isxdigit(c)) estado = D;
35 else return 0;
break;
case D: c = getchar();
if (isxdigit(c)) estado = D;
else if (c = = EOF) return 1;
40 else return 0;
break;
case E: c = getchar();
if (isdigit (c)) estado = E;
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
62 int main() {
if (yylex())
printf (” La cadena SI es un entero\n”);
65 else
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
60 Análisis léxico
5 # i n c l u d e <iostream>
6 # i n c l u d e <cctype>
7
8 namespace Excepciones {
9 struct Final {};
10 struct TransicionInvalida {};
11 struct EstadoInvalido {};
12 }
13
14 enum Estados {A,B,C,D,E,F};
15
16 using namespace std;
17 using namespace Excepciones;
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
18
19 int yylex(void) { / / esta funcion implementa el automata AFD
20 Estados estado = A; / / iniciamos en el estado inicial
21
22 try{
while (true) {
char c; / / vamos a leer caracter a caracter
25 # i f d e f DEBUG
cout < < ”estado ” < < char(estado+’A’) < < ” ” < < flush;
27 #endif
switch (estado) {
29 case A:
c = cin.get();
if (c = = EOF) throw Final();
if (c = = ’0’) estado = B;
else if (isdigit(c)) estado = F;
else throw TransicionInvalida();
break;
36 case B:
c = cin.get();
if (c = = EOF) throw Final();
if (c = = ’x’ || c = = ’X’) estado = C;
else if (isdigit (c)) estado = E;
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 61
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
62 Análisis Léxi
int main(){
cout « ” teclea un entero terminado en EOF : ”;
if (yylex())
cout « ”La cadena SI es un entero\n”;
else
cout « ”La cadena NO es un entero\n”;
} //fin de main()
# i n c l u d e <iostream>
# i n c l u d e <cctype>
namespace Excepciones {
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.
2.5 Hacia la generación automática de analizadores léxicos 63
11 struct TransicionInvalida {
12 Estados e;
13 int c;
14 TransicionInvalida(Estados es, i n t i) : e(es), c ( i ) { }
15 } ; / / fin de la estructura TransicionInvalida
16 } / / fin del namespace Excepciones
17
18
19 using namespace std;
20
21 using namespace Excepciones;
22
23 int columna(int) ;
24
25 Estados tabla[6] [5] =
26 {{B, F, ERROR, ERROR, ERROR},
27 {E, E, ERROR, C, ERROR},
28 {D, D, D, ERROR, ERROR},
29 {D, D, D, ERROR, ERROR},
30 {E, E, ERROR, ERROR, ERROR},
31 {F, F, ERROR, ERROR, ERROR}} ;
32 int yylex(void) {
33 int c;
34 Estados estado = A;
Copyright © 2009. Servicio de Publicaciones de la Universidad de Cádiz. All rights reserved.
Jiménez, Millán, José Antonio. <i>Compiladores y procesadores de lenguajes</i>, Servicio de Publicaciones de la Universidad de Cádiz,
2009. ProQuest Ebook Central, http://ebookcentral.proquest.com/lib/unadsp/detail.action?docID=3218294.
Created from unadsp on 2019-08-28 13:27:56.