Compilador Es cualquier programa que toma como entrada un texto escrito en un lenguaje, llamado fuente y da como salida otro texto en un lenguaje denominado objeto. Traductores Los procesadores de lenguajes son aquellos programas destinados a trabajar sobre una entrada, por la forma como ha sido elaborada, pertenece a un lenguaje particular. Los procesadores de lenguajes se clasifican como traductores o interpretes. El traductor es un programa que recibe una entrada escrita en un lenguaje (el lenguaje fuente) a una salida perteneciente a otro lenguaje (el lenguaje objeto). Un intérprete, no lleva a cabo tal transformación, en su lugar obtiene los resultados conforme se van analizando las entradas. Los traductores son clasificados en compiladores, ensambladores y preprocesadotes. Ensamblador Es el programa encargado de llevar a cabo un proceso denominado de ensamble o ensamblado, este proceso consiste en que a partir de un lenguaje máquina, este sea utilizado en lenguaje ensamblador: • La integración de los diversos módulos que conforman al programa • La resolución de las direcciones de memoria designadas en el área de datos para el almacenamiento de variables, constantes y estructuras complejas. • La identificación de las direcciones de memoria en la sección del código correspondientes a los puntos de entrada en saltos condicionales o incondicionales junto con los puntos de arranque de las subrutinas • la resolución de los diversos llamados a los servicios o rutinas del sistema operativo código dinámico y bibliotecas de tiempo de ejecución • Las especificaciones de la cantidad de memoria destinadas para las áreas de datos, el código, la pila, la cantidad o monto otorgados para su ejecución • La incorporación de datos y código necesarios para la carga de un programa para su ejecución. Históricamente con la escasez de memoria de las primeras computadoras, se puso de moda el uso de interpretes frente a los compiladores, pues el programa fuente sin traducir y el interprete juntos daban una ocupación de memoria menor que la resultante de los compiladores. Por ello los primeros ordenadores iban siempre acompañados de un interprete Basic (XT, Commodore, Spectrum). La mejor información sobre los errores se daba por parte del compilador así como una mayor velocidad de ejecución del código resultante hizo que poco a poco se impusieran los compiladores. Hoy en día y con el problema de memoria resuelto, se puede hablar de un gran predominio de los compiladores frente a los interpretes, aunque interpretes como los incluidos en los navegadores de Java son la gran excepción. La diferencia entre un compilador y un traductor es: En el compilador se recibe un programa escrito en un lenguaje de alto nivel, medio o bajo y lo transforma a su equivalente en un lenguaje ensamblador e inclusive a lenguaje máquina pero sin ejecutar el programa. Un compilador en un traductor la forma de cómo llevará la traducción es el objetivo central en el diseño de compilador. Ventajas de compilador frente a un intérprete • Se compila una vez, se ejecuta n−veces • En bucles, la compilación genera código equivalente al bucle pero un interpretándolo se traduce tantas 1 veces una línea como veces se repite el bucle • El compilador tiene una visión global del programa, por lo que la información de mensajes de errores es más detallada. Ventajas de un intérprete frente a compilador • Un interprete necesita menos memoria que un compilador • Permite una mayor interactividad con el código en tiempo de desarrollo. Un compilador, no es programa que funciona de manera aislada sino que necesita otro programa para conseguir su objetivo, obtener un programa ejecutable a partir de un programa fuente en un lenguaje de alto nivel. Clasificación de compiladores El programa compilador traduce las instrucciones en un lenguaje de alto nivel a instrucciones que la computadora pueda interpretar y ejecutar. Para cada lenguaje de programación se requiere un compilador separado, el compilador traduce todo el programa antes de ejecutarlo. En otras palabras un compilador traduce programas insertados en la memoria por el sistema operativo para convertirlos en pulsaciones electrónicas ejecutables (lenguaje máquina). Los compiladores pueden ser de: • Una sola pasada: Examina el código fuente una vez, generando el código o programa objeto. • Pasadas múltiples: Requiere pasos intermedios para producir un código en otro lenguaje y una pasada final para producir y optimizar el código producido durante los pasos anteriores. • Optimización: Lee un código fuente, lo analiza y descubre errores potenciales sin ejecutar el programa. • Compiladores incrementales: Generan un código objeto, instrucción por instrucción, cuando el usuario teclea cada orden individual. El otro tipo de compiladores requiere que todos los enunciados o instrucciones se compilen conjuntamente. • Ensamblador: Es un lenguaje fuente y posee una estructura sencilla. • Compilador cruzado: Se genera código en un lenguaje objeto para una máquina diferente de la que se esta utilizando para compilar. U compilador cruzado nos permite programar, por ejemplo en Windows para un ambiente como Linux. • Compiladores con montador: Ese tipo de compilador compila distintos módulos de forma independiente y después es capaz de enlazarlos. • Autocompilador: Compilador que esta escrito en el mismo lenguaje que se va a compilar, evidentemente no se puede ejecutar la primera vez. Sirve para hacer ampliaciones de lenguaje, mejorar el código generado, etc. • Metacompilador: Es sinónimo de compilador de compiladores y se refiere a un programa que recibe como entrada las especificaciones de lenguaje, para el que desea obtener un compilador y genera como salida un compilador de ese lenguaje. • Descompilador: Es un programa que acepta como entrada código máquina y lo traduce a un lenguaje de alto nivel, realizando el proceso inverso a la compilación. Funciones de un compilador Agrandes rasgos un compilador que lee un programa escrito en un lenguaje, el lenguaje fuente y lo traduce a un programa equivalente en otro lenguaje, el lenguaje objeto. Como parte importante de este proceso de traducción, el compilador informa al usuario de la presencia de errores en el programa fuente. A primera vista, la diversidad de compiladores puede parecer abrumadora. Hay miles de lenguajes fuente, desde los lenguajes tradicionales como FORTRAN o PASCAL hasta los lenguajes especializados que han surgido en todas las áreas de aplicación en la informática. 2 Un lenguaje objeto puede ser otro lenguaje de programación o el lenguaje máquina de cualquier computadora entre un microprocesador y un supercomputador. Se pueden construir compiladores para una gran diversidad de lenguajes fuente y máquina utilizando las mismas técnicas básicas. Los primeros compiladores de los años 50's, estaban relacionados con la traducción de formulas aritméticas a código de máquina. En las 50's se considero a los compiladores como programas notablemente difíciles de escribir. El primer compilador FORTRAN necesito para su implantación 18 años (Backus Fortran). Partes en las que trabaja un compilador Conceptualmente FORTRAN diseño un compilador que trabajaba en fases. Es decir, las fases de un compilador transforman el programa fuente de una representación a otra, en la práctica se agrupan fases y las representaciones intermedias entre las fases no necesitan ser construidas explícitamente. Análisis léxico Es la primera fase de un compilador. Su principal función consiste en leer los caracteres de entrada y elaborar como salida una secuencia de componentes léxicos que utiliza el analizador sintáctico para hacer el análisis. Aspectos del análisis léxico Hay varias razones para dividir en fases el análisis de la compilación. El análisis léxico y análisis sintáctico: • Un diseño sencillo es la consideración más importante, separar a estos dos tipos de análisis a menudo permite simplificar una u otra de dichas fases. • Se mejora la eficiencia del compilador además de permitir construir un procesador especializado y potencialmente más eficiente para esa función. Con algunas técnicas de manejo de buffers para la lectura de caracteres de entrada y procesamiento de componentes léxicos se pueden mejorar significativamente el rendimiento de un compilador. Errores léxicos Son pocos los errores simplemente en el nivel léxico ya que tiene una visión muy restringida de un programa fuente. El analizador léxico debe devolver el componente léxico de un identificador y dejar a otra fase se ocupe de los errores. Suponga que una situación en la cual el analizador léxico no puede continuar por que ninguno de los patrones concuerda con un prefijo de la entrada. Tal vez la estrategia de recuperación más sencilla sea recuperación EN MODO PANICO (este método de recuperación es donde se borra caracteres sucesivos de la entrada hasta que el analizador léxico pueda encontrar un componente léxico bien formado). Administrador de entradas Utilizar 2 buffer de entrada resulta útil cuando es necesario un pre−análisis en la entrada para identificar los componentes léxicos después se introducen algunas técnicas básicas para encontrar la velocidad del analizador léxico, como es el uso de centinelas que sirven para marcar el final de buffer, hay tres métodos generales de implantar un léxico: • Utilizar un generador de analizadores léxicos, como el compilador LEX para producir el analizador léxico a partir de una especificación basada en expresiones regulares, en este caso el generador proporciona rutinas 3 para leer la entrada y manejarla con buffers. • Escribir el analizador léxico en un lenguaje convencional de programación de sistemas utilizando las posibilidades de entrada y salida de este lenguaje para leer la entrada. • Escribir el analizador léxico en lenguaje ensamblador y manejar explícitamente la lectura de la entrada. Parejas de buffers Se utiliza un buffer dividido en dos mitades de n−caracteres cada una como se indica en la figura: Texto lenguaje fuente Traductor Texto lenguaje objeto Programa objeto Compilador Programa fuente Mensajes de error Programa fuente Analizador léxico Analizador sintáctico Análisis semántico Generación de código intermedio Optimización de código Generador de código Programa objeto Manejo de errores Manejo de tabla de símbolos Analizador léxico Analizador sintáctico Tabla de símbolos Componente léxico Obtén el siguiente componente léxico 4 Programa fuente Buffer = espacio en memoria 5