Compíladores
Compíladores
Ir a la navegaciónIr a la búsqueda
Este artículo o sección necesita referencias que aparezcan en una publicación acreditada.
Índice
1Historia
2Tipos de compiladores
3Proceso de compilación
4Etapas del proceso
o 4.1Fase de análisis
4.1.1Análisis léxico
4.1.2Análisis sintáctico
4.1.3Análisis semántico
o 4.2Fase de síntesis
4.2.1Generación de código intermedio
o 4.3Optimización de código
5Estructura de datos principales
o 5.1Componentes léxicos o tókenes
o 5.2Árbol sintáctico
o 5.3Tabla de símbolos
o 5.4Tabla de literales
o 5.5Código intermedio
o 5.6Archivos temporales
6Véase también
7Referencias
8Enlaces externos
Historia[editar]
Artículo principal: Historia de la construcción de los compiladores
En 1938, Konrad Zuse desarrolló la primera computadora digital electromecánica,
denominada Z1 en Alemania, y posteriormente, en 1946, se desarrolló la primera
computadora totalmente electrónica ENIAC, sucedida principalmente por
la EDVAC (1951), primera computadora electrónica digital. En un principio, estas
máquinas ejecutaban instrucciones consistentes en códigos numéricos que
señalaban a los circuitos de la máquina los estados correspondientes a cada
operación, lo que se denominó lenguaje máquina.
Pronto los primeros usuarios de estos ordenadores descubrieron la ventaja de
escribir sus programas mediante claves más fáciles de recordar que esos códigos;
al final, todas esas claves juntas se traducían manualmente a lenguaje máquina.
Estas claves constituyen los llamados lenguajes ensambladores.
Pese a todo, el lenguaje ensamblador seguía siendo el de una máquina, pero más
fácil de manejar (las instrucciones de máquina se reemplazan por mnemónicos.
Los trabajos de investigación se orientaron hacia la creación de un lenguaje que
expresara las distintas acciones a realizar de una manera lo más sencilla posible
para una persona. El primer compilador fue escrito por Grace Hopper, en 1952
para el lenguaje de programación A-0. En 1950 John Backus dirigió una
investigación en IBM sobre un lenguaje algebraico. En 1954 se empezó a
desarrollar un lenguaje que permitía escribir fórmulas matemáticas de manera
traducible por un ordenador; le llamaron FORTRAN (FORmulae TRANslator). Fue
el primer lenguaje de alto nivel y se introdujo en 1957 para el uso de la
computadora IBM modelo 704.
Surgió así por primera vez el concepto de un traductor como un programa que
traducía un lenguaje a otro lenguaje. En el caso particular de que el lenguaje a
traducir es un lenguaje de alto nivel y el lenguaje traducido de bajo nivel, se
emplea el término compilador.
El trabajo de realizar un compilador fue complicado de realizar. El primer
compilador de FORTRAN tardó 18 años-persona en realizarse y era muy sencillo.
Este desarrollo de FORTRAN estaba muy influenciado por la máquina objeto en la
que iba a ser implementado. Como un ejemplo de ello tenemos el hecho de que
los espacios en blanco fuesen ignorados, debido a que el periférico que se
utilizaba como entrada de programas (una lectora de tarjetas perforadas) no
contaba correctamente los espacios en blanco.
El primer compilador autocontenido, es decir, capaz de compilar su propio código
fuente fue el creado para Lisp por Hart y Levin en el MIT en 1962. Desde 1970 se
ha convertido en una práctica común escribir el compilador en el mismo lenguaje
que este compila, aunque PASCAL y C han sido alternativas muy usadas.
Crear un compilador autocontenido genera un problema llamado bootstrapping, es
decir el primer compilador creado para un lenguaje tiene que o bien ser compilado
por un compilador escrito en otro lenguaje o bien compilado al ejecutar el
compilador en un intérprete.
Tipos de compiladores[editar]
Esta taxonomía de los tipos de compiladores no es excluyente, por lo que puede
haber compiladores que se adscriban a varias categorías:
Proceso de compilación[editar]
Es el proceso por el cual se traducen las instrucciones escritas en un determinado
lenguaje de programación a lenguaje máquina. Además de un traductor, se
pueden necesitar otros programas para crear un programa objeto ejecutable. Un
programa fuente se puede dividir en módulos almacenados en archivos distintos.
La tarea de reunir el programa fuente a menudo se confía a un programa distinto,
llamado preprocesador. El preprocesador también puede expandir abreviaturas,
llamadas a macros, a proposiciones del lenguaje fuente.
Normalmente la creación de un programa ejecutable (un típico
archivo .exe para Windows o DOS) conlleva dos pasos. El primer paso se
llama compilación (propiamente dicho) y traduce el código fuente escrito en
un lenguaje de programación almacenado en un archivo a código en bajo nivel
(normalmente en código objeto, no directamente a lenguaje máquina). El segundo
paso se llama enlazado en el cual se enlaza el código de bajo nivel generado de
todos los ficheros y subprogramas que se han mandado a compilar y se añade el
código de las funciones que hay en las bibliotecas del compilador para que el
ejecutable pueda comunicarse directamente con el sistema operativo, traduciendo
así finalmente el código objeto a código máquina, y generando un módulo
ejecutable.
Estos dos pasos se pueden hacer por separado, almacenando el resultado de la
fase de compilación en archivos objetos (un típico.obj para Microsoft Windows,
DOS o para Unix); para enlazarlos en fases posteriores, o crear directamente el
ejecutable; con lo que la fase de compilación se almacena solo temporalmente. Un
programa podría tener partes escritas en varios lenguajes (por ejemplo C, C+
+ y Asm), que se podrían compilar de forma independiente y luego enlazar juntas
para formar un único módulo ejecutable.
temp1 := entreal(60)
temp2 := id3 * temp1 ===> (2)
temp3 := id2 + temp2
id1 := temp3
Este sencillo algoritmo no tiene nada de malo, puesto que el problema se puede
solucionar en la fase de optimización de código. Esto es, el compilador puede
deducir que la conversión de 60 de entero a real se puede hacer de una vez por
todas en el momento de la compilación, de modo que la operación "entreal( )" se
puede eliminar. Además, temp3 se usa solo una vez, para transmitir su valor a id1.
Entonces resulta seguro sustituir a id1 por temp3, a partir de lo cual la última
proposición de (2) no se necesita y se obtiene el código de (3).
Hay muchas variaciones en la cantidad de optimización de código que ejecutan los
distintos compiladores. En lo que hacen mucha optimización llamados
«compiladores optimizadores», una parte significativa del tiempo del compilador se
ocupa en esta fase. Sin embargo, hay optimizaciones sencillas que mejoran
sensiblemente el tiempo de ejecución del programa objeto sin retardar demasiado
la compilación.
Archivos temporales[editar]
Al principio las computadoras no tenían la suficiente memoria para guardar un
programa completo durante la compilación. Este problema se resolvió mediante el
uso de archivos temporales para mantener los productos de los pasos intermedios
durante la traducción o bien al compilar «al vuelo», es decir, manteniendo solo la
información suficiente de las partes anteriores del programa fuente que permita
proceder a la traducción.
Las limitaciones de memoria son ahora un problema mucho menor, y es posible
requerir que una unidad de compilación entera se mantenga en memoria, en
especial si se dispone de la compilación por separado en el lenguaje. Con todo,
los compiladores ocasionalmente encuentran útil generar archivos intermedios
durante alguna de las etapas del procesamiento. Algo típico de estos es la
necesidad de direcciones de corrección hacia atrás durante la generación de
código.
Véase también[editar]
BlueJ
Lenguaje de programación
Proceso de traducción de programas
Lenguaje ensamblador
Ensamblador
Desensamblador
Decompilador
Intérprete
Depurador
Lenguaje de alto nivel
Lenguaje de bajo nivel
Lenguaje de máquina
Historia de la construcción de los compiladores
Referencias[editar]
1. ↑ Clocksin, William (1997). Clause and effect. Springer-Verlag. p. 93. ISBN 978-3-540-62971-9. Consultado el 10-10-2021.
2. ↑ Garrido Alenda, Alicia; Iñesta Quereda, José Manuel; Moreno Seco, Francisco; Pérez Ortiz, Juan Antonio (2002). «1». Diseño de
compiladores. ISBN 978-84-7908-700-5. Consultado el 10-10-2021.
3. ↑ Laborda, Javier; Josep Galimany, Rosa María Pena, Antoni Gual (1985). «Software». Biblioteca práctica de la computación. Barcelona:
Ediciones Océano-Éxito, S.A.
4. ↑ Saltar a:a b c Grune, Dick; van Reeuwijk, Kees; Bal, Henri E.; Jacobs, Ceriel J.H.; Langendoen, Koen (2012). Modern Compiler Design (en
inglés). Springer New York. ISBN 978-1-4614-4698-9. doi:10.1007/978-1-4614-4699-6. Consultado el 11 de octubre de 2021.
6. ↑ Saltar a:a b Aho, Alfred V.; Ravi Sethi, Jeffrey D. Ullman (2008). «Introducción a la Compilación». Compiladores: Principios, técnicas y
prácticas. México: Addison Wesley.
Enlaces externos[editar]
Wikcionario tiene definiciones y otra información sobre compilador.
Let's Build a Compiler. Tutorial de Jack W. Crenshaw sobre cómo hacer un
compilador
Java a tope: Traductores y Compiladores con Lex/Yacc, JFlex/Cup y
JavaCC. Libro básico sobre compiladores