El análisis sintáctico predictivo no recursivo utiliza una tabla donde a cada símbolo de entrada le corresponde una producción de la gramática, con esto se evitan los procesos recursivos.
El análisis sintáctico predictivo no recursivo utiliza una tabla donde a cada símbolo de entrada le corresponde una producción de la gramática, con esto se evitan los procesos recursivos.
La Web está evolucionando a pasos agigantados en los últimos tiempos. Una de las direcciones de avance en este sentido apunta hacia su modularización. En lugar de construir pesadas aplicaciones monolíticas, parece estar más en sintonía con los principios arquitectónicos de la Web hacer un desarrollo dirigido por la construcción de componentes Web sencillos, atómicos y funcionales que fomenten su reutilización transversal y puedan utilizarse como etiquetas de autor personalizadas para articular soluciones elaboradas. Pero más allá de limitarnos a construir componentes Web y utilizarnos de manera conjunta en una página huesped, la orientación a componentes exige encontrar cierto grado de interoperabilidad entre los mismos para ofrecer una sensación de continuidad en su uso al usuario final.
De acuerdo a esta idea, en esta charla comenzaremos haciendo una revisión de la tecnología utilizada para la construcción de componentes Web según las especificaciones estándar de la W3C y del WWG, haciendo uso de la Plataforma de soporte Polymer de Google como implementación nuclear de referencia. Esto nos dará pie para presentar el problema de cómo puede abordarse la construcción de soluciones Web orientadas a componentes para ofrecer niveles de interoperabilidad adecuados. Ofreceremos, en este sentido, algunas soluciones arquitectónicas al respecto y presentaremos ejemplos de su aplicabilidad práctica en contextos realistas.
NodeJS es una plataforma que permite programar servidores dedicados en Javascript de forma sencilla y eficaz. Pese a que Javascript no es un lenguaje con soporte a la concurrencia, el carácter no bloqueante de las operaciones que realizan accesos de entrada salida E/S permite avanzar los flujos de ejecución aumentando la productividad y la escalabilidad del sistema total. En efecto, los tiempos de espera en cada operación motivados por los accesos a disco son aprovechados para procesar nuevas peticiones entrantes en el servidor. Pese a sus innegables ventajas en productividad, el modelo de programación se complica. Dado que ahora las operaciones se liberan del flujo de control para retomarse posteriormente, ¿cómo podemos determinar cuándo una operación ha terminado? ¿Cómo podemos recuperar sus resultados? ¿Cómo gestionamos sus errores potenciales? A lo largo de este texto presentaremos diferentes modelos de programación que pueden ser empleado para dar respuesta a estas y otras preguntas en el marco de la programación asíncrona.
Orientando a Componentes la Web
Charla Desarrollo de sobre Componentes Web en Polymer para HTML5 Spain Madrid 14/07/14
La Web está evolucionando a pasos agigantados en los últimos tiempos. Una de las direcciones de avance en este sentido apunta hacia su modularización. En lugar de construir pesadas aplicaciones monolíticas, parece estar más en sintonía con los principios arquitectónicos de la Web hacer un desarrollo dirigido por la construcción de componentes Web sencillos, atómicos y funcionales que fomenten su reutilización transversal y puedan utilizarse como etiquetas de autor personalizadas para articular soluciones elaboradas. Pero más allá de limitarnos a construir componentes Web y utilizarnos de manera conjunta en una página huesped, la orientación a componentes exige encontrar cierto grado de interoperabilidad entre los mismos para ofrecer una sensación de continuidad en su uso al usuario final.
De acuerdo a esta idea, en esta charla comenzaremos haciendo una revisión de la tecnología utilizada para la construcción de componentes Web según las especificaciones estándar de la W3C y del WWG, haciendo uso de la Plataforma de soporte Polymer de Google como implementación nuclear de referencia. Esto nos dará pie para presentar el problema de cómo puede abordarse la construcción de soluciones Web orientadas a componentes para ofrecer niveles de interoperabilidad adecuados. Ofreceremos, en este sentido, algunas soluciones arquitectónicas al respecto y presentaremos ejemplos de su aplicabilidad práctica en contextos realistas.
La reutilización ha sido desde siempre uno de los objetivos más perseguidos dentro de la ingeniería del software. La idea de convertir los procesos de construcción de aplicativos en algo automatizable, sencillo y económico siempre ha estado ahí en la cabeza de los desarrolladores. Pero, de manera recurrente, esta iniciativa se ha dado de bruces con los inamovibles mimbres de unos paradigmas de programación demasiado inflexibles a este respecto.
Sin embargo, lenguajes como Javascript se prestan mucho más a hacer del desarrollo de código un ejercicio de verdadera reutilización. A lo largo de esta charla explicaremos cuáles son las barreras paradigmáticas que suelen impedir la reutilización y cómo y en qué sentido JavaScript consigue soslayarlas con éxito. Asimismo presentaremos una colección de modelos arquitectónicos basados en Mixins, Traits, Roles, Aspectos, Subjects, etc. que se están usando en proyectos de software actuales con este lenguaje precisamente por las bondades que ellos.
This is a real estate listing presentation that drives home our clients’ USP built around our core focus of talking to buyers and sellers immediately.
Agents need to quit chasing prospects, battling voicemail and talk with people. As an agent, if you’re not talking with people you’re failing. The most successful agents are talking with people all day, every day. The key is talking to the right people, at the right time, in the right way.
Proquest Technologies goes beyond lead generation to delivering perfectly-timed live conversations with buyers and sellers. While the rest of the industry focuses on capturing more lead data, our clients are having quality conversations! The best part is their lead conversion rates are skyrocketing!
To learn more go to www.ConversationsFirst.com
Cada lenguaje, cada tecnología, cada paradigma de programación persigue siempre la reutilización de código. En la comunidad de desarrollo se habla frecuentemente de DRY (Don’t Repeat Yourself) o WORE (Write Once Run Everywhere). Pero estos manidos mantras se quedan frecuentemente en una mera declaración de principios.
El código desarrollado para su reutilización no es capaz de reubicarse en otros contextos arquitectónicos de aquellos para los que fue inicialmente diseñado. Las capacidades de meta-programación de JavaScript le convierten en un lenguaje flexible y lo suficientemente plástico como para adaptarse dinámicamente a cualquier solución construida.
En esta charla exploramos como construir programas que se modifiquen a si mismos para resolver estos problemas y hablaremos de modelos de programación basados en componentes de software.
La programación funcional está cogiendo fuerte tracción en los últimos años dentro de la comunidad de desarrollo. Tal vez ello se deba al surgimiento de nuevas arquitecturas que demandan cotas de escalabilidad, resistencia y flexibilidad en el marco de soluciones centradas en procesos de transformación. Pero más allá de una simple moda, como trataremos de mostrar en este taller, la programación funcional conduce a soluciones de código robustas, versátiles y expresivas que difícilmente son comparables con las propias de la orientación a objetos.
Además JavaScript, como la mayoría de los lenguajes de scripting es un lenguaje idiomático que invita a pensar en términos funcionales. De hecho muchas veces, cuando programamos en Javascript, desarrollamos soluciones funcionales casi sin darnos cuenta. Pero para trabajar correctamente en el marco de este paradigma debemos saber, qué es exactamente la programación funcional, cuáles son sus ventajas y principios fundacionales, de qué mecanismos se sirve, qué técnicas de programación se utilizan, qué patrones de diseño funcional existen a nuestra disposición y qué estilos arquitectónicos emergen.
Este taller trata de dar una introducción a la programación funcional que comienza desde lo más básico y va pasando progresivamente hacia conceptos más avanzados. A continuación se resume una relación del programa de contenidos para que os hagáis una idea de lo que se va a abordar.
- Diseño de Funciones I. Recursión
- Diseño de Funciones II. Inmersion
- Orden Superior I. Famila map & reduce
- Orden Superior II. Evaluación Partial
- Orden Superior III. Closures & Retentión Léxica
- Composición I. compose & sequence
- Composición II. Inversión de control
- Composición III. Streams
- Diseño sin Estado I. Fundamentos
- Diseño sin Estado II. Mónadas
- Conceptos Avanzados I. Optimización
- Conceptos Avanzados II.Inmutabilidad
Todos estos temas se abordan en 12 ficheros `.js` que se encuentran en [https://goo.gl/YwXtkV], en la carpeta `code/`. Para falilitar la realización y autoevaluación, el material de este taller se ha dividido en dos carpetas. En `code/problems` puede encontrarse una descripción de cada ejercicio planteado junto con una plantilla de código que ayuda a escribir la solución y probarla. En la carpeta `code/solutions` se ofrece una propuesta de solución para cada ejercicio planteado. Se anima al lector a no consultar la solución hasta haber intentando cada ejercicio por si mismo.
The Ultimate Guide to Creating Visually Appealing ContentNeil Patel
From videos to infographics, I’m constantly leveraging visual media.
Can you guess why?
It’s because these visual content pieces are generating more backlinks than any other form of content I publish, which—in the long run—helps increase my search engine rankings and overall readership numbers.
So, how do you create these visual masterpieces? Well, this infographic should help you.
Da una introduccion muy general sobre la historia de las computadoras, la division en hardware y software.
También explica la diferencia entre programa compilado e interpretado. Una breve historia sobre la tendencia de los lenguajes de computadora.
Las diferentes conversiones numericas entre diferentes bases como : base diez, base dos, base ocho y hexadecimal.
Da una introduccion muy general sobre la historia de las computadoras, la division en hardware y software.
También explica la diferencia entre programa compilado e interpretado. Una breve historia sobre la tendencia de los lenguajes de computadora.
Las diferentes conversiones numericas entre diferentes bases como : base diez, base dos, base ocho y hexadecimal.
Se plantea en este tema, de forma general, los lenguajes de programación de bajo y alto nivel, como el lenguaje ensamblador, entre otros.
Se describe la diferencia entre compiladores e interpretes, además de las etapas de desarrollo de un programa o software.
Presentación multimedia de investigación acerca de conceptos y tipologías de interfaces informáticas elaborada por Victor Cabral, Ayudante de la Cátedra Informática, Departamento de Ciencias de la Comunicación, Facultad de Ciencias Humanas, Universidad Nacional de Río Cuarto, 2002.
El mundo cambia. Los nuevos medios de interacción basados en texto e imagen, las interfaces orales y de realidad aumentada e inmersiva dibuja una nueva forma en la que los usuarios se acercan a los negocios. Como ingenieros debemos orientar a los clientes en este cambio. Nuestra labor como arquitectos es prepararnos tecnológicamente. En esta charla discutimos cómo podemos enfrentar este cambio y cómo debemos reorientar el diseño de nuestras arquitecturas para hacer frente a este nuevo paradigma de uso. Si quieres aprender a hacer el software del futuro esta es la charla que no te debes perder
En los últimos años se ha hablado mucho de los estilos arquitectónicos en boga para desarrollar las soluciones orientadas a servicios. Sin embargo, cuando diseñamos servicios caemos siempre en los mismos esquemas y los repetimos de proyecto a proyecto sin ponernos en cuestión su validez para cada problema en cuestión.
En esta charla haremos un recorrido de los fundamentales modelos de diseño de APIs de servicios que pueden desarrollarse para cada tipo de problema. Además ofreceremos técnicas y patrones de diseño aplicables para cada uno de estos modelos.
Tradicionalmente, los modelos de componentes utilizados en el mundo de front se utilizan como un mecanismo de modularidad para descomponer una solución. De forma más ambiciosa, se construyen sistemas de diseño basados en componentes en aras a aumentar la reutilización entre proyectos y mejorar la productividad en los desarrollos.
Sin embargo, para que la reutilización se convierta en una realidad constatable necesitamos cambiar nuestra aproximación al problema. Más que crear arquitecturas polimórficas que acepten distintos tipos de componentes. Necesitamos crear componentes que sean capaces de adaptarse plásticamente y de forma dinámica a cada contexto arquitectónico de uso.
En esta charla presentaremos una colección de técnicas y modelos de adaptación que pueden ser aplicados sobre nuestros sistemas de componentes con independencia del stack tecnológico en que estén implementados: Vue, React, Polymer, etc. Si perteneces al mundo del front y te gusta ver código esta charla te interesará.
La Web está cambiado. Es una realidad. En poco más de 20 años, esta plataforma ha evolucionado sus pragmáticas de uso impactando también el modelo cultural de nuestra sociedad. Primero fue un espacio virtual de recursos estáticos. Hoy un gran entramado de relaciones sociales donde se confunde lo virtual y lo real. ¿Internet es un reflejo de lo que somos o más bien nos hemos adaptado a como es Internet hoy en día por diseño?
Pero un nuevo cambio se vislumbra en el futuro inmediato. La Web no será una herramienta más a nuestro alcance para disfrute discrecional. Empezamos a vivir en una burbuja digital donde la Web llega a nosotros y nosotros la gestionamos de forma micro-interactiva y reactiva.
La pregunta que debemos hacernos en este nuevo escenario es, ¿Que papel jugamos como desarrolladores, diseñadores, especialista UX y personal técnico en esta nueva Web? ¿Cual es mi espacio de acción y mi responsabilidad? En esta charlase ofrece un decálogo de cambios para los que debemos prepararnos que ayudarán a responder a esta pregunta.
Esta charla es la Key Note del Keep Coding Connect 2017. Un evento para desarrolladores organizadas por una de las compañías referentes en formación técnica en este país.
Arquitectura de Componentes Web. Patrones de Acceso a DatosJavier Vélez Reyes
La mayor parte de los aplicativos que manejamos hoy en día corresponden con arquitecturas centradas en los datos. Modelos de información expuestos en forma de servicios que son explorados en profundidad. En este contexto, las arquitecturas de componentes Web se presentan como una solución idónea para llevar a cabo este proceso exploratorio de manera sencilla y declarativa. A lo largo de esta charla discutiremos este tipo de arquitecturas y presentaremos los patrones de diseño fundamentales que resuelven este tipo de escenarios.
Arquitecturas de Componentes Web. Patrones de ComposiciónJavier Vélez Reyes
La tecnología de componentes web ha supuesto un revulsivo en la forma en la que se desarrollarán soluciones web en los próximos años. Si algo hemos aprendido, en este sentido, es que debemos dejar de construir aplicaciones monolíticas y empezar a pensar en crear componentes Web estratégicamente diseñados para que cubran las necesidades más comunes dentro de este tipo de problemas.
Polymer y los estándares de componentes Web nos proporcionan ya toda una panoplia de herramientas para construir este tipo de soluciones de manera más sencilla. Sin embargo, aun faltan muchos mimbres por establecer. La necesidad de un modelo arquitectónico de referencia se dibuja como una necesidad insoslayable para poder articular soluciones de éxito de esta naturaleza. En efecto una arquitectura nos ofrece un marco prescriptivo preciso donde dar forma a las contribuciones de múltiples partes para crear un catálogo de componentes coherente que pueda ser utilizado por la comunidad para construir soluciones orientadas a componentes web.
En relación a lo anterior, a lo largo de esta charla centraremos nuestra atención en un problema nuclear: ¿Cómo deben articularse los procesos de composición en el marco de esta tecnología? Para responder esta pregunta no debemos olvidar que este nuevo paradigma prescribe un proceso constructivo desarrollado en el ámbito declarativo del lenguaje HTML y no en el espacio programático de JavaScript, dado que así se consiguen procesos de desarrollo más sencillos, ágiles y productivos. En relación a la composición todo esto implica que no sólo debemos esforzarnos por crear componentes visuales que den respuesta a las necesidades recurrentes de interacción en el plano del front sino que, adicionalmente, debemos elaborar un conjunto de componentes dedicado a a estereotipar y encapsular toda aquella lógica de composición más común. De esta manera el desarrollo de soluciones orientadas a componentes web alcanzará su madurez plena al convertir un tedioso proceso constructivo en un ejercicio de confección compositiva asistido por componentes que proporcionan código pegamento. Todo esto se resume en que debemos crear componentes visuales, sí, pero además componentes para componer.
La Web está evolucionando y los procesos de desarrollo en relación a la misma también lo hacen. Es una realidad vigente que cada vez más este tipo de soluciones pasarán por la construcción de componentes Web de negocio, etiquetas de autor que extienden el léxico del estándar HTML. Google vehicula esta solución a través del framework Polymer, cuya version 1.0 vio la luz hace pocos meses coincidiendo con la Google I/O 2015.
Pero en esta charla, no nos limitaremos a presentar las novedades de este Framework que pueden leerse directamente en la Web, que también. Hablaremos de los resultados de nuestra investigación en este terreno. Cuáles son los principios de diseño de componentes web, cuál es el modelo adecuado de componentes y cómo debe desarrollarse una arquitectura basada en componentes que cumpla con las necesidades arquetípicas de las soluciones Web y Mobil de hoy en día.
Charla para JS Day Madrid 2015 09/05/2015:
- Video: https://goo.gl/jOm4aN
- Slideshare: http://goo.gl/cnTQw9
- Github: https://goo.gl/as8pdD
Cada lenguaje, cada tecnología, cada paradigma de programación persigue siempre la reutilización de código. En la comunidad de desarrollo se habla frecuentemente de DRY (Don’t Repeat Yourself) o WORE (Write Once Run Everywhere). Pero estos manidos mantras se quedan frecuentemente en una mera declaración de principios.
El código desarrollado para su reutilización no es capaz de reubicarse en otros contextos arquitectónicos de aquellos para los que fue inicialmente diseñado. Las capacidades de meta-programación de JavaScript le convierten en un lenguaje flexible y lo suficientemente plástico como para adaptarse dinámicamente a cualquier solución construida.
En esta charla exploramos como construir programas que se modifiquen a si mismos para resolver estos problemas y discutiremos mecanismos, técnicas y patrones de metaprogramación basados en componentes de software.
Video: http://goo.gl/acVK2t
Slideshare: http://goo.gl/2OChM4
Github: http://goo.gl/29ldtQ
La Web se está orientando a componentes. El objetivo es alcanzar una Web cada vez más madura, dirigida a fomentar la sencillez en las tareas de diseño y construcción, aumentar la rapidez y agilidad de desarrollo y mejorar la productividad general de las soluciones Web. Todo esto se consigue en parte debido al carácter declarativo que confiere la tecnología de componentes Web que, además, permite encapsular un comportamiento complejo, absorber la gestión adaptativa de los contenidos y, a la postre, generar un vocabulario propio de etiquetas de autor que fomenta la reutilización de código desde el front end.
Sin embargo, la comunidad demanda de manera creciente la definición de directrices y buenas prácticas en relación con las actividades de diseño y desarrollo vinculadas a la construcción de soluciones basadas en componentes Web. En esta charla ofreceremos una colección de principios que tienen por objetivo orientar a los equipos implicados en este tipo de proyectos.
En los últimos tiempos se viene demandando dentro de las comunidades de desarrollo la construcción de arquitecturas reactivas que sean capaces de hacer frente a parámetros de rendimiento y tiempo de respuesta no conocidos hasta el momento. Una arquitectura reactiva es un sistema responsive capaz de reaccionar a tiempo a los requisitos bajo demanda, diseñado para adaptarse elásticamente a sus fluctuaciones variantes, que presenta un comportamiento altamente tolerante a fallos y que se dirige por un procesamiento masivo de mensajes.
Pero más allá de todo esto, las arquitecturas reactivas se han convertido en un modelo de programación basado en transformaciones funcionales para dar soporte a sistemas dirigidos por eventos asíncronamente. En marco del desarrollo de soluciones para Front End, este tipo de aproximaciones está cogiendo tracción debido a lo bien que se adapta al modelo de interacción de la Web. En este contexto, los eventos responden a las interacciones del usuario sobre el agente navegador y la lógica de negocio se expresa como la transformación secuencial y progresiva de los mismos de forma encadenada. A lo largo de esta charla estudiaremos cómo funcionan este tipo de arquitecturas en contraposición con las clásicas soluciones MV* y presentaremos el modelo de desarrollo asociado.
Programación Funcional en Javascript. 27/10/2014. NodeJS Madrid
Video: http://bit.ly/1xTizFc
Code: http://bit.ly/1qmmR3Q
La programación funcional está cogiendo fuerte tracción en los últimos años dentro de la comunidad de desarrollo. Tal vez ello se deba al surgimiento de nuevas arquitecturas que demandan cotas de escalabilidad, resistencia y flexibilidad en el marco de soluciones centradas en procesos de transformación. Pero más allá de una simple moda, como trataremos de mostrar en esta charla, la programación funcional conduce a soluciones de código robustas, versátiles y expresivas que difícilmente son comparables con las propias de la orientación a objetos.
Además JavaScript, como la mayoría de los lenguajes de scripting es un lenguaje idiomático que invita a pensar en términos funcionales. De hecho muchas veces, cuando programamos en Javascript, desarrollamos soluciones funcionales casi sin darnos cuenta. Pero para trabajar correctamente en el marco de este paradigma debemos saber, qué es exactamente la programación funcional, cuáles son sus ventajas y principios fundacionales, de qué mecanismos se sirve, qué técnicas de programación se utilizan, qué patrones de diseño funcional existen a nuestra disposición y qué estilos arquitectónicos emergen.
En esta charla descubriremos cómo se construyen arquitecturas funcionales dirigidas por los datos, hablaremos de programación por capas basada en orden superior y presentaremos modelos de programación concomitantes como la programación reactiva basada en streams o las arquitecturas map/reduce propias de las técnicas de big data.
Un libro sin recetas, para la maestra y el maestro Fase 3.pdfsandradianelly
Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestra y el maestro Fase 3Un libro sin recetas, para la maestr
4. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 2
Obje6vos Generales
Obje8vos Generales
› Poner en contexto y justificar la relevancia de la compilación
› Aprender la diferencia entre compiladores y traductores
› Entender la diferencia entre compiladores e interpretes
› Apreciar el contexto en el que trabaja un compilador
› Apreciar cómo interactúan sus partes
› Entender la responsabilidad de cada una de ellas
› Analizar diferentes configuraciones alternativas
› Conocer el proceso completo de compilación
› Entender la responsabilidad de cada una de sus fases
› Obtener una visión general de las técnicas empleadas en cada una
› Aprender los principales artefactos que dan soporte a la compilación
› Discutir sobre la portabilidad de compiladores
5. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 3
Índice
Índice
› Introducción
› Traductores y compiladores
› Compiladores e interpretes
› Contexto de compilación
› Proceso de compilación
› Fases de compilación
› Etapas de compilación
› Artefactos de compilación
› Análisis de compiladores
› Representación de compiladores
› Tipos de compiladores
› Portabilidad de compiladores
› Práctica
6. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 4
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
I. Arquitecturas Von Neumann
› Representación del programa como instrucciones en memoria
› La unidad de control va leyéndolo secuencialmente
› Cada instrucción tiene un código de operación y unos operandos
› Operaciones aritmético lógicas, comparativas, de salto, de E/S,…
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
Código de operación
Operando 1
Operando 2
* En esta descripción se han omitido muchos paradigmas
7. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 5
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
II. Paradigma ensamblador
› Los códigos de operación se sustituyen por acrónimos
› Los operandos se sustituyen por registros y referencias a memoria
› El juego de instrucciones sigue siendo el mismo
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX [1305]
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
MOVE AX #2
MOVE BX [1305]
MUL CX AX BX
Acrónimo de operación
Operando 1 de tipo registro
Operando 2 de tipo literal numérico
Operando 2 referencia a memoria
* En esta descripción se han omitido muchos paradigmas
8. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 6
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
III. Paradigma estructurado impera8vo
› Flujo de ejecución secuencial
› Metáfora de variables y operación de asignación
› Tipificación de los datos
› Estructuras de control iterativas y condicionales (no de salto)
› Subrutinas para modularizar los programas
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
b (x, y);
C (x, y);
if (x > y) f (x);
else g (y);
while (x = y) {
d (x, y);
e (x, y);
}
* En esta descripción se han omitido muchos paradigmas
9. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 7
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
IV. Paradigma concurrente
› Varios flujos de ejecución secuencial asociados a procesos
› Es necesario cuidar el acceso concurrente a recursos
› Mecanismos de exclusión mutua y de sincronización por condición
› Para cada proceso el algoritmo sigue siendo imperativo
› Existen lenguajes concurrentes funcionales
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
x
lector lector lector
Leer x
lector lector escritor
Escribir x
* En esta descripción se han omitido muchos paradigmas
10. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 8
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
V. Paradigma funcional declara8vo
› Únicamente declaración de funciones
› El resultado de una expresión depende sólo de sus sub-expresiones
› No hay efectos colaterales en la evaluación funcional
› No existe asignación ni estructuras de control
› Se da soporte a la definición recursiva de funciones
› Las funciones se usan como datos (orden superior, currificación,…)
› Operaciones map / reduce
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
fun invertir (l) =
[] -> []
| (p: resto) -> invertir(resto): p
* En esta descripción se han omitido muchos paradigmas
11. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 9
Introducción
Esfuerzo de abstracción
La historia de la programación puede describirse como un constante
esfuerzo por acercar el lenguaje ejecutable de las arquitecturas
hardware a un lenguaje más próximo al humano a través de
sucesivos pasos de abstracción
VI. Paradigma de orientación a objetos
› Las operaciones acompañan a las estructuras de datos
› Clases con bajo acoplamiento y fuerte cohesión
› El algoritmo se encuentra distribuido en la colaboración entre objetos
› Herencia, polimorfismo, ligadura dinámica y genericidad
› Los objetos se gestionan en el heap
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
for (i in [2..n])
for (j in [0..n-1])
if (c.mayor (a[j], a[j+1]))
intercambiar (a[j], a[j+1])
* En esta descripción se han omitido muchos paradigmas
Lista
- ordenar ()
Comparador
- mayor (x, y)
ComparadorA
ComparadorB
usa
12. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 10
Traductores y compiladores
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
¿Qué es un compilador?
Para dar soporte a este proceso de abstracción es necesario idear
programas capaces de traducir las expresiones abstractas en
secuencias de instrucciones máquina interpretables por un
ordenados
Definición
Un compilador es un programa que lee un programa escrito en
lenguaje fuente, y lo traduce a un lenguaje objeto de bajo nivel.
Además generará una lista de los posibles errores que tenga el
programa fuente
Compilador
Lenguaje
fuente
Lenguaje
objeto
Compilador
13. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 11
Traductores y compiladores
11100110 0001 0110
10101001 1100 0011
11000011 1101 1100
1945
MOVE AX #2
MOVE BX #3
MUL CX AX BX
1950
Fact = 1;
For i:=0 to 10
fact := fact * i;
1968
Wait (q);
i := fact (x);
Signal (q);
1970
fun mul (x, y) = x*y
fun fact (n, m) =
0 -> 1
| m (n, fact (n-1, m))
1990
bajo
nivel
alto
nivel
+niveldeabstracción–
Class Punto {
int x, y;
int modulo () {...}
}
1995
¿Qué es un traductor?
Cuando lo que se pretende es cambiar la expresión sintáctica de un
programa de un lenguaje de alto nivel a otro no hablamos de
compilador sino de traductor
Definición
Un traductores un programa que lee un programa escrito en
lenguaje fuente de alto nivel, y lo traduce a un lenguaje objeto
también de alto nivel.
Traductor
Lenguaje
fuente
Lenguaje
objeto
fact = 1;
for (int i = 0; i <= 10; i++)
fact *= i;
Pascal C
traductor
14. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 12
Traductores y compiladores
Traductores y compiladores
I. Traductor
II. Compilador
Un compilador es un programa que lee un programa escrito en
lenguaje fuente, y lo traduce a un lenguaje objeto de bajo nivel.
Además generará una lista de los posibles errores que tenga el
programa fuente
Un traductores un programa que lee un programa escrito en
lenguaje fuente de alto nivel, y lo traduce a un lenguaje objeto
también de alto nivel.
Compilador
Lenguaje
fuente
Lenguaje
objeto
Traductor
Lenguaje
fuente
Lenguaje
objeto
}
Foco de atención principal de la
asignatura
15. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 13
Compiladores e interpretes
Compiladores e interpretes
I. Compilador
Un compilador es un artefacto software capaz de
generar un programa ejecutable a partir de un
programa escrito en un lenguaje de alto nivel
II. Interprete
Un interprete es un artefacto software capaz de
ir interpretando secuencialmente la colección de
instrucciones de un programa escrito en un
lenguaje de alto nivel para ejecutarlas
› Se obtiene un fichero ejecutable
› El proceso de compilación se realiza sólo una vez
› El proceso de compilación es más lento
› Mayor consumo de memoria
› Mayor cantidad de detalles de errores de compilación
› Mayor velocidad de ejecución del programa ejecutable
› Los errores en ejecución se minimizan
› No se obtiene un fichero ejecutable
› El proceso de interpretación se realiza cada vez
› El proceso de interpretación es más rápido
› Menor consumo de memoria
› Menor cantidad de detalles de errores de compilación
› Menor velocidad de ejecución del programa ejecutable
› Los errores en ejecución son mayores
16. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 14
Contexto de compilación
I. Precompilador
Algunos compiladores incluyen precompiladores capaces de hacer un tratamiento
preliminar del fichero fuente para prepararlo para el proceso de la compilación. Esta
herramienta suele eliminar comentarios, sustituir constantes simbólicas por sus valores
literales, o extender en el código fuente las macros definidas
II. Compilador
El compilador es el programa encargado de realizar el proceso de traducción del
programa fuente para expresarlo en términos de una secuencia de instrucciones de
código máquina interpretables por un ordenador
}
Foco de atención
principal de la
asignatura
III. Enlazador o montador
El producto resultante del compilador no es un fichero directamente ejecutable en la
arquitectura. Muchas funciones, invocadas desde el programa fuente, y cuyo código se
encuentra programado y compilado en otro fichero deben ser incorporadas al fichero
resultante de la compilación para que sea autónomo. De esto se encarga el montador
Elementos del contexto de la compilación
17. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 15
Contexto de compilación
Elementos del contexto de la compilación
IV. Enlazador dinámico
Con el ánimo de que los programas finales no sean muy pesados, muchas funciones
externas no se incluyen en el ejecutable final sino que son enlazadas dinámica y
automáticamente por el sistema operativo, que se encarga de gestionarlas. Como
consecuencia los ejecutables son más pequeños pero establecen dependencias con
recursos que han de estar presentes en el sistema operativo
V. Depurador
Los errores producidos en tiempo de compilación son reportados por el compilador para
su corrección. Sin embargo los ocurridos en tiempo de ejecución pueden ser más
difíciles de detectar. Es necesario hacer ejecuciones paso a paso para comprobar el
estado que va tomando cada variable del programa. El depurador ayuda a realizar este
tipo de trazas
VI. Ensamblador
A veces los compiladores no generan programas directamente ejecutables en código
máquina sino ficheros que corresponden a la expresión en ensamblador del código
fuente. Esto puede ser tremendamente útil - aunque en la actualidad no frecuente –
para permitir al programador optimizar los resultados generados por el compilador
18. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 16
Contexto de compilación
Ejecutable DOS
Ejecutable Windows
.C .H
Precompilador
.I .ASM
Compilador Ensamblador
.OBJ .OBJ .OBJ
Enlazador
. LIB
.ASM .EXE .EXE Ensamblador
Enlazador dinámico
. DLL
Proceso
Recurso
Compilador de C
19. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 17
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que
convierte un programa escrito en un lenguaje fuente de alto nivel en
otro programa escrito en un lenguaje objeto de bajo nivel. Ese
proceso se articula conceptualmente en una secuencia de fases
› Análisis léxico
› Análisis sintáctico
› Análisis semántico
› Generación de código intermedio
› Generación de código final
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Código final
e · l · i · h · w <WHILE, PR> S
WHILE E DO S
E > E
S
WHILE E DO S
E > E
√ LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
While ( a > b ) do
a := a + 1;
20. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 18
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador léxico
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
I. Análisis léxico
El analizador léxico (scanner) va leyendo caracteres del fichero hasta
encontrar una entidad con significado léxico. Estas entidades se llaman
tokens y son una estructura de datos que contiene información acerca
del mismo (tipo, lexema, número de fila y columna, valor, etc.)
La construcción de analizadores léxicos suele hacerse mediante
herramientas que hay que configurar indicando el tipo de token que es
necesario emitir para cada posible patrón léxico
while : <WHILE, PR>
do : <DO, PR>
l (l | d)* : <a, ID>
...
21. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 19
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador sintác8co
<WHILE, PR>
II. Análisis sintác8co
El analizador sintáctico (parser) va pidiendo tokens al analizador léxico
y los va organizando en frases de acuerdo a las reglas de construcción
gramatical del lenguaje. Como resultado genera un árbol de análisis
sintáctico que representa todo el programa en memoria
La construcción de analizadores sintácticos suele hacerse mediante
herramientas que hay que configurar indicando la colección de reglas
sintácticas que definen las construcciones del lenguaje gramaticalmente
correctas
S ::= SIf | Swhlile | ...
SWhile ::= while PI E PD
do S;
E ::= E + E
E ::= E * E
E ::= E > E
E ::= E < E
E ::= id
...
SWhile
WHILE E DO S
E > E
<a, ID>
<>, GT>
<b, ID>
<DO, PR>
<a, ID>
<:=, ASIG>
...
<(, PI>
<), PD>
22. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 20
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Analizador
semán8co
III. Análisis semán8co
El analizador semántico se encarga de gestionar la declaración de
constantes, funciones, procedimientos y variables y de comprobar la
corrección de tipos a lo largo de todo el programa. Como resultado se
obtiene un árbol de análisis sintáctico anotado, con atributos en cada
uno de sus nodos
La implementación del analizado semántico se realiza insertando
acciones semánticas en las partes derechas de las reglas de
producción gramatical
S ::= SIf | Swhlile | ...
SWhile ::= while PI E PD
do S;
{: if (E.tipo != booleano) error (); :}
...
SWhile
WHILE E DO S
E > E
SWhile
WHILE E DO S
E > E
√
23. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 21
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Código intermedio
IV. Generación de código intermedio
El generador de código intermedio traduce la representación
arborescente del programa en una secuencia ordenada de instrucciones
llamadas cuádruplas próximas al lenguaje máquina. Se trata de un
lenguaje abstracto y genérico que aún mantiene las referencias
simbólicas a los elementos declarados en el programa (variables,
parámetros, funciones, etc.)
La implementación del generador de código intermedio se realiza
insertando acciones en las partes derechas de las reglas de producción
que acumulan la traducción parcial del subárbol en cada nodo
exp ::= exp:e1 > exp:e2
{:...
e.código = e1.código +
e2.código +
CMP e1.temp r2.temp e.temp
:};
SWhile
WHILE E DO S
E > E
√
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
24. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 22
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
Op8mización Código
intermedio
V. Op8mización de código intermedio
En los compiladores comerciales es frecuente optimizar el resultado de
la fase anterior para hacer el programa más compacto y más rápido.
Suelen aplicarse estrategias de transformaciones heurísticas y
elementales que ofrecen buenos resultados
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
√
WHILE (A>B) AND (A<2*B-5) DO
A:=A+B
L1: IF A>B GOTO L2
GOTO L3
L2: T1 := 2*B
T2 := T1 – 5
IF A< T2 GOTO L4
GOTO L3
L4: A := A + B
GOTO L1
L3: ...
Optimización
Código intermedio
L1: IF A<=B GOTO L2
T1 := 2*B
T2 := T1 – 5
IF A>= T2 GOTO L2
A := A + B
GOTO L1
L2: …
25. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 23
Proceso de compilación
Fases de compilación
Toda compilación es un proceso de transformación paulatina que convierte un programa escrito en un lenguaje
fuente de alto nivel en otro programa escrito en un lenguaje objeto de bajo nivel. Ese proceso se articula
conceptualmente en una secuencia de fases
VI. Código final
Una vez que el código intermedio ha sido generado y optimizado
pueden resolverse las referencias simbólicas a posiciones de memoria
física y a recursos de la máquina (registros, pila, etc.). Además debe
traducirse cada cuarteto a sus equivalentes instrucciones en código
máquina
La traducción a código final se encarga de hacerla una rutina de
traducción ubicada en la acción semántica final ubicada al final de la
regla de producción del axioma
Código final
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
...
0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
26. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 24
Proceso de compilación
Etapas de compilación
› Expertos en lenguajes
› Independencia de arquitectura
› Dependencia de lenguaje
› Optimización de lenguajes
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Código final
e · l · i · h · w <WHILE, PR> S
WHILE E DO S
E > E
S
WHILE E DO S
E > E
√ 0000 0011
0000 0011
0100 0001
0100 0000
0001 0010
…
While ( a > b ) do
a := a + 1;
Etapa de análisis Etapa de síntesis
› Expertos en arquitecturas
› Dependencia de arquitectura
› Independencia de lenguaje
› Optimización de ejecución
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
27. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 25
Proceso de compilación
Equipos de compilación
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
While ( a > b ) do
a := a + 1;
EquipodeLenguaje
Op8mización Código
intermedio
Código final
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Op8mización Código
intermedio
Código final
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1 …
Equipode
arquitectura
Pascal C
Intel Solaris
Código intermedio
M
N
x
…
…
while ( a > b )
a++;
28. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 26
Proceso de compilación
Artefactos de compilación
A lo largo de todo el proceso de compilación se una colección de
artefactos para dar soporte al mismo. A lo largo del curso los
estudiaremos en detalle. Dos son de vital importancia
I. Tabla de símbolos
La tabla de símbolos se utiliza para gestionar todos los elementos
declarados por programador (constantes, tipos, variables, funciones y
procedimientos)
Analizador léxico
Analizador sintác8co
Analizador
semán8co
Código intermedio
Op8mización Código
intermedio
Código final
Tabla de símbolos
Analizador léxico En compiladores antiguos utilizado para
reconocer palabras clave
Analizador semántico Registra los elementos declarados por
el programador y los consulta para
efectuar la comprobación de tipos
Código intermedio Se consulta para conocer el espacio de
memoria que debe reservarse para
gestionar la activación de subrutinas y
para determinar el ámbito de
declaración de los elementos
Código final Se utiliza para traducir las referencias
simbólicas a posiciones de memorial
Fase Descripción
29. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 27
Proceso de compilación
Artefactos de compilación
A lo largo de todo el proceso de compilación se una colección de
artefactos para dar soporte al mismo. A lo largo del curso los
estudiaremos en detalle. Dos son de vital importancia
II. Gestor de errores
Las tres primeras fases pueden generar errores durante el proceso de
compilación. El gestor de errores se encarga de emitir mensajes de
los mismos para informar al programador
Gestor de errores
Analizador léxico
Carácter ñ no válido
Whiñe ( a > b ) do
a := a + 1;
Analizador sintác8co
Analizador
semán8co
SWhile ::= WHILE e DO s
Analizador léxico
While ( a > b )
a := a + 1;
Analizador sintác8co
Analizador léxico
While ( a > b ) do
a := a + ‘c’;
Se esperaba un
entero en expresión
de suma
30. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 28
Análisis de compiladores
Representación de un compilador
Como se ha discutido a lo largo del tema un compilador es una máquina de transformación
capaz de traducir un programa escrito en un lenguaje fuente a otro programa escrito en otro
lenguaje objeto. A su vez, éste está implementado en un tercer lenguaje llamado lenguaje
anfitrión. Por tanto, para representar en abstracto un compilador suele emplearse una
representación en forma de T que incluye los 3 lenguajes que lo caracterizan
› Lenguaje objeto (T)
› Lenguaje fuente (S)
› Lenguaje anfitrión (H)
S T
H }
H es un lenguaje máquina
frecuentemente igual a T
31. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 29
Análisis de compiladores
Tipos de compiladores
H
I. Ensamblador
ASM Máquina
H
II. Compilador cruzado
S T
H = T
H
III. Autocompilador
S T
H != T H = S
H
IV. Metacompilador
S T
H
V. Descompilador
T S
S especificaciones
T es un compilador
Se traduce de T a S
32. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 30
Análisis de compiladores
Portabilidad de compiladores
I. Portabilidad fuente des8no
A B
H
B C
H
= A C
H
II. Portabilidad de host
A B
H H K
M
= A B
K
La concatenación transitiva
de dos compiladores da
como resultado un
compilador del fuente del
primero al objeto del segundo
Si tenemos un compilador con anfitrión
H y necesitamos uno con anfitrión K
podemos usar un compilador H a K y
traducir los anfitriones
33. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 31
Análisis de compiladores
Portabilidad de compiladores
III. Arranque automá8co por transferencia
Java ENS
Java Java ENS
ENS
= Java ENS
ENS
Construimos un compilador de java
provisional en ensamblador.
Construirnos un compilador de java a
ensamblador en java. Para compilarlo
utilizamos el compilador provisional y
obtenemos un compilador de java a
ensamblador en ensamblador
mejorado. Recurrimos iterativamente
sustituyendo en cada pasada el
compilador provisional por el nuevo en
la iteración anterior
34. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 32
Construcción de compiladores en la prác6ca
Descripción de la prác8ca
S ENS2001
Java
› Lenguaje fuente : S
› Lenguaje objeto : ENS2001
› Lenguaje anfitrión : Java
Entrega de Febrero Entrega de Junio
› Analizador léxico
› Analizador sintáctico
50% especificación
Sesión de control (Enero)
› Analizador léxico
› Analizador sintáctico
› Analizador semántico
› Generación de código intermedio
› Generación de código final
50% especificación
Sesión de control (Mayo)
Test
Entrega de Septiembre
› Analizador léxico
› Analizador sintáctico
› Analizador semántico
› Generación de código intermedio
› Generación de código final
100% especificación
Sesión de control (Junio)
Test
› JFlex
› Cup
› Ant
› Marco de desarrollo
› ENS2001
Caracterís8cas Herramientas
35. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 33
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› Instalar JDK
› Descargar JDK de la página Web
› Ejecutar el instalable
› Comprobar la actualización de las variables de entorno path y classpath
› Descargar un IDE de desarrollo
› NetBeans
› Eclipse
› Descargar el marco de desarrollo proporcionado
› Descargar del entorno virtual
› Crear un proyecto a partir del marco de desarrollo
› Actualizar el IDE para que reconozca todas las libarías
› Crear tareas ant desde el IDE para ejecutar los scripts de ejecución y prueba de la práctica
I. Instalación y descarga
36. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 34
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Las clases compiladas se generan aquí
Las documentación de la arquitectura (sobre todo en 2ºcuatrimestre)
Tareas ant para ejecutar y depurar la práctica
§ clear
§ jflex
§ cup
§ build
§ flexTest
§ cupTest
§ finalTest
Memoria de la práctica según formato establecido
Consúltese el documento
“Directrices de implementación”
Especificaciones gramaticales de Cup
Especificaciones léxicas de JFlex
Test de prueba para las especificaciones A y B
Librerías necesariasCon8núa…
Esta primera parte del framework contiene la
documentación, ficheros de configuración, librerías de
ejecución, y directorios de soporte a la compilación
37. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 35
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Consúltese el documento
“Directrices de implementación”
Esta segunda parte del framework contiene la
infraestructura de clases abiertas que el usuario debe
extender o completar
Acceso a los artefactos del compilador
Entorno de ejecución donde se efectúa la generación del código final
Artefactos para la generación de código intermedio
Clase Token para comunicar el analizador léxico con el sintáctico
Clases Symbol y Type para representar los tipos y símbolos
Clases para representar los no terminales del árbol de análisis sintáctico
Programar para la prueba y depuración
§ LexicalTestCase
§ SyntaxTestCase
§ FinalTestCase
Con8núa…
38. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 36
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
II. Desarrollo sobre el framework de soporte
Consúltese el documento
“Directrices de implementación”
Esta tercera parte del framework contiene la
infraestructura de clases cerradas que ofrecen al
usuario funcionalidades completas para utilizar
Entorno de ejecución donde se efectúa la generación del código final
Artefactos para la generación de código intermedio
Artefactos para el análisis léxicos y el control de errores
Artefactos para el análisis semántico y el control de errores
Artefactos para el análisis sintáctico y el control de errores
39. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 37
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› La ejecución y prueba del marco de trabajo esta dirigida por tareas ant
› Clear: Borrar el contenido de /clases
› JFlex: Generar el analizador léxico (como un fichero fuente en src/lexical/scanner.java)
› Cup: Generar el analizador sintáctico (como un fichero fuente en src/syntax/parser.java)
› Build: Cup + Jflex + Compile
› flexTest: Ejecuta la prueba LexicalTestCase (generar tokens hasta final de fichero)
› cupTest: Ejecuta la prueba SyntaxTestCase (ejecuta el parser)
› finalTest: Ejecuta la prueba FinalTestCase (ejecuta el parser y traza el estado del compilador)
› Familia de tablas de símbolos creadas
› Familia de tablas de tipos creadas
III. Ejecución y prueba
40. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 38
Construcción de compiladores en la prác6ca
Primeros pasos con la prác8ca
› Especificación del analizador léxico
› Generación (Jflex + compilar)
› Prueba (FlexTest)
› Especificación del analizador sintáctico
› Generación (Build)
› Prueba (CupTest)
› Integración del analizador lexico con el sintáctico
› Generación (Build)
› Prueba (CupTest)
III. Fases de desarrollo del compilador
› Implementación en cup del sistema de tipos
› Generación (Build)
› Prueba (FinalTest)
› Generación de código intermedio
› Generación (Build)
› Prueba (FinalTest)
› Generación de código Final
› Generación (Build)
› Prueba (FinalTest)
› Pruebas finales con fichero de test
1er cuatrimestre 2º cuatrimestre
41. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 39
Bibliograca
Material de estudio
Bibliografía básica
Construcción de compiladores: principios y práctica
Kenneth C. Louden International Thomson Editores,
2004 ISBN 970-686-299-4
42. Javier Vélez Reyes jvelez@lsi.uned.es
Introducción. El proceso de compilación
1 - 40
Bibliograca
Material de estudio
Bibliografía complementaria
Compiladores: Principios, técnicas y herramientas.
Segunda Edición Aho, Lam, Sethi, Ullman
Addison – Wesley, Pearson Educación, México 2008
Diseño de compiladores. A. Garrido, J. Iñesta, F. Moreno
y J. Pérez. 2002. Edita Universidad de Alicante
45. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 2
Obje6vos
Obje8vos
› Conocer las responsabilidades de un analizador léxico
› Aprender cómo funciona
› Entender los diferentes tipos de patrones que reconoce
› Aprender a especificar formalmente analizadores léxicos
› A través de gramáticas formales
› A través de expresiones regulares
› A través de autómatas finitos
› Estudiar la implementación de analizadores léxicos
› Conocer las distintas estrategias de implementación
› Entender las posibles relaciones con la tabla de símbolos
› Estudiar la generación de errores léxicos
46. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 3
Índice
Índice
› Introducción
› Token
› Patrón léxico
› Lexema
› Lenguaje regular
› Especificación de analizadores léxicos
› Lenguajes regulares
› Gramáticas lineales
› Expresiones regulares
› Autómatas finitos
› Conversión de formalismos
› Implementación de analizadores léxicos
› basada en casos
› dirigida por tabla
› guiada por herramientas
› Estrategias de implementación
› Gestión de errores
› Construcción de A. léxicos en en la práctica
› ¿Qué es JFlex?
› ¿Cómo funciona JFlex?
› ¿Cómo se usa JFlex?
› Gestión de errores en JFlex
› Desarrollo paso a paso
› Bibliografía
47. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 4
Introducción
Analizador léxico
· i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
Analizador sintác8co
nextToken ()
Introducción
El primer paso para procesar un programa es convertir la colección de caracteres del
mismo en una colección de componentes léxicos con significado único dentro del
lenguaje llamados tokens. De eso se encarga el analizador léxico o escáner
El analizador sintáctico va
pidiendo nuevos tokens al
analizador léxico y éste los
sirve bajo demanda
Foco de atención
¿Cómo se formaliza un
analizador léxico?
¿Cómo se implementa un
analizador léxico?
› Formalismos
› Conversión entre formalismos
› Estrategias de implementación
› Buenas prácticas
48. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 5
Introducción
Introducción
El primer paso para procesar un programa es convertir la colección de caracteres del
mismo en una colección de componentes léxicos con significado único dentro del
lenguaje llamados tokens. De eso se encarga el analizador léxico o escáner
Definición de token
Un token es una unidad léxica indivisible con
significado único dentro del lenguaje. Desde el punto
de vista tecnológico se trata de una estructura de
datos que contiene información sobre
› ID: Tipo del token
› Número de línea
› Número de columna
› Lexema
› Valor…
Categorías de token
Los tipos de tokens existentes en un lenguaje son
una característica intrínseca al mismo. No obstante,
pueden encontrarse categorías generales
Categoría Ejemplos
Delimitadores
Palabras reservadas
Iden8ficadores
Números enteros
Números flotantes
Simbolos especiales
Cadenas
( ) , ; : [ ]
while true do if for
Index f isEven
3 -4 55 0 7658
4.5 .3 0.5 8.4e-5
+ -* / . = < > <= >= != ++
“Hola mundo!”
49. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 6
Introducción
Introducción
Cada tipo de token representa a un conjunto de tokens (construcciones léxicas
diferentes) con unos mismos propósitos dentro del lenguaje. Estos tipos se definen a
través de un patrón léxico al que se adscriben los lexemas del tipo
Definición de patrón léxico
Un patrón léxico es una expresión abstracta llamada
expresión regular que permite identificar
unívocamente un tipo de token y referenciar al
conjunto de todos los tokens que se ajustan a él.
Definición de lexema
La cadena de caracteres específica de un token
que se ajusta al patrón léxico de su tipo se llama
lexema. Existen dos tipos de lexemas
› Cadena propia: lexema idéntica al patrón
› Cadena no propia: lexema encaja con patrón
Tipo de token Patrón léxico
While
Enteros
División
Iden8ficador
while
digito+
/
letra (letra |digito)*
Ejemplos de lexema
while
12 123 0 45
/
Index f isEven
Cadena propia
SI
NO
SI
NO
50. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 7
Introducción
Introducción
Desde la perspectiva léxica un programa es una familia ordenada de
tokens de varios tipos. Cada tipo, a través de su patrón léxico, define
un micro lenguaje formado por todos aquellos lexemas que encajan
con el patrón léxico. Este tipo de lenguajes sencillos se llaman
lenguajes regulares
Definición de lenguaje regular
Un lenguaje regular describe una familia de tokens
que se ajustan a un determinado patrón léxico.
program burbuja;
uses crt;
const
n = 5;
var
i,j,temp:integer;
a:array[1..n] of integer;
begin
for i := 1 to n do
readln(a[i]);
for j := (n - 1) downto 1 do
for i := 1 to j do
if (a[i])>(a[i+1]) then
begin
temp := a[i];
a[i] := a[i+1];
a[i+1] := temp;
end;
writeln ('El resultado es:');
for i := 1 to n do
writeln (a[i]);
readln;
end.
Lenguaje de
iden8ficadores Pascal
burbuja
ctr
n
i
j
temp
a
readln
writeln
...
Lenguaje de palabras
reservadas de Pascal
program
uses
const
var
intger
of
array
begin
for
to
do
downti
if
then
End
...
Lenguaje de
delimitadores de Pascal
;
=
,
:
[
..
]
(
)
...
51. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 8
Especificación formal de analizadores léxicos
Especificación de lenguajes regulares
Además de la declaración extensiva – sólo viable en los lenguajes finitos – existen 3
diferentes maneras de definir formalmente un lenguaje regular. A lo largo de esta
sección estudiaremos cada una de ellas en detalle y veremos cómo se puede pasar de
cada una a las otras 2
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas finitos
› Elementos
› Gramáticas lineales
› Expresiones regulares
› Autómatas finitos
› Transformaciones
› De gramáticas a expresiones
› De gramáticas a autómatas
› De expresiones a gramáticas
› De expresiones a autómatas
› De autómatas a gramáticas
› De autómatas a expresiones
52. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 9
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Definición de gramá8ca lineal
Una gramática lineal es un conjunto de 4 elementos
G = (T, N, S, P) donde:
› T es un conjunto de símbolos terminales
› N es un conjunto de símbolos no terminales
› S Є N axioma gramatical
› P un conjunto de reglas de producción de la forma
1. A ::= B x donde A, B Є N y x Є T
2. A ::= x B donde A, B Є N y x Є T
3. A ::= x donde x Є T U { }ﻉ
A veces T se elide, N se deduce de los antecedentes de
las reglas de P y se asume que el antecedente de la
primera regla es S con lo G sólo a través de P
Tipos de gramá8cas lineales
Existen en realidad 2 tipos de gramáticas lineales. En
función de la forma del conjunto de reglas de
producción podemos distinguir entre:
› Gramáticas lineales por la izquierda
› Usan reglas A ::= B x
› Usan reglas A ::= x
› Gramáticas lineales por la derecha
› Usan reglas A ::= x B
› Usan reglas A ::= x
Dada una gramática G lineal por la izquierda siempre
se puede encontrar una gramática G’ lineal por la
derecha y recíprocamente
)representa la cadena vacía (ausencia de terminal ﻉ
53. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 10
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Derivación grama8cal
Una gramática debe interpretarse como un conjunto de reglas de reescritura o
transformación de elementos no terminales en elementos terminales o no
terminales.
› La primera transformación parte del axioma
› En cada paso se aplica una única regla
› Las reglas pueden extender la transformación ( A::= B x / A ::= x B)
› Las reglas pueden ser recursivas (A ::= A x / A ::= x A)
› Las reglas pueden ser terminales (A ::= x)
› El proceso debe ser convergente
LG = {a b*}
Sea G = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
A ::= a
B ::= b B
B ::= b
}
Ejemplo
54. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 11
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Derivación grama8cal
El problema ahora se traduce en, dada una cadena formada por una secuencia de
elementos terminales de T, demostrar que dicha cadena pertenece al lenguaje
definido por la gramática
LG = {a b*}
Sea G = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
A ::= a
B ::= b B
B ::= b
}
A → aB → abB → abbB → abbb
Ejemplo
axioma
Paso de
derivación
asidero
FraseF o r m a
de frase
Cadena de
derivación
55. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 12
› L1 = conjunto de todas las palabras sobre {a, b} que empiezan por a
› L2 = conjunto de todas las palabras sobre {a, b} que empiezan por a y continúan con secuencias ab
› L3 = Números fraccionarios
› L4 = Identificadores
Especificación formal de analizadores léxicos
Especificación mediante gramá8cas lineales
Una forma de definir formalmente un lenguaje regular es utilizar una gramática lineal,
que describe todas las reglas que se pueden aplicar para la construcción de lexemas
que pertenecen al lenguaje regular
Ejercicios
Definir formalmente a través de una gramática lineal
los siguientes lenguajes descritos informalmente
GD = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= a B
B ::= a B
B ::= b B
B ::= ﻉ
}
GI = (T, N A, P) con
T = {a, b}
N = {A, B}
P = {
A ::= A a
A ::= A b
A ::= a
}
L1
56. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 13
Especificación formal de analizadores léxicos
Especificación mediante expresiones regulares
Otra forma de definir lenguajes regulares es a través del uso de expresiones regulares.
Una expresión regular utiliza los términos del alfabeto de terminales operados a través
de operaciones con una semántica especifica
Una expresión regular sobre un conjunto T es un conjunto
ER = (T, | , · , *) que cumple las siguientes propiedades:
Definición de expresión regular
› Ø es una expresión regular que define el lenguaje L = Ø
} ﻉ { = )ﻉ ( cadena vacía) es una expresión regular que define el lenguaje L( ﻉ ›
› Cualquier símbolo a Є T es una expresión regular que define el lenguaje L ( a ) = { a }
› Si x, y son dos expresiones regulares, x·y es una expresión regular que define L ( x·y ) = L ( x ) L ( y )
› Si x, y son dos expresiones regulares, x | y es una expresión regular que define L (x | y) = L ( x ) U L ( y )
› Si x es una expresión regular x* es una expresión regular que define L ( x* ) = U L( x )
› Si x es una expresión regular x+ es una expresión regular que define el lenguaje L ( x* ) = U L( x )
› No existen más expresiones regulares
i =0
∞ i
∞
i =1
i
57. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 14
Especificación formal de analizadores léxicos
Especificación mediante expresiones regulares
Otra forma de definir lenguajes regulares es a través del uso de expresiones regulares.
Una expresión regular utiliza los términos del alfabeto de terminales operados a través
de operaciones con una semántica especifica
Definir los siguientes lenguajes regulares
utilizando para ello expresiones regulares
Ejercicios
› L1 = Lenguaje de identificadores
› L2 = Lenguaje de números naturales
› L3 = Lenguaje de números fraccionarios
› L4 = Lenguaje de números enteros con exponente
› L5 = Lenguaje de números fraccionarios con exponente
› L6 = Lenguaje de números pares
› L7 = Lenguaje de las cuentas de correo
› L8 = Lenguajes de las URL
L1 = l ( l | d )* l Є {a..z} d Є {0..9}
L3 = d+ . d+ d Є {0..9}
L6 = d+ p d Є {0..9} p Є {0, 2, 4, 6, 8}
L7 = nombre @ host
nombre = L1 (. L1)*
host = L1 (. L1)*
58. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 15
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Un autómata finito determinista es un conjunto
AFD = (T, Q, f, q, F) donde:
Autómata finito determinista
› T es un alfabeto de símbolos terminales de entrada
› Q es un conjunto de estados finito no vacío
› f: Q x T → Q es una función de transición
› q Є Q es un estado inicial o estado de arranque
› F C Q es un subconjunto de estados finales de aceptación
Gráficamente, un autómata finito determinista es
una colección de estados unidos por arcos,
donde para cada estado existe un arco
etiquetado con cada elemento de T. El estado
inicial tiene una flecha entrante y los estados
finales tienen un doble borde
Interpretación gráfica
letra
letra, dígito
letra, dígito
dígito
letra Є [a..z]
dígito Є [0..9]
1
2
0
59. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 16
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Con el ánimo de simplificar el trabajo con los autómatas finitos
deterministas, dentro de la teoría de compiladores se utilizan las
siguientes extensiones notacionales
Extensión de los autómatas finitos deterministas Interpretación gráfica
› Las transiciones ausentes se asumen como errores
› Se omiten los estados de absorción de errores
› Se usa la etiqueta otro para representar el resto de alternativas
› Los estados finales paran el proceso y emiten token
› Los estados finales con * recuperan el carácter de tránsito
› Se espera a reconocer el posible toquen de lexema más largo
› El estado final ya no es final
› Al llegar un carácter terminador se pasa a uno final
› Entonces se emite el token
› Si es necesario se marca con * el estado final
0
letra
letra, dígito
A continuación representamos el
autómata finito determinista anterior
aplicando las extensiones descritas
otro
letra Є [a..z]
dígito Є [0..9]
*
2
1
60. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 17
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Los autómatas arrancan en el estado de inició y comienzan a
consumir caracteres de la entrada lo que provoca una transición
a un nuevo estado o un error. En cuanto se alcanza un estado de
aceptación final, el autómata para y se emite el token reconocido
Como se usan los autómatas finitos deterministas
→ c → o → u → n → t → e → r → 0 → 1 → +
letra
letra, dígito
otro
letra Є [a..z]
dígito Є [0..9]
*
caracteres
Estado 0 Estado 1 Estado 2
transiciones
token
Carácter delimitador (otro)
0
2
1
61. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 18
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Definir los siguientes lenguajes regulares utilizando
para ello autómatas finitos deterministas
Ejercicios
› L1 = Lenguaje de identificadores
› L2 = Lenguaje de números naturales
› L3 = Lenguaje de números fraccionarios
› L4 = Lenguaje de números naturales con exponente
› L5 = Lenguaje de números fraccionarios con exponente
› L6 = When
letra
letra, dígito
otro
*
L1
0
2
1
62. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 19
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Para construir un analizador léxico completo es
necesario combinar en un único autómata todos los
autómatas correspondientes a los micro-lenguajes
que aparecen en el lenguaje. Este proceso se
puede hacer mediante una aproximación holística
Construcción manual composi8va de autómatas
› L7 = Números naturales y fraccionarios con exponente
› L8 = {<, <<,<=, =, ==, +, ++, -, --, *, *=}
› L9 = {While, When, Do, Downto}
› L10 = L1 U L7 U L9
› L11 = U Li con i Є [1..11]
0
<
*
=
+
<
*
–
=
otro
=
otro
+
otro
–
otro
=
otro
<<
<=
<
==
=
++
+
– –
–
*=
*
*
*
*
*
16
15
13
12
10
9
7
6
4
3
2
11
14
L8
Definir los siguientes lenguajes regulares utilizando
para ello autómatas finitos deterministas
Ejercicios
0
5
8
63. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 20
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Cuando el número de micro-lenguajes es grande y éstos son complejos la aproximación
manual se convierte en un proceso prolijo por eso conviene establecer un proceso
sistemático. Este proceso se basa en definir formalmente la composición de autómatas
sobre las operaciones legítimas de composición de autómatas
Construcción sistemá8ca composi8va de autómatas
L (x) x
L (x) L (y) x y
ﻉ
L (x) U L (y)
x ﻉ
y
ﻉ
L (x)+ x
ﻉ
L (x)* x
ﻉ
0
0
1
ﻉ
ﻉ
Las –ﻉ transiciones deben
interpretarse como
transiciones que no
consumen caracteres
}
x
0 n 1 n-1…≡
64. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 21
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
Cuando el número de micro-lenguajes es grande y éstos son complejos la aproximación
manual se convierte en un proceso prolijo por eso conviene establecer un proceso
sistemático. Este proceso se basa en definir formalmente la composición de autómatas
sobre las operaciones legítimas de composición de autómatas
Construcción sistemá8ca composi8va de autómatas
L = {<, <<, <=}Ejemplo
0 <
1
4
7 =
otro
5
8<
<
2
<
ﻉ
ﻉ
ﻉ
0
1
3
5 =
otro
<
Uso de –ﻉtransiciones para construir el
autómata
}
La eliminación de las –ﻉtransiciones provoca varias
transiciones iguales desde el mismo nodo
}
<
<
<
<
<<
<=
<
<<
<=
3
6
9
2
4
6
65. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 22
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
La construcción sistemática de autómatas
genera autómatas finitos no deterministas. Un
autómata finito no determinista es un autómata
finito donde cada estado:
Autómatas finitos no deterministas
› Puede tener ﻉ – transiciones
› Puede tener varias transiciones con la misma etiqueta
Genera indeterminación porque desde ese
estado no se sabe si avanzar por otra
transición normal consumiendo un
carácter o hacerlo por la ﻉ – transición sin
consumir ningún carácter
Genera indeterminación porque desde ese
estado, si el carácter a la entrada tiene
varias posibles transiciones no se sabe
cual escoger
Los autómatas finitos deterministas no son
formalismos adecuados para representar
lenguajes regulares
66. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 23
Especificación formal de analizadores léxicos
Especificación mediante autómatas finitos
La tercera forma de definir lenguajes regulares es a través del uso de autómatas finitos.
Un autómata finito reconoce una cadena de entrada si consumidos todos los caracteres
de la misma acaba en un estado final de aceptación
La construcción de un autómata finito determinista a partir de uno no determinista
requiere de la identificación de todos los estados alcanzables desde cada estado a
través de –ﻉtransiciones y transiciones múltiples
Conversión de autómatas finitos no deterministas a autómatas finitos deterministas
L = {<, <<, <=}Ejemplo
0 <
1
4
7 =
otro
5
8<
<
2
<
ﻉ
ﻉ
ﻉ
<
<<
<=
› {0} = {1 4 7}
› {1 4 7} < = {2 5 8}
› {2 5 8} < = {6}
› {2 5 8} = = {9}
› {2 5 8} otro = {3}
{1 4 7} {2 5 8}
< <
=
3
6
9
{3}
{6}
{9}
67. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 24
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Cada regla se expresa en términos de los
operadores de concatenación, cierre + y
cierre *
Conversión de Gramá8cas a expresiones
A ::= l B A = l B
B ::= l B B = l B = l +
B ::= d B B = d B = d +
B ::= ﻉ B = ﻉ
B = ( l+ | d+ | )ﻉ = ( l | d | ﻉ )+ = ( l | d )*
A = l ( l | d ) *
Se genera un estado por cada no terminal. El estado
del axioma es el de inicio. Las reglas se traducen a
transiciones. Si la regla es terminal (A ::= x) entonces
se genera una transición otro a un estado de
aceptación final. Si sale no determinista, convertirlo a
determinista.
Conversión de Gramá8cas a autómatas
A ::= l B
B ::= l B
B ::= d B
B ::= ﻉ
A
l
l, d
otro
*
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
B
2
68. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 25
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Transformar primero la expresión regular
desfactorizando los cierres + y *. Después
aplicar las transformaciones + a recursividad
y * a recursividad con ﻉ producción
Conversión de Expresiones a gramá8cas
L = l ( l | d ) * = l ( l * | d * )
A ::= l B B representa ( l* | d* )
B ::= l B Se captura l+
B := d B Se captura d+
B ::= ﻉ Se captura l* | d*
La conversión de expresiones regulares a autómatas
finitos se realiza utilizando las transformaciones
atómicas definidas anteriormente al discutir la
composición de lenguajes
Conversión de Expresiones a autómatas
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
x . y x y
ﻉ
x | y
x ﻉ
y
ﻉ
x+ x
ﻉ
x* x
ﻉ
ﻉ
ﻉ
69. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 26
Especificación formal de analizadores léxicos
Conversión de formalismos
Dado cualquiera de los 3 formalismos de representación
estudiados es posible encontrar un isomorfismo para
expresarlo en cualquiera de los otros 2
Cada estado se convierte a un no terminal. El
estado de arranque corresponde con el
axioma. Cada transición A → B etiquetada
con x se traduce en A ::= x B. Si B es un
estado final se genera A ::= x. Si x = otro se
genera A ::= ﻉ
Conversión de autómatas a gramá8cas
[0] ::= l [1]
[1] ::= l [1]
[1] := d [1]
ﻉ =:: ]1[
Para la transformación de autómatas a expresiones
basta con hacer una lectura inversa de las
transformaciones atómicas definidas anteriormente
Conversión de autómatas a expresión
Lenguajes
regulares
Gramá8cas
lineales
Expresiones
regulares
Autómatas
finitos
ﻉ
x . y x y
ﻉ
x | y
x ﻉ
y
ﻉ
x+ x
ﻉ
x* x
ﻉ
ﻉ
ﻉ
0
l
l, d
otro
*
1
2
70. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 27
Implementación de analizadores léxicos
¿Qué es un analizador léxico?
El analizador léxico responde bajo demanda a las
solicitudes de siguiente token que le va haciendo el
analizado sintáctico. Cada vez que éste último hace una
solicitud al primero, el analizador léxico consume un
número de caracteres de la entrada y retorna un artefacto
computacional que representa el siguiente token en la
entrada. En lo venidero utilizaremos el término token para
referirnos a dicho artefacto
Analizador léxico
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
Analizador sintác8co
}
nextToken ()
Id
nFila
nColumna
lexema
valor
En la práctica el artefacto software que
representa un token suele ser una estructura de
datos o un objeto en los lenguajes orientados a
objetos
}
Un analizador léxico o scanner es un programa capaz de descomponer una entrada de caracteres –
generalmente contenidas en un fichero – en una secuencia ordenada de tokens.
71. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 28
Implementación de analizadores léxicos
Implementación de analizadores léxicos basada en casos
letra = [a..z]
digito = [0..9]
estado = 0
fin = false
c = leerCaracter ()
while (!fin) {
switch (estado) {
0: switch (c) {
letra : estado = 1
lexema += c
c = leerCaracter ()
break
digito : throw error ()
}
De acuerdo a esta estrategia de implementación es necesario disponer de una
variable de estado para codificar el estado actual y una batería de casos que
describen la lógica de transición del autómata finito determinista.
break;
1: switch (c) {
letra :
digito : estado = 1
lexema += c
c = leerCaracter ()
break
default: estado = 2;
}
break
2: token = crearToken (lexema...)
fin = true
}
return token
letra
letra, dígito
otro
*
0
2
1
72. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 29
Implementación de analizadores léxicos
Implementación de analizadores léxicos dirigida por tabla
tTransicion = [][]
sFinales = {estados finales}
estado = 0
fin = false
c = leerCaracter ()
while (!fin) {
s = tTransicion [s][c]
if (s != null)
if (!(s in sFinales)) {
lexema += c
c = leerCaracter ()
} else fin = true
else throw error () }
return crearToken (lexema...)
Podemos codificar computacionalmente un autómata como una matriz bidimensional
de Q x T → Q que indique, para cada entrada y estado el nuevo estado. El algoritmo
se limita a leer dicha matriz
letra
letra, dígito
otro
*
0
2
1
73. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 30
Implementación de analizadores léxicos
Implementación de analizadores léxicos guiada por herramientas
letra = [a..z]
digito = [0..9]
letra (letra | digito)* { return new Token (ID); }
digito+ { return new Token (ENT); }
digito* . digito+ { return new Token (FRAC); }
“(” { return new Token (PI); }
“)” { return new Token (PD); }
“[” { return new Token (PI); }
“]” { return new Token (PD); }
...
Existen herramientas para la construcción automática de analizadores léxicos [Lex]
[Flex] [JFlex]. Estas herramientas se basan en la definición de una colección de reglas
patrón - acción
› Dan prioridad al token más largo
› DO / DOT
› > / >=
› Ante igualdad de longitud
› Anteponer la regla mas específica
› When
› While
› Id
}
74. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 31
Implementación de analizadores léxicos
Estrategias de implementación
I. Reconocimiento de palabras reservadas
Reconocimiento de
palabras reservadas
Resolución
explícita
Resolución
implícita
› Se indican todas con su patrón léxico
› Se integran en el diagrama global
› Se utilizan herramientas generadoras (FLex)
› Las palabras reservadas (PR) se reconocen como identificadores
› Las k palabras reservadas se meten en la tabla de símbolos (TS)
› Se busca cada id en TS. Si su índice es < k es PR
II. Reconocimiento estructuras complejas de forma híbrida
› Implementación manual de las estructuras más sencillas
› Operadores
› Identificadores
› Números
› Implementación tabular o guiada por herramientas con estructuras complejas
› Cadenas no específicas
› Prefijos comunes
75. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 32
Ges6ón de errores
Errores léxicos
Los errores léxicos son aquellos que se producen en el ámbito del reconocimiento de
patrones para construir tokens del lenguaje. Podemos establecer una clasificación de
errores de naturaleza léxica
› Errores básicos
› Aparición de caracteres ajenos al conjunto T (ñ, Ç, etc.)
› Ausencia de concordancia con ningún patrón (1abc, +*, etc.)
› Errores complejos
› Cadena de caracteres sin cierre (falta “ final)
› Cadena de caracteres sin apertura (falta “ inicial)
› Comentario sin cierre (falta */ final)
› Comentario sin apertura (falta /* inicial)
› Error en el anidamiento de comentarios (/* .. /* .. */)
Son en realidad de
esta categoría
No son en realidad errores
capturables por un reconocedor de
lenguajes regulares aunque las
herramientas generadoras son
capaces de reconocerlos
76. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 33
Construcción de analizadores léxicos en la prác6ca
¿Qué es JFlex?
JFlex es una herramienta para la generación de analizadores léxicos escritos en java.
A partir de un fichero de especificación que describe las características léxicas de un
lenguaje, JFlex genera un código fuente compilable que puede ser utilizado como
analizador léxico
JFlex Javac Scanner.flex
Framework
Scanner.java Java
Scanner.clas
s
JFlex compile JFlexTest
Esta es la especificación del
analizador léxico. Todo
cambio en el escáner debe
indicarse aquí
Esta es la clase generada a partir de la
especificación. Atención! No incluir aquí
ningún código manualmente ya que en la
próxima generación se perderá
Esta es la clase java
compilada que puede ser
interpretada por la JVM
77. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 34
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
I. Sección de código de usuario
La sección de código de usuario se utiliza para incluir
cualquier declaración java (paquete, importación o
clase) que sea necesario para compilar el scanner
78. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 35
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
II. Sección de direc8vas
Se incluyen directivas de compatibilidad con cup,
gestión de fila, columna y lexema, declaración de
estados y macros e inclusión de código de
inicialización
79. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 36
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
El fichero de especificación de JFlex esta dividido en
tres secciones separadas por el delimitador %%. Cada
una de ellas tiene una semántica diferente
III. Sección de reglas patrón - acción
En esta última sección se define una familia de
escáneres léxicos, cada uno asociado a un estado
distinto (YYINITIAL, COMMENT, etc.). Es posible
saltar de uno a otro. La definición se basa en reglas
patrón acción que indican el código java que debe
ejecutarse cuando la entrada encaja con determinado
patrón léxico. Si el código java no acaba con un return
el scanner continua buscando un nuevo token
80. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 37
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
I. Sección de código de usuario
La sección de código intermedio se copia tal cual al
inicio de la clase fuente que representa el escáner
(Scanner.java), por tanto todo lo que va en esta sección
es código puro java de carácter declarativo
Copia en vervatim
Scanner.java
81. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 38
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Directiva
› %full
› %unicode
› %{ … %}
› %init{ … %}
› %intthow{ … %}
› %yylexthrow{ … %}
› %eof{ … %}
› %eofval{ … %}
› %eofthrow{… %}
› %ignorecase
› %char
› %line
› %notunix
Descripción
Utiliza el código ASCII extendido 8 bits
Utiliza codificación UNICODE de 16 bits
Se incluye el código como declaración dentro de la clase Scanner
Incluye código dentro de los constructores
Declara excepciones que el constructor puede lanzar
Declara excepciones que el método de escaneo puede lanzar
Incluye código que se ejecuta tras encontrar EOF
Define el valor de retorno al encontrar EOF
Excepción de se lanza al encontrar EOF
No distinguir entre mayúsculas y minúsculas
Contabiliza el número de caracteres en la variable yychar
Contabiliza el número de líneas en la variable yyline
Reconoce rn como carácter (doble) de nueva línea
Consúltese el documento
“Manual de JFlex”
II. Sección de direc8vas
82. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 39
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Directiva
› %class name
› %public
› %function name
› %interface name
› %type name
› %integer
› %intwrap
› %yyeof
› %cup
› %state nombre
› nombre = valor
Descripción
Da nombre a la clase del escáner
Define como pública la clase del escáner
Da nombre a la función de escaneo
Declara los interfaces que debe implementar el escáner
Define el tipo de retorno de la función de escaneo
Define el tipo de retorno de la función de escaneo como un int
Define el tipo de retorno de la función de escaneo como Integer
Define la constante Yylex.YYEOF (obligatorio uso de %integer)
Habilita la compatibilidad con Cup
Define el estado nombre
Define una macro (LETRA = [A-Za-z])
Consúltese el documento
“Manual de JFlex”
II. Sección de direc8vas
83. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 40
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
III. Reglas patrón-acción
› Despliegue de macros
› Utilización de estados
{LETRA} ( {LETRA} |{DIGITO})* { return crearToken
(ID); }
{DIGITO} * { return crearToken
(NUM); }
Se utilizan los caracteres { y } para encerrar
el nombre de la macro, definida en la sección
de directivas, que se quiere desplegar
Cada estado, declarado en la sección de
directivas, corresponde con un autómata
distinto. Cada regla debe asociarse a un
estado precediendo al patrón léxico el
nombre del mismo encerrando entre < y >
Desde una regla r de un estado A se puede
saltar a un estado B mediante la instrucción
yybegin (B) invocada en la acción de r.
El estado inicial por defecto es YYINITIAL.
Este es un estado que no es preciso declarar
<YYINITIAL> “+” { return crearToken (MAS); }
<YYINITIAL> “-” { return crearToken (MENOS); }
<YYINITIAL> “*” { return crearToken (MUL); }
<YYINITIAL> “/” { return crearToken (DIV); }
...
<YYINITIAL> “/*” { yybegin (COMMENT); }
...
<COMMENT> “/*” { nComments ++; }
<COMMENT> “*/” { nComments --;
if (nComments == 0)
yybegin (YYINITIAL); }
<COMMENT> {COMMENT} { }
84. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 41
Construcción de analizadores léxicos en la prác6ca
¿Cómo funciona JFlex?
Consúltese el documento
“Manual de JFlex”
III. Reglas patrón-acción
Secuencias de escape
› b
› n
› t
› f
› r
› ddd
› xdd
› udddd
› ^C
› c
Descripción
Retroceso
Nueva línea
Tabulador
Avance de página
Retorno de carro
Número octal
Número hexadecimal
Hexadecimal de 4 dígitos
Carácter de control
Backslash seguido del c
Metacaracteres
› b
› $
› .
› “…”
› {name}
› *
› +
› ?
› (…)
› […]
› [^…]
› a-b
Descripción
Retroceso
Fin de fichero
Cualquier carácter menos n
…
Expansión de una macro
Clausura de Kleene
Una o más repeticiones
Opcionalidad
Agrupación de expresiones regulares
Conjunto de caracteres
Conjunto complementario
Rango a - b
Secuencias de escape Descripción
› yychar
› yyline
› yytext ()
Número de columna
Numero de línea
lexema
85. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 42
Construcción de analizadores léxicos en la prác6ca
¿Cómo se usa JFlex?
Los analizadores sintácticos de JFlex están pensados
para usarse bajo demanda. Se trata de artefactos con
una API bien definida. El método más relevante es el
de escaneo que devuelve el siguiente token a la
entrada.
El framework prescribe que el método de escaneo
debe devolver un objeto de la clase Token
Analizador léxico
Analizador sintác8co
e · l · i · h · w
<WHILE, PR>
While ( a > b ) do
a := a + 1;
La clase Token
Token es una clase hija que hereda de la clase que
u s a c u p p a r a i n t e g r a r s e c o n J F l e x
(javacup.runtime.Symbol). Esta clase facilita y
encapsula la comunicación entre el analizador léxico
y el analizador sintáctico desarrollado en Cup
proporcionando una colección de métodos de
interés
Javacup.run6me.Symbol
Token
+ getID ()
+ getLexema ()
+ getline ()
+ getColumn ()
JFlex Cup
next_Token ()
Token next_Token ()
}
}
Consúltese el documento
“Directrices de implementación”
86. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 43
Construcción de analizadores léxicos en la prác6ca
¿Cómo se usa JFlex?
Para adaptar JFlex al framework de desarrollo es
necesario realizar una serie de tareas sobre el
fichero de especificación. Éstas ya vienen
realizadas en la plantilla Jflex que proporciona el
framework por lo tanto lo aquí contado es
meramente explicativo y no requiere trabajo
alguno del estudiante
› El escáner pertenece al paquete compiler.lexical
› Debe importarse
› La clase Token
› El interfaz ScannerIF
› Las clases de gestión de errores
› Debe activarse la compatibilidad con el framework
› %cup
› %implements ScannerIF
› %scanerror LexicalError
› Opcionalmente declararse la función crearToken
› Cada acción debe acabar con un return crearToken (…);
Œ
Œ
Ž
Ž
87. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 44
Construcción de analizadores léxicos en la prác6ca
Ges8ón de errores en JFlex
La gestión de errores léxicos está soportada dentro
del framework por la clase LexicalErrorManager. Los
métodos para emitir error son
LexicalError
usa
<YYINITIAL> “+” { return crearToken (MAS); }
<YYINITIAL> “-” { return crearToken (MENOS); }
<YYINITIAL> “*” { return crearToken (MUL); }
<YYINITIAL> “/” { return crearToken (DIV); }
...
<YYINITIAL> . { LexicalErrorManager.lexicalFatal (“ufff!”); }
› error (). Emite un mensaje de error
› fatal (). Emite un mensaje de error y para el scanner
Ejemplo
Estos métodos están doblemente sobrecargados.
Pueden recibir un mensaje de error (String) o un
objeto LexicalError que representa un error léxico
Consúltese el documento
“Directrices de implementación”
LexicalErrorManager
+ lexicalDebug (String message)
+ lexicalInfo (String message)
+ lexicalWarn (String message)
+ lexicalError (String message)
+ lexicalError (LexicalError error)
+ lexicalFatal (String message)
+ lexicalFatal (LexicalError error)
88. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 45
Construcción de analizadores léxicos en la prác6ca
Desarrollo paso a paso
1. Especificación del escáner
› Abrir el documento de especificaciones JFlex doc/specs/scanner.flex
› No cambiar nada de lo que está escrito!
› Declarar macros necesarias (ALFA, DIGIT, SPACE, NEWLINE…)
› Declarar el estado de comentarios %%state COMMENT
› Definir las reglas de YYINITIAL
› Definir las reglas de COMMENT (contemplar el anidamiento si procede)
2. Generar el escáner
› Limpiar (tarea clear)
› Generar el escáner (tarea jflex)
› Compilar el escáner (tarea compile)
3. Probar el escáner
› Abrir fichero LexicalTestCase src/compiler/test/LexicalTestCase.java
› Descomentar y comentar lo indicado en el fichero (léelo atentamente)
› Si funciona, fin. Sino volver a 1
89. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 46
Bibliograla
Material de estudio
Bibliografía básica
Construcción de compiladores: principios y práctica
Kenneth C. Louden International Thomson Editores,
2004 ISBN 970-686-299-4
90. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis léxico. Lenguajes Regulares
2 - 47
Bibliograla
Material de estudio
Bibliografía complementaria
Compiladores: Principios, técnicas y herramientas.
Segunda Edición Aho, Lam, Sethi, Ullman
Addison – Wesley, Pearson Educación, México 2008
Diseño de compiladores. A. Garrido, J. Iñesta, F. Moreno
y J. Pérez. 2002. Edita Universidad de Alicante
92. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 2
Obje6vos
Obje8vos
› Conocer los lenguajes libres de contexto
› Conocer las responsabilidades del analizador sintáctico
› Aprender a utilizar gramáticas libres de contexto
› Aprender a diseñar gramáticas libres de contexto
› Aprender a reconocer y resolver fuentes de ambigüedad
› Aprender a eliminar la recursividad por la izquierda
› Aprender a factorizar por la izquierda
› Conocer el uso y tipos de derivaciones y árboles sintácticos
› Conocer la representación de lenguajes mediante diagramas de sintaxis
› Presentar los diferentes tipos de autómatas utilizados para construir analizadores sintácticos
› Discutir los diferentes tipos de analizadores sintácticos
93. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 3
Índice
Índice
› Introducción
› Gramáticas libres de contexto
› Notación BNF y EBNF
› Derivación gramatical
› Árboles sintácticos
› Limpieza gramatical
› Ambigüedad gramatical
› Recursividad por la izquierda
› Factorización por la izquierda
› Diagramas de sintaxis
› Autómatas a pila deterministas
› Bibliografía
94. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 4
Introducción
Análisis sintác8co
La fase de análisis sintáctico tiene por objetivo solicitar tokens al analizador léxico y
construir una representación arborescente de todo el código fuente. Este proceso se
encuentra dirigido por el conocimiento gramatical que del lenguaje tiene el analizador
sintáctico
El analizador sintáctico va
pidiendo nuevos tokens al
analizador léxico para construir
un árbol del programa fuente
Foco de atención
¿Cómo se especifica formalmente
un analizador sintáctico?
¿Cómo se implementa un
analizador sintáctico?
› Formalismos
› Tratamiento de formalismos
› Conversión entre formalismos
› Estrategias análisis sintáctico
› Tipos de gramáticas
› Tipos de analizadores
Analizador sintác8co
SWhile
WHILE E DO S
E > E
<WHILE, PR>
<a, ID>
<>, GT>
<b, ID>
<DO, PR>
...
<(, PI>
<), PD>
Tema 3
Temas 4 y 5
}
}
95. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 5
Introducción
Lenguajes libres de contexto
Desde una perspectiva sintáctica un lenguaje es una colección de construcciones sintácticas
bien formadas desde un alfabeto de entrada y correctamente combinadas entre sí de
acuerdo a una colección de reglas sintácticas
Ejemplo
El lenguaje Pascal tiene unas normas de
carácter gramatical que definen su
naturaleza y expresividad. Visto de
manera extensiva, el lenguaje Pascal
sería el conjunto infinito de todos los
posibles códigos fuente correctos
escritos en sintaxis Pascal
Pascal
Uses crt;
var
cantidad,cont,numero,s:integer;
begin
clrScr;
s:=0;
write('Cantidad:');
read(canditad);
for cont:=1 to cantidad do
begin
write('Numero ',cont,': ');
Read(numero);
s:=s+numero;
end;
write('Promedio:',s/cantidad:0:2);
readKey;
end;.
uses
crt;
var
contador:integer;
begin
ClrScr;
for contador:=2 to 999 do
begin
contador:=contador+1;
Write(contador,', ');
if contador>999 then
begin contador:=999;
end;
end;
ReadKey;
end.
Uses crt;
var
suma,numero,contador:integer;
begin
clrScr;
write('Numero: ');
readln(numero);
suma:=0;
for contador:=1 to numero do
begin
suma:=suma + contador;
end;
write('Suma: ',suma);
readKey;
end.
…
96. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 6
Introducción
Especificación de lenguajes libres de contexto
Existen 3 diferentes maneras de definir formalmente un lenguaje de contexto libre. A lo
largo de esta sección estudiaremos cada una de ellas en detalle y veremos cómo se
puede pasar de cada una a las otras 2
Lenguajes
libres de
contexto
Gramá8cas libres
de contexto
Diagramas de
sintaxis
Autómatas
a pila
› Elementos
› Gramáticas libres de contexto
› Diagramas de sintaxis
› Autómatas a pila
97. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 7
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Definición de gramá8ca libre de
contexto Una gramática libre de contexto es un conjunto de 4
elementos G = (T, N, S, P) donde:
› T es un conjunto de símbolos terminales
› N es un conjunto de símbolos no terminales
› S Є N axioma gramatical
› P un conjunto de reglas de producción de la forma
1. A ::= X donde X es una secuencia de elementos en N U T
2. A ::= x donde x es una secuencia de elementos en T
3. A :: = ﻉ siendo ﻉ la cadena vacía
A veces T se elide, N se deduce de los antecedentes de las
reglas de P y se asume que el antecedente de la primera regla
es S con lo G sólo a través de P
Ejemplo
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
E ::= E + E
E ::= E - E
E ::= E * E
E ::= E / E
E ::= n
}
98. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 8
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Notación
E → E + E
E → E – E
E → id
¿Cómo se escriben
las reglas?
Notación BNF
Las reglas se escriben como A ::= X.
Las reglas de un mismo antecedente
se escriben como A ::= X | Y | Z…
Cada regla con antecendente distinto
se escribe en una nueva línea
Notación EBNF
Se usa la notación BNF. Las reglas
recursivas se pueden esquematizar
con los meta-caracteres { y }
Notación estándar
Las reglas se escriben como A → X.
Cada regla se escribe en una linea
distinta
D ::= T L
T ::= int | bool | char
L ::= id , L | id
D ::= T L
T ::= int | bool | char
L ::= { id , } id
Focode
atención
99. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 9
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
Derivación grama8cal
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
E ::= E + E
E ::= E - E
E ::= E * E
E ::= E / E
E ::= n
}
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
E → E + E → n + E → n + E * E → n + n * E → n + n * n
axioma
Paso de
derivación
asidero
FraseF o r m a
de frase
Cadena de
derivación
2 + 3 * 5
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
(2) (3) (5)
100. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 10
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Derivación grama8cal
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
Cadena de
derivación
Secuencia de pasos de derivación que
parten del axioma gramatical para
intentar alcanzar la frase analizada x.
Demostración de x Є L (G)
Frase Secuencia de terminales que
pertenece al lenguaje definido por la
gramática. Si x Є L (G), x es frase de L
Forma de
frase
Secuencia de terminales y no
terminales que representa una
colección de frases del lenguaje. Existe
una cadena de derivación que llega
hasta ella
Axioma Forma de frase más abstracta que
representa a L (cualquier derivación de
Si x Є L (G) comienza por el axioma)
Asidero Parte izquierda de cualquier forma de
frase de x Є L (G) formada únicamente
por símbolos terminales
Paso de
derivación
Aplicación de una regla de producción
que transforma una forma de frase más
general en otra más especifica para x
101. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 11
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Derivación grama8cal
Se plantea el siguiente problema de decisión: Dado un lenguaje descrito a
través de una gramática G, L(G) determinar si la colección de terminales x
pertenece o no al lenguaje al mismo. Esto es ¿x Є L (G)?
E → E + E →
n + E →
n + E * E →
n + n * E →
n + n * n
¿ En qué orden se
aplican las reglas?
Left Most Derivation
En cada paso de derivación se
escoge el no terminal más a la
izquierda de la forma de frase a
derivar
Right Most Derivation
En cada paso de derivación se
escoge el no terminal más a la
derecha de la forma de frase a
derivar
E → E + E →
E + E * E →
E + E * n →
E + n * n →
n + n + n
102. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 12
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Frecuentemente no es preciso reflejar el orden de aplicación de las
derivaciones sino solamente el proceso de derivación desde el axioma a la
frase final. Para ello se interpreta cada regla como un árbol con raíz en el
antecedente e hijos los símbolos terminales y no terminales del consecuente
de la regla
2 + 3 * 5
L = Lenguaje de operadores
Sea G = (T, N A, P) con
T = {+, -, *, /, n}
N = {E}
P = {
R1: E ::= E + E
R2: E ::= E - E
R3: E ::= E * E
R4: E ::= E / E
R5: E ::= ( E )
R6: E ::= n
}
E
E + E
n E * E
n n
(2)
(3) (5)
R1
R3
R6
antecedente
consecuente
frase
103. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 13
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Existen dos tipos de representaciones arborescentes que se utilizan frecuentemente
para representar las derivaciones de una frase de un lenguaje.
Tipos de árboles
sintácticos
Arboles de análisis sintáctico
Los hijos de cada regla son una
representación exacta de la
colección de terminales y no
terminales que aparecen en el
consecuente de la misma
Arboles sintácticos abstractos
Se hace una representación
abstracta de la gramática de tal
manera que en los hijos del árbol
solo aparecen los símbolos
semánticamente relevantes
Foco de
atención de la
asignatura
104. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 14
If (a>b) then a:=b else b:=a If (a>b) then a:=b else b:=a
(2 + 3) * 5
(2 + 3) * 5
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Árboles de análisis sintác8co y arboles sintác8cos abstractos
Arboles de análisis sintác8co Arboles sintác8cos abstractos
E
E * E
( E ) n
E + E
nn
*
+ n
n n
IF
> := :=
ID ID ID ID
SIf
IF ( E ) THEN S ELSE S
E > E
while (a>b) do a++
SWhile
WHILE ( E ) DO S
E > E
while (a>b) do a++
WHILE
> ++
ID ID
ID
ID ID
105. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 15
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Ejercicios
› L1. Declaración de variables en Pascal
› L2. Declaración de estructuras en C
› L3. Declaración de procedimientos en Pascal
› L4. Declaración de procedimientos en C
› L5. Declaración de sentencias en C
› L6. Declaración de sentencias en Pascal
› L7. Sentencia for en C
› L8. Sentencia Repeat – Until en Pascal
Sentencia ::= BloqueSentencias |
SentenciaIf |
Sentencia While
BloqueSentencias ::= { listaSentencias }
listaSentencias ::= sentencia ; ListaSentencias |
ﻉ
SentenciaIf ::= …
SentenciaWhile ::= …
L5
Construya arboles de análisis sintáctico para frases en
cada uno de los lenguajes anteriores
106. Javier Vélez Reyes jvelez@lsi.uned.es
Análisis sintác8co. Lenguajes libres de contexto
3 - 16
Gramá6cas libres de contexto
Especificación mediante gramá8cas libres de contexto
De manera similar a como ocurre en los lenguajes regulares, los lenguajes libres de
contexto se pueden expresar mediante el uso de gramáticas libres de contexto. Su
definición es una extensión de las gramáticas regulares con reglas de producción
potencialmente más complejas
Limpieza grama8cal
Para no tener problemas en la construcción de analizadores sintácticos es
conveniente aplicar ciertas operaciones de trasformación gramatical. Estos problemas
son:
Limpieza
gramatical
Eliminación de la ambigüedad
Es necesario eliminar las expresiones gramaticales que
generen una interpretación potencialmente gramatical
ambigua
Factorización por la izquierda
Las reglas con partes comunes a la izquierda de los
consecuentes pueden también generar problemas, en
función del analizador que se construya
Eliminación de la recursividad a izquierdas
En algunos casos las reglas con recursividad a
izquierdas de la forma A ::= A α pueden acarrear
problemas en la construcción de analizadores