4. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 2
Obje6vos Generales
Obje8vos Generales
› Poner en contexto y justificar la relevancia de la compilación
› Aprender la diferencia entre compiladores y traductores
› Entender la diferencia entre compiladores e interpretes
› Apreciar el contexto en el que trabaja un compilador
› Apreciar cómo interactúan sus partes
› Entender la responsabilidad de cada una de ellas
› Analizar diferentes configuraciones alternativas
› Conocer el proceso completo de compilación
› Entender la responsabilidad de cada una de sus fases
› Obtener una visión general de las técnicas empleadas en cada una
› Aprender los principales artefactos que dan soporte a la compilación
› Discutir sobre la portabilidad de compiladores
5. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 3
Índice
Índice
› Introducción
› Traductores y compiladores
› Compiladores e interpretes
› Contexto de compilación
› Proceso de compilación
› Fases de compilación
› Etapas de compilación
› Artefactos de compilación
› Análisis de compiladores
› Representación de compiladores
› Tipos de compiladores
› Portabilidad de compiladores
› Práctica
6. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 4
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
I. Arquitecturas Von Neumann
› Representación del programa como instrucciones en memoria
› La unidad de control va leyéndolo secuencialmente
› Cada instrucción tiene un código de operación y unos operandos
› Operaciones aritmético lógicas, comparativas, de salto, de E/S,…
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
Código de operación
Operando 1
Operando 2
* En esta descripción se han omitido muchos paradigmas
7. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 5
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
II. Paradigma ensamblador
› Los códigos de operación se sustituyen por acrónimos
› Los operandos se sustituyen por registros y referencias a memoria
› El juego de instrucciones sigue siendo el mismo
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX [1305]
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
MOVE AX #2
MOVE BX [1305]
MUL CX AX BX
Acrónimo de operación
Operando 1 de tipo registro
Operando 2 de tipo literal numérico
Operando 2 referencia a memoria
* En esta descripción se han omitido muchos paradigmas
8. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 6
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
III. Paradigma estructurado impera8vo
› Flujo de ejecución secuencial
› Metáfora de variables y operación de asignación
› Tipificación de los datos
› Estructuras de control iterativas y condicionales (no de salto)
› Subrutinas para modularizar los programas
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
b (x, y);
C (x, y);
if (x > y) f (x);
else g (y);
while (x = y) {
d (x, y);
e (x, y);
}
* En esta descripción se han omitido muchos paradigmas
9. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 7
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
IV. Paradigma concurrente
› Varios flujos de ejecución secuencial asociados a procesos
› Es necesario cuidar el acceso concurrente a recursos
› Mecanismos de exclusión mutua y de sincronización por condición
› Para cada proceso el algoritmo sigue siendo imperativo
› Existen lenguajes concurrentes funcionales
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
x
lector lector lector
Leer x
lector lector escritor
Escribir x
* En esta descripción se han omitido muchos paradigmas
10. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 8
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
V. Paradigma funcional declara8vo
› Únicamente declaración de funciones
› El resultado de una expresión depende sólo de sus sub-expresiones
› No hay efectos colaterales en la evaluación funcional
› No existe asignación ni estructuras de control
› Se da soporte a la definición recursiva de funciones
› Las funciones se usan como datos (orden superior, currificación,…)
› Operaciones map / reduce
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
fun invertir (l) =
[] -> []
| (p: resto) -> invertir(resto): p
* En esta descripción se han omitido muchos paradigmas
11. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 9
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
VI. Paradigma de orientación a objetos
› Las operaciones acompañan a las estructuras de datos
› Clases con bajo acoplamiento y fuerte cohesión
› El algoritmo se encuentra distribuido en la colaboración entre objetos
› Herencia, polimorfismo, ligadura dinámica y genericidad
› Los objetos se gestionan en el heap
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
for (i in [2..n])
for (j in [0..n-1])
if (c.mayor (a[j], a[j+1]))
intercambiar (a[j], a[j+1])
* En esta descripción se han omitido muchos paradigmas
Lista
- ordenar ()
Comparador
- mayor (x, y)
ComparadorA
ComparadorB
usa
12. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 10
Traductores y compiladores
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
¿Qué es un compilador?
Para dar soporte a este proceso de abstracción es necesario idear
programas capaces de traducir las expresiones abstractas en
secuencias de instrucciones máquina interpretables por un
ordenados
Definición
Un compilador es un programa que lee un programa escrito en
lenguaje fuente, y lo traduce a un lenguaje objeto de bajo nivel.
Además generará una lista de los posibles errores que tenga el
programa fuente
Compilador
Lenguaje
fuente
Lenguaje
objeto
Compilador
13. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 11
Traductores y compiladores
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
¿Qué es un traductor?
Cuando lo que se pretende es cambiar la expresión sintáctica de un
programa de un lenguaje de alto nivel a otro no hablamos de
compilador sino de traductor
Definición
Un traductores un programa que lee un programa escrito en
lenguaje fuente de alto nivel, y lo traduce a un lenguaje objeto
también de alto nivel.
Traductor
Lenguaje
fuente
Lenguaje
objeto
fact = 1;
for (int i = 0; i <= 10; i++)
fact *= i;
Pascal C
traductor
14. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 12
Traductores y compiladores
Traductores y compiladores
I. Traductor
II. Compilador
Un compilador es un programa que lee un programa escrito en
lenguaje fuente, y lo traduce a un lenguaje objeto de bajo nivel.
Además generará una lista de los posibles errores que tenga el
programa fuente
Un traductores un programa que lee un programa escrito en
lenguaje fuente de alto nivel, y lo traduce a un lenguaje objeto
también de alto nivel.
Compilador
Lenguaje
fuente
Lenguaje
objeto
Traductor
Lenguaje
fuente
Lenguaje
objeto
}
Foco de atención principal de la
asignatura
15. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 13
Compiladores e interpretes
Compiladores e interpretes
I. Compilador
Un compilador es un artefacto software capaz de
generar un programa ejecutable a partir de un
programa escrito en un lenguaje de alto nivel
II. Interprete
Un interprete es un artefacto software capaz de
ir interpretando secuencialmente la colección de
instrucciones de un programa escrito en un
lenguaje de alto nivel para ejecutarlas
› Se obtiene un fichero ejecutable
› El proceso de compilación se realiza sólo una vez
› El proceso de compilación es más lento
› Mayor consumo de memoria
› Mayor cantidad de detalles de errores de compilación
› Mayor velocidad de ejecución del programa ejecutable
› Los errores en ejecución se minimizan
› No se obtiene un fichero ejecutable
› El proceso de interpretación se realiza cada vez
› El proceso de interpretación es más rápido
› Menor consumo de memoria
› Menor cantidad de detalles de errores de compilación
› Menor velocidad de ejecución del programa ejecutable
› Los errores en ejecución son mayores
16. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 14
Contexto de compilación
I. Precompilador
Algunos compiladores incluyen precompiladores capaces de hacer un tratamiento
preliminar del fichero fuente para prepararlo para el proceso de la compilación. Esta
herramienta suele eliminar comentarios, sustituir constantes simbólicas por sus valores
literales, o extender en el código fuente las macros definidas
II. Compilador
El compilador es el programa encargado de realizar el proceso de traducción del
programa fuente para expresarlo en términos de una secuencia de instrucciones de
código máquina interpretables por un ordenador
}
Foco de atención
principal de la
asignatura
III. Enlazador o montador
El producto resultante del compilador no es un fichero directamente ejecutable en la
arquitectura. Muchas funciones, invocadas desde el programa fuente, y cuyo código se
encuentra programado y compilado en otro fichero deben ser incorporadas al fichero
resultante de la compilación para que sea autónomo. De esto se encarga el montador
Elementos del contexto de la compilación
17. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 15
Contexto de compilación
Elementos del contexto de la compilación
IV. Enlazador dinámico
Con el ánimo de que los programas finales no sean muy pesados, muchas funciones
externas no se incluyen en el ejecutable final sino que son enlazadas dinámica y
automáticamente por el sistema operativo, que se encarga de gestionarlas. Como
consecuencia los ejecutables son más pequeños pero establecen dependencias con
recursos que han de estar presentes en el sistema operativo
V. Depurador
Los errores producidos en tiempo de compilación son reportados por el compilador para
su corrección. Sin embargo los ocurridos en tiempo de ejecución pueden ser más
difíciles de detectar. Es necesario hacer ejecuciones paso a paso para comprobar el
estado que va tomando cada variable del programa. El depurador ayuda a realizar este
tipo de trazas
VI. Ensamblador
A veces los compiladores no generan programas directamente ejecutables en código
máquina sino ficheros que corresponden a la expresión en ensamblador del código
fuente. Esto puede ser tremendamente útil - aunque en la actualidad no frecuente –
para permitir al programador optimizar los resultados generados por el compilador
18. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 16
Contexto de compilación
Ejecutable DOS
Ejecutable Windows
.C .H
Precompilador
.I .ASM
Compilador Ensamblador
.OBJ .OBJ .OBJ
Enlazador
. LIB
.ASM .EXE .EXE Ensamblador
Enlazador dinámico
. DLL
Proceso
Recurso
Compilador de C
19. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 17
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que
convierte un programa escrito en un lenguaje fuente de alto nivel en
otro programa escrito en un lenguaje objeto de bajo nivel. Ese
proceso se articula conceptualmente en una secuencia de fases
› Análisis léxico
› Análisis sintáctico
› Análisis semántico
› Generación de código intermedio
› Generación de código final
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Código final
e · l · i · h · w <WHILE, PR> S
WHILE E DO S
E > E
S
WHILE E DO S
E > E
√ LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
While ( a > b ) do
a := a + 1;
20. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 18
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador léxico
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
I. Análisis léxico
El analizador léxico (scanner) va leyendo caracteres del fichero hasta
encontrar una entidad con significado léxico. Estas entidades se llaman
tokens y son una estructura de datos que contiene información acerca
del mismo (tipo, lexema, número de fila y columna, valor, etc.)
La construcción de analizadores léxicos suele hacerse mediante
herramientas que hay que configurar indicando el tipo de token que es
necesario emitir para cada posible patrón léxico
while : <WHILE, PR>
do : <DO, PR>
l (l | d)* : <a, ID>
...
21. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 19
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador sintác8co
<WHILE, PR>
II. Análisis sintác8co
El analizador sintáctico (parser) va pidiendo tokens al analizador léxico
y los va organizando en frases de acuerdo a las reglas de construcción
gramatical del lenguaje. Como resultado genera un árbol de análisis
sintáctico que representa todo el programa en memoria
La construcción de analizadores sintácticos suele hacerse mediante
herramientas que hay que configurar indicando la colección de reglas
sintácticas que definen las construcciones del lenguaje gramaticalmente
correctas
S ::= SIf | Swhlile | ...
SWhile ::= while PI E PD
do S;
E ::= E + E
E ::= E * E
E ::= E > E
E ::= E < E
E ::= id
...
SWhile
WHILE E DO S
E > E
<a, ID>
<>, GT>
<b, ID>
<DO, PR>
<a, ID>
<:=, ASIG>
...
<(, PI>
<), PD>
22. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 20
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador
semán8co
III. Análisis semán8co
El analizador semántico se encarga de gestionar la declaración de
constantes, funciones, procedimientos y variables y de comprobar la
corrección de tipos a lo largo de todo el programa. Como resultado se
obtiene un árbol de análisis sintáctico anotado, con atributos en cada
uno de sus nodos
La implementación del analizado semántico se realiza insertando
acciones semánticas en las partes derechas de las reglas de
producción gramatical
S ::= SIf | Swhlile | ...
SWhile ::= while PI E PD
do S;
{: if (E.tipo != booleano) error (); :}
...
SWhile
WHILE E DO S
E > E
SWhile
WHILE E DO S
E > E
√
23. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 21
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Código intermedio
IV. Generación de código intermedio
El generador de código intermedio traduce la representación
arborescente del programa en una secuencia ordenada de instrucciones
llamadas cuádruplas próximas al lenguaje máquina. Se trata de un
lenguaje abstracto y genérico que aún mantiene las referencias
simbólicas a los elementos declarados en el programa (variables,
parámetros, funciones, etc.)
La implementación del generador de código intermedio se realiza
insertando acciones en las partes derechas de las reglas de producción
que acumulan la traducción parcial del subárbol en cada nodo
exp ::= exp:e1 > exp:e2
{:...
e.código = e1.código +
e2.código +
CMP e1.temp r2.temp e.temp
:};
SWhile
WHILE E DO S
E > E
√
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
24. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 22
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Op8mización Código
intermedio
V. Op8mización de código intermedio
En los compiladores comerciales es frecuente optimizar el resultado de
la fase anterior para hacer el programa más compacto y más rápido.
Suelen aplicarse estrategias de transformaciones heurísticas y
elementales que ofrecen buenos resultados
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
√
WHILE (A>B) AND (A<2*B-5) DO
A:=A+B
L1: IF A>B GOTO L2
GOTO L3
L2: T1 := 2*B
T2 := T1 – 5
IF A< T2 GOTO L4
GOTO L3
L4: A := A + B
GOTO L1
L3: ...
Optimización
Código intermedio
L1: IF A<=B GOTO L2
T1 := 2*B
T2 := T1 – 5
IF A>= T2 GOTO L2
A := A + B
GOTO L1
L2: …
25. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 23
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
VI. Código final
Una vez que el código intermedio ha sido generado y optimizado
pueden resolverse las referencias simbólicas a posiciones de memoria
física y a recursos de la máquina (registros, pila, etc.). Además debe
traducirse cada cuarteto a sus equivalentes instrucciones en código
máquina
La traducción a código final se encarga de hacerla una rutina de
traducción ubicada en la acción semántica final ubicada al final de la
regla de producción del axioma
Código final
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
26. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 24
Proceso de compilación
Etapas de compilación
› Expertos en lenguajes
› Independencia de arquitectura
› Dependencia de lenguaje
› Optimización de lenguajes
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Código final
e · l · i · h · w <WHILE, PR> S
WHILE E DO S
E > E
S
WHILE E DO S
E > E
√ 0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
While ( a > b ) do
a := a + 1;
Etapa de análisis Etapa de síntesis
› Expertos en arquitecturas
› Dependencia de arquitectura
› Independencia de lenguaje
› Optimización de ejecución
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
27. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 25
Proceso de compilación
Equipos de compilación
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
While ( a > b ) do
a := a + 1;
EquipodeLenguaje
Op8mización Código
intermedio
Código final
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Op8mización Código
intermedio
Código final
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
Equipode
arquitectura
Pascal C
Intel Solaris
Código intermedio
M
N
x
…
…
while ( a > b )
a++;
28. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 26
Proceso de compilación
Artefactos de compilación
A lo largo de todo el proceso de compilación se una colección de
artefactos para dar soporte al mismo. A lo largo del curso los
estudiaremos en detalle. Dos son de vital importancia
I. Tabla de símbolos
La tabla de símbolos se utiliza para gestionar todos los elementos
declarados por programador (constantes, tipos, variables, funciones y
procedimientos)
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Op8mización Código
intermedio
Código final
Tabla de símbolos
Analizador léxico En compiladores antiguos utilizado para
reconocer palabras clave
Analizador semántico Registra los elementos declarados por
el programador y los consulta para
efectuar la comprobación de tipos
Código intermedio Se consulta para conocer el espacio de
memoria que debe reservarse para
gestionar la activación de subrutinas y
para determinar el ámbito de
declaración de los elementos
Código final Se utiliza para traducir las referencias
simbólicas a posiciones de memorial
Fase Descripción
29. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 27
Proceso de compilación
Artefactos de compilación
A lo largo de todo el proceso de compilación se una colección de
artefactos para dar soporte al mismo. A lo largo del curso los
estudiaremos en detalle. Dos son de vital importancia
II. Gestor de errores
Las tres primeras fases pueden generar errores durante el proceso de
compilación. El gestor de errores se encarga de emitir mensajes de
los mismos para informar al programador
Gestor de errores
Analizador léxico
Carácter ñ no válido
Whiñe ( a > b ) do
a := a + 1;
Analizador sintác8co
Analizador
semán8co
SWhile ::= WHILE e DO s
Analizador léxico
While ( a > b )
a := a + 1;
Analizador sintác8co
Analizador léxico
While ( a > b ) do
a := a + ‘c’;
Se esperaba un
entero en expresión
de suma
30. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 28
Análisis de compiladores
Representación de un compilador
Como se ha discutido a lo largo del tema un compilador es una máquina de transformación
capaz de traducir un programa escrito en un lenguaje fuente a otro programa escrito en otro
lenguaje objeto. A su vez, éste está implementado en un tercer lenguaje llamado lenguaje
anfitrión. Por tanto, para representar en abstracto un compilador suele emplearse una
representación en forma de T que incluye los 3 lenguajes que lo caracterizan
› Lenguaje objeto (T)
› Lenguaje fuente (S)
› Lenguaje anfitrión (H)
S T
H }
H es un lenguaje máquina
frecuentemente igual a T
31. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 29
Análisis de compiladores
Tipos de compiladores
H
I. Ensamblador
ASM Máquina
H
II. Compilador cruzado
S T
H = T
H
III. Autocompilador
S T
H != T H = S
H
IV. Metacompilador
S T
H
V. Descompilador
T S
S especificaciones
T es un compilador
Se traduce de T a S
32. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 30
Análisis de compiladores
Portabilidad de compiladores
I. Portabilidad fuente des8no
A B
H
B C
H
= A C
H
II. Portabilidad de host
A B
H H K
M
= A B
K
La concatenación transitiva
de dos compiladores da
como resultado un
compilador del fuente del
primero al objeto del segundo
Si tenemos un compilador con anfitrión
H y necesitamos uno con anfitrión K
podemos usar un compilador H a K y
traducir los anfitriones
33. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 31
Análisis de compiladores
Portabilidad de compiladores
III. Arranque automá8co por transferencia
Java ENS
Java Java ENS
ENS
= Java ENS
ENS
Construimos un compilador de java
provisional en ensamblador.
Construirnos un compilador de java a
ensamblador en java. Para compilarlo
utilizamos el compilador provisional y
obtenemos un compilador de java a
ensamblador en ensamblador
mejorado. Recurrimos iterativamente
sustituyendo en cada pasada el
compilador provisional por el nuevo en
la iteración anterior
34. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 32
Construcción de compiladores en la prác6ca
Descripción de la prác8ca
S ENS2001
Java
› Lenguaje fuente : S
› Lenguaje objeto : ENS2001
› Lenguaje anfitrión : Java
Entrega de Febrero Entrega de Junio
› Analizador léxico
› Analizador sintáctico
50% especificación
Sesión de control (Enero)
› Analizador léxico
› Analizador sintáctico
› Analizador semántico
› Generación de código intermedio
› Generación de código final
50% especificación
Sesión de control (Mayo)
Test
Entrega de Septiembre
› Analizador léxico
› Analizador sintáctico
› Analizador semántico
› Generación de código intermedio
› Generación de código final
100% especificación
Sesión de control (Junio)
Test
› JFlex
› Cup
› Ant
› Marco de desarrollo
› ENS2001
Caracterís8cas Herramientas
35. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 33
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› Instalar JDK
› Descargar JDK de la página Web
› Ejecutar el instalable
› Comprobar la actualización de las variables de entorno path y classpath
› Descargar un IDE de desarrollo
› NetBeans
› Eclipse
› Descargar el marco de desarrollo proporcionado
› Descargar del entorno virtual
› Crear un proyecto a partir del marco de desarrollo
› Actualizar el IDE para que reconozca todas las libarías
› Crear tareas ant desde el IDE para ejecutar los scripts de ejecución y prueba de la práctica
I. Instalación y descarga
36. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 34
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Las clases compiladas se generan aquí
Las documentación de la arquitectura (sobre todo en 2ºcuatrimestre)
Tareas ant para ejecutar y depurar la práctica
§ clear
§ jflex
§ cup
§ build
§ flexTest
§ cupTest
§ finalTest
Memoria de la práctica según formato establecido
Consúltese el documento
“Directrices de implementación”
Especificaciones gramaticales de Cup
Especificaciones léxicas de JFlex
Test de prueba para las especificaciones A y B
Librerías necesariasCon8núa…
Esta primera parte del framework contiene la
documentación, ficheros de configuración, librerías de
ejecución, y directorios de soporte a la compilación
37. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 35
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Consúltese el documento
“Directrices de implementación”
Esta segunda parte del framework contiene la
infraestructura de clases abiertas que el usuario debe
extender o completar
Acceso a los artefactos del compilador
Entorno de ejecución donde se efectúa la generación del código final
Artefactos para la generación de código intermedio
Clase Token para comunicar el analizador léxico con el sintáctico
Clases Symbol y Type para representar los tipos y símbolos
Clases para representar los no terminales del árbol de análisis sintáctico
Programar para la prueba y depuración
§ LexicalTestCase
§ SyntaxTestCase
§ FinalTestCase
Con8núa…
38. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 36
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Consúltese el documento
“Directrices de implementación”
Esta tercera parte del framework contiene la
infraestructura de clases cerradas que ofrecen al
usuario funcionalidades completas para utilizar
Entorno de ejecución donde se efectúa la generación del código final
Artefactos para la generación de código intermedio
Artefactos para el análisis léxicos y el control de errores
Artefactos para el análisis semántico y el control de errores
Artefactos para el análisis sintáctico y el control de errores
39. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 37
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› La ejecución y prueba del marco de trabajo esta dirigida por tareas ant
› Clear: Borrar el contenido de /clases
› JFlex: Generar el analizador léxico (como un fichero fuente en src/lexical/scanner.java)
› Cup: Generar el analizador sintáctico (como un fichero fuente en src/syntax/parser.java)
› Build: Cup + Jflex + Compile
› flexTest: Ejecuta la prueba LexicalTestCase (generar tokens hasta final de fichero)
› cupTest: Ejecuta la prueba SyntaxTestCase (ejecuta el parser)
› finalTest: Ejecuta la prueba FinalTestCase (ejecuta el parser y traza el estado del compilador)
› Familia de tablas de símbolos creadas
› Familia de tablas de tipos creadas
III. Ejecución y prueba
40. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 38
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› Especificación del analizador léxico
› Generación (Jflex + compilar)
› Prueba (FlexTest)
› Especificación del analizador sintáctico
› Generación (Build)
› Prueba (CupTest)
› Integración del analizador lexico con el sintáctico
› Generación (Build)
› Prueba (CupTest)
III. Fases de desarrollo del compilador
› Implementación en cup del sistema de tipos
› Generación (Build)
› Prueba (FinalTest)
› Generación de código intermedio
› Generación (Build)
› Prueba (FinalTest)
› Generación de código Final
› Generación (Build)
› Prueba (FinalTest)
› Pruebas finales con fichero de test
1er cuatrimestre 2º cuatrimestre
41. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 39
Bibliograca
Material de estudio
Bibliografía básica
Construcción de compiladores: principios y práctica
Kenneth C. Louden International Thomson Editores,
2004 ISBN 970-686-299-4
42. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 40
Bibliograca
Material de estudio
Bibliografía complementaria
Compiladores: Principios, técnicas y herramientas.
Segunda Edición Aho, Lam, Sethi, Ullman
Addison – Wesley, Pearson Educación, México 2008
Diseño de compiladores. A. Garrido, J. Iñesta, F. Moreno
y J. Pérez. 2002. Edita Universidad de Alicante
45. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 2
Obje6vos
Obje8vos
› Conocer las responsabilidades de un analizador léxico
› Aprender cómo funciona
› Entender los diferentes tipos de patrones que reconoce
› Aprender a especificar formalmente analizadores léxicos
› A través de gramáticas formales
› A través de expresiones regulares
› A través de autómatas finitos
› Estudiar la implementación de analizadores léxicos
› Conocer las distintas estrategias de implementación
› Entender las posibles relaciones con la tabla de símbolos
› Estudiar la generación de errores léxicos
46. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 3
Índice
Índice
› Introducción
› Token
› Patrón léxico
› Lexema
› Lenguaje regular
› Especificación de analizadores léxicos
› Lenguajes regulares
› Gramáticas lineales
› Expresiones regulares
› Autómatas finitos
› Conversión de formalismos
› Implementación de analizadores léxicos
› basada en casos
› dirigida por tabla
› guiada por herramientas
› Estrategias de implementación
› Gestión de errores
› Construcción de A. léxicos en en la práctica
› ¿Qué es JFlex?
› ¿Cómo funciona JFlex?
› ¿Cómo se usa JFlex?
› Gestión de errores en JFlex
› Desarrollo paso a paso
› Bibliografía
47. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 4
Introducción
Analizador léxico
· i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
Analizador sintác8co
nextToken ()
Introducción
El primer paso para procesar un programa es convertir la colección de caracteres del
mismo en una colección de componentes léxicos con significado único dentro del
lenguaje llamados tokens. De eso se encarga el analizador léxico o escáner
El analizador sintáctico va
pidiendo nuevos tokens al
analizador léxico y éste los
sirve bajo demanda
Foco de atención
¿Cómo se formaliza un
analizador léxico?
¿Cómo se implementa un
analizador léxico?
› Formalismos
› Conversión entre formalismos
› Estrategias de implementación
› Buenas prácticas
48. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 5
Introducción
Introducción
El primer paso para procesar un programa es convertir la colección de caracteres del
mismo en una colección de componentes léxicos con significado único dentro del
lenguaje llamados tokens. De eso se encarga el analizador léxico o escáner
Definición de token
Un token es una unidad léxica indivisible con
significado único dentro del lenguaje. Desde el punto
de vista tecnológico se trata de una estructura de
datos que contiene información sobre
› ID: Tipo del token
› Número de línea
› Número de columna
› Lexema
› Valor…
Categorías de token
Los tipos de tokens existentes en un lenguaje son
una característica intrínseca al mismo. No obstante,
pueden encontrarse categorías generales
Categoría Ejemplos
Delimitadores
Palabras reservadas
Iden8ficadores
Números enteros
Números flotantes
Simbolos especiales
Cadenas
( ) , ; : [ ]
while true do if for
Index f isEven
3 -4 55 0 7658
4.5 .3 0.5 8.4e-5
+ -* / . = < > <= >= != ++
“Hola mundo!”
49. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 6
Introducción
Introducción
Cada tipo de token representa a un conjunto de tokens (construcciones léxicas
diferentes) con unos mismos propósitos dentro del lenguaje. Estos tipos se definen a
través de un patrón léxico al que se adscriben los lexemas del tipo
Definición de patrón léxico
Un patrón léxico es una expresión abstracta llamada
expresión regular que permite identificar
unívocamente un tipo de token y referenciar al
conjunto de todos los tokens que se ajustan a él.
Definición de lexema
La cadena de caracteres específica de un token
que se ajusta al patrón léxico de su tipo se llama
lexema. Existen dos tipos de lexemas
› Cadena propia: lexema idéntica al patrón
› Cadena no propia: lexema encaja con patrón
Tipo de token Patrón léxico
While
Enteros
División
Iden8ficador
while
digito+
/
letra (letra |digito)*
Ejemplos de lexema
while
12 123 0 45
/
Index f isEven
Cadena propia
SI
NO
SI
NO
50. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 7
Introducción
Introducción
Desde la perspectiva léxica un programa es una familia ordenada de
tokens de varios tipos. Cada tipo, a través de su patrón léxico, define
un micro lenguaje formado por todos aquellos lexemas que encajan
con el patrón léxico. Este tipo de lenguajes sencillos se llaman
lenguajes regulares
Definición de lenguaje regular
Un lenguaje regular describe una familia de tokens
que se ajustan a un determinado patrón léxico.
program burbuja;
uses crt;
const
n = 5;
var
i,j,temp:integer;
a:array[1..n] of integer;
begin
for i := 1 to n do
readln(a[i]);
for j := (n - 1) downto 1 do
for i := 1 to j do
if (a[i])>(a[i+1]) then
begin
temp := a[i];
a[i] := a[i+1];
a[i+1] := temp;
end;
writeln ('El resultado es:');
for i := 1 to n do
writeln (a[i]);
readln;
end.
Lenguaje de
iden8ficadores Pascal
burbuja
ctr
n
i
j
temp
a
readln
writeln
...
Lenguaje de palabras
reservadas de Pascal
program
uses
const
var
intger
of
array
begin
for
to
do
downti
if
then
End
...
Lenguaje de
delimitadores de Pascal
;
=
,
:
[
..
]
(
)
...
51. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 8
Especificación formal de analizadores léxicos
Especificación de lenguajes regulares
Además de la declaración extensiva – sólo viable en los lenguajes finitos – existen 3
diferentes maneras de definir formalmente un lenguaje regular. A lo largo de esta
sección estudiaremos cada una de ellas en detalle y veremos cómo se puede pasar de
cada una a las otras 2
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas finitos
› Elementos
› Gramáticas lineales
› Expresiones regulares
› Autómatas finitos
› Transformaciones
› De gramáticas a expresiones
› De gramáticas a autómatas
› De expresiones a gramáticas
› De expresiones a autómatas
› De autómatas a gramáticas
› De autómatas a expresiones
52. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 9
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Definición de gramá8ca lineal
Una gramática lineal es un conjunto de 4 elementos
G = (T, N, S, P) donde:
› T es un conjunto de símbolos terminales
› N es un conjunto de símbolos no terminales
› S Є N axioma gramatical
› P un conjunto de reglas de producción de la forma
1. A ::= B x donde A, B Є N y x Є T
2. A ::= x B donde A, B Є N y x Є T
3. A ::= x donde x Є T U { }ﻉ
A veces T se elide, N se deduce de los antecedentes de
las reglas de P y se asume que el antecedente de la
primera regla es S con lo G sólo a través de P
Tipos de gramá8cas lineales
Existen en realidad 2 tipos de gramáticas lineales. En
función de la forma del conjunto de reglas de
producción podemos distinguir entre:
› Gramáticas lineales por la izquierda
› Usan reglas A ::= B x
› Usan reglas A ::= x
› Gramáticas lineales por la derecha
› Usan reglas A ::= x B
› Usan reglas A ::= x
Dada una gramática G lineal por la izquierda siempre
se puede encontrar una gramática G’ lineal por la
derecha y recíprocamente
)representa la cadena vacía (ausencia de terminal ﻉ
53. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 10
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Derivación grama8cal
Una gramática debe interpretarse como un conjunto de reglas de reescritura o
transformación de elementos no terminales en elementos terminales o no
terminales.
› La primera transformación parte del axioma
› En cada paso se aplica una única regla
› Las reglas pueden extender la transformación ( A::= B x / A ::= x B)
› Las reglas pueden ser recursivas (A ::= A x / A ::= x A)
› Las reglas pueden ser terminales (A ::= x)
› El proceso debe ser convergente
LG = {a b*}
Sea G = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
A ::= a
B ::= b B
B ::= b
}
Ejemplo
54. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 11
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Derivación grama8cal
El problema ahora se traduce en, dada una cadena formada por una secuencia de
elementos terminales de T, demostrar que dicha cadena pertenece al lenguaje
definido por la gramática
LG = {a b*}
Sea G = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
A ::= a
B ::= b B
B ::= b
}
A → aB → abB → abbB → abbb
Ejemplo
axioma
Paso de
derivación
asidero
FraseF o r m a
de frase
Cadena de
derivación
55. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 12
› L1 = conjunto de todas las palabras sobre {a, b} que empiezan por a
› L2 = conjunto de todas las palabras sobre {a, b} que empiezan por a y continúan con secuencias ab
› L3 = Números fraccionarios
› L4 = Identificadores
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Ejercicios
Definir formalmente a través de una gramática lineal
los siguientes lenguajes descritos informalmente
GD = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
B ::= a B
B ::= b B
B ::= ﻉ
}
GI = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= A a
A ::= A b
A ::= a
}
L1
56. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 13
Especificación formal de analizadores léxicos
Especificación mediante expresiones regulares
Otra forma de definir lenguajes regulares es a través del uso de expresiones regulares.
Una expresión regular utiliza los términos del alfabeto de terminales operados a través
de operaciones con una semántica especifica
Una expresión regular sobre un conjunto T es un conjunto
ER = (T, | , · , *) que cumple las siguientes propiedades:
Definición de expresión regular
› Ø es una expresión regular que define el lenguaje L = Ø
} ﻉ { = )ﻉ ( cadena vacía) es una expresión regular que define el lenguaje L( ﻉ ›
› Cualquier símbolo a Є T es una expresión regular que define el lenguaje L ( a ) = { a }
› Si x, y son dos expresiones regulares, x·y es una expresión regular que define L ( x·y ) = L ( x ) L ( y )
› Si x, y son dos expresiones regulares, x | y es una expresión regular que define L (x | y) = L ( x ) U L ( y )
› Si x es una expresión regular x* es una expresión regular que define L ( x* ) = U L( x )
› Si x es una expresión regular x+ es una expresión regular que define el lenguaje L ( x* ) = U L( x )
› No existen más expresiones regulares
i =0
∞ i
∞
i =1
i
57. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 14
Especificación formal de analizadores léxicos
Especificación mediante expresiones regulares
Otra forma de definir lenguajes regulares es a través del uso de expresiones regulares.
Una expresión regular utiliza los términos del alfabeto de terminales operados a través
de operaciones con una semántica especifica
Definir los siguientes lenguajes regulares
utilizando para ello expresiones regulares
Ejercicios
› L1 = Lenguaje de identificadores
› L2 = Lenguaje de números naturales
› L3 = Lenguaje de números fraccionarios
› L4 = Lenguaje de números enteros con exponente
› L5 = Lenguaje de números fraccionarios con exponente
› L6 = Lenguaje de números pares
› L7 = Lenguaje de las cuentas de correo
› L8 = Lenguajes de las URL
L1 = l ( l | d )* l Є {a..z} d Є {0..9}
L3 = d+ . d+ d Є {0..9}
L6 = d+ p d Є {0..9} p Є {0, 2, 4, 6, 8}
L7 = nombre @ host
nombre = L1 (. L1)*
host = L1 (. L1)*
58. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 15
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Un autómata finito determinista es un conjunto
AFD = (T, Q, f, q, F) donde:
Autómata finito determinista
› T es un alfabeto de símbolos terminales de entrada
› Q es un conjunto de estados finito no vacío
› f: Q x T → Q es una función de transición
› q Є Q es un estado inicial o estado de arranque
› F C Q es un subconjunto de estados finales de aceptación
Gráficamente, un autómata finito determinista es
una colección de estados unidos por arcos,
donde para cada estado existe un arco
etiquetado con cada elemento de T. El estado
inicial tiene una flecha entrante y los estados
finales tienen un doble borde
Interpretación gráfica
letra
letra, dígito
letra, dígito
dígito
letra Є [a..z]
dígito Є [0..9]
1
2
0
59. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 16
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Con el ánimo de simplificar el trabajo con los autómatas finitos
deterministas, dentro de la teoría de compiladores se utilizan las
siguientes extensiones notacionales
Extensión de los autómatas finitos deterministas Interpretación gráfica
› Las transiciones ausentes se asumen como errores
› Se omiten los estados de absorción de errores
› Se usa la etiqueta otro para representar el resto de alternativas
› Los estados finales paran el proceso y emiten token
› Los estados finales con * recuperan el carácter de tránsito
› Se espera a reconocer el posible toquen de lexema más largo
› El estado final ya no es final
› Al llegar un carácter terminador se pasa a uno final
› Entonces se emite el token
› Si es necesario se marca con * el estado final
0
letra
letra, dígito
A continuación representamos el
autómata finito determinista anterior
aplicando las extensiones descritas
otro
letra Є [a..z]
dígito Є [0..9]
*
2
1
60. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 17
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Los autómatas arrancan en el estado de inició y comienzan a
consumir caracteres de la entrada lo que provoca una transición
a un nuevo estado o un error. En cuanto se alcanza un estado de
aceptación final, el autómata para y se emite el token reconocido
Como se usan los autómatas finitos deterministas
→ c → o → u → n → t → e → r → 0 → 1 → +
letra
letra, dígito
otro
letra Є [a..z]
dígito Є [0..9]
*
caracteres
Estado 0 Estado 1 Estado 2
transiciones
token
Carácter delimitador (otro)
0
2
1
61. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 18
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Definir los siguientes lenguajes regulares utilizando
para ello autómatas finitos deterministas
Ejercicios
› L1 = Lenguaje de identificadores
› L2 = Lenguaje de números naturales
› L3 = Lenguaje de números fraccionarios
› L4 = Lenguaje de números naturales con exponente
› L5 = Lenguaje de números fraccionarios con exponente
› L6 = When
letra
letra, dígito
otro
*
L1
0
2
1
62. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 19
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Para construir un analizador léxico completo es
necesario combinar en un único autómata todos los
autómatas correspondientes a los micro-lenguajes
que aparecen en el lenguaje. Este proceso se
puede hacer mediante una aproximación holística
Construcción manual composi8va de autómatas
› L7 = Números naturales y fraccionarios con exponente
› L8 = {<, <<,<=, =, ==, +, ++, -, --, *, *=}
› L9 = {While, When, Do, Downto}
› L10 = L1 U L7 U L9
› L11 = U Li con i Є [1..11]
0
<
*
=
+
<
*
–
=
otro
=
otro
+
otro
–
otro
=
otro
<<
<=
<
==
=
++
+
– –
–
*=
*
*
*
*
*
16
15
13
12
10
9
7
6
4
3
2
11
14
L8
Definir los siguientes lenguajes regulares utilizando
para ello autómatas finitos deterministas
Ejercicios
0
5
8
63. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 20
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Cuando el número de micro-lenguajes es grande y éstos son complejos la aproximación
manual se convierte en un proceso prolijo por eso conviene establecer un proceso
sistemático. Este proceso se basa en definir formalmente la composición de autómatas
sobre las operaciones legítimas de composición de autómatas
Construcción sistemá8ca composi8va de autómatas
L (x) x
L (x) L (y) x y
ﻉ
L (x) U L (y)
x ﻉ
y
ﻉ
L (x)+ x
ﻉ
L (x)* x
ﻉ
0
0
1
ﻉ
ﻉ
Las –ﻉ transiciones deben
interpretarse como
transiciones que no
consumen caracteres
}
x
0 n 1 n-1…≡
64. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 21
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Cuando el número de micro-lenguajes es grande y éstos son complejos la aproximación
manual se convierte en un proceso prolijo por eso conviene establecer un proceso
sistemático. Este proceso se basa en definir formalmente la composición de autómatas
sobre las operaciones legítimas de composición de autómatas
Construcción sistemá8ca composi8va de autómatas
L = {<, <<, <=}Ejemplo
0 <
1
4
7 =
otro
5
8<
<
2
<
ﻉ
ﻉ
ﻉ
0
1
3
5 =
otro
<
Uso de –ﻉtransiciones para construir el
autómata
}
La eliminación de las –ﻉtransiciones provoca varias
transiciones iguales desde el mismo nodo
}
<
<
<
<
<<
<=
<
<<
<=
3
6
9
2
4
6
65. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 22
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
La construcción sistemática de autómatas
genera autómatas finitos no deterministas. Un
autómata finito no determinista es un autómata
finito donde cada estado:
Autómatas finitos no deterministas
› Puede tener ﻉ – transiciones
› Puede tener varias transiciones con la misma etiqueta
Genera indeterminación porque desde ese
estado no se sabe si avanzar por otra
transición normal consumiendo un
carácter o hacerlo por la ﻉ – transición sin
consumir ningún carácter
Genera indeterminación porque desde ese
estado, si el carácter a la entrada tiene
varias posibles transiciones no se sabe
cual escoger
Los autómatas finitos deterministas no son
formalismos adecuados para representar
lenguajes regulares
66. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 23
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
La construcción de un autómata finito determinista a partir de uno no determinista
requiere de la identificación de todos los estados alcanzables desde cada estado a
través de –ﻉtransiciones y transiciones múltiples
Conversión de autómatas finitos no deterministas a autómatas finitos deterministas
L = {<, <<, <=}Ejemplo
0 <
1
4
7 =
otro
5
8<
<
2
<
ﻉ
ﻉ
ﻉ
<
<<
<=
› {0} = {1 4 7}
› {1 4 7} < = {2 5 8}
› {2 5 8} < = {6}
› {2 5 8} = = {9}
› {2 5 8} otro = {3}
{1 4 7} {2 5 8}
< <
=
3
6
9
{3}
{6}
{9}
67. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 24
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Cada regla se expresa en términos de los
operadores de concatenación, cierre + y
cierre *
Conversión de Gramá8cas a expresiones
A ::= l B A = l B
B ::= l B B = l B = l +
B ::= d B B = d B = d +
B ::= ﻉ B = ﻉ
B = ( l+ | d+ | )ﻉ = ( l | d | ﻉ )+ = ( l | d )*
A = l ( l | d ) *
Se genera un estado por cada no terminal. El estado
del axioma es el de inicio. Las reglas se traducen a
transiciones. Si la regla es terminal (A ::= x) entonces
se genera una transición otro a un estado de
aceptación final. Si sale no determinista, convertirlo a
determinista.
Conversión de Gramá8cas a autómatas
A ::= l B
B ::= l B
B ::= d B
B ::= ﻉ
A
l
l, d
otro
*
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
B
2
68. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 25
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Transformar primero la expresión regular
desfactorizando los cierres + y *. Después
aplicar las transformaciones + a recursividad
y * a recursividad con ﻉ producción
Conversión de Expresiones a gramá8cas
L = l ( l | d ) * = l ( l * | d * )
A ::= l B B representa ( l* | d* )
B ::= l B Se captura l+
B := d B Se captura d+
B ::= ﻉ Se captura l* | d*
La conversión de expresiones regulares a autómatas
finitos se realiza utilizando las transformaciones
atómicas definidas anteriormente al discutir la
composición de lenguajes
Conversión de Expresiones a autómatas
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
x . y x y
ﻉ
x | y
x ﻉ
y
ﻉ
x+ x
ﻉ
x* x
ﻉ
ﻉ
ﻉ
69. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 26
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Cada estado se convierte a un no terminal. El
estado de arranque corresponde con el
axioma. Cada transición A → B etiquetada
con x se traduce en A ::= x B. Si B es un
estado final se genera A ::= x. Si x = otro se
genera A ::= ﻉ
Conversión de autómatas a gramá8cas
[0] ::= l [1]
[1] ::= l [1]
[1] := d [1]
ﻉ =:: ]1[
Para la transformación de autómatas a expresiones
basta con hacer una lectura inversa de las
transformaciones atómicas definidas anteriormente
Conversión de autómatas a expresión
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
ﻉ
x . y x y
ﻉ
x | y
x ﻉ
y
ﻉ
x+ x
ﻉ
x* x
ﻉ
ﻉ
ﻉ
0
l
l, d
otro
*
1
2
70. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 27
Implementación de analizadores léxicos
¿Qué es un analizador léxico?
El analizador léxico responde bajo demanda a las
solicitudes de siguiente token que le va haciendo el
analizado sintáctico. Cada vez que éste último hace una
solicitud al primero, el analizador léxico consume un
número de caracteres de la entrada y retorna un artefacto
computacional que representa el siguiente token en la
entrada. En lo venidero utilizaremos el término token para
referirnos a dicho artefacto
Analizador léxico
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
Analizador sintác8co
}
nextToken ()
Id
nFila
nColumna
lexema
valor
En la práctica el artefacto software que
representa un token suele ser una estructura de
datos o un objeto en los lenguajes orientados a
objetos
}
Un analizador léxico o scanner es un programa capaz de descomponer una entrada de caracteres –
generalmente contenidas en un fichero – en una secuencia ordenada de tokens.
71. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 28
Implementación de analizadores léxicos
Implementación de analizadores léxicos basada en casos
letra = [a..z]
digito = [0..9]
estado = 0
fin = false
c = leerCaracter ()
while (!fin) {
switch (estado) {
0: switch (c) {
letra : estado = 1
lexema += c
c = leerCaracter ()
break
digito : throw error ()
}
De acuerdo a esta estrategia de implementación es necesario disponer de una
variable de estado para codificar el estado actual y una batería de casos que
describen la lógica de transición del autómata finito determinista.
break;
1: switch (c) {
letra :
digito : estado = 1
lexema += c
c = leerCaracter ()
break
default: estado = 2;
}
break
2: token = crearToken (lexema...)
fin = true
}
return token
letra
letra, dígito
otro
*
0
2
1
72. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 29
Implementación de analizadores léxicos
Implementación de analizadores léxicos dirigida por tabla
tTransicion = [][]
sFinales = {estados finales}
estado = 0
fin = false
c = leerCaracter ()
while (!fin) {
s = tTransicion [s][c]
if (s != null)
if (!(s in sFinales)) {
lexema += c
c = leerCaracter ()
} else fin = true
else throw error () }
return crearToken (lexema...)
Podemos codificar computacionalmente un autómata como una matriz bidimensional
de Q x T → Q que indique, para cada entrada y estado el nuevo estado. El algoritmo
se limita a leer dicha matriz
letra
letra, dígito
otro
*
0
2
1
73. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 30
Implementación de analizadores léxicos
Implementación de analizadores léxicos guiada por herramientas
letra = [a..z]
digito = [0..9]
letra (letra | digito)* { return new Token (ID); }
digito+ { return new Token (ENT); }
digito* . digito+ { return new Token (FRAC); }
“(” { return new Token (PI); }
“)” { return new Token (PD); }
“[” { return new Token (PI); }
“]” { return new Token (PD); }
...
Existen herramientas para la construcción automática de analizadores léxicos [Lex]
[Flex] [JFlex]. Estas herramientas se basan en la definición de una colección de reglas
patrón - acción
› Dan prioridad al token más largo
› DO / DOT
› > / >=
› Ante igualdad de longitud
› Anteponer la regla mas específica
› When
› While
› Id
}
74. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 31
Implementación de analizadores léxicos
Estrategias de implementación
I. Reconocimiento de palabras reservadas
Reconocimiento de
palabras reservadas
Resolución
explícita
Resolución
implícita
› Se indican todas con su patrón léxico
› Se integran en el diagrama global
› Se utilizan herramientas generadoras (FLex)
› Las palabras reservadas (PR) se reconocen como identificadores
› Las k palabras reservadas se meten en la tabla de símbolos (TS)
› Se busca cada id en TS. Si su índice es < k es PR
II. Reconocimiento estructuras complejas de forma híbrida
› Implementación manual de las estructuras más sencillas
› Operadores
› Identificadores
› Números
› Implementación tabular o guiada por herramientas con estructuras complejas
› Cadenas no específicas
› Prefijos comunes
75. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 32
Ges6ón de errores
Errores léxicos
Los errores léxicos son aquellos que se producen en el ámbito del reconocimiento de
patrones para construir tokens del lenguaje. Podemos establecer una clasificación de
errores de naturaleza léxica
› Errores básicos
› Aparición de caracteres ajenos al conjunto T (ñ, Ç, etc.)
› Ausencia de concordancia con ningún patrón (1abc, +*, etc.)
› Errores complejos
› Cadena de caracteres sin cierre (falta “ final)
› Cadena de caracteres sin apertura (falta “ inicial)
› Comentario sin cierre (falta */ final)
› Comentario sin apertura (falta /* inicial)
› Error en el anidamiento de comentarios (/* .. /* .. */)
Son en realidad de
esta categoría
No son en realidad errores
capturables por un reconocedor de
lenguajes regulares aunque las
herramientas generadoras son
capaces de reconocerlos
76. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 33
Construcción de analizadores léxicos en la prác6ca
¿Qué es JFlex?
JFlex es una herramienta para la generación de analizadores léxicos escritos en java.
A partir de un fichero de especificación que describe las características léxicas de un
lenguaje, JFlex genera un código fuente compilable que puede ser utilizado como
analizador léxico
JFlex Javac Scanner.flex
Framework
Scanner.java Java
Scanner.clas
s
JFlex compile JFlexTest
Esta es la especificación del
analizador léxico. Todo
cambio en el escáner debe
indicarse aquí
Esta es la clase generada a partir de la
especificación. Atención! No incluir aquí
ningún código manualmente ya que en la
próxima generación se perderá
Esta es la clase java
compilada que puede ser
interpretada por la JVM
77. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 34
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
I. Sección de código de usuario
La sección de código de usuario se utiliza para incluir
cualquier declaración java (paquete, importación o
clase) que sea necesario para compilar el scanner
78. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 35
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
II. Sección de direc8vas
Se incluyen directivas de compatibilidad con cup,
gestión de fila, columna y lexema, declaración de
estados y macros e inclusión de código de
inicialización
79. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 36
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
III. Sección de reglas patrón - acción
En esta última sección se define una familia de
escáneres léxicos, cada uno asociado a un estado
distinto (YYINITIAL, COMMENT, etc.). Es posible
saltar de uno a otro. La definición se basa en reglas
patrón acción que indican el código java que debe
ejecutarse cuando la entrada encaja con determinado
patrón léxico. Si el código java no acaba con un return
el scanner continua buscando un nuevo token
80. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 37
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
I. Sección de código de usuario
La sección de código intermedio se copia tal cual al
inicio de la clase fuente que representa el escáner
(Scanner.java), por tanto todo lo que va en esta sección
es código puro java de carácter declarativo
Copia en vervatim
Scanner.java
81. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 38
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Directiva
› %full
› %unicode
› %{ … %}
› %init{ … %}
› %intthow{ … %}
› %yylexthrow{ … %}
› %eof{ … %}
› %eofval{ … %}
› %eofthrow{… %}
› %ignorecase
› %char
› %line
› %notunix
Descripción
Utiliza el código ASCII extendido 8 bits
Utiliza codificación UNICODE de 16 bits
Se incluye el código como declaración dentro de la clase Scanner
Incluye código dentro de los constructores
Declara excepciones que el constructor puede lanzar
Declara excepciones que el método de escaneo puede lanzar
Incluye código que se ejecuta tras encontrar EOF
Define el valor de retorno al encontrar EOF
Excepción de se lanza al encontrar EOF
No distinguir entre mayúsculas y minúsculas
Contabiliza el número de caracteres en la variable yychar
Contabiliza el número de líneas en la variable yyline
Reconoce rn como carácter (doble) de nueva línea
Consúltese el documento
“Manual de JFlex”
II. Sección de direc8vas
82. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 39
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Directiva
› %class name
› %public
› %function name
› %interface name
› %type name
› %integer
› %intwrap
› %yyeof
› %cup
› %state nombre
› nombre = valor
Descripción
Da nombre a la clase del escáner
Define como pública la clase del escáner
Da nombre a la función de escaneo
Declara los interfaces que debe implementar el escáner
Define el tipo de retorno de la función de escaneo
Define el tipo de retorno de la función de escaneo como un int
Define el tipo de retorno de la función de escaneo como Integer
Define la constante Yylex.YYEOF (obligatorio uso de %integer)
Habilita la compatibilidad con Cup
Define el estado nombre
Define una macro (LETRA = [A-Za-z])
Consúltese el documento
“Manual de JFlex”
II. Sección de direc8vas
83. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 40
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
III. Reglas patrón-acción
› Despliegue de macros
› Utilización de estados
{LETRA} ( {LETRA} |{DIGITO})* { return crearToken
(ID); }
{DIGITO} * { return crearToken
(NUM); }
Se utilizan los caracteres { y } para encerrar
el nombre de la macro, definida en la sección
de directivas, que se quiere desplegar
Cada estado, declarado en la sección de
directivas, corresponde con un autómata
distinto. Cada regla debe asociarse a un
estado precediendo al patrón léxico el
nombre del mismo encerrando entre < y >
Desde una regla r de un estado A se puede
saltar a un estado B mediante la instrucción
yybegin (B) invocada en la acción de r.
El estado inicial por defecto es YYINITIAL.
Este es un estado que no es preciso declarar
<YYINITIAL> “+” { return crearToken (MAS); }
<YYINITIAL> “-” { return crearToken (MENOS); }
<YYINITIAL> “*” { return crearToken (MUL); }
<YYINITIAL> “/” { return crearToken (DIV); }
...
<YYINITIAL> “/*” { yybegin (COMMENT); }
...
<COMMENT> “/*” { nComments ++; }
<COMMENT> “*/” { nComments --;
if (nComments == 0)
yybegin (YYINITIAL); }
<COMMENT> {COMMENT} { }
84. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 41
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
III. Reglas patrón-acción
Secuencias de escape
› b
› n
› t
› f
› r
› ddd
› xdd
› udddd
› ^C
› c
Descripción
Retroceso
Nueva línea
Tabulador
Avance de página
Retorno de carro
Número octal
Número hexadecimal
Hexadecimal de 4 dígitos
Carácter de control
Backslash seguido del c
Metacaracteres
› b
› $
› .
› “…”
› {name}
› *
› +
› ?
› (…)
› […]
› [^…]
› a-b
Descripción
Retroceso
Fin de fichero
Cualquier carácter menos n
…
Expansión de una macro
Clausura de Kleene
Una o más repeticiones
Opcionalidad
Agrupación de expresiones regulares
Conjunto de caracteres
Conjunto complementario
Rango a - b
Secuencias de escape Descripción
› yychar
› yyline
› yytext ()
Número de columna
Numero de línea
lexema
85. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 42
Construcción de analizadores léxicos en la prác6ca
¿Cómo se usa JFlex?
Los analizadores sintácticos de JFlex están pensados
para usarse bajo demanda. Se trata de artefactos con
una API bien definida. El método más relevante es el
de escaneo que devuelve el siguiente token a la
entrada.
El framework prescribe que el método de escaneo
debe devolver un objeto de la clase Token
Analizador léxico
Analizador sintác8co
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
La clase Token
Token es una clase hija que hereda de la clase que
u s a c u p p a r a i n t e g r a r s e c o n J F l e x
(javacup.runtime.Symbol). Esta clase facilita y
encapsula la comunicación entre el analizador léxico
y el analizador sintáctico desarrollado en Cup
proporcionando una colección de métodos de
interés
Javacup.run6me.Symbol
Token
+ getID ()
+ getLexema ()
+ getline ()
+ getColumn ()
JFlex Cup
next_Token ()
Token next_Token ()
}
}
Consúltese el documento
“Directrices de implementación”
86. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 43
Construcción de analizadores léxicos en la prác6ca
¿Cómo se usa JFlex?
Para adaptar JFlex al framework de desarrollo es
necesario realizar una serie de tareas sobre el
fichero de especificación. Éstas ya vienen
realizadas en la plantilla Jflex que proporciona el
framework por lo tanto lo aquí contado es
meramente explicativo y no requiere trabajo
alguno del estudiante
› El escáner pertenece al paquete compiler.lexical
› Debe importarse
› La clase Token
› El interfaz ScannerIF
› Las clases de gestión de errores
› Debe activarse la compatibilidad con el framework
› %cup
› %implements ScannerIF
› %scanerror LexicalError
› Opcionalmente declararse la función crearToken
› Cada acción debe acabar con un return crearToken (…);
Œ
Œ
Ž
Ž
87. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 44
Construcción de analizadores léxicos en la prác6ca
Ges8ón de errores en JFlex
La gestión de errores léxicos está soportada dentro
del framework por la clase LexicalErrorManager. Los
métodos para emitir error son
LexicalError
usa
<YYINITIAL> “+” { return crearToken (MAS); }
<YYINITIAL> “-” { return crearToken (MENOS); }
<YYINITIAL> “*” { return crearToken (MUL); }
<YYINITIAL> “/” { return crearToken (DIV); }
...
<YYINITIAL> . { LexicalErrorManager.lexicalFatal (“ufff!”); }
› error (). Emite un mensaje de error
› fatal (). Emite un mensaje de error y para el scanner
Ejemplo
Estos métodos están doblemente sobrecargados.
Pueden recibir un mensaje de error (String) o un
objeto LexicalError que representa un error léxico
Consúltese el documento
“Directrices de implementación”
LexicalErrorManager
+ lexicalDebug (String message)
+ lexicalInfo (String message)
+ lexicalWarn (String message)
+ lexicalError (String message)
+ lexicalError (LexicalError error)
+ lexicalFatal (String message)
+ lexicalFatal (LexicalError error)
88. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 45
Construcción de analizadores léxicos en la prác6ca
Desarrollo paso a paso
1. Especificación del escáner
› Abrir el documento de especificaciones JFlex doc/specs/scanner.flex
› No cambiar nada de lo que está escrito!
› Declarar macros necesarias (ALFA, DIGIT, SPACE, NEWLINE…)
› Declarar el estado de comentarios %%state COMMENT
› Definir las reglas de YYINITIAL
› Definir las reglas de COMMENT (contemplar el anidamiento si procede)
2. Generar el escáner
› Limpiar (tarea clear)
› Generar el escáner (tarea jflex)
› Compilar el escáner (tarea compile)
3. Probar el escáner
› Abrir fichero LexicalTestCase src/compiler/test/LexicalTestCase.java
› Descomentar y comentar lo indicado en el fichero (léelo atentamente)
› Si funciona, fin. Sino volver a 1
89. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 46
Bibliograla
Material de estudio
Bibliografía básica
Construcción de compiladores: principios y práctica
Kenneth C. Louden International Thomson Editores,
2004 ISBN 970-686-299-4
90. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 47
Bibliograla
Material de estudio
Bibliografía complementaria
Compiladores: Principios, técnicas y herramientas.
Segunda Edición Aho, Lam, Sethi, Ullman
Addison – Wesley, Pearson Educación, México 2008
Diseño de compiladores. A. Garrido, J. Iñesta, F. Moreno
y J. Pérez. 2002. Edita Universidad de Alicante
92. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 2
Obje6vos
Obje8vos
› Conocer los lenguajes libres de contexto
› Conocer las responsabilidades del analizador sintáctico
› Aprender a utilizar gramáticas libres de contexto
› Aprender a diseñar gramáticas libres de contexto
› Aprender a reconocer y resolver fuentes de ambigüedad
› Aprender a eliminar la recursividad por la izquierda
› Aprender a factorizar por la izquierda
› Conocer el uso y tipos de derivaciones y árboles sintácticos
› Conocer la representación de lenguajes mediante diagramas de sintaxis
› Presentar los diferentes tipos de autómatas utilizados para construir analizadores sintácticos
› Discutir los diferentes tipos de analizadores sintácticos
93. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 3
Índice
Índice
› Introducción
› Gramáticas libres de contexto
› Notación BNF y EBNF
› Derivación gramatical
› Árboles sintácticos
› Limpieza gramatical
› Ambigüedad gramatical
› Recursividad por la izquierda
› Factorización por la izquierda
› Diagramas de sintaxis
› Autómatas a pila deterministas
› Bibliografía
94. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 4
Introducción
Análisis sintác8co
La fase de análisis sintáctico tiene por objetivo solicitar tokens al analizador léxico y
construir una representación arborescente de todo el código fuente. Este proceso se
encuentra dirigido por el conocimiento gramatical que del lenguaje tiene el analizador
sintáctico
El analizador sintáctico va
pidiendo nuevos tokens al
analizador léxico para construir
un árbol del programa fuente
Foco de atención
¿Cómo se especifica formalmente
un analizador sintáctico?
¿Cómo se implementa un
analizador sintáctico?
› Formalismos
› Tratamiento de formalismos
› Conversión entre formalismos
› Estrategias análisis sintáctico
› Tipos de gramáticas
› Tipos de analizadores
Analizador sintác8co
SWhile
WHILE E DO S
E > E
<WHILE, PR>
<a, ID>
<>, GT>
<b, ID>
<DO, PR>
...
<(, PI>
<), PD>
Tema 3
Temas 4 y 5
}
}
95. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 5
Introducción
Lenguajes libres de contexto
Desde una perspectiva sintáctica un lenguaje es una colección de construcciones sintácticas
bien formadas desde un alfabeto de entrada y correctamente combinadas entre sí de
acuerdo a una colección de reglas sintácticas
Ejemplo
El lenguaje Pascal tiene unas normas de
carácter gramatical que definen su
naturaleza y expresividad. Visto de
manera extensiva, el lenguaje Pascal
sería el conjunto infinito de todos los
posibles códigos fuente correctos
escritos en sintaxis Pascal
Pascal
Uses crt;
var
cantidad,cont,numero,s:integer;
begin
clrScr;
s:=0;
write('Cantidad:');
read(canditad);
for cont:=1 to cantidad do
begin
write('Numero ',cont,': ');
Read(numero);
s:=s+numero;
end;
write('Promedio:',s/cantidad:0:2);
readKey;
end;.
uses
crt;
var
contador:integer;
begin
ClrScr;
for contador:=2 to 999 do
begin
contador:=contador+1;
Write(contador,', ');
if contador>999 then
begin contador:=999;
end;
end;
ReadKey;
end.
Uses crt;
var
suma,numero,contador:integer;
begin
clrScr;
write('Numero: ');
readln(numero);
suma:=0;
for contador:=1 to numero do
begin
suma:=suma + contador;
end;
write('Suma: ',suma);
readKey;
end.
…
96. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 6
Introducción
Especificación de lenguajes libres de contexto
Existen 3 diferentes maneras de definir formalmente un lenguaje de contexto libre. A lo
largo de esta sección estudiaremos cada una de ellas en detalle y veremos cómo se
puede pasar de cada una a las otras 2
Lenguajes
libres de
contexto
Gramá8cas libres
de contexto
Diagramas de
sintaxis
Autómatas
a pila
› Elementos
› Gramáticas libres de contexto
› Diagramas de sintaxis
› Autómatas a pila
97. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 7
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Definición de gramá8ca libre de
contexto Una gramática libre de contexto es un conjunto de 4
elementos G = (T, N, S, P) donde:
› T es un conjunto de símbolos terminales
› N es un conjunto de símbolos no terminales
› S Є N axioma gramatical
› P un conjunto de reglas de producción de la forma
1. A ::= X donde X es una secuencia de elementos en N U T
2. A ::= x donde x es una secuencia de elementos en T
3. A :: = ﻉ siendo ﻉ la cadena vacía
A veces T se elide, N se deduce de los antecedentes de las
reglas de P y se asume que el antecedente de la primera regla
es S con lo G sólo a través de P
Ejemplo
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
E ::= E + E
E ::= E - E
E ::= E * E
E ::= E / E
E ::= n
}
98. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 8
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Notación
E → E + E
E → E – E
E → id
¿Cómo se escriben
las reglas?
Notación BNF
Las reglas se escriben como A ::= X.
Las reglas de un mismo antecedente
se escriben como A ::= X | Y | Z…
Cada regla con antecendente distinto
se escribe en una nueva línea
Notación EBNF
Se usa la notación BNF. Las reglas
recursivas se pueden esquematizar
con los meta-caracteres { y }
Notación estándar
Las reglas se escriben como A → X.
Cada regla se escribe en una linea
distinta
D ::= T L
T ::= int | bool | char
L ::= id , L | id
D ::= T L
T ::= int | bool | char
L ::= { id , } id
Focode
atención
99. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 9
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
Derivación grama8cal
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
E ::= E + E
E ::= E - E
E ::= E * E
E ::= E / E
E ::= n
}
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
E → E + E → n + E → n + E * E → n + n * E → n + n * n
axioma
Paso de
derivación
asidero
FraseF o r m a
de frase
Cadena de
derivación
2 + 3 * 5
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
(2) (3) (5)
100. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 10
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Derivación grama8cal
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
Cadena de
derivación
Secuencia de pasos de derivación que
parten del axioma gramatical para
intentar alcanzar la frase analizada x.
Demostración de x Є L (G)
Frase Secuencia de terminales que
pertenece al lenguaje definido por la
gramática. Si x Є L (G), x es frase de L
Forma de
frase
Secuencia de terminales y no
terminales que representa una
colección de frases del lenguaje. Existe
una cadena de derivación que llega
hasta ella
Axioma Forma de frase más abstracta que
representa a L (cualquier derivación de
Si x Є L (G) comienza por el axioma)
Asidero Parte izquierda de cualquier forma de
frase de x Є L (G) formada únicamente
por símbolos terminales
Paso de
derivación
Aplicación de una regla de producción
que transforma una forma de frase más
general en otra más especifica para x
101. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 11
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Derivación grama8cal
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
E → E + E →
n + E →
n + E * E →
n + n * E →
n + n * n
¿ En qué orden se
aplican las reglas?
Left Most Derivation
En cada paso de derivación se
escoge el no terminal más a la
izquierda de la forma de frase a
derivar
Right Most Derivation
En cada paso de derivación se
escoge el no terminal más a la
derecha de la forma de frase a
derivar
E → E + E →
E + E * E →
E + E * n →
E + n * n →
n + n + n
102. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 12
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Frecuentemente no es preciso reflejar el orden de aplicación de las
derivaciones sino solamente el proceso de derivación desde el axioma a la
frase final. Para ello se interpreta cada regla como un árbol con raíz en el
antecedente e hijos los símbolos terminales y no terminales del consecuente
de la regla
2 + 3 * 5
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
R1: E ::= E + E
R2: E ::= E - E
R3: E ::= E * E
R4: E ::= E / E
R5: E ::= ( E )
R6: E ::= n
}
E
E + E
n E * E
n n
(2)
(3) (5)
R1
R3
R6
antecedente
consecuente
frase
103. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 13
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Existen dos tipos de representaciones arborescentes que se utilizan frecuentemente
para representar las derivaciones de una frase de un lenguaje.
Tipos de árboles
sintácticos
Arboles de análisis sintáctico
Los hijos de cada regla son una
representación exacta de la
colección de terminales y no
terminales que aparecen en el
consecuente de la misma
Arboles sintácticos abstractos
Se hace una representación
abstracta de la gramática de tal
manera que en los hijos del árbol
solo aparecen los símbolos
semánticamente relevantes
Foco de
atención de la
asignatura
104. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 14
If (a>b) then a:=b else b:=a If (a>b) then a:=b else b:=a
(2 + 3) * 5
(2 + 3) * 5
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Arboles de análisis sintác8co Arboles sintác8cos abstractos
E
E * E
( E ) n
E + E
nn
*
+ n
n n
IF
> := :=
ID ID ID ID
SIf
IF ( E ) THEN S ELSE S
E > E
while (a>b) do a++
SWhile
WHILE ( E ) DO S
E > E
while (a>b) do a++
WHILE
> ++
ID ID
ID
ID ID
105. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 15
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Ejercicios
› L1. Declaración de variables en Pascal
› L2. Declaración de estructuras en C
› L3. Declaración de procedimientos en Pascal
› L4. Declaración de procedimientos en C
› L5. Declaración de sentencias en C
› L6. Declaración de sentencias en Pascal
› L7. Sentencia for en C
› L8. Sentencia Repeat – Until en Pascal
Sentencia ::= BloqueSentencias |
SentenciaIf |
Sentencia While
BloqueSentencias ::= { listaSentencias }
listaSentencias ::= sentencia ; ListaSentencias |
ﻉ
SentenciaIf ::= …
SentenciaWhile ::= …
L5
Construya arboles de análisis sintáctico para frases en
cada uno de los lenguajes anteriores
106. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 16
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Limpieza grama8cal
Para no tener problemas en la construcción de analizadores sintácticos es
conveniente aplicar ciertas operaciones de trasformación gramatical. Estos problemas
son:
Limpieza
gramatical
Eliminación de la ambigüedad
Es necesario eliminar las expresiones gramaticales que
generen una interpretación potencialmente gramatical
ambigua
Factorización por la izquierda
Las reglas con partes comunes a la izquierda de los
consecuentes pueden también generar problemas, en
función del analizador que se construya
Eliminación de la recursividad a izquierdas
En algunos casos las reglas con recursividad a
izquierdas de la forma A ::= A α pueden acarrear
problemas en la construcción de analizadores