You are on page 1of 62

ndice

1. Introduccin ................................................................................................................................ 7
1.1 Tipos de traductores ......................................................................................................... 7
1.2 Autmatas ........................................................................................................................... 10
1.2.1 Autmatas finitos (FA finite automata) .................................................................... 10
1.2.1.1 Autmatas finitos deterministas (DFA deterministic finite automata) .............. 11
1.2.1.2 Autmatas finitos no deterministas (NFA nondeterministic finite automata) ... 12
1.2.2 Autmata de Pila (PDA push-down automaton) ...................................................... 13
1.2.2.1 Autmatas de pila ................................................................................................. 13
1.3 Gramticas formales ........................................................................................................... 14
1.3.1 Gramtica Regular ....................................................................................................... 15
1.3.2 Gramtica libre de contexto (CFG Context Free Grammar) .................................... 16
1.4 Fases de un compilador ....................................................................................................... 16
2. Anlisis Lxico ......................................................................................................................... 21
2.1 Definicin de un reconocedor de cadenas no trivial ........................................................... 22
2.1.1 Las operaciones regulares ............................................................................................ 23
2.1.2 Definicin formal de una expresin regular ................................................................ 23
2.2 Programar sistemticamente el reconocedor en lo referente a la obtencin del autmata,
almacenarlo eficientemente y manejar adecuadamente el archivo fuente ................................ 24
2.2.1 Conversin de una expresin regular a un autmata finito no determinista (NFA) .... 24
2.2.2 Conversin de un autmata finito no determinista (NFA) a su correspondiente
autmata finito determinista (DFA) ...................................................................................... 34
2.2.3 Codificacin de un DFA en pseudocdigo .................................................................. 41
3. Anlisis sintctico ..................................................................................................................... 45
3.1 Construccin de tablas parse LR(1) .................................................................................... 52
Algoritmo para construir el FA que servir de base para la tabla parse LR(1) ........................ 52
3.2 Anlisis sintctico LALR(1) ............................................................................................... 56
3.2.1 Primer principio del anlisis sintctico LALR(1) ........................................................ 56
3.2.2 Segundo principio del anlisis sintctico LALR(1) ..................................................... 56
3.3 Anlisis sintctico LR(1) cannico ..................................................................................... 57
3.3.1 Autmatas finitos de elementos LR(1) ........................................................................ 57
3.3.3 Definicin de transiciones LR(1) (parte 1) .................................................................. 58
3.4 Conjuntos primero .............................................................................................................. 59
4. Anlisis Lxico ......................................................................................................................... 61
4.1 Planteamiento del problema ................................................................................................ 61
4.2 Solucin .............................................................................. Error! Marcador no definido.
4.2.1 Anlisis ........................................................................ Error! Marcador no definido.
4.2.2 Diseo .......................................................................... Error! Marcador no definido.
4.2.2.1 Expresiones regulares y NFA's ............................. Error! Marcador no definido.
4.2.2.2 DFA....................................................................... Error! Marcador no definido.
4.3 Implementacin................................................................... Error! Marcador no definido.
4.3.1 main.cpp (primera parte) .............................................. Error! Marcador no definido.
4.3.2 Cdigo referente al anlisis lxico (compilador.cpp primera parte) . Error! Marcador
no definido.
4.3.3 Implementacin alternativa en Flex ............................. Error! Marcador no definido.
5. Anlisis sintctico ..................................................................................................................... 62
5.1 Planteamiento del problema ................................................................................................ 62
5.2 Solucin .............................................................................. Error! Marcador no definido.
5.2.1 Anlisis ........................................................................ Error! Marcador no definido.
5.2.2 Diseo .......................................................................... Error! Marcador no definido.
5.3 Implementacin................................................................... Error! Marcador no definido.
5.3.1 main.cpp ....................................................................... Error! Marcador no definido.
5.3.2 compilador.ui ............................................................... Error! Marcador no definido.
5.3.3 compilador.h ................................................................ Error! Marcador no definido.
5.3.4 Cdigo referente al anlisis sintctico (compilador.cpp parte 2) . Error! Marcador no
definido.
5.3.5 Implementacin alternativa Bison ............................... Error! Marcador no definido.


ndice de figuras
Fig. 1: Proceso de interpretacin .................................................................................................... 9
Fig. 2: Un compilador ..................................................................................................................... 9
Fig. 3: rbol sintctico para............................................................................................................ 9
Fig. 4: Traductor hbrido para .................................. 10
Fig. 5: DFA que reconoce cadenas que contienen ........................................................................ 11
Fig. 6: NFA que reconoce a la cadena vaca o cadenas que tienen .............................................. 12
Fig. 7: PDA que reconoce lenguajes del tipo ..................................................................... 14
Fig. 8: Ejemplo de reglas gramaticales ......................................................................................... 15
Fig. 9: Ejemplo de reglas permitidas en una gramtica regular (izquierda) y de reglas no
permitidas en una gramtica regular (derecha) ............................................................................. 15
Fig. 10: Ejemplo de una CFG ....................................................................................................... 16
Fig. 11: Fases de un compilador ................................................................................................... 17
Fig. 12: rbol sintctico de la expresin

a [ index ] = 4+2 ........................................................ 18
Fig. 13: rbol semntico (corregir este rbol) de la expresin

a [ index ] = 4+2 ...................... 19
Fig. 14: Optimizador de cdigo fuente ......................................................................................... 19
Fig. 15: cdigo objeto en ensamblador generado a partir de la representacin intermedia de la
Fig. 14 ........................................................................................................................................... 20
Fig. 16: Cdigo objeto optimizado ............................................................................................... 20
Fig. 17: Un pequeo ejemplo de un programa fuente ................................................................... 21
Fig. 18: un pequeo ejemplo de un programa fuente con un error lxico .................................... 21
Fig. 19: un pequeo ejemplo de un programa fuente sin error lxico .......................................... 22
Fig. 20: Un NFA que reconoce a la cadena vaca o cadenas que tienen cualquier nmero de as25
Fig. 21: Construccin de un NFA para reconocer
2 1
A A .......................................................... 27
Fig. 22: Construccin de M para reconocer
2 1
A A .................................................................... 28
Fig. 23: Construimos M para que reconozca
*
A ......................................................................... 29
Fig. 24: Autmata que reconoce a z . ........................................................................................... 30
Fig. 25: Autmata que reconoce a y ............................................................................................ 30
Fig. 26: Autmata que reconoce a x ............................................................................................ 30
Fig. 27: Autmata que reconoce y z ........................................................................................ 30
Fig. 28: Autmata que reconoce
*
) ( y z .................................................................................... 31
Fig. 29: Autmata que reconoce .................................................................................. 32
Fig. 30: Ejemplo de un NFA ......................................................................................................... 35
Fig. 31: Estado inicial del DFA
1
q ............................................................................................... 37
Fig. 32: Segundo estado del DFA ................................................................................................. 37
Fig. 33: Siguiente estado del DFA ................................................................................................ 37
Fig. 34: NFA correspondiente a x y z
*
) ( .................................................................................. 38
Fig. 35: Estado inicial del DFA .................................................................................................... 38
Fig. 36: Nuevo estado del DFA generado por la transicin x del NFA en
1
q ............................ 38
Fig. 37: Estado 3 del DFA ............................................................................................................ 39
Fig. 38: Estado 4 del DFA ............................................................................................................ 39
Fig. 39: Agregacin de estado de ERROR ................................................................................... 39
Fig. 40: Transicin del estado 3 al estado 2 .................................................................................. 40
Fig. 41: Transicin del estado 3 a l mismo ................................................................................. 40
Fig. 42: Transicin del estado 3 al estado 4 .................................................................................. 40
Fig. 43: Transicin del estado 4 a estado 2 ................................................................................. 41
Fig. 44: Algn ttulo ...................................................................................................................... 41
Fig. 45: Transicin del estado 4 a l mismo ................................................................................. 41
Fig. 46: DFA representando la sintaxis de un nombre de variable (identificador) ....................... 42
Fig. 47: PDA que reconoce lenguajes del tipo ................................................................... 45
Fig. 48: Estados del PDA .............................................................................................................. 46
Fig. 49: Introduccin de la primera transicin ) # , ; , , (
0
p q ................................................... 47
Fig. 50: Introduccin de la segunda transicin ) , ; , , ( S q p .................................................... 47
Fig. 51: Introducir transiciones por cada regla de produccin ...................................................... 47
Fig. 52: Introducir una transicin por cada smbolo terminal ....................................................... 47
Fig. 53: PDA para la gramtica dada. ........................................................................................... 48
Fig. 54: Gramtica ........................................................................................................................ 48
Fig. 55: PDA del Ejercicio 1 ......................................................................................................... 49
Fig. 56: PDA del ejercicio 2 ......................................................................................................... 49
Fig. 57: PDA del ejercicio 3 ......................................................................................................... 49
Fig. 58: Establecimiento de 4 estados ........................................................................................... 50
Fig. 59: Primeras dos transiciones ................................................................................................ 50
Fig. 60: Una transicin por cada smbolo terminal ....................................................................... 51
Fig. 61: Una transicin por cada regla gramatical ........................................................................ 51
Fig. 62: ltima transicin ............................................................................................................. 51
Fig. 63: Gramtica ........................................................................................................................ 52
Fig. 64: Estado inicial del FA cerradura de S S ' ..................................................................... 53
Fig. 65: Segundo estado ................................................................................................................ 53
Fig. 66: Tercer estado ................................................................................................................... 54
Fig. 67: Estado 4 del AF ............................................................................................................... 54
Fig. 68: Estado 5 del AF ............................................................................................................... 54
Fig. 69: Transicin x ..................................................................................................................... 55
Fig. 70: Transicin del estado 3 al estado 4 con ........................................................................ 55
Fig. 71: Ultimo estado del AF....................................................................................................... 55
Fig. 72: LR(0) ............................................................................................................................... 56
Fig. 73: Otra figura ...................................................................................................................... 56
Fig. 74: DFA de a A A | ) ( ........................................................................................................ 57
Fig. 75: LR(1) ............................................................................................................................... 57
Fig. 76: Algn ttulo ...................................................................................................................... 58
Fig. 77: Algn ttulo ...................................................................................................................... 59
Fig. 78: NFA que reconoce una letra ............................................ Error! Marcador no definido.
Fig. 79: NFA que reconoce un dgito............................................ Error! Marcador no definido.
Fig. 80: NFA que reconoce un identificador ................................ Error! Marcador no definido.
Fig. 81: NFA que reconoce un dgito............................................ Error! Marcador no definido.
Fig. 82: NFA que reconoce un punto y coma ............................... Error! Marcador no definido.
Fig. 83: NFA que reconoce el operador de asignacin (:=) .......... Error! Marcador no definido.
Fig. 84: NFA que reconoce un parntesis abierto ......................... Error! Marcador no definido.
Fig. 85: NFA que reconoce un parntesis cerrado ........................ Error! Marcador no definido.
Fig. 86: Autmata finito que reconoce algn operador de suma .. Error! Marcador no definido.
Fig. 87: Autmata finito que reconoce algn operador de multiplicacin ... Error! Marcador no
definido.
Fig. 88: Autmata Finito no Determinista .................................... Error! Marcador no definido.
Fig. 89: Autmata Finito Determinista ......................................... Error! Marcador no definido.
Fig. 90: Algn ttulo ...................................................................... Error! Marcador no definido.
Fig. 91: Interfaz de usuario ........................................................... Error! Marcador no definido.

ndice de tablas
Tabla 1: Salida del analizador lxico para la expresin ................................... 18
Tabla 2: Tokens del programa fuente de la Fig. 17 ...................................................................... 21
Tabla 3: Resultado de la funcin de transicin para el NFA de la Fig. 20 ................................... 25
Tabla 4: Secuencia de instrucciones sugerida por el diagrama de transicin de la Fig. 46. ......... 43
Tabla 5: Tabla de transicin construida del diagrama de transicin de la figura 9. ..................... 43
Tabla 6: Anlisis lxico basado en la Tabla 4 de transiciones ...................................................... 44
Tabla 7: Tabla parse LL(1) para la gramtica de la izquierda ...................................................... 48
Tabla 8: Rutina parse LL(1) genrica ........................................................................................... 48
Tabla 9: Tabla LALR(1) ............................................................................................................... 57
Tabla 10: Tabla LR(1) .................................................................................................................. 57
Tabla 11: Algoritmo ...................................................................................................................... 59
Tabla 12: Algn ttulo ................................................................................................................... 60
Tabla 13: Tabla de cerraduras de los elementos del NFA de laFig. 88 ........ Error! Marcador no
definido.
Tabla 14: Cdigo escrito en Flex .................................................. Error! Marcador no definido.
Tabla 15: Gramtica ...................................................................................................................... 62
Tabla 16: Gramtica re-escrita ...................................................... Error! Marcador no definido.
Tabla 17: Tabla parse (parte 1) ..................................................... Error! Marcador no definido.
Tabla 18: Tabla parse (parte 2) ..................................................... Error! Marcador no definido.
Tabla 19: Tabla parse (parte 3) ..................................................... Error! Marcador no definido.
Tabla 20: Tabla parse (parte 4) ..................................................... Error! Marcador no definido.
Tabla 21: Cdigo correspondiente al anlisis sintctico escrito en Bison .... Error! Marcador no
definido.


1. Introduccin
Idealmente, un curso de compiladores debera llevarse en 2 semestres. Durante el primero
de stos, se revisaran con detenimiento las tcnicas asociadas a los diferentes tipos de anlisis
que involucra la construccin de un compilador: autmatas de estados finitos y gramticas
regulares para el anlisis lxico, y autmatas de pila y gramticas libres de contexto para el
anlisis sintctico y semntico. Durante el segundo semestre, se revisaran las tcnicas asociadas
a la generacin de cdigo: grafos dirigidos acclicos y cdigo de tres direcciones para la
generacin de cdigo intermedio, asignacin de registros y grafos de flujo para la generacin de
cdigo, y transformaciones para la optimizacin de cdigo, entre otras. Adems, hay que
mencionar que en ambos semestres se deben revisar las tcnicas para la construccin de las
tablas de literales y de smbolos, as como para el mdulo de manejo de errores pues todos ellos
guardan una estrecha relacin con cada una de las fases de anlisis y sntesis (esta ltima es la
encargada de la generacin de cdigo). En la realidad, en general, un curso de compiladores se
lleva en slo un semestre. Esto hace que el material del curso se tenga que revisar rpidamente y
que con frecuencia dicho material no pueda cubrirse en su totalidad. Hay que mencionar tambin
que un curso de compiladores se ensea a los estudiantes que estn cursando los ltimos
semestres de su carrera pues se necesitan varios cursos pre-requisito para entenderlo:
matemticas discretas, algoritmos y estructuras de datos, lenguajes de programacin,
programacin de sistemas, teora de la computacin, arquitectura de computadoras e ingeniera
de software, como mnimo. En la medida de lo posible, el material expuesto en el presente libro
ser autocontenido; esto con la finalidad de revisar ms rpidamente los temas aqu incluidos.
Sin embargo, es necesario hacer hincapi en que, dada la complejidad de un curso de esta
naturaleza, el estudiante lo aprovechar ms si realiza por su cuenta los ejercicios de cada
captulo as como si refuerza cada tema consultando fuentes complementarias. Por si esto fuera
poco, un curso de compiladores no slo exige al estudiante desarrollar sus saberes tericos sino
tambin los prcticos: para entender con mayor claridad el poder de un compilador, es necesario
no slo comprender los conceptos tericos a partir de los cuales se construye sino adems
implementar dichos conceptos que lo harn darse cuenta que, al menos en este tpico en
particular, la teora no est muy alejada de la prctica. Hay que decir, finalmente, que la
construccin de un compilador comercial involucra un equipo de al menos decenas de personas:
desarrolladores, diseadores, ingenieros y arquitectos de software, testers, etc. Es por esto que
un curso de compiladores a nivel licenciatura slo puede aspirar a proveer al estudiante con las
tcnicas bsicas necesarias para la construccin de un compilador sencillo que pueda mostrar el
potencial de dichas tcnicas en la construccin de un compilador comercial. Si el estudiante
entiende claramente todas estas tcnicas, no le ser muy difcil involucrarse en el proceso de
construccin de un compilador de este tipo, sea cual sea su participacin.
En este captulo, revisaremos brevemente los conceptos fundamentales sobre compiladores
y veremos cmo se aplican en cada una de las fases de un compilador. En cierta medida, es
como un resumen del resto del libro: presentaremos cmo un programa en cdigo fuente es
traducido a su equivalente en cdigo objeto, el cual puede ser entendido y ejecutado por la
computadora en cuestin. El resto de los captulos exponen de manera ms detallada cada una de
las tcnicas para lograr este objetivo.
1.1 Tipos de traductores
Un lenguaje de programacin sirve como canal de comunicacin entre un usuario
humano y una computadora. Es decir, si un humano quiere implementar la solucin de un
problema especfico en una computadora, ste debe usar un lenguaje de programacin. Hoy en
da es tan comn la nocin de lenguaje de programacin (generalmente de alto nivel) que nos
olvidamos de que la computadora no entiende directamente dicho lenguaje: el lenguaje que
sta entiende est formado por largas cadenas de ceros y unos. Para que la computadora
entienda y ejecute las instrucciones contenidas en un programa escrito en algn lenguaje de
programacin, dichas instrucciones deben ser traducidas al lenguaje que s entiende la mquina:
el lenguaje binario. Podramos programar una computadora usando directamente estas largas
secuencias de ceros y unos pero esto involucra una ardua y difcil tarea que hace muy
complicada la interaccin con ella. La idea fundamental es entonces construir un traductor que
tome como entrada un programa escrito en un lenguaje de programacin (frecuentemente de alto
nivel) y lo convierta en una versin equivalente en lenguaje de mquina. El lenguaje de mquina
es una representacin abreviada de las secuencias de ceros y unos usando cdigos numricos, los
cuales representan operaciones en la mquina anfitrin. Un lenguaje de mquina representa el
ms bajo nivel de un lenguaje de programacin. Por ejemplo,
C7 06 0000 0002
representa la instruccin para mover el nmero 2 a la ubicacin 0000 (en sistema hexadecimal)
en los procesadores Intel 8x86 que se utilizan en las PC de IBM
En general, al programa de entrada se le conoce como programa fuente y al programa de
salida como programa objeto o programa destino. Es importante sealar que el programa fuente
est escrito en un lenguaje fuente (comnmente de alto nivel) y que el programa objeto
pertenece a un lenguaje objeto (que bien puede ser lenguaje mquina, lenguaje ensamblador o
incluso otro lenguaje de alto nivel). Un compilador que toma como entrada un programa fuente
escrito en un lenguaje de alto nivel y produce como salida un programa objeto escrito tambin en
un lenguaje de alto nivel se le conoce como source-to-source. En este libro construiremos un
compilador para un lenguaje de programacin sencillo cuyos programas objeto estarn en
lenguaje ensamblador. Esta prctica es til ya que no slo es ms fcil producir programas en
ensamblador (pues se evita generar cdigo para la arquitectura de una computadora en
particular) sino que tambin es ms fcil depurar los programas objeto escritos en este lenguaje.
Nos concentraremos entonces en la generacin de cdigo en lenguaje ensamblador que puede a
su vez ser ledo por un programa ensamblador (de los cuales existen varias versiones que pueden
descargarse de la red e instalarse de forma gratuita) y as ste traducirlo a cdigo mquina. De
hecho, algunos diseadores de lenguajes de programacin van ms all de esta prctica al
construir compiladores source-to-source para programas cuyo cdigo fuente es traducido a
cdigo que est en algn lenguaje de alto nivel (como C). As, ellos aprovechan los
compiladores existentes que reciben como entrada el cdigo escrito en este lenguaje objeto y
pueden revisar rpidamente el funcionamiento del lenguaje de su propio diseo sin tener que
preocuparse demasiado por los detalles de la generacin de cdigo en lenguaje mquina.
Aunque por el momento hemos hablado solamente de compiladores como traductores,
existen tambin otros tipos: ensambladores e intrpretes.
Un ensamblador (assembler) es un traductor cuya entrada es un programa escrito en
lenguaje ensamblador (assembly language) y cuya salida es un programa escrito en lenguaje de
mquina. Una posible secuencia de cdigo en lenguaje ensamblador es la siguiente:
MOV R0, index ;; valor de index R0
MUL R0, 2 ;; duplica el valor en R0
MOV R1, &a ;; direccin de a R1
ADD R1, R0 ;; sumar R0 a R1
MOV *R1, 6 ;; constante 6 direccin en R1
Un intrprete es tambin un traductor que no genera cdigo objeto (como lo hace un
compilador) sino que ejecuta el programa fuente inmediatamente. En otras palabras, un
intrprete procesa y ejecuta al mismo tiempo el programa fuente y los datos de entrada para ste.
La Fig. 1 muestra a grandes rasgos como funciona un intrprete.

Fig. 1: Proceso de interpretacin
Como puede apreciarse, el proceso de traduccin usando un intrprete se realiza cada vez
que ste es ejecutado. Por ende, en general, los intrpretes tienden a ser mucho ms lentos que
los compiladores (hasta por un factor de 10 o ms) [ref. Louden, p. 5]. Sin embargo, por otro
lado, un intrprete puede por lo regular proveer un mejor diagnstico de errores que un
compilador toda vez que aqul ejecuta el programa fuente instruccin por instruccin.
Un compilador es, como mencionamos, un traductor que toma como entrada un programa
fuente y lo convierte a un programa objeto o destino. Este programa objeto es una traduccin fiel
del programa fuente escrita en lenguaje mquina, lenguaje ensamblador o incluso en algn otro
lenguaje de programacin. Una vez generado el programa objeto, ste es ejecutado al recibir sus
respectivas entradas (ver Fig. 2 y Fig. 3).

Fig. 2: Un compilador
suma
deposito_inicial
interes
60
:=
+
*

Fig. 3: rbol sintctico para

De haber errores en el programa fuente, el compilador deber reportarlos y, de ser
posible, corregirlos. En comparacin con un intrprete, un compilador traduce una sola vez el
programa fuente (el cual se convierte, despus del proceso de traduccin, en el programa objeto).
As, cada vez que se ejecute el correspondiente programa objeto, ya no es necesario hacer de
nuevo otra traduccin, lo cual ahorrar tiempo significativo de procesamiento. Es por esta razn
que un compilador es en general mucho ms rpido que un intrprete. En la seccin 1.4
mencionamos brevemente las fases de un compilador para que se pueda apreciar, entre otras
cosas, la complejidad en el proceso de traduccin. El resto del libro (a partir del captulo 2)
revisa con detalle cada una de estas fases.
Es importante mencionar que existen traductores hbridos, los cuales combinan el
proceso de interpretacin con el de compilacin. Los traductores para el lenguaje de
programacin Java son un ejemplo de este tipo: un programa fuente escrito en Java puede
compilarse en una representacin intermedia llamada bytecodes que despus es interpretada
por una mquina virtual. El beneficio de este tipo de traductores es que la representacin
intermedia puede compilarse en una computadora e interpretarse en otra distinta (revisar el
concepto de portabilidad). La Fig. 4 muestra un traductor hbrido.
posicion
identificador
identificador
numero
expresion expresion +
Expresion aditiva
identificador expresion :=
Expresion de asignacion
inicial identificador
expresion *
velocidad
expresion
60

Fig. 4: Traductor hbrido para
Finalmente, para cerrar esta seccin, hay que decir que hay otros programas relacionados
estrechamente con los compiladores: preprocesadores, ligadores, cargadores, editores y
depuradores, entre otros. Todos estos programas complementan la labor de un compilador y
cuyas tareas van desde facilitar al programador la escritura del programa fuente hasta crear el
programa objeto y determinar los errores de ejecucin en dicho programa. Para mayores detalles
sobre dichos programas, se sugiere al lector consultar [ref. Louden y dragn].
1.2 Autmatas
Aunque en la seccin 1.4 mencionaremos las fases de las que tpicamente consta un
compilador, en esta seccin aprovechamos para revisar brevemente los modelos de cmputo que
se usan en las fases correspondientes al anlisis: autmatas de estados finitos para el anlisis
lxico y autmatas de pila para el anlisis sintctico y semntico. Por el momento, no entramos
en detalles sobre estos modelos pero s presentamos sus correspondientes definiciones formales
para que el lector aprecie que un compilador est basado en fundamentos matemticos slidos.
En el captulo 2 presentamos minuciosamente a los autmatas finitos y sus correspondientes
lenguajes y gramticas asociados: lenguajes y gramticas regulares. En los captulos 3 y 5
revisamos a los autmatas de pila y sus correspondientes lenguajes y gramticas asociadas:
lenguajes y gramticas libres de contexto.
1.2.1 Autmatas finitos (FA finite automata)
Los autmatas de estados finitos, o simplemente autmatas finitos, son el modelo ms
sencillo de cmputo. Esto no significa que tienen poco poder: de hecho, los autmatas finitos
son poderosos reconocedores de patrones en los datos. Esto es precisamente lo que queremos
hacer en primer lugar con el programa fuente: reconocer en l ciertos patrones que nos permitan
clasificarlos en tokens (los tokens son conjuntos de caracteres que forman una entidad).
Ejemplos tpicos de tokens son: nombres de variables (o identificadores), signos de agrupacin
(como parntesis, corchetes y llaves), smbolos de operaciones (suma, resta, multiplicacin,
divisin), signos de puntuacin (punto, coma, punto y coma) y nmeros (enteros, reales), entre
otros. Para clarificar el concepto de token, en la seccin 1.4 presentamos un ejemplo de cmo un
analizador lxico divide el programa fuente en dichos elementos. Adems, en el captulo 2,
revisaremos paso a paso cmo usar los autmatas finitos (y modelos equivalentes como las
expresiones y gramticas regulares) para este fin. Por el momento, daremos las definiciones
formales de un FA para que el lector empiece a apreciar los fundamentos matemticos que
soportan la construccin de un compilador.
La teora sobre autmatas finitos suele revisarse en un curso de matemticas discretas, de
teora de la computacin o de programacin de sistemas. De cualquier manera, aqu repasaremos
estos conceptos pero nos concentraremos, en el captulo 2, en cmo usarlos para construir un
analizador lxico.
Un FA puede ser de dos tipos: determinista (DFA) o no determinista (NFA). Aunque
estas definiciones difieren una de la otra principalmente en la funcin de transicin, el poder de
cmputo de cada uno de estos tipos es equivalente: aquellas cadenas de smbolos que reconoce
uno las reconoce el otro y viceversa. De hecho, en el captulo 2, revisamos un par de teoremas (y
sus respectivas demostraciones) que nos permiten construir, para cada NFA, su equivalente
DFA. En las secciones siguientes, damos la definicin formal de DFA y NFA respectivamente.
1.2.1.1 Autmatas finitos deterministas (DFA deterministic finite automata)
Un DFA es una 5-tupla
) , , , , (
0
F q Q o E
donde:
- Q es un conjunto finito llamado estados
- E es un conjunto finito llamado alfabeto
- Q Q E : o es la funcin de transicin
- Q q e
0
es el estado inicial
- Q F _ es el conjunto de estados de aceptacin
Un ejemplo de un DFA aparece en la Fig. 5

Fig. 5: DFA que reconoce cadenas que contienen
al menos 2 as (sin importar el orden)
Como puede observarse, este DFA contiene 3 estados (q
1
, q
2
, q
3
), 2 elementos en el
alfabeto (a, b), un estado inicial (q
1
, el cual est marcado por la flecha viniendo de ningn
lugar), un estado final (q
3
, el cual se identifica con un doble crculo) y una funcin de transicin
determinista: para cada entrada compuesta por cualquier combinacin entre un estado y un
elemento del alfabeto, existe una nica salida (un estado). Esta funcin de transicin es la que
caracteriza a los DFA. En el captulo 2 revisaremos con detalle cada una de las partes de dicha
funcin. En la siguiente seccin veremos que la funcin de transicin que caracteriza a los NFA
contiene un ingrediente distinto al de los DFA: el no determinismo.
1.2.1.2 Autmatas finitos no deterministas (NFA nondeterministic finite automata)
Un NFA es una 5-tupla ) , , , , (
0
F q Q o E donde:
- Q es un conjunto finito de estados
- E es un alfabeto finito
-

o : QE
c
P ) (Q es la funcin de transicin
- Q q e
0
es el estado inicial
-

F _Q es el conjunto de estados de aceptacin
Un ejemplo de un DFA aparece en la Fig. 6

Fig. 6: NFA que reconoce a la cadena vaca o cadenas que tienen
cualquier nmero de as
Como puede observarse, este NFA contiene 4 estados (q
1
,
q2,
q
3
, q
4
), 1 elemento en el
alfabeto (a), un estado inicial (q
1
), un estado final (q
4
) y una funcin de transicin no
determinista: en contraste con un DFA, un NFA no tiene necesariamente que tener, para cada
entrada compuesta por cualquier combinacin entre un estado y un elemento del alfabeto, una
nica salida (un estado). De hecho, la definicin de la funcin de transicin para un NFA
cualquiera contempla como salida un conjunto de estados (incluido por supuesto el conjunto
vaco). Es por esto que esta funcin de transicin incluye la definicin del conjunto potencia
sobre el conjunto de estados as como la posibilidad de tener la cadena vaca como entrada en
uno de los argumentos de dicha funcin. Esto significa, para el primer caso (la definicin del
conjunto potencia sobre el conjunto de estados), que dados como entrada un estado y un
elemento del alfabeto (incluida la cadena vaca), la salida es un conjunto de estados: esta
caracterstica es la que define principalmente a la propiedad de no determinismo. Por ejemplo,
para nuestro NFA de la Fig. 6, si el autmata se encuentra en el estado q
1
, ste puede saltar tanto
al estado q
2
como al estado q
4
con la cadena vaca. Para el segundo caso (la posibilidad de tener
la cadena vaca como entrada), tener transiciones con la cadena vaca como entrada significa que
el autmata puede pasar de un estado a otro sin tener que leer absolutamente nada de la cadena
de entrada. Adems, un NFA permite que no necesariamente para cada combinacin de entrada
(estado x elemento del alfabeto) exista una salida determinada. Para esta misma figura podemos
apreciar que no existe transicin (por mencionar una de ellas) cuando se est en el estado q
1
y se
tiene una a. Las implicaciones de estas caractersticas las revisaremos con detalle en el captulo
2. En esta seccin slo queremos introducir algunos conceptos fundamentales que servirn de
base para construir un analizador lxico. Para finalizar dicha seccin, debemos decir nuevamente
que usaremos la teora de autmatas finitos para construir un analizador lxico pasando por los
siguientes pasos:
Expresin regular NFA DFA Programa
A partir de una expresin regular (la cual revisaremos en el captulo 2 y que sirve para
representar los tokens de un programa fuente), podemos construir un NFA que represente esa
expresin; despus, a partir de ese NFA, se construye su DFA equivalente, el cual sirve para
codificar, en algn lenguaje de programacin, el reconocedor lxico para ese token en
especfico. Una vez ms, en el captulo 2 revisaremos a detalle cada uno de estos pasos.
1.2.2 Autmata de Pila (PDA push-down automaton)
Los autmatas de pila tienen un componente extra respecto a los FA (sean deterministas
o no deterministas): una memoria tipo pila. Los FA en general slo cuentan con sus estados
como memoria; es por ello que los FA son el modelo ms sencillo de cmputo. Cada estado en
un FA slo recuerda el ltimo elemento del alfabeto con el cual se lleg a dicho estado. Si
necesitramos que el autmata recuerde una secuencia de estos elementos, es necesario entonces
agregarle explcitamente una memoria. Para los PDA, la memoria es de tipo pila (LIFO last
input first output). Con este componente extra, es posible reconocer lenguajes que no pueden ser
reconocidos por los FA. A los lenguajes aceptados/reconocidos por un PDA se les conoce como
lenguajes libres de contexto. Un ejemplo de un PDA con su correspondiente lenguaje libre de
contexto que reconoce se presenta en la Fig. 7. El lenguaje reconocido por este autmata es

(con ), es decir, dicho PDA reconoce cadenas conformadas por un nmero especfico
de ceros (denotado por ) seguido del mismo nmero de unos. Es importante mencionar que no
existe un FA que reconozca dicho lenguaje: es aqu donde queda de manifiesto su limitacin
para reconocer lenguajes que no son regulares. Por supuesto que se revisarn a detalle los
conceptos de lenguajes/gramticas regulares y libres de contexto en los captulos 2 y 3
respectivamente. Por el momento, el lector puede intentar construir un FA que reconozca este
lenguaje. Al intentarlo, podr notar que lo mejor que podr hacer es construir un FA con
instancias especficas de este lenguaje:

, etc., pero no lograr construir un solo NFA


que pueda contender con el caso general; i.e., con cualquier valor de n. Dicho sea de paso,
cuando , entonces la cadena resultante es la cadena vaca. Esta cadena cumple con la
condicin que impone este lenguaje: un nmero especfico de ceros (en este caso ninguno)
seguido del mismo nmero de unos. Entonces, para poder reconocer este lenguaje, se necesita un
elemento extra: la pila. Los PDA son la base para construir analizadores sintcticos. Para el caso
concreto de un compilador, un analizador sintctico sirve para verificar que la estructura del
programa fuente sea la correcta; i.e., que el programa fuente est correctamente escrito. Como
los lenguajes de programacin estn basados en gramticas libres de contexto, y stas son
definiciones equivalentes a los autmatas de pila, stos entonces pueden ser usados para
reconocer que la estructura de un programa fuente (escrito en algn lenguaje de programacin)
sea correcta. En el captulo 3 revisamos cmo se logra esto. Por el momento, veamos la
definicin formal de un PDA para que el lector empiece a familiarizarse con este tipo de
autmata.
1.2.2.1 Autmatas de pila
Un PDA es una 6-tupla

(Q, E, I, o, q
0
, F)
donde
Q
,
E
,
I
y
F
son todos conjuntos
finitos y:
- Q es el conjunto finito de estados.
- E es el alfabeto de entrada.
- I es el alfabeto de la pila.
- I E
c c
o Q : P

(Q I
c
) es la funcin de transicin.
- Q q e
0
es el estado inicial.
- Q F _ es el conjunto de estados de aceptacin.
q1
q4
, $
1, 0
, $
0, 0
1, 0
q2
q3

Fig. 7: PDA que reconoce lenguajes del tipo


Como puede observarse en la definicin, un PDA consta de 6 partes. La parte extra con
respecto a los FA es la pila, la cual acepta un alfabeto especfico que bien puede ser diferente al
alfabeto de entrada. Por ejemplo, en el PDA de la Fig. 7, el alfabeto de entrada * +,
mientras que el alfabeto de la pila es * +. Por otro lado, tenemos a la funcin de transicin
que, debido a la pila, se vuelve ms compleja: la entrada de dicha funcin est formada por un
elemento de los estados del autmata, un elemento del alfabeto de entrada (incluida la cadena
vaca) y uno de la pila respectivamente (incluida la cadena vaca), y la salida por un elemento en
el conjunto de estados y un elemento en la pila (incluida la cadena vaca). Aunque revisaremos a
detalle los PDA en el captulo 3, podemos mencionar aqu brevemente el significado de la
funcin de transicin. Tomando como referencia a la Fig. 7, podemos decir por ejemplo que para
que el autmata pase del estado

al

, tienen que cumplirse 2 condiciones: que no se lea nada


de la entrada (esto es, que se lea la cadena vaca - representada por c) y que no se lea nada de la
pila (representado tambin por c); el resultado ser entonces pasar al estado q
2
desde el estado q
1

modificando el contenido de la pila al meter a sta el smbolo especial $. Las operaciones de
lectura y escritura de la pila se conocen comnmente como pop y push respectivamente. En
el captulo 3 construiremos un analizador sintctico a partir de la teora de autmatas de pila y
gramticas libres de contexto (stas ltimas son una definicin equivalente a los PDA). En la
siguiente seccin, presentamos brevemente los dos tipos de gramticas que usaremos para el
anlisis lxico y sintctico respectivamente: gramticas regulares y gramticas libres de
contexto.
1.3 Gramticas formales
Antes de hablar de gramticas formales, debemos mencionar brevemente qu es un
lenguaje formal. A diferencia de un lenguaje natural (como el ingls, espaol, francs, etc.), un
lenguaje formal est definido por reglas preestablecidas; ejemplos de lenguajes formales son los
lenguajes de programacin, el lgebra y la lgica proposicional. Para el caso de un lenguaje de
programacin, esta caracterstica de los lenguajes formales permite la construccin eficiente de
un traductor automtico (por ejemplo, un compilador). Para el caso de un lenguaje natural, es la
falta de estas reglas preestablecidas la que hace una tarea compleja la construccin de un
traductor automtico para dicho lenguaje. Son precisamente estas reglas las que conforman
principalmente una gramtica. Una gramtica permite entonces verificar si un enunciado est
correctamente escrito dado un lenguaje especfico. En nuestro caso, un enunciado ser un
programa fuente escrito en algn lenguaje de programacin. Utilizaremos un tipo de gramtica
conocida como gramtica regular para verificar si los tokens de un programa fuente pertenecen
al lenguaje de programacin en cuestin; usaremos una gramtica conocida como gramtica
libre de contexto para verificar que la sintaxis de un programa fuente es correcta, de acuerdo a
dicho lenguaje de programacin. En las siguientes secciones revisamos brevemente las
definiciones de una gramtica regular y una gramtica libre de contexto respectivamente.
1.3.1 Gramtica Regular
En general, una gramtica consiste en un conjunto de reglas de sustitucin o de re-
escritura conocidas tambin como producciones. Cada regla aparece en una lnea de la gramtica
conteniendo un smbolo (variable) del lado izquierdo de una flecha y una cadena de smbolos
(que pueden ser variables y smbolos terminales) del lado derecho de dicha flecha (Fig. 8). Las
variables estn comnmente representadas por letras maysculas mientras que los smbolos
terminales por letras minsculas, nmeros o smbolos especiales (los smbolos terminales son
anlogos al alfabeto de entrada). Adems, una de las variables se designa como el smbolo
inicial de la gramtica y frecuentemente se escribe del lado izquierdo de la primera regla de la
gramtica. Para el caso de la Fig. 8, la nica variable es la letra S, la cual, por ende, coincide con
ser el smbolo inicial de la gramtica. Los smbolos terminales son las letras x, y, z. Para el caso
especfico de una gramtica regular, las reglas de re-escritura se conforman de acuerdo a las
siguientes restricciones: el lado izquierdo de cualquiera de estas reglas de re-escritura debe
consistir en un solo no-terminal y el lado derecho debe ser un terminal seguido por un no-
terminal, un solo terminal o la cadena vaca (representada por c o ). Las reglas de la Fig. 8
conforman una gramtica regular as como las de la Fig. 9 (izquierda). Las reglas de la derecha
de esta ltima figura no son permitidas en una gramtica regular pues no cumplen con las
restricciones antes mencionadas.
S xS
S y
S z
Fig. 8: Ejemplo de reglas gramaticales

Z yX

Z x

W

Reglas
permitidas en
una
gramtica
regular


yW X


X Zy
WyZ YX

Reglas no
permitidas
en una
gramtica
regular
Fig. 9: Ejemplo de reglas permitidas en una gramtica regular (izquierda) y de reglas no permitidas en una
gramtica regular (derecha)
Formalmente, una gramtica regular es una 4-tupla ) , , , ( S R V E donde:
1. V es un conjunto finito, llamado variables (o no-terminales).
2. E es un conjunto finito disjunto de V, llamado terminales.
3. R es un conjunto finito de reglas, con cada regla siendo una variable y una cadena de
variables y terminales conforme a las restricciones antes mencionadas.
4. S es la variable inicial.
En el captulo 2 revisaremos la manera detallada de construir la siguiente secuencia:
Expresin regular NFA DFA Programa
Por el momento, podemos decir que una expresin regular es equivalente a una gramtica
regular (buscar teorema). Dichas expresiones regulares pueden usarse para definir los tokens de
nuestros programas fuente (basados en algn lenguaje de programacin especfico) y, a partir de
stas, construir un autmata finito que reconozca dichos tokens. Una vez hecho esto, es posible
escribir un programa que identifique estos tokens y as verificar que cada uno de stos sean
expresiones vlidas dentro de nuestro lenguaje de programacin de referencia.
1.3.2 Gramtica libre de contexto (CFG Context Free Grammar)
Una CFG es una 4-tupla ) , , , ( S R V E donde:
5. V es un conjunto finito, llamado variables (o no-terminales).
6. E es un conjunto finito disjunto de V, llamado terminales.
7. R es un conjunto finito de reglas, con cada regla siendo una variable a la izquierda de la
flecha y una cadena de variables y terminales a la derecha de la flecha.
8. S es la variable inicial.
Un ejemplo de una CFG aparece en la Fig. 10.
zMNz S

aMa M


M z

bNb N


N z
Fig. 10: Ejemplo de una CFG
En el captulo 3 revisaremos diferentes tcnicas para construir un analizador sintctico
basado en una CFG. Por el momento, podemos decir que la mayora de los lenguajes de
programacin estn basados en una CFG, lo cual nos permite utilizar a los PDA para verificar si
un programa fuente, escrito en algn lenguaje de programacin especfico, est escrito
correctamente o, dicho de otra manera, si su estructura gramatical es la correcta.
1.4 Fases de un compilador
En esta seccin revisaremos brevemente las fases de un compilador (ver Error! No se
encuentra el origen de la referencia.).
Analizador lxico
o rastreador
Analizador
sintctico
Analizador
semntico
Optimizador de
cdigo fuente
Generador de
cdigo
Optimizador de
cdigo objetivo
Cdigo fuente
Tokens
rbol sintctico
rbol con anotaciones
Cdigo intermedio
Cdigo objetivo
Cdigo objetivo
Tabla de
literales
Tabla de
smbolos
Manejador
de errores

Fig. 11: Fases de un compilador
En primer lugar, el programa fuente (escrito en algn lenguaje de programacin
determinado) sirve de entrada al analizador lxico o rastreador [ref.]. Como ejemplo, digamos
que nuestro programa fuente consta de la siguiente lnea:
a[index] = 4+2
La salida del analizador lxico es un conjunto de tokens que forman parte del lenguaje de
programacin en cuestin (ver Tabla 1):
Lexema
1
Tipo de token

1
Un lexema es un conjunto de caracteres del programa fuente que representan una secuencia
significativa
a identificador
[ corchete izquierdo
index identificador
] corchete derecho
4 nmero
+ operador de adicin
2 Nmero
Tabla 1: Salida del analizador lxico para la expresin,-
Como se puede apreciar en la Tabla 1, el analizador lxico ignora los espacios en blanco.
Toca ahora el turno del analizador sintctico, el cual toma como entrada los tokens
producidos en la fase anterior y genera con ellos un rbol sintctico (ver Fig. 12).
Identificador
a
Identificador
index
expresion expresion
Expresion de subindice
[ ]
numero
4
numero
2
expresion expresion +
Expresion aditiva
expresion expresion =
Expresion de asignacion
expresion

Fig. 12: rbol sintctico de la expresin

a [ index ] = 4+2
Como se puede apreciar en la Fig. 12, la lnea de cdigo del presente ejemplo se
representa en forma de un rbol, en el cual los nodos internos de dicho rbol representan una
operacin y los hijos de cada uno de estos nodos representan los argumentos de sus respectivas
operaciones.
La tercera fase corresponde al analizador semntico, el cual toma como entrada el rbol
sintctico y produce como salida un rbol con anotaciones (ver Fig. 13). stas incluyen las
declaraciones y la verificacin de tipos.

Fig. 13: rbol semntico (corregir este rbol) de la expresin

a [ index ] = 4+2
La cuarta fase corresponde al optimizador de cdigo fuente (Fig. 14). Esta fase toma
como entrada el rbol con anotaciones y produce como salida una representacin intermedia (o
cdigo intermedio) entre el programa fuente y el programa objeto, el cual optimiza (siempre que
sea posible) las operaciones representadas en el rbol sintctico. Por ejemplo, en el rbol de la
Fig. 14, la rama derecha de dicho rbol es el resultado de colapsar el subrbol derecho de la Fig.
12. Es importante mencionar que aunque muchas optimizaciones se pueden llevar a cabo
directamente sobre el rbol, en varios casos se utiliza una representacin lineal de ste conocida
como cdigo en tres direcciones (pues contiene hasta tres operandos por instruccin, tal y como
sucede en las instrucciones en lenguaje ensamblador). Este tipo de representacin se revisar
ms a detalle en el captulo 5.

Fig. 14: Optimizador de cdigo fuente
La quinta fase se refiere a la generacin de cdigo. sta toma como entrada la
representacin intermedia generada en la fase anterior y produce su correspondiente cdigo para
la mquina objeto. Como mencionamos ya en la seccin 1.1, en este libro construiremos un
compilador para un lenguaje de programacin sencillo cuyos programas objeto estarn en
lenguaje ensamblador. El cdigo en un hipottico lenguaje ensamblador (considerar agregar
cdigo en ensamblador real producido en el compilador de Louden) que se genera a partir de la
representacin intermedia mostrada en la Fig. 14, se presenta en la Fig. 15.

MOV R0, index ;; Valor de index R0
MUL R0, 2 ;; Doble valor en R0
MOV R1, &a ;; Direccin de a R1
ADD R1, R0 ;; Sumar R0 a R1
MOV *R1, 6 ;; Constante 6 direccin en R1
Fig. 15: cdigo objeto en ensamblador generado a partir de la representacin intermedia de la Fig. 14
Para este ejemplo especfico, &a es la direccin de a y *R1 significa direccionamiento
indirecto de registro, por lo que la ltima instruccin guarda el valor 6 en la direccin apuntada
por R1. En el captulo 6 revisaremos con detalle cmo generar cdigo objeto a partir de una
representacin intermedia.
La ltima fase propiamente dicha es la optimizacin de cdigo objeto, la cual intenta
mejorar el cdigo que ha sido generado en la fase anterior. La optimizacin incluye, en trminos
generales, que se sustituyan instrucciones lentas por otras ms rpidas as como que se eliminen
operaciones redundantes o innecesarias. La Fig. 16 muestra la optimizacin del cdigo objeto de
la Fig. 15.
Optimizador de cdigo objeto
MOV R0, index ;; Valor de index R0
SHL R0 ;; doble valor en R0
MOV &a[R0], 6 ;; constante 6 direccin a + R0
Fig. 16: Cdigo objeto optimizado
Como se puede apreciar en la Fig. 16, el optimizador ha reducido el nmero de lneas con
respecto al cdigo de la Fig. 15 manteniendo el mismo significado del programa pero reduciendo
el tiempo de ejecucin. En el captulo 7 revisaremos con detalle las tcnicas para la optimizacin
de cdigo objeto.
Para terminar esta seccin, es importante mencionar que cada una de las fases de un
compilador interactan con 3 componentes, tal y como lo muestra la Error! No se encuentra el
origen de la referencia.: la tabla de literales, la tabla de smbolos y el manejador de errores.
Brevemente podemos mencionar que la tabla de literales se utiliza bsicamente para almacenar
constantes y cadenas que se usan a lo largo de un programa, la tabla de smbolos guarda la
informacin asociada con los identificadores (tales como funciones, variables, constantes y tipos
de datos) mientras que el manejador de errores es el mdulo que se encarga no slo de reportar
claramente los problemas generados en cada fase del compilador sino tambin de corregirlos. En
los captulos 3 y 4 veremos algunas tcnicas para la recuperacin de errores sintcticos y la
construccin de tablas de smbolos respectivamente. En el siguiente captulo, revisaremos las
tcnicas para construir la primera fase de un compilador: el analizador lxico.

2. Anlisis Lxico
En esta unidad revisaremos a detalle las tcnicas asociadas a la fase de anlisis lxico de
un compilador. Bsicamente lo que queremos lograr es construir la siguiente secuencia:
Expresin regular NFA DFA Programa
Recordemos que el trabajo del analizador lxico es dividir en tokens (unidades
significativas del lenguaje en cuestin) el programa fuente y reconocer si dichos tokens forman
parte del lenguaje para el cual se est llevando a cabo el proceso de traduccin. Por ejemplo,
dado el siguiente programa:
comienza
a:=b3;
termina;
Fig. 17: Un pequeo ejemplo de un programa fuente
Nuestro analizador deber reconocer los siguientes tokens:
Lexema Tipo
comienza palabra clave
a identificador
:= operador de asignacin
b3 identificador
; Smbolo especial
termina palabra clave
Tabla 2: Tokens del programa fuente de la Fig. 17
Si algn token no estuviera previamente incluido en la definicin de nuestro lenguaje de
programacin como un token vlido, entonces la labor de nuestro analizador lxico es detectar a
dicho token como invlido. Por ejemplo, podemos observar que el operador de asignacin est
formado por el smbolo compuesto :=. Si el programa estuviera escrito de la siguiente forma
(Fig. 18):
comienza
a=b3;
termina;
Fig. 18: un pequeo ejemplo de un programa fuente con un error lxico
Y suponiendo que el smbolo = (sin los dos puntos) no ha sido incluido como smbolo
vlido en la definicin de nuestro lenguaje de programacin, entonces nuestro analizador lxico
deber producir un mensaje de error cuando encuentra dicho smbolo en el programa fuente. Por
otro lado, suponiendo que el parntesis izquierdo y el parntesis derecho son smbolos vlidos
dentro de nuestro lenguaje de programacin, entonces en programas como el de la Fig. 19 no
existe error lxico:
comienza
a=b3));
termina
Fig. 19: un pequeo ejemplo de un programa fuente sin error lxico

La razn es porque al dividir en tokens el programa de la Fig. 19, el analizador lxico
reconocer los 2 parntesis derechos que aparecen en la lnea 2 como tokens vlidos. La fase que
debera reconocer este error (asumiendo que tener 2 parntesis que cierran sin sus
correspondientes parntesis que abren es un error estructural del programa fuente) es la fase de
anlisis sintctico (los detalles de esta fase los veremos en el captulo 3). Mientras tanto,
revisaremos paso a paso las tcnicas necesarias para poder construir la secuencia de arriba y as
poder llegar a codificar, como paso final de dicha secuencia, nuestro analizador lxico.
2.1 Definicin de un reconocedor de cadenas no trivial
Antes de definir un reconocedor de cadenas no trivial, necesitamos algunos conceptos
que servirn de fundamento para construir nuestra conocida secuencia:
Expresin regular NFA DFA Programa
En primer lugar, debemos mencionar que las cadenas de caracteres representan bloques
de construccin fundamentales dentro de la Ciencia de la Computacin. El alfabeto sobre el cual
dichas cadenas se encuentran definidas puede variar de aplicacin en aplicacin. Para nuestro
primer propsito (la construccin de un analizador lxico), definimos un alfabeto como un
conjunto finito no vaco de smbolos. En general, usamos las letras griegas y para designar
alfabetos como se muestra a continuacin:
* +
* +
Una cadena definida sobre un alfabeto es una secuencia finita de smbolos tomados de
ese alfabeto, usualmente escritos uno junto al otro y no separados por comas. Por ejemplo, si E
es el alfabeto mostrado arriba, entonces 011101 es una cadena sobre dicho alfabeto. Si I es el
alfabeto mostrado arriba tambin, entonces abracadabra es una cadena sobe ese alfabeto. Si w
es una cadena sobre , la longitud de dicha cadena es el nmero de smbolos que contiene y se
representa como . Es importante mencionar que la cadena que no contiene smbolos (es decir,
de longitud cero) se le llama cadena vaca y se escribe comnmente o . As que un lenguaje
es un conjunto de cadenas definidas sobre un alfabeto que cumplen cierta condicin. Por
ejemplo, el lenguaje * + definido sobre el alfabeto * +
contiene todas las cadenas de y que cumplan con la condicin de que dichas cadenas
contengan al menos 2. As que las cadenas abaaabb y bbbbaaaa son elementos del
lenguaje mientras que las cadenas bbbbb y bbbbbabbbb no lo son. Hay que notar que el
conjunto de cadenas pertenecientes al lenguaje es infinito. Para nuestro caso especfico
(anlisis lxico), el tipo de lenguaje que nos atae es el de los lenguajes regulares. Los lenguajes
regulares pueden ser descritos usando expresiones regulares, lo que hace que podamos construir
nuestro analizador lxico usando nuestra conocida secuencia:
Expresin regular NFA DFA Programa
El teorema 2.1 asegura que podamos representar un lenguaje regular mediante una
expresin regular:
Teorema 2.1: Un lenguaje es regular si y slo si alguna expresin regular lo describe.
Aunque no demostraremos aqu dicho teorema, podemos apreciar que ste nos permite
pasar de una representacin a otra con la seguridad de que ambas son equivalentes. El lector
interesado en la demostracin puede consultar [ref. libro Sipser]. Antes de dar la definicin
formal de una expresin regular, necesitamos definir las operaciones regulares de las que dicha
definicin hace uso.
2.1.1 Las operaciones regulares
La siguiente definicin y su respectivo ejemplo los tomamos de [ref. Sipser]. Sean A y
B lenguajes. Definimos las operaciones regulares unin, concatenacin y estrella (Kleene)
como sigue:
UNION: } | { B x A x x B A e v e =
CONCATENACIN: } | { B y A x y x B A e . e =
ESTRELLA: } cada y 0 | {
3 2 1
*
A x k x x x x A
i k
e > =
Ejemplo: Sea E el alfabeto estndar de 26 letras } , , , , , , { z y x c b a . Si

A={ good, bad } y
} , { girl boy B = entonces:
} , , , { girl boy bad good B A =
} , , , { badgirl badboy goodgirl goodboy B A =
} , , , , , , , , , {
*
od goodgoodgo d goodgoodba badbad badgood goodbad goodgood bad good A c =

Una vez definidas las operaciones regulares, podemos definir una expresin regular.
Dicha definicin tambin est tomada de [ref. Sipser].
2.1.2 Definicin formal de una expresin regular
Decimos que R es una expresin regular si R es:
1. a para cualquier E e a
2. c
3. C
4. ) (
2 1
R R , donde
1
R y
2
R son expresiones regulares
5.

(R
1
-R
2
)
6. ) ( 1
*
R donde
1
R es una expresin regular
Para el punto 1, cualquier elemento que pertenezca al alfabeto es una expresin regular.
En este caso, la expresin regular a representa el lenguaje {a}. Para el punto 2, la expresin
regular formada por la cadena vaca (representada por c) representa el lenguaje {c}. Para el
punto 3, la expresin regular C representa el lenguaje vaco. Es importante aclarar que la
expresin regular c representa el lenguaje que contiene una sola cadena: la cadena vaca;
mientras que la expresin regular C representa el lenguaje que no contiene ninguna cadena
(incluida la cadena vaca). Se deja como ejercicio al lector disear un autmata finito que acepte
el lenguaje representado por c y el lenguaje representado por C respectivamente. Para los puntos
4, 5, y 6, las expresiones regulares representan los lenguajes obtenidos al aplicar las operaciones
regulares de unin, concatenacin y estrella respectivamente.
A primera vista, la definicin anterior parece ser una definicin circular ya que parece
que definimos las expresiones regulares en trminos de s mismas. Sin embargo, las expresiones
regulares R1 y R2 son siempre ms pequeas que R, lo que nos permite evitar la circularidad en
la definicin. A una definicin de este tipo se le llama definicin inductiva. Los parntesis en las
expresiones regulares pueden omitirse: la evaluacin entonces se hace usando la precedencia de
los operadores: estrella, concatenacin y unin.
Una vez que se tienen los conceptos y definiciones anteriores, es posible entonces definir
un reconocedor de cadenas no trivial usando una expresin regular. Esto lo haremos en la
siguiente seccin.
2.2 Programar sistemticamente el reconocedor en lo referente a la obtencin
del autmata, almacenarlo eficientemente y manejar adecuadamente el
archivo fuente
Para construir nuestro analizador lxico, debemos cubrir los siguientes pasos: a)
conversin de una expresin regular a un autmata finito no determinista (NFA), b) conversin
de un NFA a un autmata finito determinista (DFA), y c) codificacin del DFA resultante en un
programa (pseudocdigo). Una vez que se tiene el programa en pseudocdigo es posible, sin
mayores complicaciones, la codificacin de ste en un lenguaje de programacin propiamente
dicho. En las siguientes secciones, describiremos a detalle cada uno de estos pasos.
2.2.1 Conversin de una expresin regular a un autmata finito no determinista
(NFA)
Antes de hacer la conversin propiamente dicha de una expresin regular a un NFA,
recordemos la definicin de este tipo de autmata vista en el captulo 1.
Un NFA es una 5-tupla ) , , , , (
0
F q Q o E donde:
- es un conjunto finito de estados
- es un alfabeto finito
-

o : QE
c
P ) (Q es la funcin de transicin
-
Q q e
0
es el estado inicial
-

F _Q
es el conjunto de estados de aceptacin
Un ejemplo de un NFA aparece en la Fig. 20.
Q
E
q
1
q
2
q
3
b
a
a, b
a


Fig. 20: Un NFA que reconoce a la cadena vaca o cadenas que tienen cualquier nmero de as
Analicemos cada una de las partes de este NFA.
1. Q = {q
1
, q
2
, q
3
}
2. E = {a,b}
3. Revisemos con detenimiento la funcin de transicino. Una funcin es un objeto que
define una relacin de entrada-salida; i.e., una funcin recibe una cierta entrada y
produce una salida especfica. El lado izquierdo de la flecha en la funcin de transicin
es la entrada para esa funcin y el lado derecho de la flecha denota la salida. As que la
funcin de transicin toma como entrada un par ordenado cuyo primer elemento es un
elemento de Q y cuyo segundo elemento es un elemento de E
c
(i.e., E c). Este conjunto
de pares ordenados est definido por el producto cartesiano, representado por Q E
c
,
entre el conjunto de estados y el alfabeto (incluida la cadena vaca). As que el producto
cartesiano de dos conjuntos, digamos Q y E
c
, es el conjunto de todos los pares ordenados
cuyo primer elemento pertenece a Q y cuyo segundo elemento pertenece a E
c
. Note que
el orden de los elementos de un par ordenado, a diferencia del orden de los elementos de
un conjunto, s importa, por lo que en general, dados 2 conjuntos A y B, A B = B A.
Ahora bien, la salida de la funcin de transicin es un elemento del conjunto potencia del
conjunto de estados. El conjunto potencia de un conjunto A es el conjunto de todos los
subconjuntos de A. Para este caso especfico, el conjunto potencia de Q, denotado P(Q) =
{C, {q
1
}, {q
2
}, {q
3
}, {q
1
,q
2
}, {q
1
,q
3
}, {q
2
,q
3
}, {q
1
,q
2
,q
3
}}. Con estas definiciones en
mano, podemos ya saber cul es la salida de la funcin de transicin para cada par
ordenado. Dado el NFA de la Fig. 20, las entradas y salidas correspondientes a dicha
funcin las representamos en la Tabla 3: Resultado de la funcin de transicin para el
NFA de la Fig. 20
a b c
q
1
C {q
2
} {q
3
}
q
2
{q
2
,q
3
} {q
3
} C
q
3
{q
1
} C C
Tabla 3: Resultado de la funcin de transicin para el NFA de la Fig. 20
Como se puede observar, el resultado de cualquier combinacin estado-elemento del
alfabeto es un conjunto de estados que pertenece al conjunto potencia. Adems, note que el
conjunto potencia nos permite representar el no-determinismo: por ejemplo, dado el estado q
2
y
una entrada a, el NFA nos permite quedarnos en ese estado o ir al estado q
3
lo cual lo
representamos como el estado combinado {q
2
,q
3
}; o bien, el conjunto potencia nos permite
representar que no hay transicin definida para el estado q
1
y una entrada a, representndola
como C.
4. El estado inicial q
0
= q
1

5. El conjunto de estados de aceptacin F = {q
1
}
Para realizar la conversin de una expresin regular a su correspondiente NFA, necesitamos
la ayuda de 3 teoremas, los cuales presentamos a continuacin [ref. Sipser].
Teorema 1: La clase de lenguajes regulares es cerrada bajo la operacin de unin.
Sean
1
A y
2
A dos lenguajes regulares, queremos probar que
2 1
A A es regular. La idea
es tomar dos NFAs,
1
M y
2
M para
1
A y
2
A , respectivamente, y combinarlos en un nuevo NFA
que llamaremos M .
La mquina M debe aceptar una estrada si
1
M o
2
M aceptan esa entrada. La nueva
mquina tiene una nuevo estado inicial, con una transicin c al estado inicial de
1
M y otra
transicin c al estado inicial de
2
M . De esta manera la nueva mquina adivina no
deterministicamente cul de las dos mquinas acepta dicha entrada. Si una de ellas acepta una
entrada M la aceptar tambin.
Representamos esta construccin en la Fig. 21. En la parte superior podemos ver a las
dos mquinas
1
M y
2
M , en cada una se encuentran el estado inicial, el o los estados finales (en
doble circulo) y algunos estado intermedios. La parte inferior muestra a la mquina M , la cual
contiene tanto a
1
M como a
2
M , adems de tener un estado adicional que contiene dos
transiciones c , una a
1
M y otra a
2
M .

Fig. 21: Construccin de un NFA para reconocer
2 1
A A
Demostracin
Sean ) , , , , (
1 1 1 1 1
F q Q M o E = que reconoce a
1
A y ) , , , , (
2 2 2 2 2
F q Q M o E = que reconoce a
2
A . Construyamos ) , , , , (
0
F q Q M o E = para que reconozca a
2 1
A A
1.
2 1 0
} { Q Q q Q =
Los estados de M son todos los estados de
1
M y
2
M , con la adicin de un nuevo estado
0
q .
2. El estado
0
q es el estado inicial de M .
3. El conjunto de estados de aceptacin
2 1
F F F = .
Los estados de aceptacin M son todos los estados de aceptacin de
1
M y
2
M . De esta
manera M acepta si lo hacen
1
M o
2
M
4. Definimos o de manera tal que para cualquier Q qe y cualquier
c
E e a .

= =
= =
e
e
=
c |
c
o
o
o
a q q
a q q q q
Q q a q
Q q a q
a q
y
y } , {
) , (
) , (
) , (
0
0 2 1
2 2
1 1

Teorema 2: La clase de lenguajes regulares es cerrada bajo la concatenacin.
Tenemos dos lenguajes regulares
1
A y
2
A queremos probar que
2 1
A A es regular. La
idea es tomar dos s ' NFA ,
1
M y
2
M para
1
A y
2
A , respectivamente, y combinarlos en un nuevo
NFA que llamaremos M , como lo hicimos en el caso de la unin, pero sta vez de una manera
un poco diferente, como se muestra en la Fig. 22.

Fig. 22: Construccin de M para reconocer
2 1
A A
Asignaremos a M en estado inicial
de
1
M . Los estados de aceptacin de
1
M tendrn transiciones c que
permitan no determinsticamente
anclar a
2
M con
1
M , es decir, dichas
transiciones irn de los estados finales
de
1
M al estado inicial de
2
M ; de esta
manera, cada vez que nos encontremos
en un estado de aceptacin de
1
M
significa que ste ha encontrado una
pieza inicial de la entrada que
constituye un carcter en
1
A . Los
estados de aceptacin de M sern slo
los estados de aceptacin de
2
M . Por lo
tanto, M
Acepta una cadena cuando la entrada puede ser dividida en dos partes, la primera
aceptada por
1
M y la segunda por
2
M .
Demostracin
Sean ) , , , , (
1 1 1 1 1
F q Q M o E = que reconoce a
1
A y ) , , , , (
2 2 2 2 2
F q Q M o E = que reconoce
a
2
A . Construyamos ) , , , , (
0
F q Q M o E = para que reconozca a
2 1
A A .
1.
2 1
Q Q Q =
Los estados de M son todos los estados de
1
M y
2
M .
2. El estado
1
q es el estado inicial de
1
M .
3. El conjunto de estados de aceptacin
2
F F = .
Los estados de aceptacin M son todos los estados de aceptacin de
2
M
4. Definimos o de manera tal que para cualquier Q qe y cualquier
c
E e a .

=
= =
= e
e e
=
2 2
1 2 1
1 1
1 1 1
) , (
y } { ) , (
y ) , (
y ) , (
) , (
Q q a q
a F q q a q
a F q a q
F q Q q a q
a q
o
c o
c o
o
o
Teorema 3: La clase de lenguajes regulares es cerrada bajo la estrella de Kleene.

Fig. 23: Construimos M para que reconozca
*
A
Tenemos un lenguaje
regular
1
A y lo modificamos
para que reconozca
*
1
A , como se
muestra en la figura 3.

Demostracin
Sea ) , , , , (
1 1 1 1 1
F q Q M o E = que reconoce a
1
A . Construyamos ) , , , , (
0
F q Q M o E = para
que reconozca a
*
1
A .
1.
1 0
} { Q q Q =
Los estados de M son todos los estados de
1
M mas un nuevo estado inicial.
2. El estado
0
q es el nuevo estado inicial.
3. El conjunto de estados de aceptacin
1 0
} { F q F = .
Los estados de aceptacin M son todos los estados de aceptacin de
1
M , con los que ya
contaba, ms el nuevo estado inicial.
4. Definimos o de manera tal que para cualquier Q qe y cualquier
c
E e a .

= =
= =
= e
e e
=
c |
c o
c o
o
o
a q q
a F q q a q
a F q a q
F q Q q a q
a q
y
y } { ) , (
y ) , (
y ) , (
) , (
0
1 1 1
1 1
1 1 1

Una vez teniendo estos 3 teoremas, contamos con las herramientas necesarias para
convertir una expresin regular en su correspondiente NFA. A continuacin presentamos un
ejemplo, paso a paso, de cmo realizar dicha conversin.
Convertir la siguiente expresin regular en su correspondiente NFA:
x y z
*
) (
1.1. Construimos los autmatas que reconocen a (Fig. 24), (Fig. 25) y (Fig. 26)

Fig. 24: Autmata que
reconoce a z .

Fig. 25: Autmata que
reconoce a y

Fig. 26: Autmata que
reconoce a x
1.2. Construimos el autmata que reconoce a y z .
Siguiendo el Teorema 1,
agregamos un nuevo estado inicial,
2
q en nuestro caso, y llevamos una
transicin vaca al autmata que
reconoce a z , y otra transicin vaca
al autmata que reconoce a (Fig.
27)

Fig. 27: Autmata que reconoce y z

1.3. Construimos el autmata que reconoce
*
) ( y z
Siguiendo el Teorema 3,
agregaremos un nuevo estado inicial
1
q que adems ser un estado final.
Agregamos transiciones vacas de
todos los estados finales de y z al
estado inicial de y z (
2
q ), adems
de una transicin vaca de
1
q a


(Fig. 28)

Fig. 28: Autmata que reconoce
*
) ( y z
Compiladores Nicandro Cruz Ramrez
32
1.4. Finalmente, concatenamos el autmata anterior con el autmata que reconoce al carcter
x . Como se vio en el Teorema 2, debemos llevar los estados de aceptacin de
*
) ( y z
con el estado inicial del autmata que reconoce a x a travs de transiciones c . Como se
menciona en el teorema, los nicos estados de aceptacin que existen son los de x (
8
q ),
y el estado inicial del nuevo autmata ser el estado inicial de
*
) ( y z , a saber

(Fig.
29).

Fig. 29: Autmata que reconoce ( )


En los ejemplos que presentamos a continuacin, construimos directamente un NFA a
partir de la expresin regular correspondiente. Quedan como ejercicios para el lector, la
construccin paso a paso de dichos NFA.
2.
* *
) ( x y z


Compiladores Nicandro Cruz Ramrez
33
3.
* *
) ( z y x

4.
* *
10 0

5. 10 01
.


6.
* *
1 01
.


7. aba b a
*
) (
Compiladores Nicandro Cruz Ramrez
34

8.
*
0 ) 1 0 (

9.
*
) | ( digito letra letra
.


2.2.2 Conversin de un autmata finito no determinista (NFA) a su
correspondiente autmata finito determinista (DFA)
Para completar el recorrido de nuestra conocida secuencia,
Expresin regular NFA DFA Programa
nos hace falta convertir un NFA en su correspondiente DFA y ste a su vez codificarlo en forma
de programa. En esta seccin revisamos las herramientas necesarias para convertir un NFA en su
correspondiente DFA. Para lograr esto, afortunadamente contamos con el siguiente teorema:
Teorema 4: Cada NFA tiene un DFA equivalente
Existen al menos 2 demostraciones que nos permiten pasar de un NFA a su
correspondiente DFA [ref. Sipser y Louden]. Aqu mencionaremos slo una de ellas que se
conoce como construccin de subconjuntos [ref. Louden]. Antes de ver formalmente dicha
demostracin, es importante mencionar que para que un DFA acepte las mismas cadenas que un
NFA, necesitamos una manera de eliminar tanto las transiciones c como las transiciones
mltiples que caracterizan a los NFA de tal forma que stas puedan representarse
Compiladores Nicandro Cruz Ramrez
35
determinsticamente. Para recordar los elementos y propiedades de un DFA vistos en el captulo
anterior, escribimos nuevamente la definicin de un DFA.
Un DFA es una 5-tupla
) , , , , (
0
F q Q o E
donde:
- es un conjunto finito llamado estados
- es un conjunto finito llamado alfabeto
- Q Q E : o es la funcin de transicin
-

q
0
eQ
es el estado inicial
-

F _Q
es el conjunto de estados de aceptacin

Como podemos observar, la funcin de transicin de un DFA, a diferencia de la de un
NFA, nos permite ir, dados un estado y un smbolo del alfabeto, a uno y slo un estado. As que
la pregunta es: cmo podemos eliminar las transiciones c y las transiciones mltiples que se
presentan en los NFA?
Primero que nada necesitamos definir la cerradura c de un conjunto de estados. La
siguiente definicin la tomamos de [ref. Louden]. La cerradura c de un estado simple s es el
conjunto de estados alcanzables por una serie de cero o ms transiciones c. A este conjunto lo
denotamos como

s . Para ejemplificar ms claramente este concepto de cerradura, usamos la
figura 9, la cual es un NFA que representa la expresin regular a*.

Fig. 30: Ejemplo de un NFA
La cerradura c del conjunto de estados del NFA de la Fig. 30 se muestra a continuacin:

q
1
={q
1
, q
2
, q
4
}

q
2
={q
2
}

q
3
={q
2
, q
3
, q
4
}

q
4
={q
4
}
Para este ejemplo especfico, la cerradura c de q
1
es el conjunto de estados a los que se
puede llegar desde q
1
con cero o ms transiciones c. Siguiendo estos mismos pasos, podemos
entonces encontrar la cerradura c de q
2
, q
3
y q
4
como se muestra arriba.
Ahora definimos la cerradura c ya no de un solo estado sino de un conjunto de estados
como sigue:

S ={ U
seS
s }

Donde S es un conjunto de estados. Por ejemplo, para el NFA de la Fig. 30:

{q
1
q
3
}=q
1
q
3
={q
1
, q
2
, q
4
}{q
2
, q
3
, q
4
}={q
1
, q
2
, q
3
, q
4
}
Una vez que se tienen estas definiciones, es posible describir el procedimiento para la
construccin de un DFA M a partir de un NFA N.
Q
E
Compiladores Nicandro Cruz Ramrez
36
PASO 1: Calcular la cerradura c del estado inicial de N (consideramos el NFA de la Fig. 30):

q
1
={q
1
, q
2
, q
4
}
PASO 2: Calcular para todo s e S y para toda a e E

S'
a
={t | para cualquier s e S existe una transicin de s a t con a}
En otras palabras, el conjunto

S'
a
es un conjunto de estados que cumplen con la
condicin de pertenecer a S y de tener una transicin hacia cualquier otro estado t con cualquier
elemento del alfabeto a. Para nuestro ejemplo en particular, consideremos el estado inicial de
nuestro NFA:

S'
a
={q1,q2,q4}a =

{q3}
Es decir, consideramos todos los estados a los que se pueden llegar desde q
1
, q
2
y q
4
con
a. Como puede observarse, el nico estado al que se puede llegar con a desde este conjunto de
estados es q
3
.
PASO 3: Calculamos

S '
a
: la cerradura c de

S'
a
. Esto define un nuevo estado para el DFA junto
con una nueva transicin

S'
a


S '
a
con a e E. En nuestro ejemplo:

S '
a
={q1,q2,q4}a =

{q3}=

{q2,q3,q4}
Este paso se aplica repetidamente a cada nuevo estado creado hasta que ya no se crean
nuevos estados o transiciones. Adems, los estados de aceptacin de este DFA resultante son
aqullos que contengan en cualquiera de sus estados un estado de aceptacin del NFA original.
Como se puede apreciar, el DFA resultante no contiene transiciones c ya que todo estado
en este DFA se construye como una cerradura c. Adems, la funcin de transicin es
determinista pues el procedimiento nos asegura que existe uno y slo un estado al que ir desde
cualquier estado con un elemento especfico del alfabeto.
Para ilustrar mejor lo anterior, tomemos nuevamente de ejemplo el NFA mostrado en la Fig.
30. Debemos transformarlo a su correspondiente DFA siguiendo los pasos anteriores y tomando
en cuenta que } {a = E .
1. Obtengamos la cerradura de cada uno de los estados:

q
1
={q
1
, q
2
, q
4
}

q
2
={q
2
}

q
3
={q
2
, q
3
, q
4
}

q
4
={q
4
}
2. El estado inicial de nuestro DFA ser la cerradura c del estado inicial del NFA
(cerradura de
1
q ) , como se muestra en la Fig. 31. En este momento verificamos si
alguno de los estados de
1
q es un estado de aceptacin en el DFA, de ser as tambin lo
ser
1
q en el NFA. Para este ejemplo
4
q es estado de aceptacin del DFA y como
1 4
q q e , entonces
1
q ser estado de aceptacin.
Compiladores Nicandro Cruz Ramrez
37

Fig. 31: Estado inicial del DFA
1
q
3. Para definir el segundo estado en el DFA (Fig. 32), verificamos para cada estado de
1
q si
existen transiciones no vacas en el NFA a otros estados con cada uno de los elementos
de E ; es decir, } , , {
4 2 1 1
q q q q = , verificamos si en
1
q existe alguna transicin distinta de
c hacia algn estado en el NFA, cmo esto no sucede seguimos con el siguiente estado
de
1
q . Ahora verificaremos si
2
q tiene alguna transicin distinta de psilon hacia algn
estado en el NFA, en este caso si existe una transicin diferente de c y es aquella que va
del estado
2
q a
3
q a travs de una a . Por ltimo, verificamos si
4
q tiene alguna
transicin diferente de c hacia algn estado en el NFA, lo cual no sucede. Por lo tanto,
nuestro siguiente estado en el DFA ser
3
q a travs de una transicin con a . Si ms
estados hubieran resultado de ir de un estado a otro con transiciones diferentes de c con
a , entonces la unin de las cerraduras de todos esos estados hubiera sido el siguiente
estado en el DFA. Nuevamente, verificamos si alguno de los elementos de
3
q es un
estado de aceptacin en el NFA tambin lo ser
3
q en el DFA.

Fig. 32: Segundo estado del DFA
4. Verificamos las transiciones existentes en el NFA con los elementos de } , , {
4 3 2 3
q q q q = .
Realizamos los mismos pasos que en el inciso anterior y observamos que slo existe una
transicin en el NFA diferente de c que es de
2
q a
3
q con a . As el siguiente estado
ser de
3
q a
3
q con (Fig. 33).

Fig. 33: Siguiente estado del DFA
5. Aqu termina la construccin del DFA, pues ya no existen nuevos estados que agregar o
nuevas transiciones.
Hagamos otro ejercicio para reforzar los conceptos involucrados en la transformacin de un
NFA en un DFA.
Transforme el NFA de la Fig. 34 en su respectivo DFA, con } , , { z y x = E
Compiladores Nicandro Cruz Ramrez
38

Fig. 34: NFA correspondiente a x y z
*
) (
1. Obtenemos las cerraduras c para cada estado del NFA.
} , , , , {
7 5 3 2 1 1
q q q q q q = } , , {
5 3 2 2
q q q q = } {
3 3
q q =
} , , , , {
7 5 4 3 2 4
q q q q q q = } {
5 5
q q = } , , , , {
7 6 5 3 2 6
q q q q q q =
} {
7 7
q q = } {
8 8
q q =
Dibujamos el estado inicial del DFA que ser
1
q (Fig. 35).

Fig. 35: Estado inicial del DFA
2. Verificamos las transiciones de cada elemento de
1
q con cada elemento del alfabeto E .
2.1. Verificamos si los elementos de
1
q tienen transiciones a otros estados en el NFA para
E e x , en este caso slo
7
q va a
8
q con x , por lo tanto } {
8 8
q q = ser el estado 2 del
DFA (Fig. 36). Por ser
8
q estado de aceptacin en el NFA entonces tambin lo ser en
el DFA

Fig. 36: Nuevo estado del DFA generado
por la transicin x del NFA en
1
q
2.2. Verificamos si los elementos de
1
q tienen transiciones a otros estados en el NFA para
E e y , en este caso slo
5
q va a
6
q con y , por lo tanto } , , , , {
7 6 5 3 2 6
q q q q q q = ser el
estado 3 del DFA (Fig. 37).
Compiladores Nicandro Cruz Ramrez
39

Fig. 37: Estado 3 del DFA
2.3. Verificamos si los elementos del estado 1 del DFA tienen transiciones a otros estados en
el NFA para E e z , en este caso slo
3
q va a
4
q con y , por lo tanto
} , , , , {
7 5 4 3 2 4
q q q q q q = ser el estado 4 del DFA (Fig. 38).

Fig. 38: Estado 4 del DFA
3. Como ya no existen elementos en el alfabeto, realizamos el mismo proceso para el estado 2
del DFA. Como podemos observar slo tiene un elemento,
8
q , verificamos en el NFA si
8
q
tiene alguna transicin a otro estado para E e x , no la hay entonces creamos una transicin a
un estado | (estado 5) que nos indica error. Hacemos lo mismo para E e y , pero
nuevamente no hay ms transiciones, igual sucede con E e z ; por lo tanto, se crean
transiciones hacia el estado | para y (Fig. 39).

Fig. 39: Agregacin de estado de ERROR
4. Como ya no existen elementos en el alfabeto, realizamos el mismo proceso para el estado 3
del DFA.
5.1. Verificamos los elementos del estado 3 que tienen transiciones a otros elementos en el
NFA para E e x , slo
7
q tiene una transicin a
8
q con x , por lo tanto, el DFA va a
8
q ,
que es el estado 2 (Fig. 40).
Compiladores Nicandro Cruz Ramrez
40

Fig. 40: Transicin del estado 3 al estado 2
5.2. Hacemos el procedimiento anterior pero ahora para E e y ; slo
5
q tiene una transicin
a
6
q con x , por lo tanto, el DFA va a
6
q , que es el estado 3 (Fig. 41)

Fig. 41: Transicin del estado 3 a l mismo
5.3. Finalmente verificamos para E e z . Slo
3
q tiene una transicin a
4
q con x , por lo
tanto, el DFA va a
4
q , que es el estado 4 (Fig. 42).

Fig. 42: Transicin del estado 3 al estado 4
5. Como ya no existen elementos en el alfabeto, realizamos el mismo proceso para el estado 4
del DFA.
6.1. Verificamos los electos del estado 4 que tienen transiciones a otros elementos en el NFA
para E e x , slo
7
q tiene una transicin a
8
q con x , por lo tanto, el DFA va a
8
q , que
es el estado 2 (Fig. 43).
Compiladores Nicandro Cruz Ramrez
41

Fig. 43: Transicin del estado 4 a estado 2
6.2. Hacemos el procedimiento anterior pero ahora para E e y ; slo
5
q tiene una transicin
a
6
q con x , por lo tanto, el DFA va a
6
q , que es el estado 3.

Fig. 44: Algn ttulo
6.3. Finalmente verificamos para E e z . Slo
3
q tiene una transicin a
4
q con x , por lo
tanto, el DFA va a
4
q , que es el estado 4 (Fig. 45).

Fig. 45: Transicin del estado 4 a l mismo
Aqu ha terminado la construccin del DFA
2.2.3 Codificacin de un DFA en pseudocdigo
Para terminar nuestro recorrido por la conocida secuencia,
Expresin regular NFA DFA Programa
Compiladores Nicandro Cruz Ramrez
42
nos hace falta codificar el correspondiente DFA en forma de programa (pseudocdigo). Aqu
mostramos 2 diferentes maneras de hacerlo. Para la primera, podemos escribir pseudocdigo
directamente del DFA correspondiente. Consideremos el DFA de la Error! No se encuentra el
origen de la referencia. que reconoce un nombre de variable o identificador vlido as como su
pseudocdigo correspondiente (ver Tabla 4):

Fig. 46: DFA representando la sintaxis de un nombre de variable (identificador)
Como podemos apreciar, es posible escribir rutinas (programa) a partir de un DFA. Sin
embargo, el cdigo que se genera a partir de este diagrama de transiciones no representa
necesariamente una solucin ptima al problema de codificacin. Esto es debido a que, para
cada estado, sus posibles opciones de transicin se manejan con estructuras condicionales
anidadas lo que hace que el programa crezca significativamente en funcin del nmero de
estados y el nmero de elementos en el alfabeto. Es principalmente por esta razn que se
propone una mejor solucin basada en el uso de tablas de transicin: esta es la segunda manera
de escribir cdigo a partir de un NFA. Un ejemplo de esto se muestra en la Tabla 5 que toma
como entrada la tabla de transicin de la Tabla 4. Es importante mencionar que la Tabla 4 se
construy a partir del DFA de la figura Fig. 46. EOS en la Tabla 5 significa fin de cadena (end-
of-string).
Compiladores Nicandro Cruz Ramrez
43
Estado := 1;
LEER(siguiente Smbolo de entrada);
MIENTRAS ( ! FinDeCadena ) HACER
CASE Estado DE
1: SI Smbolo = letra ENTONCES
Estado := 3;
SI NO
SI Smbolo = dgito
ENTONCES
Estado := 2;
SI NO
Salir a RutinaError
FIN-SI
FIN-SI

2: Salir a RutinaError

3: SI Smbolo = letra ENTONCES
Estado := 3;
SI NO
SI Smbolo = dgito
ENTONCES
Estado := 3;
SI NO
Salir a RutinaError
FIN-SI
FIN-SI
FIN-case

LEER(siguiente Smbolo de entrada)

FIN-MIENTRAS

SI Estado ! = 3 ENTONCES
Salir a RutinaError;

Tabla 4: Secuencia de instrucciones sugerida por el diagrama de transicin de la Fig. 46.
letra nmero EOS
1 3 2 Error
2 Error Error Error
3 3 3 ACCEPT
Tabla 5: Tabla de transicin construida del diagrama de transicin de la figura 9.
Compiladores Nicandro Cruz Ramrez
44
Estado := 1;
REPETIR
LEER(siguiente Smbolo de entrada);
CASE Smbolo DE
letra : Entrada := letra;
dgito: Entrada := dgito;
MarcadorDeFinDeCadena: Entrada := EOS;
NingunoDeLosAnteriores: Salir A RutinaError;
FIN-CASE
Estado := Tabla [Estado, Entrada] ;
SI Estado = Error ENTONCES
SalirRutinaError;
FIN-SI
HASTA Estado = ACCEPT
Tabla 6: Anlisis lxico basado en la Tabla 4 de transiciones

Compiladores Nicandro Cruz Ramrez
45
zMNz S

a M a M

z M
b N b N

z N
3. Anlisis sintctico
Verificar si la cadena z az abz bz es generada por la gramtica mostrada en el
cuadro de la izquierda.


1. Comenzamos escribiendo la regla perteneciente a la
variable inicial:

Nz M z S

2. Aplicamos, para M la regla
a M a M

aNz M za
3. Aplicamos, para M la regla z M

z N zaza
4. Aplicamos, para
N
la regla
b N b N

bz N zazab
5. Aplicamos, para
N
la regla
z N


z a z a b z b z

Un autmata de pila (PDA Push Down Automaton) es una 6-tupla ) , , , , , (
0
F q Q o I E
donde Q, E , I y F son todos conjuntos finitos y:
1. Q es el conjunto finito de estados.
2. E es el alfabeto de entrada.
3. I es el alfabeto de la pila.
4. I E
c c
o Q : P ) (
c
I Q es la funcin de transicin.
5. Q q e
0
es el estado inicial.
6. Q F _ es el conjunto de estados de aceptacin.
Recuerde que } {c
c
E = E y } {c
c
I = I
q1
q4
, $
1, 0
, $
0, 0
1, 0
q2
q3

Fig. 47: PDA que reconoce lenguajes del tipo


Una gramtica libre de contexto (CFG, Context Free Grammar) es una 4-tupla ) , , , ( S R V E
donde:
1. V es un conjunto finito llamado las variables.
2. E es un conjunto finito llamado los terminales
Compiladores Nicandro Cruz Ramrez
46
3. R es un conjunto finito de reglas, con cada regla siendo una variable y una cadena de
variables y terminales.
4. V S e es la variable inicial.
Teorema: Para cada CFG existe un PDA M tal que ) ( ) ( M L G C =
Demostracin
Dada una CFG construimos un PDA M como sigue:
1. Designe el alfabeto de M como los smbolos terminales de G y los smbolos de la pila
como los terminales y no terminales de G junto con el smbolo especial # (asumimos que
# no es ni terminal ni no-terminal en G).
2. Designe los estados de M como q p q , ,
0
y f , siendo
0
q el estado inicial y f el nico
estado de aceptacin.
3. Introduzca la transicin ) # , ; , , (
0
p q .
4. Introduzca una transicin ) , ; , , ( S q p , donde S es el smbolo inicial en G.
5. Introduzca una transicin de la forma ) , ; , , ( w q N q para cada regla de reescritura
w N en G (aqu estamos usando nuestra convencin que permite a una transicin
simple meter ms de un smbolo a la pila. En particular, w puede ser una cadena de cero
o ms smbolos incluyendo terminales y no terminales).
6. Introduzca una transicin de la forma ) , ; , , ( q x x q para cada Terminal x en G (es
decir, para cada smbolo en el alfabeto de M).
7. Introduzca la transicin ) , ; # , , ( f q .
Veamos el teorema anterior aplicado a la siguiente gramtica:
z N
bNb N
z M
aMa M
zMNz S


1. Sea } # , , , , , , { b a z N M S = E el alfabeto.
2. Designamos los estados q p q , ,
0
y f , siendo
0
q el estado inicial y f el nico estado de
aceptacin (Fig. 48).

Fig. 48: Estados del PDA
3. Introducimos la transicin ) # , ; , , (
0
p q , es decir, una transicin de
0
q a p que tenga
como entrada el par ) , ( y como salida el smbolo # que ser introducido a la pila
(Fig. 49).
Compiladores Nicandro Cruz Ramrez
47

Fig. 49: Introduccin de la primera transicin ) # , ; , , (
0
p q
4. Introducimos la transicin ) , ; , , ( S q p , donde S es el smbolo inicial en G, es decir,
una transicin de p a q , que tiene como entrada el par ) , ( y como salida el smbolo
S , que ser metido a la pila (Fig. 50).

Fig. 50: Introduccin de la segunda transicin ) , ; , , ( S q p
5. Introducimos una transicin de la forma ) , ; , , ( w q N q para cada regla de reescritura
w N en G. Para nuestro ejemplo, introduciremos las transiciones ) , ; , , ( zMNz q S q ,
) , ; , , ( aMa q M q , ) , ; , , ( z q M q , ) , ; , , ( bNb q N q , ) , ; , , ( z q N q (Fig. 51).

Fig. 51: Introducir transiciones por cada regla de produccin
6. Introducimos una transicin de la forma ) , ; , , ( q x x q para cada Terminal x en G, en
nuestro caso, los terminales son a , b y z (Fig. 52).

Fig. 52: Introducir una transicin por cada smbolo terminal
7. Introducir la transicin ) , ; # , , ( f q , es decir, la transicin que une al estado q con el
estado f (Fig. 53).
Compiladores Nicandro Cruz Ramrez
48

Fig. 53: PDA para la gramtica dada.
De esta manera hemos comprobado que para cada CFG existe un PDA M tal que
) ( ) ( M L G C =
Una tabla parse para un parser LL(1) es un arreglo bidimensional. Los renglones se
etiquetan con los no terminales de la gramtica y las columnas con los terminales de la gramtica
ms una columna adicional llamada EOS (End Of String).
La ) , ( n m -sima entrada de la Tabla 7 indica que accin debe llevarse a cabo cuando el
no-terminal m aparece hasta arriba de la pila y el smbolo hacia delante es n .
z N
bNb N
z M
aMa M
zMNz S


Fig. 54: Gramtica


a b z EOS
S ERROR ERROR zMNz ERROR
M aMa ERROR Z ERROR
N ERROR bNb z ERROR
Tabla 7: Tabla parse LL(1) para la gramtica de la izquierda

push (s)
read (symbol)
while (snack_not_empty) do
case top_of_stack of
terminal: if top_of_stack = symbol then
pop stack and read (symbol.)
else
exit_to_error_routine;
non-terminal: if table[top_of_stack, symbol]
error then
replace top_of_stack with
table[top_of_stack, symbol]
else
exit_to_error_routine;
end-case
end-while
if symbol not end_of_string marker then
exit_to_error_routine

Tabla 8: Rutina parse LL(1) genrica
Compiladores Nicandro Cruz Ramrez
49
1. Ejercicio 1: Dibujar el PDA correspondiente a la gramtica:

S
y S x S
(Fig. 55)

Fig. 55: PDA del Ejercicio 1
2. Ejercicio 2: Dibujar el PDA correspondiente a la gramtica:

S
z S y S
z S x S
(Fig. 56)

Fig. 56: PDA del ejercicio 2
3. Ejercicio 3: Dibujar el PDA correspondiente a la gramtica:
y x S
y S x S

(Fig. 57)

Fig. 57: PDA del ejercicio 3

Teorema: Para cada CFG existe un PDA M tal que L(G) = L(M)
Demostracin
1. Establecer cuatro estados, un estado inicial llamado
0
q , un estado final llamado f y
otros dos estados p , q .
2. Introduzca la transiciones ) # , ; , , (
0
p q y ) , ; # , , ( f q , donde asumimos que # es
un smbolo que no ocurre en la gramtica.
Compiladores Nicandro Cruz Ramrez
50
3. Para cada smbolo Terminal x de la gramtica, introduzca la transicin ) , ; , , ( x p x p .
Estas transiciones permiten al autmata transferir los smbolos de entrada a la pila,
mientras que permanece en el estado p . La ejecucin de esta operacin de llama
operacin de cambio (shift operation), ya que su efecto es cambiar un smbolo de la
entrada a la pila.
4. Para cada regla de reescritura w N (donde w representa una cadena de 1 o ms
smbolos) de la gramtica, introduzca la transicin ) , ; , , ( N p w p (aqu permitimos a
una transicin remover ms de un smbolo de la pila). As que para ejecutar la transicin
) , ; , , ( z p y x p

un autmata debe tener una y hasta arriba de la pila con una x debajo
de ella. La presencia de stas transiciones significa que si los smbolos de la parte de ms
arriba de la pila concuerdan con el lado derecho de una regla de reescritura entonces
dichos smbolos pueden reemplazarse con el nico no-terminal del lado izquierdo de esa
regla. La ejecucin de tal transicin se llama operacin de reduccin (reduce operation)
ya que su efecto es el de reducir el contenido de la pila a una forma ms simple.
5. Introduzca la transicin ) , ; , , ( q S p donde S es el smbolo inicial de la gramtica.
Veamos el teorema anterior aplicado a la siguiente gramtica:
z N
bNb N
z M
aMa M
zMNz S


1. Establecer cuatro estados, un estado inicial llamado
0
q , un estado final llamado f y
otros dos estados p , q (Fig. 58).

Fig. 58: Establecimiento de 4 estados
2. Introducir las transiciones ) # , ; , , (
0
p q y ) , ; # , , ( f q , donde asumimos que # es
un smbolo que no ocurre en la gramtica (Fig. 59).

Fig. 59: Primeras dos transiciones
3. Para cada smbolo Terminal x de la gramtica, introduzca la transicin ) , ; , , ( x p x p .
La ejecucin de esta operacin de llama operacin de cambio (shift operation), ya que
su efecto es cambiar un smbolo de la entrada a la pila (Fig. 60).
Compiladores Nicandro Cruz Ramrez
51

Fig. 60: Una transicin por cada smbolo terminal
4. Para cada regla de reescritura w N (donde w representa una cadena de 1 o ms
smbolos) de la gramtica, introduzca la transicin ) , ; , , ( N p w p (Fig. 61)

Fig. 61: Una transicin por cada regla gramatical
5. Introducir la transicin ) , ; , , ( q S p donde S es el smbolo inicial de la gramtica (Fig.
62).

Fig. 62: ltima transicin
Compiladores Nicandro Cruz Ramrez
52
3.1 Construccin de tablas parse LR(1)
z N
bNb N
z M
aMa M
zMNz S


Fig. 63: Gramtica
1. Introducir un nuevo smbolo inicial ' S y una nueva regla S S ' .
2. Introducimos el marcador ^ para indicar el estatus del proceso de
anlisis sintctico. Por ejemplo, usando el marcador podemos
escribir: MNz z S ^ para indicar que se ha ledo la primera z y se
prepara para leer el resto de la regla: MNz
terminal Forma ^
^
^
^
inicial Forma ^
zMNz S
z zMN S
Nz zM S
MNz z S
zMNz S


3. Cerradura de un conjunto de reglas marcadas. Formamos dicha cerradura al encontrar
primero todos los no-terminales que aparezcan de inmediato a la derecha de un marcador en
alguna regla del conjunto.
Entonces aadimos al conjunto las formas iniciales de todas las reglas de la gramtica
cutos lados izquierdos consistan en esos no-terminales. Si algunas de estas reglas aadidas
tienen no-terminales que aparezcan inmediatamente a la derecha de un marcador, agregamos
las formas iniciales de esas reglas para esos no-terminales tambin. Continuamos ste
proceso hasta que algn no-terminal nuevo aparezca inmediatamente a la derecha de un
marcador.
Cul es la cerradura del conjunto que contiene a las 2 reglas
Ma a M
Nz zM S
^
^

?
Respuesta: z M Ma a M z N bNb N Ma a M Nz M S < , ^ , ^ , ^ , ^ , ^
Algoritmo para construir el FA que servir de base para la tabla parse LR(1)
1. Forme la cerradura del conjunto que contiene solamente la regla marcada ' ^S S .
Establezca este conjunto como el estado inicial del diagrama de transicin.
2. Mientras sea posible, sin redundancia haga lo siguiente:
a. Seleccione un smbolo s (Terminal o no-terminal) que aparezca inmediatamente a la
derecha del marcador en una regla de algn estado A.
b. Sea X la coleccin de todas las reglas marcadas en A que tengan s inmediatamente
a la derecha de sus marcadores.
c. Sea Y el conjunto de reglas marcadas obtenidas al mover el marcador de cada regla
en X a la derecha del smbolo s .
d. Si la cerradura de Y no se ha establecido como estado, hgalo.
e. Dibuje un arco etiquetado como s desde A hacia la cerradura de Y .
3. Sea cada estado representado por reglas marcadas en su forma Terminal, un estado de
aceptacin en el autmata.
Compiladores Nicandro Cruz Ramrez
53
Ejercicio: Construir el AF para la gramtica
y S
z S x S


1. Introducimos un nuevo smbolo inicial ' S y una nueva regla S S ' , as como un
marcador que indique la forma inicial de cada regla gramatical.
y S
z S x S
S S
^
^
^ '


2. Formamos la cerradura de la regla S S ^ ' , sta servir como primer estado (Fig. 64).

Fig. 64: Estado inicial del FA cerradura de S S '
3. Seleccionamos S s = , con lo cual } ^ ' { S S X = y } ^ ' { S S Y = , observamos que
^ ' S S se encuentra en su forma Terminal, con lo cual Y Y = . Agregamos ese nuevo
estado (estado 2) y una transicin a l con el smbolo S (Fig. 65).

Fig. 65: Segundo estado
4. Escogemos para el estado 1 x s = , con lo cual } ^ { z S x S X = y } ^ { z S x S Y = .
Obtenemos la cerradura de Y .
} , ^ , ^ { y S z S x S z S x S Y =
Como no existe un estado con esas reglas gramaticales se agrega al AF (estado 3), junto
con una transicin de 1 a 3 para el smbolo x (Fig. 66).
Compiladores Nicandro Cruz Ramrez
54

Fig. 66: Tercer estado
5. Sea y s = , el ltimo smbolo para el estado 1. Por lo que } ^ { y S X = , } ^ { y S Y = ,
con lo que Y Y = . Como Y no se encuentra en el AF lo agregamos (estado 4). Como
adems la regla se encuentra en su estado Terminal, el estado 4 ser de aceptacin (Fig.
67).

Fig. 67: Estado 4 del AF
6. Como ya no existen ms smbolos en el estado 1 y el estado 2 ya es un estado de
aceptacin, hacemos el mismo proceso para el estado 3.
Sea S s = , con lo cual } ^ { z S x S X = y } ^ { z S x S Y = . Debido a que no
existen reglas de produccin que comiencen con smbolos terminales Y Y = . Como Y no
existe como estado en el AF se agrega (estado 5), junto con una transicin del estado 3 al
estado 5 con el smbolo S (Fig. 68).

Fig. 68: Estado 5 del AF
7. Sea x s = , con lo cual } ^ { z S x S X = y } ^ { z S x S Y = . De lo cual
} ^ , ^ , ^ { y S z S x S z S x S Y = que es el mismo estado 3. Con lo cual, slo
agregamos una transicin a l mismo con el smbolo x (Fig. 69).
Compiladores Nicandro Cruz Ramrez
55

Fig. 69: Transicin x
8. Sea y s = , con lo cual } ^ { y S X = y Y y S Y = = } ^ { que es el estado 4, con lo
cual, agregamos una transicin del Estado 3 al estado 4 con el smbolo y (Fig. 70).

Fig. 70: Transicin del estado 3 al estado 4 con
9. Como ya no existen ms smbolos en el estado 3 y el estado 4 ya es un estado de
aceptacin, hacemos el mismo proceso para el estado 5.
Sea z s = , con lo cual } ^ { z S x S X = y Y z S x S Y = = } ^ { . Como no
existe Y en el AF se agrega como estado (estado 6), junto con una transicin con el
smbolo z . Como adems es una regla en su estado terminal, el estado 6 es un estado de
aceptacin (Fig. 71).

Fig. 71: Ultimo estado del AF
Compiladores Nicandro Cruz Ramrez
56
3.2 Anlisis sintctico LALR(1)
Este anlisis est basado en la observacin de que en muchos casos el tamao del DFA
de conjuntos de elementos LR(1) se debe en parte a la existencia de muchos estados diferentes
que tienen el mismo conjunto de primeros componentes en sus elementos, mientras que difieren
slo en sus segundos componentes (los smbolos de bsqueda hacia adelante).
El algoritmo de anlisis sintctico LALR(1) expresa el hecho de que tiene sentido
identificar todos esos estados y combinar sus bsquedas hacia delante. Al hacerlo as, siempre
debemos finalizar con un DFA que sea idntico el DFA de los elementos LR(0) excepto si cada
estado se compone de elementos con conjuntos de bsqueda hacia delante.
Considere la siguiente gramtica: a A A | ) (

Fig. 72: LR(0)

Fig. 73: Otra figura

3.2.1 Primer principio del anlisis sintctico LALR(1)
El ncleo de un estado del DFA de elementos LR(1) es un estado del DFA de elementos
LR(0).
3.2.2 Segundo principio del anlisis sintctico LALR(1)
Dados dos estados
1
s y
2
s del DFA
de elementos LR(1) que tengan el mismo
ncleo, suponga que hay una transicin con
el smbolo x desde
1
s a un estado
1
t .
Entonces existe tambin una transicin con
x del estado
2
s al estado
2
t , y los estados
1
t
y
2
t tienen el mismo ncleo.
Considere la siguiente gramtica
a A A | ) ( cuyo DFA es:



Compiladores Nicandro Cruz Ramrez
57
Fig. 74: DFA de a A A | ) (

A a ( ) $
0 1 3 2
1
2
3 4 2 3
4 5
5
Tabla 9: Tabla LALR(1)
Algn texto


Fig. 75: LR(1)

A a ( ) $
0 1 3 2
1 ACCEPT
2 4 6 5
3 Aa
4 Aa,)
5 8 6 5
6 Aa,)
7 A(A) A(A)
8 8
9 A(A)
Tabla 10: Tabla LR(1)
3.3 Anlisis sintctico LR(1) cannico
3.3.1 Autmatas finitos de elementos LR(1)
La dificultad con el mtodos SLR(1) es que aplica las bsquedas hacia delante despus
de construir el DFA de elementos LR(0), una construccin que ignora bsquedas hacia adelante.
La potencia del mtodo LR(1) general (cannico) se debe a que utiliza un nuevo DFA que tiene
las bsquedas integradas en su construccin desde el inicio.
Este DFA utiliza elementos que son una extensin de los elementos LR(0) se conocen
como elementos LR(1), es un par compuesto de un elemento LR(0) un token de bsqueda hacia
adelante simple en cada elemento. Ms exactamente, un elemento LR(1) es un par compuesto de
un elemento LR(0) y un token de bsqueda hacia adelante. Escribimos elementos LR(1)
utilizando corchetes como:
] , [ a A | o
Donde | o A es un elemento LR(0) y a es un token (la bsqueda hacia adelante)
Compiladores Nicandro Cruz Ramrez
58
Para completar la definici+on del autmata utilizado para el anlisis sintctico LR(1)
general, necesitamos definir las transiciones LR(0), excepto por que tambin se mantienen al
tanto de las bsquedas hacia delante. Como con los elementos LR(0) que incluyen transiciones
c , es necesario construir un DFA cuyos estados sean conjuntos de elementos que sean
cerraduras c . La diferencia principal entre los autmatas LR(0) y LR(1) viene en la definicin
de las transiciones c . Daremos primero la definicin del caso ms fcil (las transiciones no c ),
que son esencialmente idnticas a las correspondientes al caso LR(0).
3.3.3 Definicin de transiciones LR(1) (parte 1)
Dado un elemento LR(1) ] , [ a X A o donde X es cualquier smbolo (Terminal o
no-terminal), existe una transicin con X al elemento ] , [ a X A o .
Observe que en este caso la misma a de bsqueda hacia adelante aparece en ambos
elementos. De este modo, estas transiciones no provocan la aparicin de nuevas bsquedas hacia
adelante. Slo las transiciones c crean nuevas bsquedas hacia delante de la manera siguiente:
- Dado un elemento LR(1) ] , [ a B A o , donde B es un no Terminal, existen
transiciones c para elementos ] , [ b B | para cada produccin | B y para cada
token b en ) ( Pr a imero
- Un elemento LR(0) de una CFG es una regla de produccin con una posicin distinguida
en su lado derecho. Indicaremos esta posicin distinguida mediante un punto. De este
modo si o A es una regla de produccin, y si | y son dos cadenas cualesquiera de
smbolos (incluyendo c ), tales como o | = , entonces | A es un elemento LR(0).
Estos se conocen como elementos LR(0), por que no contienen referencia explcita a la
bsqueda hacia delante.
Considere la siguiente CFG

Fig. 76: Algn ttulo
c

S
S S S
S S
) (
'






S S S S
S S S S S S
S S S S S S
S S S S
) (
) ( ) (
) ( ) (
' '


Compiladores Nicandro Cruz Ramrez
59

Fig. 77: Algn ttulo
3.4 Conjuntos primero
Si x es un smbolo de la gramtica (terminal o no-terminal) o c , entonces el conjunto
) (x primero compuesto de terminales y posiblemente de c , se define de la siguiente manera:
1. Si x es un terminal o c , entonces } { ) ( x x primero =
2. Si x es un no-terminal entonces, para cada seleccin de produccin
n
x x x x , , ,
2 1
,
) (x primero contiene } { ) (
1
c x primero . Si tambin para cualquier n i < , todos los
conjuntos ) ( , ), (
1 n
x primero x primero , ) (
1
x primero contiene c , entonces ) (x primero
contiene } { ) (
1
c
+ i
x primero . Si todos los conjuntos ) ( , ), (
1 n
x primero x primero
contienen c , entonces ) (x primero tambin contiene c
Ahora definamos ) (o primero para cualquier cadena
n
x x x
2 1
= o (una cadena de
terminales y no-terminales) de la siguiente manera.
- ) (o primero contiene } { ) (
1
c x primero para cada n i , , 2 = . Si ) (
k
x primero contiene
c para toda 1 , , 1 = i k , entonces ) (o primero contiene } { ) ( c
i
x primero .
Finalmente, si para toda n i , , 1 = , ) (
i
x primero contiene c , ) (o primero contiene c .
Algoritmo simplificado para calcular ) (A primero para todos los no-terminales A en
ausencia de producciones c (Tabla 11).
for todos_los_no_terminales_A do
{}; : ) ( = A primero
while existan_cambios_para_cualquier_primero(A) do
for cada_seleccion_de_produccin
n
x x x A
2 1
do
Agregue ) (
1
x primero a ) (A primero ;
Tabla 11: Algoritmo
Calcular los conjuntos ) (A primero para la siguiente CFG
Compiladores Nicandro Cruz Ramrez
60
nmero factor
factor
opMult
opMult
factor term
factor opMult term term
opSuma
opSuma
term
term opSuma

(exp)
/
*
exp
exp exp

Algoritmo para calcular ) (A primero para todos los no-terminales A (Tabla 12).
for todos_los_no_terminales_A do
{}; : ) ( = A primero
while existan_cambios_para_cualquier_primero(A) do
for cada_seleccion_de_produccin
n
x x x A
2 1
do
; 1 := k
; : verdadero continuar =
While (continuar=verdadero) and ( n k <= ) do
agregue } { ) ( c
k
x primero a ) (A primero ;
if ( ) (
k
x primero e c ) then
continuar:=falso;
k=k+1;
if(continuar=verdadero) then
agregue c a ) (A primero ;
Tabla 12: Algn ttulo
Compiladores Nicandro Cruz Ramrez
61
4. Anlisis Lxico
4.1 Planteamiento del problema
Ada es un lenguaje de programacin orientado a objetos, diseado por Jean Ichbiah de CII
Honeywell Bull por encargo del Departamento de Defensa de los Estados Unidos. Los siguientes
son tokens de un muy pequeo subconjunto de ADA:comienza
- termina
- ;
- :=
- +
- -
- *
- /
- (
- )
- mod
- rem
- identificadores
- enteros

Se pretende realizar un Analizador Lxico para determinar las clasificaciones de los tokens
anteriores como sigue:
1. Un identificador se ha definido como una letra seguida por un nmero arbitrario de letras
o dgitos

2. Las palabras comienza y termina son palabras reservadas.

3. Los smbolo punto y coma (;), parntesis abierto y parntesis cerrado son smbolos
permitidos.

4. Un entero ha sido definido como un dgito seguido por una secuencia de dgitos

5. Los smbolos + y - han sido denominados como OpSuma

6. Los smbolos *, / y las palabras mod y rem sern identificados como OpMultiplicacion.

7. El smbolo := se defini como Asignacin.
En la etapa de pruebas se ejecutar el analizador lxico en (a) el programa siguiente, y (b)
un programa arbitrario.
comienza
a:=b3;
xyz := a + b + c
-p / q;
a := xyz * (p + q);
p:= a - xyz - p;
termina;
La salida esperada es la siguiente:
Tipo Lexema
Palabra clave comienza
Identificador a
Asignacin :=

Compiladores Nicandro Cruz Ramrez
62
5. Anlisis sintctico
5.1 Planteamiento del problema
Considere la siguiente gramtica
Programa Comienza SecuenciaDeSentencias termina; ; aZb S
SecuenciaDeSentencias Sentencia{Sentencia} Y Z
Sentencia SentenciaSimple X Y
SentenciaSimple SentenciaDeAsignacion W X
SentenciaDeAsignacion Nombre:=Expresion; ; : E V W =
Nombre NombreSimple T V
NombreSimple Identificador c T
Expresion Relacin R E
Relacion ExpresionSimple Q R
ExpresionSimple Termino{OpSuma Termino} PMP Q
Termino Factor{OpMul Factor} FNF P
Factor Primario L F
Primario Nombre V L
Primario LiteralNumerica K L
Primario (Expresion) ) (E L
OpSuma + + M
OpSuma - M
OpMul * * N
OpMul / / N
OpMul Mod m N
OpMul rem r N
LiteralNumerica LiteralDecimal J K
LiteralDecimal Entero e J
Tabla 13: Gramtica
Disee un analizador sintctico LR(1) que implementar esta gramtica. Ejecute su
analizador sintctico con el programa siguiente, y en un programa de su propio diseo:
comienza
a:=b3;
xyz := a + b + c
-p / q;
a := xyz * (p + q);
p:= a - xyz - p;
termina;

You might also like