Está en la página 1de 16

COMPILADORES

Concepto:
Compilador: es un programa que traduce código escrito en
un lenguaje de programación (llamado fuente) a otro
lenguaje (conocido como objeto).

En este tipo de traductor el lenguaje fuente es


generalmente un lenguaje de alto nivel y el objeto un
lenguaje de bajo nivel, como assembly o código máquina,
este proceso de traducción se conoce como compilación.
Historia

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.
Proceso de la construcción de un compilador

La construcción de un compilador involucra la división del proceso en una serie de


fases que variará con su complejidad. Generalmente estas fases se agrupan en dos
tareas: el análisis del programa fuente y la síntesis del programa objeto.

Análisis: se trata de la comprobación de la corrección del programa fuente, según la


definición del lenguaje en términos de teoría de lenguajes formales. Incluye las fases
correspondientes al análisis léxico (que consiste en la descomposición del programa
fuente en componentes léxicos), análisis sintáctico (agrupación de los componentes
léxicos en frases gramaticales ) y análisis semántico (comprobación de la validez
semántica de las sentencias aceptadas en la fase de análisis sintáctico).
Síntesis: su objetivo es la generación de la salida expresada en el
lenguaje objeto y suele estar formado por una o varias
combinaciones de fases de generación de código (normalmente se
trata de código intermedio o de código objeto) y de optimización
de código  (en las que se busca obtener un programa objetivo lo
más eficiente posible, según su complejidad computacional o
complejidad de Kolmogórov: tiempo de ejecución, espacio
durante ejecución, espacio para ser almacenado fuera de
ejecución, etc.)
Alternativamente, las fases descritas para las
tareas de análisis y síntesis se pueden agrupar en:
Analizador o front-end: es la parte que analiza el código fuente,5​ comprueba
su validez, genera el árbol de derivación y rellena los valores de la tabla de
símbolos. Esta parte suele ser independiente de la plataforma o sistema para
el cual se vaya a compilar, y está compuesta por las fases comprendidas entre
el análisis léxico y la generación de código intermedio.
Generador o back-end: es la parte que genera el código máquina, específico
de una plataforma, a partir de los resultados de la fase de análisis.5​
Esta división permite que el mismo generador se utilice para crear el código
máquina de varios lenguajes de programación distintos y que el mismo
analizador que sirve para examinar el código fuente de un lenguaje de
programación concreto sirva para producir código máquina en varias
plataformas.
Tipos de compiladores

Compiladores cruzados: generan código para una plataforma distinta a aquella en la que están
funcionando

Compiladores optimizadores: realizan cambios en el código para mejorar su eficiencia, pero


manteniendo la funcionalidad del programa original.

Compiladores de una sola pasada: generan el código máquina a partir de una única lectura del
código fuente.

Compiladores de varias pasadas: necesitan leer el código fuente varias veces antes de poder
producir el código máquina.

Compiladores JIT (just in time): forman parte de un intérprete y compilan partes del código según
se necesitan.
Proceso de compilación

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.
Etapas del proceso

El proceso de traducción se compone internamente de varias etapas o


fases, que realizan distintas operaciones lógicas. Es útil pensar en estas
fases como en piezas separadas dentro del traductor, y pueden en
realidad escribirse como operaciones codificadas separadamente
aunque en la práctica a menudo se integren juntas.
Fase de análisis:

El análisis léxico constituye la primera fase, aquí se lee el programa fuente de izquierda a derecha y
se agrupa en componentes léxicos (tókenes), que son secuencias de caracteres que tienen un
significado. Además, todos los espacios en blanco, líneas en blanco, comentarios y demás
información innecesaria se elimina del programa fuente. También se comprueba que los símbolos del
lenguaje (palabras clave, operadores, etc.) se han escrito correctamente.

Como la tarea que realiza el analizador léxico es un caso especial de coincidencia de patrones, se
necesitan los métodos de especificación y reconocimiento de patrones, se usan principalmente los
autómatas finitos que acepten expresiones regulares. Sin embargo, un analizador léxico también es
la parte del traductor que maneja la entrada del código fuente, y puesto que esta entrada a menudo
involucra un importante gasto de tiempo, el analizador léxico debe funcionar de manera tan
eficiente como sea posible.
Análisis sintáctico

En esta fase los caracteres o componentes léxicos se agrupan jerárquicamente en frases gramaticales que el compilador utiliza para
sintetizar la salida. Se comprueba si lo obtenido de la fase anterior es sintácticamente correcto (obedece a la gramática del
lenguaje). Por lo general, las frases gramaticales del programa fuente se representan mediante un árbol de análisis sintáctico.
La estructura jerárquica de un programa normalmente se expresa utilizando reglas recursivas. Por ejemplo, se pueden dar las
siguientes reglas como parte de la definición de expresiones:
Un identificador puede ser una expresión.
Un número puede ser una expresión.
Si expresión1 y expresión2 son expresiones, entonces también lo son:
expresión1 + expresión2
expresión1 * expresión2
( expresión1 )
Las reglas 1 y 2 son reglas básicas (no recursivas), en tanto que la regla 3 define expresiones en función de operadores aplicados a
otras expresiones.
La división entre análisis léxico y análisis sintáctico es algo arbitraria. Un factor para
determinar la división es si una construcción del lenguaje fuente es inherentemente
recursiva o no. Las construcciones léxicas no requieren recursión, mientras que las
construcciones sintácticas suelen requerirla. No se requiere recursión para
reconocer los identificadores, que suelen ser cadenas de letras y dígitos que
comienzan con una letra. Normalmente, se reconocen los identificadores por el
simple examen del flujo de entrada, esperando hasta encontrar un carácter que no
sea ni letra ni dígito, y agrupando después todas las letras y dígitos encontrados
hasta ese punto en un componente léxico llamado identificador. Por otra parte, esta
clase de análisis no es suficientemente poderoso para analizar expresiones o
proposiciones. Por ejemplo, no podemos emparejar de manera apropiada los
paréntesis de las expresiones, o las palabras begin y end en proposiciones sin
imponer alguna clase de estructura jerárquica o de anidamiento a la entrada.
Análisis semántico

La fase de análisis semántico revisa el programa fuente para tratar de encontrar errores semánticos
y reúne la información sobre los tipos para la fase posterior de generación de código. En ella se
utiliza la estructura jerárquica determinada por la fase de análisis sintáctico para identificar los
operadores y operandos de expresiones y proposiciones.

Un componente importante del análisis semántico es la verificación de tipos. Aquí, el compilador


verifica si cada operador tiene operandos permitidos por la especificación del lenguaje fuente. Por
ejemplo, las definiciones de muchos lenguajes de programación requieren que el compilador indique
un error cada vez que se use un número real como índice de una matriz. Sin embargo, la
especificación del lenguaje puede imponer restricciones a los operandos, por ejemplo, cuando un
operador aritmético binario se aplica a un número entero y a un número real.7​ Revisa que los
arreglos tengan definido el tamaño correcto.
Optimización de código

La fase de optimización de código consiste en mejorar el código intermedio,


de modo que resulte un código máquina más rápido de ejecutar. Esta fase de
la etapa de síntesis es posible sobre todo si el traductor es un compilador
(difícilmente un intérprete puede optimizar el código objeto). Hay mucha
variación en la cantidad de optimización de código que ejecutan los distintos
compiladores. En los 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.

También podría gustarte