EXAMEN DE RECUPERACION
ICCD422-COMPILADORES Y LENGUAJES
Nombre: Alfonso Rodrigo Carrera Marmolejo
Fecha: 19/08/2024
1. Describa lo que es una Arquitectura de compiladores y muestre
una imagen.
Una arquitectura de compiladores es la estructura que organiza las etapas
del proceso de traducción de un lenguaje de alto nivel a código máquina.
Estas etapas suelen incluir análisis léxico, análisis sintáctico, análisis
semántico, optimización de código, y generación de código. La arquitectura
permite que el compilador transforme el código fuente en un programa
ejecutable.
El diagrama muestra un flujo secuencial con cajas que representan las
etapas del proceso de compilación. Cada caja está conectada por flechas
que indican el avance entre las fases. Las cajas están etiquetadas de la
siguiente manera:
Entrada de código fuente: Representa el código en un lenguaje de alto
nivel.
Análisis léxico: Fase donde el código se divide en tokens.
Análisis sintáctico: Verificación de la estructura del código según las
reglas gramaticales.
Análisis semántico: Se asegura que el código tenga sentido lógico.
Generación de código intermedio: Convierte el código fuente en una
representación intermedia abstracta, útil para optimización y portabilidad.
Optimización: Mejora del código para hacerlo más eficiente.
Generación de código: Conversión del código optimizado a código
máquina.
Código ejecutable: Resultado final en un formato que la máquina puede
ejecutar.
Este diagrama visualiza cómo un compilador procesa el código fuente de
manera estructurada y progresiva hasta producir un programa ejecutable.
2. ¿Qué son los Procesadores de lenguajes?, mencione 2 ejemplos.
Los procesadores de lenguajes son programas que traducen o ejecutan
código escrito en lenguajes de programación. Estos incluyen compiladores,
intérpretes y ensambladores, que convierten el código fuente en un formato
que la máquina puede entender y ejecutar.
Ejemplos:
Compilador: Traductor que convierte código fuente en un programa
ejecutable.
Intérprete: Ejecuta código línea por línea sin generar un archivo
ejecutable.
3. Muestre el Diagrama general de un Traductor y describa dicho
diagrama.
Traductor: Es un programa que recibe un código fuente y lo traduce a otro
código, generalmente a un código destino, sin perder su funcionamiento.
Interprete: Es un programa diseñado para ejecutar
instrucciones de un código determinado, no genera ningún tipo
de código adicional, y es ejecutable.
Compilador: Traductor cuyo programa fuente está escrito en
un lenguaje de alto nivel y cuyo programa objeto está escrito
en un lenguaje de bajo nivel.
Ensamblador: Convierte el código ensamblador a código
máquina
Preprocesador: Modifica el código fuente, manejando macros
e inclusiones.
4. ¿Qué piensa usted de los ensambladores, compiladores,
intérpretes y simuladores?
Son traductores que son útiles de acuerdo con un contexto determinado, ya
que cada uno ofrece ventajas específicas para distintos objetivos de
desarrollo y ejecución:
Ensambladores: Son ideales cuando se necesita un control preciso sobre
el hardware.
Compiladores: Son adecuados para la creación de aplicaciones eficientes y
optimizadas, especialmente en lenguajes de alto nivel.
Intérpretes: Son útiles en situaciones donde la ejecución inmediata y la
flexibilidad son prioritarias.
Simuladores: Son útiles para probar y depurar código en un entorno
virtual.
5. Describa 2 Similitudes y 2 Diferencias de los Lenguajes de
programación.
Similitudes:
1. Sintaxis Estructurada: La mayoría de los lenguajes de
programación tienen una sintaxis estructurada que define cómo
deben escribirse las instrucciones y los comandos para que el
compilador o intérprete los entienda.
2. Capacidad de Abstracción: Tanto los lenguajes de alto nivel como
los de bajo nivel permiten abstraer operaciones complejas en
instrucciones más simples, facilitando el desarrollo de software.
Diferencias:
1. Nivel de Abstracción: Los lenguajes de alto nivel (como Python o
Java) están diseñados para ser más fáciles de usar y entender,
abstraen detalles del hardware y permiten un desarrollo más rápido.
Los lenguajes de bajo nivel (como C o ensamblador) proporcionan un
control más directo sobre el hardware y el sistema operativo, pero
son más complejos de usar.
2. Gestión de Memoria: Algunos lenguajes (como C o C++) requieren
que los programadores gestionen manualmente la memoria, mientras
que otros lenguajes (como Java o Python) proporcionan recolección de
basura automática para gestionar la memoria de manera más segura
y conveniente.
6. Identifique 2 Compiladores y 2 intérpretes con los cuales usted
puede trabajar.
Compiladores:
1. GCC (GNU Compiler Collection): Soporta múltiples lenguajes de
programación como C, C++, y Fortran. Es ampliamente utilizado en
sistemas Unix y Linux.
2. Clang: Un compilador para C, C++, y Objective-C, conocido por su
rapidez y mensajes de error detallados. Es parte del proyecto LLVM y
se utiliza en macOS y otros sistemas.
Intérpretes:
1. Python Interpreter: Ejecuta código escrito en Python línea por
línea. Es muy popular para desarrollo rápido, scripting y prototipado.
2. Ruby Interpreter (MRI): Ejecuta código Ruby y es conocido por su
simplicidad y flexibilidad. Es útil para desarrollo web y scripting.
7. ¿Qué entiende usted por Set de Instrucciones en los lenguajes de
programación?
Son un conjunto de operaciones básicas y comandos que permiten controlar
el flujo de un programa.
8. Describa 3 funcionalidades del Analizador Lexicográfico.
Genera tokens: Divide el código fuente en unidades significativas llamadas
tokens, como palabras clave, identificadores, operadores y literales. Esto
convierte el texto plano en una secuencia de tokens que son más fáciles de
manejar.
Eliminación de Espacios en Blanco y Comentarios: Elimina todo lo que
no sirva para la ejecución: comentarios, espacios en blanco, tabuladores,
saltos de línea, etc.
Detección de Errores Léxicos: Comprueba la escritura correcta de los
símbolos con los que cuenta el lenguaje de programación: Identificadores,
números, operadores aritméticos, relacionales y de comparación, símbolos
de agrupación y puntuación, palabras reservadas y todo lo que comprende
el programa fuente.
9. Describa una característica importante de los Lexemas, Patrones
y Tokens.
Lexemas: Son las secuencias de caracteres en el código fuente que
corresponden a un token específico. Por ejemplo, en la expresión x = 10, x,
= y 10 son lexemas
Patrones: Son las reglas o expresiones regulares que definen cómo se
reconocen los lexemas. Un patrón describe la forma general que un lexema
debe seguir para ser clasificado como un tipo de token específico, como una
palabra clave, un identificador o un número.
Tokens: Son las categorías o clases de elementos que resultan de la
tokenización del código fuente. Cada token representa un tipo de lexema
identificado según un patrón, como IDENTIFICADOR, OPERADOR, o
LITERAL_NUMÉRICO.
10. ¿Qué es un Alfabeto, Cadena y Lenguaje que se lo considera en
el Análisis Léxico?
Alfabeto: Es el conjunto finito de símbolos básicos utilizados para construir
las cadenas en un lenguaje. Por ejemplo, en un lenguaje de programación,
el alfabeto puede incluir letras, dígitos y símbolos como +, -, *, =, etc.
Cadena: Es una secuencia finita de símbolos tomados del alfabeto. En el
análisis léxico, una cadena podría ser cualquier combinación de caracteres
válida en el código fuente, como x = 10;.
Lenguaje: En el análisis léxico, el lenguaje se refiere a todas las cadenas
válidas que el compilador puede aceptar según la sintaxis del lenguaje de
programación.
11. Escriba una expresión regular con al menos 5 meta-caracteres y
encuentre el lenguaje que genera.
^[A-Za-z]+\d{3,}\W? $
Meta-caracteres utilizados:
1. ^: Indica el inicio de la cadena.
2. +: Indica uno o más caracteres precedentes (en este caso, letras).
3. \d{3,}: Indica al menos tres dígitos consecutivos.
4. \W?: Indica cero o un carácter no alfanumérico (caracteres
especiales).
5. $: Indica el final de la cadena.
Lenguaje que genera: Este lenguaje genera cadenas que:
Comienzan con una o más letras (mayúsculas o minúsculas).
Tienen al menos tres dígitos consecutivos después de las letras.
Opcionalmente, terminan con un carácter especial (no alfanumérico).
Ejemplos de cadenas válidas:
alfonsoCarrera333$
ChancusigFabian000!
Nombre999
12. ¿Cómo identifica usted a una Máquina de Estado Finito
Determinísticas y una No Determinísticas?
Analizando si la máquina de estado finito tiene una sola transición para cada
par (estado, símbolo) la identificaría como DFA, mientras que, si encuentro
que para un mismo par (estado, símbolo) existen múltiples transiciones
posibles, o transiciones que no requieren consumir ningún símbolo, la
identificaría como un NFA.
13. ¿Cuál es la particularidad de las Máquinas Push-Down?
La particularidad de las Máquinas Push-Down (PDA) es que, además de
contar con un conjunto de estados finitos y transiciones como una Máquina
de Estado Finito, tienen un pila (stack) que les permite almacenar y
recuperar información de manera Last In, First Out (LIFO).
14. ¿Para qué sirve la herramienta informática Flex/Lex? ¿Existen
otras similares?
La herramienta informática Flex/Lex se utiliza para generar analizadores
léxicos (también llamados escáneres o lexers), que son programas
encargados de identificar y clasificar las distintas unidades léxicas (tokens)
en un texto de entrada.
Funciones principales de Flex/Lex:
Definición de patrones léxicos: Permite definir reglas y patrones
(expresiones regulares) que representan los tokens.
Generación automática del código: Con base en las reglas
definidas, Flex/Lex genera el código C/C++ que implementa el
analizador léxico.
Compatibilidad con Yacc/Bison: Flex/Lex se suele utilizar junto con
Yacc o Bison, que generan analizadores sintácticos.
Herramientas similares:
JFlex: Similar a Flex, pero diseñado para generar analizadores léxicos en
Java.
Re2c: Una herramienta que, al igual que Flex, genera analizadores léxicos a
partir de expresiones regulares, pero suele ser más rápida y eficiente.
15. Describa 3 funcionalidades del Analizador sintáctico.
Verificación de la estructura gramatical: El analizador sintáctico se
encarga de comprobar si la secuencia de tokens generada por el analizador
léxico cumple con las reglas gramaticales del lenguaje. Construye un árbol
de derivación (o árbol sintáctico) que representa la estructura jerárquica de
la entrada basada en la gramática libre de contexto del lenguaje.
Construcción del árbol sintáctico: El analizador construye un árbol
sintáctico o árbol de derivación, que representa la estructura del código
fuente en función de las reglas gramaticales. Este árbol se utiliza para
realizar análisis posteriores, como la generación de código intermedio o la
optimización.
Detección y recuperación de errores: Si el código fuente contiene
errores sintácticos, el analizador sintáctico los identifica y reporta, indicando
el tipo y la ubicación del error. En algunos casos, también intenta
recuperarse del error para continuar el análisis del resto del código y
detectar otros posibles problemas.
16. ¿Qué Gramáticas se utilizan para escribir lenguajes de
programación de tercera generación?
Para escribir lenguajes de programación de tercera generación, como C,
Java, Python y otros, se suelen utilizar gramáticas libres de contexto.
Estas gramáticas son lo suficientemente expresivas para describir las
estructuras jerárquicas y anidadas que caracterizan a los lenguajes de
programación modernos.
17. ¿Qué son las Producciones gramaticales y cómo se usan en los
árboles de derivación?
Las producciones gramaticales son reglas que definen cómo se pueden
sustituir los símbolos no terminales en una gramática formal. Estas
producciones son fundamentales para la construcción de estructuras en un
lenguaje formal
Uso en los Árboles de Derivación:
Construcción del Árbol.
Raíz: Comienza con el símbolo inicial de la gramática en la raíz del árbol.
Niveles: En cada nivel del árbol, las producciones se aplican para
reemplazar los símbolos no terminales con secuencias de símbolos según
las reglas definidas en la gramática.
Hojas: Las hojas del árbol representan los símbolos terminales de la cadena
final.
18. Exprese su punto de vista de los Procesamientos top-down y
bottom-up dentro del análisis sintáctico.
Los procesamientos top-down y bottom-up representan dos estrategias
diferentes para construir un árbol sintáctico a partir de una secuencia de
tokens. Cada enfoque tiene sus propias ventajas y desventajas, y se elige
según las necesidades determinadas.
19. Describa la Traducción dirigida por la sintaxis.
La traducción dirigida por la sintaxis es un enfoque en la compilación que
asocia acciones semánticas con las reglas de producción de una gramática
formal. Se basa en la estructura del árbol de análisis sintáctico para generar
código intermedio o realizar transformaciones semánticas.
Características Clave:
Gramáticas de Atributos: Utiliza atributos en los nodos del árbol para
almacenar información semántica, permitiendo la evaluación de estos
atributos durante el análisis.
Atributos Sintetizados y Heredados: Implementa atributos sintetizados
(calculados a partir de nodos hijos) y heredados (dependientes de nodos
padres y/o hermanos) para propagar información a través del árbol.
Acciones Semánticas: Las acciones se definen en las reglas de
producción, permitiendo la generación de código o la verificación de
propiedades semánticas en el momento de analizar la estructura del
programa.
20. Exprese las funcionalidades de los Tipos de atributos usados en
la Traducción dirigida por la sintaxis.
En la traducción dirigida por la sintaxis, los dos tipos de atributos utilizados
son:
Atributos Sintetizados
Se evalúan en un análisis sintáctico ascendente, calculando su valor a
partir de los atributos de los nodos hijos en el árbol sintáctico.
Dependen exclusivamente de los atributos de los nodos hijos.
Permiten generar valores utilizados en la traducción de expresiones y
declaraciones.
Atributos Heredados
Se evalúan en un análisis sintáctico descendente, definiendo su valor
a partir de los atributos de los nodos padres y/o hermanos.
Pueden depender de los atributos del nodo padre y/o hermanos.
Expresan la dependencia de una construcción en su contexto,
permitiendo una traducción más precisa.
21. ¿Para qué sirve la herramienta informática Bison/Yacc? ¿Existen
otras similares?
Bison y Yacc son herramientas utilizadas para la generación de analizadores
sintácticos, que son componentes clave en el proceso de construcción de
compiladores e intérpretes.
Otras similares:
ANTLR (Another Tool for Language Recognition): ANTLR es una
herramienta poderosa y moderna para la generación de analizadores léxicos
y sintácticos. A diferencia de Bison/Yacc.
Berkeley Yacc: Una variante de Yacc que ofrece algunas mejoras y
características adicionales. Es compatible con la versión original de Yacc.
22. Describa 3 funcionalidades del Analizador semántico.
1. Verificación de Declaraciones: Comprueba que todas las variables y
funciones estén declaradas antes de ser utilizadas, generando errores si se
detectan identificadores sin declarar previa.
2. Comprobación de Tipos: Valida la compatibilidad de tipos en
expresiones, asignaciones y operaciones, asegurando que se respeten las
reglas de tipado del lenguaje.
3. Gestión de Ámbitos: Controla el alcance de variables y funciones,
verificando que se utilicen dentro del ámbito donde fueron declaradas y
evitando conflictos por redefinición.
23. Describa una técnica usada en el Análisis semántico en los
compiladores actuales.
Una técnica utilizada en el análisis semántico de los compiladores actuales
es la decoración del árbol de sintaxis abstracta (AST). Esta técnica implica
asociar información semántica a los nodos del AST, permitiendo la
verificación de propiedades como la existencia de variables y el tipo de
datos en expresiones. Durante el recorrido del árbol, se evalúan atributos
sintetizados y heredados, lo que facilita la detección de errores semánticos
y la generación de código intermedio adecuado.
24. ¿Qué particularidad tiene el bloque funcional de Generación de
Código Intermedio?
La generación de código intermedio tiene una particularidad importante en
el proceso de compilación: es una fase independiente del lenguaje de
programación fuente y de la máquina destino para la que se genera el
código objeto final.
25. ¿Por qué es importante que el compilador tenga un bloque de
Optimización de Código en los compiladores modernos?
Mejora del Rendimiento
La optimización permite al compilador transformar el código fuente en
código objeto más eficiente, reduciendo el tiempo de ejecución del
programa. Esto se logra aplicando técnicas como:
Eliminación de código muerto y redundante
Desenrollado y fusión de bucles
Propagación de constantes
Asignación eficiente de registros
Reducción del Consumo de Recursos
Al generar código más optimizado, se minimiza el uso de recursos como
memoria y energía. Esto es especialmente importante en sistemas
embebidos y dispositivos móviles con restricciones de recursos.
Adaptación a Diferentes Plataformas
Al tener un bloque de optimización, el compilador puede generar código
optimizado para diferentes arquitecturas a partir del mismo código
intermedio. Esto facilita la portabilidad y reutilización del código fuente.
26. Describa cómo el bloque funcional de Generación de Código
Objeto realiza la Distribución y Asignación de registros.
En el bloque funcional de Generación de Código Objeto, la distribución y
asignación de registros se lleva a cabo de la siguiente manera:
Distribución de Registros
Análisis de Uso: Se evalúa el uso de variables y temporales en el código
intermedio para determinar cuáles deben ser almacenados en registros,
priorizando las que se utilizan con mayor frecuencia.
Selección de Registros: Se eligen los registros disponibles en la
arquitectura de destino para almacenar las variables que se utilizarán en las
operaciones.
Asignación de Registros
Asignación Específica: Se asignan registros específicos a cada variable o
temporal, utilizando algoritmos como la coloración de grafos para manejar
interferencias (conflictos entre variables que no pueden coexistir en el
mismo registro).
Manejo de Desbordamientos: Si hay más variables que registros, se
implementan estrategias para almacenar algunas variables en memoria y
cargarlas en registros solo cuando sea necesario.
27. ¿Qué estructura de datos utiliza el compilador de Java para el
bloque funcional de Tabla de Símbolos?
El compilador de Java utiliza principalmente tablas hash para implementar el
bloque funcional de la tabla de símbolos. Esta estructura permite un acceso
eficiente a la información sobre identificadores, como variables y funciones,
facilitando operaciones de búsqueda, inserción y eliminación en tiempo
constante promedio O(1) .
28. ¿Cuál es la funcionalidad del bloque de Manejador de errores en
los Compiladores e Intérpretes actuales?
El bloque de manejador de errores en los compiladores e intérpretes
actuales tiene varias funcionalidades clave:
Detección de Errores: Identifica y clasifica errores de sintaxis, semántica
y ejecución que ocurren durante el análisis del código fuente, permitiendo al
compilador detectar problemas antes de la ejecución.
Reporte de Errores: Proporciona mensajes de error claros y específicos
que indican la naturaleza del problema y su ubicación en el código,
facilitando la identificación y corrección por parte del programador.
Recuperación de Errores: Implementa estrategias para continuar el
procesamiento del código después de encontrar un error, como ignorar
errores menores o realizar correcciones automáticas, lo que permite al
compilador seguir analizando el resto del programa sin detenerse por
completo.
29. Identifique dos lenguajes de programación modernos que
permiten desarrollar sistemas a nivel de infraestructura de
conectividad y servidores hardware.
Dos lenguajes de programación modernos que permiten desarrollar
sistemas a nivel de infraestructura de conectividad y servidores hardware
son:
C++: Utilizado en el desarrollo de sistemas operativos, controladores de
hardware y aplicaciones que requieren un alto rendimiento y acceso a
recursos del sistema.
Java: Ampliamente utilizado para crear aplicaciones de servidor,
especialmente en entornos de red y sistemas distribuidos, gracias a su
portabilidad y robustez en la gestión de conexiones y servicios.
30. Identifique dos lenguajes de programación modernos que
permiten desarrollar aplicaciones a nivel de usuario final.
Dos lenguajes de programación modernos que permiten desarrollar
aplicaciones a nivel de usuario final son:
JavaScript: Utilizado principalmente para el desarrollo de aplicaciones web
interactivas y dinámicas en el lado del cliente.
Python: Ampliamente utilizado para desarrollar aplicaciones de escritorio,
scripts y aplicaciones web, gracias a su simplicidad y versatilidad.
Bibliografía:
Universidad Europea de Madrid. (s.f.). Conceptos básicos del análisis léxico.
Recuperado
de https://www.cartagena99.com/recursos/alumnos/apuntes/ININF2_M4_U2_
T1.pdf Universidad Autónoma del Estado de Hidalgo. (s.f.). Máquinas de
estados finitos. Recuperado
de https://www.uaeh.edu.mx/scige/boletin/icbi/n4/multimedia/e4/e4.pdf Univ
ersidad Interamericana para el Desarrollo. (s.f.). Push-down y Turing:
Ejemplos. Recuperado
de https://www.studocu.com/es-mx/document/universidad-interamericana-
para-el-desarrollo/teoria-de-la-comunicacion/push-down-y-turing-ejemplos/
23912330Calameo. (s.f.). Máquinas de estados finitos. Recuperado
de https://www.calameo.com/books/0058965942f7346a4f5b1Universidad de
Huelva. (s.f.). Tema 2: Análisis léxico. Recuperado
de https://www.uhu.es/francisco.moreno/gii_pl/docs/Tema_2.pdfUniversitat
Jaume I. (2021). Arquitectura de compiladores. Recuperado
de https://repositori.uji.es/xmlui/handle/10234/168269Materia Compiladores
3110. (2017). Arquitectura de los compiladores: Etapas. Recuperado
de https://materiacompliladores3110.blogspot.com/2017/02/arquitectura-de-
los-compiladores-e.html
Carvajal, J., & Fonseca, S. (2008). Traducción Dirigida por Sintaxis.
Universidad de Costa Rica. Recuperado de Di-Mare.com .
Tema 3: Traducción dirigida por sintaxis. (n.d.). Recuperado de
Cartagena99.com .
Compiladores. (n.d.). Recuperado de Lcc.uma.es .
Traducción dirigida por la sintaxis. (n.d.). Dtt ECYS. Recuperado de Dtt-
ecys.org .
Juan Fuente, A., Cueva Lovelle, J. M., Ortín Soler, F., Izquierdo Castanedo, R.,
Luengo Díez, M. C., & Labra Gayo, J. E. (2006). Tablas de Símbolos de
Procesadores de Lenguaje. Cuaderno Didáctico Nº 41. Universidad de
Oviedo. Recuperado de di002.edv.uniovi.es.
Tutorials Point. (n.d.). Tabla de Símbolos. Recuperado de tutorialspoint.com.
Apuntes de Compiladores. (n.d.). Recuperado de cartagena99.com.
Manejo de Errores Sintácticos. (n.d.). Recuperado de
cidecame.uaeh.edu.mx.
Compiladores. (n.d.). Recuperado de arantxa.ii.uam.es.
FasterCapital. (n.d.). Manejo de errores en atoi: mejores prácticas y solución
de problemas. Recuperado de fastercapital.com.