Compiladores - Una Vision General

15
UNIVERSIDAD NACIONAL DE TRUJILLO COMPILADORES Una Visión General Alvarez Alvarez, Gustavo Alexander

description

Formalmente se puede decir que es aquel traductor que tiene como entrada una sentencia en lenguaje formal y como salida tiene un fichero ejecutable, es decir, realiza una traducción de un código de alto nivel a código máquina.

Transcript of Compiladores - Una Vision General

Page 1: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLO 

COMPILADORES Una Visión General 

Alvarez Alvarez, Gustavo Alexander   

Page 2: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

2

1. PROGRAMACION DE SISTEMAS 1.1. DEFINICIÓN

Se entiende por programación de sistemas el conjunto de programas necesario para que una computadora de una imagen coherente y monolítica ante sus usuarios. Es un área especializada dentro de las ciencias de la computación. Así, mediante la programación de sistemas, no solo se manejan las computadoras por medio del lenguaje maquina (0 y 1) sino por otros sistemas operativos, sin lo cual sería muy difícil la interacción con la maquina.

1.2. HERRAMIENTAS DESARROLLADAS Las herramientas de programación, son aquellas que permiten realizar aplicativos, programas, rutinas, utilitarios y sistemas para que la parte física del computador u ordenador, funcione y pueda producir resultados. Hoy día existen múltiples herramientas de programación en el mercado, tanto para analistas expertos como para analistas inexpertos. Las herramientas de programación más comunes del mercado, cuentan hoy día con programas de depuración o debugger, que son utilitarios que nos permiten detectar los posibles errores en tiempo de ejecución o corrida de rutinas y programas. Muchas herramientas de software que manipulan programas fuente realizan primero algún tipo de análisis. Algunos ejemplos de tales herramientas son:

1. Editores de Estructuras Un editor de estructuras toma como entrada una secuencia de órdenes para construir un programa fuente. El editor de estructuras no sólo realiza las funciones de creación y modificación de textos de un editor de textos ordinario, sino que también analiza el texto del programa, imponiendo al programa fuente una estructura jerárquica apropiada. De esa manera, el editor de estructuras puede realizar tareas adicionales útiles para la preparación de programas. Por ejemplo, puede comprobar si la entrada está formada correctamente, puede proporcionar palabras clave de manera automática (por ejemplo, cuando el usuario escribe while, el editor proporciona el correspondiente do y le recuerda al usuario que entre las dos palabras debe ir un condicional) y puede saltar desde un begin o un paréntesis izquierdo hasta su correspondiente end o paréntesis derecho. Además, la salida de tal editor suele ser similar a la salida de la fase de análisis de un compilador.

2. Impresoras Estéticas Una impresora estética analiza un programa y lo imprime de forma que la estructura del programa resulte claramente visible. Por ejemplo, los comentarios pueden aparecer con un tipo de letra especial, y las proposiciones pueden aparecer con una indentación proporcional a la profundidad de su anidamiento en la organización jerárquica de las proposiciones.

3. Verificadores estáticos

Un verificador estático lee un programa, lo analiza e intenta descubrir errores potenciales sin ejecutar el programa. La parte de análisis a menudo es similar a la que se encuentra en los compiladores de optimización. Así, un verificador estático puede detectar si hay partes de un programa que nunca se podrán ejecutar o si cierta variable se usa antes de ser definida. Además, puede detectar errores de lógica, como intentar utilizar una variable real como apuntador, empleando las técnicas de verificación de tipos.

4. Intérpretes En lugar de producir un programa objeto como resultado de una traducción, un intérprete realiza las operaciones que implica el programa fuente. Para una proposición de asignación, por ejemplo, un intérprete podría construir un árbol como y después efectuar las operaciones de los nodos conforme “recorre” el árbol. En la raíz descubriría que tiene

Page 3: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

3

que realizar una asignación, y llamaría a una rutina para evaluar la expresión de la derecha y después almacenaría el valor resultante en la localidad de memoria asociada con el identificador de posición. En el hijo derecho de la raíz, la rutina descubriría que tiene que calcular la suma de dos expresiones. Se llamaría a sí misma de manera recursiva para calcular el valor de la expresión velocidad*60. Después sumaría ese valor de la variable inicial. Muchas veces los intérpretes se usan para ejecutar lenguajes de órdenes, pues cada operador que se ejecuta en un lenguaje de órdenes suele ser una invocación de una rutina compleja, como un editor o un compilador. Del mismo modo algunos lenguajes de “muy alto nivel”, normalmente son interpretados, porque hay muchas cosas sobre los datos, como el tamaño y la forma de las matrices, que no se pueden deducir en el momento de la compilación.

1.3. LENGUAJES

Se llama lenguaje a cualquier tipo de código semiótico estructurado, para el que existe un contexto de uso y ciertos principios combinatorios formales. Existen muchos contextos tanto naturales como artificiales donde aparecen lenguajes.

El lenguaje humano se basa en la capacidad de los seres humanos para comunicarse mediante de signos. Principalmente lo hacemos utilizando el signo lingüístico. Aún así, hay diversos tipos de lenguaje. El lenguaje humano puede estudiarse en cuanto a su desarrollo desde dos puntos de vista complementarios: la ontogenia, que remite al proceso de adquisición del lenguaje por el ser humano, y la filogenia El lenguaje animal se basa en el uso de señales sonoras, visuales y olfativas a modo de signos para referirse a un referente o un significado diferente de dichas señales. Dentro del lenguaje animal están los gritos de alarma, el lenguaje de las abejas, etc. Los lenguajes formales son construcciones artificiales humanas, que se usan en matemática y otras disciplinas formales, incluyendo lenguajes de programación. Estas construcciones tienen estructuras internas que comparten con el lenguaje humano natural, por lo que pueden ser en parte analizados con los mismos conceptos que éste.

1.2.1 Lenguajes Naturales Este tipo de lenguaje es el que nos permite el designar las cosas actuales y razonar a cerca de ellas, fue desarrollado y organizado a partir de la experiencia humana y puede ser utilizado para analizar situaciones altamente complejas y razonar muy sutilmente. La riqueza de sus componentes semánticos da a los lenguajes naturales su gran poder expresivo y su valor como una herramienta para razonamiento sutil. Por otro lado la sintaxis de un LN puede ser modelada fácilmente por un lenguaje formal, similar a los utilizados en las matemáticas y la lógica. Otra propiedad de los lenguajes naturales es la polisemántica, es decir la posibilidad de que una palabra en una oración tenga diversos significados. En un primer resumen, los lenguajes naturales se caracterizan por las siguientes propiedades:

• Desarrollados por enriquecimiento progresivo antes de cualquier intento de formación de una teoría.

• La importancia de su carácter expresivo debido grandemente a la riqueza del componente semántico (polisemántica).

• Dificultad o imposibilidad de una formalización completa.

1.2.2 Lenguajes Artificiales El lenguaje artificial, en oposición al natural, tiene como finalidad evitar –justamente- los inconvenientes de ambigüedad y vaguedad de los lenguajes naturales u ordinarios y, por ello, presenta un grado de artificialidad y convencionalidad mucho mayor por lo que se refiere a la construcción de símbolos y al significado que se les asigna. Símbolos y significados no pertenecen a ninguna comunidad natural de

Page 4: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

4

hablantes, sino a grupos de hablantes relacionados por objetivos científicos o técnicos. El lenguaje artificialmente construido se divide en técnico y formal.

2 PROCESADORES DE LENGUAJES

2.1 DEFINICIÓN Nombre genérico que reciben todas las aplicaciones informáticas en las cuales uno de los datos fundamentales de entrada es un lenguaje. La definición anterior afecta a una gran variedad de herramientas software, algunas de ellas son las siguientes (expresando entre paréntesis el término equivalente en lengua inglesa):

Traductores (translators) Compiladores (compilers) Ensambladores (assemblers) Montadores de enlaces o enlazadores (linkers) Cargadores (loaders) Intérpretes (interpreters) Desensambladores (dissemblers) Decompiladores (decompilers) Depuradores (debuggers) Analizadores de rendimiento (profilers) Optimizadores de código (code optimizers) Compresores (compressors) Preprocesadores (preprocessors) Formateadores (formatters) Editores (editors)

2.2 APLICACIONES

Las técnicas empleadas en la construcción de traductores, compiladores e intérpretes pueden aplicarse en la construcción de otras herramientas algunas de las cuales se presentan a continuación: Editores sensibles al contexto

Los editores permiten crear y modificar programas fuente, sin embargo los editores sensibles al contexto avisan al programador de posibles errores sintácticos cuando está escribiendo un programa fuente en un determinado lenguaje de programación. Actualmente la mayor parte de los compiladores incluyen un entorno de programación con un editor con sintaxis resaltada por colores.

Conversores de formatos Utilizan la tecnología de los traductores para convertir una descripción de ficheros en otra.

Preprocesadores Toman como entrada un conjunto de instrucciones y generan código en un lenguaje de alto o medio nivel.

Formateadores de código fuente Tienen como entrada un código fuente, y obtienen como salida el mismo código fuente mostrado de forma que se puede seguir perfectamente la estructura del programa.

Generadores de código Permiten desarrollar aplicaciones a partir de unas especificación es muy compactas, que pueden ser tratadas como un lenguaje de aplicación.

Generadores de pantallas Son un caso particular de los generadores de código.

Verificación estática de programas

Page 5: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

5

Leen el programa fuente y lo analizan para descubrir errores potenciales, sin ejecutar dicho programa. Ejemplo lint (incorporado de forma estándar por UNIX) y PC-lint (disponible comercialmente para DOS).

Formateadores de texto Reciben como entrada un texto con indicaciones de como se desea la salida y generan dicho texto formateado en un fichero, o para una determinada impresora. Pueden estar especializados en fórmulas matemáticas, químicas, escritura de música, etc... Ejemplos TROFF, EQN, etc...

Intérpretes de comandos de un sistema operativo Reciben las órdenes del sistema operativo, las analizan y las ejecutan. Ejemplo COMMAND.COM de MS-DOS.

Construcción de entornos operativos Es un caso particular del anterior en el cual las órdenes suelen recibirse en forma gráfica. Ejemplos WINDOWS, GEM, Macintosh, etc.

Intérpretes para consultar bases de datos Reciben las consultas de la base de datos, las analizan y las ejecutan. Ejemplos SQL, DBASE, etc...

Compiladores de silicio (silicon compilers) Utilizan las mismas técnicas de construcción de traductores, compiladores e intérpretes pero implementadas en hardware.

Procesamiento de lenguajes naturales Aplican las técnicas de construcción de traductores a los lenguajes naturales (Inglés, Castellano, etc...) permitiendo el análisis, comprensión y traducción.

Reconocimiento del habla Se realiza un análisis de los sonidos para construir las palabras.

Desarrollo de pequeños lenguajes Suelen ser pequeños lenguajes específicos para el problema que resuelve la aplicación informática dentro de la cual se desarrollan.

3 INTERPRETES, TRADUCTORES, COMPILADORES Y ENSAMBLADORES

3.1 INTERPRETES

Los intérpretes se definieron anteriormente, como programas que analizan y ejecutan simultáneamente el programa fuente, es decir no producen un código objeto, siendo su ejecución simultánea a la del programa fuente. Es como un compilador, solo que la salida es una ejecución. El programa de entrada se reconoce y ejecuta a la vez. No se produce un resultado físico (código máquina) sino lógico (una ejecución). Hay lenguajes que sólo pueden ser interpretados, como p.ej. SNOBOL (StriNg Oriented SimBOlyc Language), LISP (LISt Processing), algunas versiones de BASIC (Beginner’s All-purpose Symbolic Instruction Code), etc.

Su principal ventaja es que permiten una fácil depuración. Entre los inconvenientes podemos citar, en primer lugar, la lentitud de ejecución, ya que al ejecutar a la vez que se traduce no puede aplicarse un alto grado de optimización; por ejemplo, si el programa entra en un bucle y la optimización no está muy afinada, las mismas instrucciones se interpretarán y ejecutarán una y otra vez, ralentizando la ejecución del programa. Otro inconveniente es que durante la ejecución, el intérprete debe residir en memoria, por lo que consumen más recursos.

Además de que la traducción optimiza el programa acercándolo a la máquina, los lenguajes interpretados tienen la característica de que permiten construir programas que se pueden modificar a sí mismos.

Page 6: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

6

Algunos lenguajes intentan aunar las ventajas de los compiladores y de los intérpretes y evitar sus desventajas; son los lenguajes pseudointerpretados. En estos, el programa fuente pasa por un pseudocompilador que genera un pseudoejecutable. Para ejecutar este pseudoejecutable se le hace pasar por un motor de ejecución que lo interpreta de manera relativamente eficiente. Esto tiene la ventaja de la portabilidad, ya que el pseudoejecutable es independiente de la máquina en que vaya a ejecutarse, y basta con que en dicha máquina se disponga del motor de ejecución apropiado para poder interpretar cualquier pseudoejecutable. El ejemplo actual más conocido lo constituye el lenguaje Java; también son pseudointerpretadas algunas versiones de Pascal y de COBOL (COmmon Bussiness Oriented Language). La figura 3.1 muestra los pasos a seguir en estos lenguajes para obtener una ejecución.

Figura 3.1 Esquema de traducción/ejecución de un programa interpretado

Se pueden clasificar desde el punto de vista de su estructura en varios tipos: intérpretes puros, intérpretes avanzados o normales, e intérpretes incrementales. 3.1.1 Interpretes Puros

Los intérpretes puros son los que analizan una sentencia y la ejecutan, y así sucesivamente todo el programa fuente. Fueron los intérpretes desarrollados en la primera generación de ordenadores, pues permitían la ejecución de largos programas con ordenadores de memoria muy reducida, ya que sólo debían contener en memoria el intérprete y la sentencia a analizar y ejecutar. El principal problema de este tipo de intérpretes es que si a mitad del programa fuente se producen errores, se debe de volver a comenzar el proceso. En la figura 3.2 se representa el esquema general de un intérprete puro, donde se puede observar que el lenguaje fuente se traduce a una representación interna (texto o binaria) que puede ser almacenada en memoria o en disco. Esta representación interna tiene todas las instrucciones numeradas o colocadas consecutivamente en estructuras de tamaño fijo (por ejemplo un array o posiciones consecutivas de memoria, o un fichero binario de estructuras de tamaño fijo).

Mientras se realiza este paso se puede construir la tabla de etiquetas, que es una tablas que contiene una estructura donde están todas las etiquetas y su posición en el programa fuente (las etiquetas se utilizan tanto en las instrucciones de salto como en las llamadas a procedimientos y funciones).Una vez que este proceso ha finalizado, comienza la ejecución por la primera instrucción del código, que se envía al evaluador de instrucciones, éste la ejecuta (recibiendo datos si es necesario o enviando un mensaje de error). El evaluador de instrucciones también determina la instrucción siguiente a ejecutar, en algunos casos previa consulta a la tabla de etiquetas. En el caso de que no haya saltos (GOTO) o llamadas a procedimientos o funciones se ejecuta la siguiente instrucción a la instrucción en curso. El evaluador de instrucciones puede utilizar dos métodos de evaluación. El método clásico es la evaluación voraz o ansiosa, donde se evalúan las expresiones completamente. Otro método es la evaluación perezosa, evaluándose sólo la parte necesaria de la expresión (el resto no se evalúa).

Page 7: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

7

Sobre la construcción de un intérprete puro de un mini-lenguaje orientado a objetos denominado Bob puede consultarse el artículo de David Betz, autor del intérprete XLISP.

Figura 3.2 Esquema General de un Interprete Puro

3.1.2 Interpretes Avanzados

Los intérpretes avanzados o normales incorporan un paso previo de análisis de todo el programa fuente. Generando posteriormente un lenguaje intermedio que es ejecutado por ellos mismos. De esta forma en caso de errores sintácticos no pasan de la fase de análisis. En la figura 3.3 se representa el esquema general de un intérprete avanzado.

Figura 3.3 Esquema General de un interprete Avanzado

Page 8: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

8

Existen lenguajes que comenzaron siendo interpretados y que posteriormente se desarrollaron compiladores para ellos, por ejemplo Quick-BASIC, pudiendo utilizarse el intérprete en la fase de elaboración y depuración de programas, y el compilador para la ejecución rutinaria del programa compilado Otros ejemplos son los compiladores orientados a la enseñanza, como el TURBO PASCAL�, que generan un código intermedio que se ejecuta en memoria (es decir en este caso trabaja como intérprete avanzado), o también generan un programa ejecutable en disco (en este caso trabaja como compilador al crear un código objeto con la extensión .exe). Un ejemplo de intérprete avanzado es el que utiliza el lenguaje Java. Así un programa en lenguaje java (con la extensión .java) se compila y produce uno o varios ficheros con la extensión .class, estos ficheros están en un formato binario denominado bytecode independiente de plataforma, que se interpreta posteriormente. Esto permite que el bytecode se ejecute en cualquier sistema operativo que disponga de un intérprete de bytecode. Dado que la mayor parte de los navegadores de Internet llevan inmerso un intérprete de bytecode, esto ha permitido al lenguaje Java ser uno de los más utilizados en aplicaciones que usen Internet. Las aplicaciones de los intérpretes avanzados son:

Emulación de arquitecturas de ordenadores. Método para facilitar la portabilidad de aplicaciones entre distintas

arquitecturas de ordenadores. Fase de prueba de lenguajes y arquitecturas de máquinas abstractas, antes de

construir los traductores a código objeto de una arquitectura determinada.

3.1.3 Interpretes incrementales Algunos lenguajes no se pueden compilar, debido a que entre sus características pueden manejar objetos o funciones que no son conocidos en tiempo de compilación, ya que son creados en ejecución. Para este tipo de lenguajes existen los intérpretes incrementales, que permiten compilar los módulos completamente definidos, y recompilar en tiempo de ejecución los nuevos módulos. Están a medio camino entre los intérpretes puros y los intérpretes avanzados o normales. Los intérpretes incrementales tienen gran interés en los lenguajes que permiten no definir los problemas completamente en tiempo de compilación. En estos casos se utilizan evaluadores parciales (partial evaluators) que toman como entrada el programa fuente junto con algunos datos (pero no todos), realizándose los cálculos que se pueden hacer con dicho subconjunto de datos, y produciendo una salida que contiene un residuo del programa fuente que se ha introducido. Algunos fabricantes de software denominan a los intérpretes incrementales como compiladores incrementales, debido a que la palabra intérprete está desprestigiada, y prefieren acogerse a la parte del intérprete avanzado.

3.2 TRADUCTOR

Un traductor es un programa que procesa un texto fuente y genera un texto objeto. El traductor está escrito en un lenguaje de implementación (LI) o también denominado

lenguaje host. El texto fuente está escrito en lenguaje fuente (LF), por ejemplo un lenguaje de alto nivel. El texto objeto está escrito en lenguaje objeto (LO), por ejemplo un lenguaje máquina,

ensamblador u otro lenguaje de alto nivel. Se suele utilizar la notación en T, tal como se muestra en la figura 3.4. La notación en T también se puede representar de una forma abreviada como: LFLILO. El lenguaje fuente (LF) es el lenguaje origen que transforma el traductor (por ejemploC, C++, Pascal, FORTRAN, PL/I,COBOL, ADA, MODULA-2, BASIC). También pueden ser lenguajes de bajo nivel.

Page 9: Compiladores - Una Vision General

El lenguaje pueden sermicroprocesEl lenguajetraductor. Pmáquina.

Los traduccódigo máqacciones atóque compon

Es importanEn la décadde escribir. para su imptanto puestolenguajes fode problemade carrera d

3.2.1 TipDelasintfacdiftip

3.2.2 Es

UnestPofig

objeto (LO)r por ejemsador determ

e de implemPuede ser cu

ctores englobquina) como ómicas que pne a un comp

F

nte destacar da de 1950, s

El primer plementacióno que el trabormales no sas y errores.

de cualquier e

pos esde los oríges personas exerpretar inst

cilitar el trabferentes camos de traduct

tructura n traductor tructuras inter tanto, el es

gura 3.6.

) es el lenguamplo otro leminado, un lementación (LI

ualquier len

Fi

ban tanto a loa los intérprepuede ejecutpilador/intérp

Figura 3.5 E

la velocidadse consideró compilador

n el equivalenbajo se desase aplicó a laSin embargo

estudiante un

enes de la coxpresan sus ntrucciones. Lajo a los hum

mpos y áreas tores que ver

divide su laermedias y osquema de u

aje al que seenguaje de

enguaje ensamI) o lenguaj

nguaje, desd

igura 3.4 No

os compiladoetes (en los qtar el intérpreprete.

Esquema prel

d con la que ha los traducde Fortran

nte a 18 añoarrolló en eqa creación deo, hoy día unniversitario d

omputación, necesidades Los traductomanos, lo qu

concretas dremos a cont

abor en dos eotra que sintun traductor p

UNIV

e traduce el talto nivel,

mblador. e host es el

de un lengua

otación en T

ores (en los que el lenguaete). La figu

liminar de un

hoy en día sctores como

(Formula Ts de trabajo

quipo). Hastae traductoresn compiladorde Informátic

ha existido y la forma e

ores han intue ha llevado de la informátinuación.

etapas: una tetiza la salidpasa de ser e

VERSIDAD NA

texto fuente. , el lengua

l lenguaje enaje de alto

que el lenguaje destino esura 3.5 muest

n traductor

se puede conprogramas n

Translator), pindividual (ra que la tes, su desarrolr básico pueca.

un abismo een que un ortentado salva aplicar la

ática, dando

que analiza da a partir del de la figu

ACIONAL DE TCOMPIL

Los lenguajaje máquina

n que está enivel a un

uaje destino stá constituidtra el esquem

nstruir un comnotablementepor ejemplo,realmente noeoría de autllo ha estado

ede ser el pro

entre la formrdenador es

var este abisteoría de autlugar a los

la entrada de dichas estura 3.4, a se

TRUJILLOLADORES

9

9

es objeto a de un

escrito el lenguaje

suele ser do por las ma básico

mpilador. e difíciles necesitó

o se tardó ómatas y o plagado oyecto fin

ma en que capaz de

smo para tómatas a distintos

y genera tructuras. r el de la

Page 10: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

10 

10

Figura 3.6 Esquema de un Traductor

Básicamente los objetivos de la etapa de análisis son: a) Controlar la corrección del programa fuente, y b) Generar las estructuras necesarias para comenzar la etapa de síntesis. Para llevar esto a cabo, la etapa de análisis consta de las siguientes fases: Análisis lexicográfico. Divide el programa fuente en los componentes básicos del

lenguaje a compilar. Cada componente básico es una subsecuencia de caracteres del programa fuente, y pertenece a una categoría gramatical: números, identificadores de usuario (variables, constantes, tipos, nombres de procedimientos,...), palabras reservadas, signos de puntuación, etc.

Análisis sintáctico. Comprueba que la estructura de los componentes básicos sea correcta según las reglas gramaticales del lenguaje que se compila.

Análisis semántico. Comprueba que el programa fuente respeta las directrices del lenguaje que se compila (todo lo relacionado con el significado): chequeo de tipos, rangos de valores, existencia de variables, etc.

Cualquiera de estas tres fases puede emitir mensajes de error derivados de fallos cometidos por el programador en la redacción de los textos fuente. Mientras más errores controlen un compilador, menos problemas dará un programa en tiempo de ejecución. Por ejemplo, el lenguaje C no controla los límites de un array, lo que provoca que en tiempo de ejecución puedan producirse comportamientos del programa de difícil explicación.

La etapa de síntesis construye el programa objeto deseado (equivalente semánticamente al fuente) a partir de las estructuras generadas por la etapa de análisis. Para ello se compone de tres fases fundamentales: Generación de código intermedio. Genera un código independiente de la máquina

muy parecido al ensamblador. No se genera código máquina directamente porque así es más fácil hacer pseudo-compiladores y además se facilita la optimización de código independientemente del microprocesador.

Generación del código máquina. Crea un bloque de código máquina ejecutable, así como los bloques necesarios destinados a contener los datos.

Fase de optimización. La optimización puede realizarse sobre el código intermedio (de forma independiente de las características concretas del microprocesador), sobre el código máquina, o sobre ambos. Y puede ser una aislada de las dos anteriores, o estar integrada con ellas.

3.2.3 Procesos

La construcción de un traductor de un determinado lenguaje es una tarea compleja, que se puede reducir siguiendo una metodología, que consistirá en dividir en

Page 11: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

11 

11

módulos las distintas fases del traductor. La complejidad del traductor dependerá de las características del lenguaje fuente y del lenguaje objeto, y de su distancia medida en términos de diferencias de niveles. Así es más sencillo traducir entre dos lenguajes del mismo nivel, que entre un lenguaje de alto nivel y uno de bajo nivel. En la figura XX se muestra la estructura de un traductor. En un principio todas las fases se pueden agrupar en dos tareas:

Análisis del programa fuente y Síntesis en el correspondiente programa objeto.

El análisis consiste en verificar la corrección del programa fuente, para lo cual se descompone el programa fuente en trozos elementales o unidades mínimas sintácticas denominadas componentes léxicos o en inglés tokens (análisis léxico). Los tokens se pueden agrupar para comprobar su disposición correcta en las distintas construcciones y sentencias del lenguaje a analizar (análisis sintáctico y semántico). Comprobándose de esta forma la validez sintáctica y semántica del programa fuente. En caso contrario se emiten los errores oportunos (manejo de errores). La información de cada identificador recogida durante la fase de análisis se almacena en la tabla de símbolos. Esta información también se utiliza durante la fase de análisis (por ejemplo para comprobar si una variable se intento declarar dos veces). La tarea de síntesis tiene por objeto la generación del código del lenguaje objeto. En el caso particular de los compiladores suele incluirse también la generación de código intermedio, como un medio para garantizar la transportabilidad entre distintas máquinas objeto o como método para poder utilizar el mismo back-end, entre compiladores de lenguajes diferentes. La generación de código intermedia se apoya directamente en la información recogida en la tabla de símbolos durante la fase de análisis. La generación de código para la máquina objeto definitivo tan sólo se apoya en el código intermedio. También es necesario un tratamiento de errores para la fase de síntesis.

Page 12: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

12 

12

Figura 3.7 Fases de un Traductor

3.2.4 Fases

El modelo de traductor que se acaba de mostrar separa al traductor en distintos módulos, dando una idea de secuencialidad, sin embargo en muchos casos estos módulos se ejecutan simultáneamente. En la exposición anterior se ha omitido como se produce la secuencia de ejecución entre los distintos módulos del traductor. Tal como se explicó en los apartados precedentes hay interacciones entre el analizador léxico y el analizador sintáctico. La primera posibilidad es que el analizador léxico genere un token para que sea procesado por el analizador sintáctico. Una vez que el analizador sintáctico lo ha procesado pedirá al analizador léxico el siguiente token, o en el caso de que no lo necesite se lo devuelva,

Page 13: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

13 

13

repitiéndose este proceso durante el análisis del lenguaje fuente. Otra posibilidad es que el analizador léxico genere todos los tokens del programa fuente de una pasada, y los almacene en memoria o en un disco para que sean procesados posteriormente por el analizador sintáctico. En este caso esta parte del traductor se dice que es de paso separado (separate pass). Algunos traductores realizan todo el proceso en un solo paso (traductores de un paso), mientras que otros realizan hasta más de 30 pasos (por ejemplo los primeros compiladores de PL/I de IBM). Los factores que influyen en el número de pasos de un compilador son los siguientes:

1. Complejidad del lenguaje fuente. 2. Distancia entre el lenguaje fuente y el lenguaje objeto. 3. Memoria mínima necesaria para compilar. 4. Velocidad y tamaño del compilador. 5. Velocidad y tamaño del programa objeto. 6. Necesidades de depuración (debugging). 7. Técnicas de detección y reconocimiento de errores. 8. Número de personas y tiempo disponible para realizar el traductor.

La complejidad del lenguaje fuente también puede implicar que el compilador necesite realizar varias pasadas al lenguaje fuente para realizar el análisis del programa fuente, es decir es necesario leer varias veces el lenguaje fuente para obtener toda la información necesaria para la fase de análisis. Así por ejemplo la complejidad del lenguaje Eiffel obliga a sus compiladores a dar varias pasadas a los ficheros fuente. Los compiladores orientados a educación de estudiantes de lenguajes de programación son compiladores de un paso. La optimización de código que se realiza en ellos es muy pequeña o no se hace, ya que la mayoría de los programas se compilarán muchas veces hasta que se pongan a punto. Ejecutándose una vez y descargándose. Las fases de análisis y generación de código se realizan a la vez. La parte más importante de este tipo de compiladores es la detección y reconocimiento de errores. Por ejemplo los compiladores Turbo Pascal y Turbo C++ de Borland.

Los compiladores profesionales, en general no suelen de ser de un paso, sino que son de varios pasos. Se suele cuidar mucho la fase de optimización de código. Normalmente los fabricantes de compiladores comerciales suelen tener varias gamas de compiladores según el usuario al que vayan destinados. Así las gamas de compiladores Quick de Microsoft o Turbo de Borland van destinadas a estudiantes o a profesionales que busquen la velocidad de compilación sobre la optimización de código. Para profesionales que deseen una mejor calidad de código objeto, perdiendo velocidad de compilación, estos mismos fabricantes ofrecen las gamas Professional y Borland respectivamente.

Page 14: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

14 

14

Figura 3.8 Esquema General de un Traductor de un Paso

Los traductores de un paso y de una pasada única al lenguaje fuente son los más rápidos. Así los diseñadores de traductores eligen este esquema cuando la complejidad del lenguaje lo permite construirlos. En este caso el esquema habitual de los traductores está dirigido por el analizador sintáctico, que constituye el centro del proceso de traducción o módulo principal, y el resto de los módulos cooperan a su alrededor.

3.3 Compiladores

Un traductor que transforma textos fuente de lenguajes de alto nivel a lenguajes de bajo nivel se le denomina compilador (en inglés compiler). Formalmente se puede decir que es aquel traductor que tiene como entrada una sentencia en lenguaje formal y como salida tiene un fichero ejecutable, es decir, realiza una traducción de un código de alto nivel a código máquina (también se entiende por compilador aquel programa que proporciona un fichero objeto en lugar del ejecutable final). El tiempo que se necesita para traducir un lenguaje de alto nivel a lenguaje objeto se denomina tiempo de compilación (compilation time). El tiempo que tarda en ejecutarse un programa objeto se denomina tiempo de ejecución (run time).

Figura 3.9 Concepto de Tiempo de Compilación

Se Nótese que el programa fuente y los datos se procesan en diferentes momentos, denominados tiempo de compilación y tiempo de ejecución.

Figura 3.10 Concepto de Tiempo e Ejecución

Page 15: Compiladores - Una Vision General

UNIVERSIDAD NACIONAL DE TRUJILLOCOMPILADORES

15 

15

3.4 Ensambladores

Si el lenguaje fuente es el lenguaje ensamblador (en inglés assembly) y el lenguaje objeto es el lenguaje máquina, entonces al traductor se le llama ensamblador (en inglés assembler). Los ensambladores son traductores sencillos, en los que el lenguaje fuente tiene una estructura simple, que permite una traducción de una sentencia fuente a una instrucción en lenguaje máquina, guardándose en casi todos los casos esta relación uno a uno. Hay ensambladores que tienen macroinstrucciones en su lenguaje. Estas macroinstrucciones, de acuerdo con su nombre, se suelen traducir a varias instrucciones de máquina. A este tipo de ensambladores se les denomina macroensambladores (en inglés macroassembler). Actualmente la mayor parte de los ensambladores comerciales son macroensambladores. El término ensamblador (del inglés assembler) se refiere a un tipo de programa informático que se encarga de traducir un fichero fuente escrito en un lenguaje ensamblador, a un fichero objeto que contiene código máquina, ejecutable directamente por la máquina para la que se ha generado. El propósito para el que se crearon este tipo de aplicaciones es la de facilitar la escritura de programas, ya que escribir directamente en código binario, que es el único código entendible por la computadora, es en la práctica imposible. La evolución de los lenguajes de programación a partir del lenguaje ensamblador originó también la evolución de este programa ensamblador hacia lo que se conoce como programa compilador.

Funcionamiento

El programa lee el fichero escrito en lenguaje ensamblador y sustituye cada uno de los códigos mnemotécnicos que aparecen por su código de operación correspondiente en sistema binario.

Tipos de ensambladores Podemos distinguir entre tres tipos de ensambladores: o Ensambladores básicos.

Son de muy bajo nivel, y su tarea consiste básicamente en ofrecer nombres simbólicos a las distintas instrucciones, parámetros y cosas tales como los modos de direccionamiento. Además, reconoce una serie de directivas (o meta instrucciones) que indican ciertos parámetros de funcionamiento del ensamblador.

o Ensambladores modulares, o macro ensambladores. Descendientes de los ensambladores básicos, fueron muy populares en las décadas de los 50 y los 60, antes de la generalización de los lenguajes de alto nivel. Hacen todo lo que puede hacer un ensamblador, y además proporcionan una serie de directivas para definir e invocar macroinstrucciones (o simplemente, macros). Véase X86.

o Ensambladores modulares 32-bits o de alto nivel. Son ensambladores que aparecieron como respuesta a una nueva arquitectura de procesadores de 32 bits, muchos de ellos teniendo compatibilidad hacia atrás pudiendo trabajar con programas con estructuras de 16 bits. Además de realizar la misma tarea que los anteriores, permitiendo también el uso de macros, permiten utilizar estructuras de programación más complejas propias de los lenguajes de alto nivel.

4 Referencias Bibliograficas

Java a Tope: Traductores y Compiladores con Lex/Yacc, JFlex/Cup y JavaCC, Sergio Gálvez Rojas Miguel Angel Mora Mata, Universidad de Málaga, 2005

Conceptos Básicos de Procesadores de Lenguajes, Juan Manuel Cueva Lovelle, Universidad de Oviedo, 1998