Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Procesadores de Lenguajes II

823 views

Published on

Material Completo de la asignatura Procesadores de Lenguajes II correspondiente al Grado en Ingeniería Informática impartido por la UNED

Published in: Education
  • Be the first to comment

  • Be the first to like this

Procesadores de Lenguajes II

  1. 1. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas Informá6cos UNED Universidad Nacional de Educación a Distancia Grado en Ingeniería Informática
  2. 2. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas Informá?cos UNED Parte I Presentación
  3. 3. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas InformáAcos UNED 1 Introducción El proceso de compilación
  4. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  43. 43. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas Informá?cos UNED Parte II Etapa de análisis
  44. 44. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas InformáAcos UNED 2 Análisis léxico Lenguajes regulares
  45. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  91. 91. Procesadores de Lenguajes Ingeniería Técnica superior de Ingeniería Informá8ca Departamento de Lenguajes y Sistemas informá6cos Javier Vélez Reyes jvelez@lsi.uned.es Departamento de Lenguajes Y Sistemas InformáAcos UNED 3 Análisis sintác*co I Lenguajes libres de contexto
  92. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

×