Introducción Lenguajes de programación Primera generación: lenguajes máquina Los programas se escriben en código binario 000001011010000000000000 Segunda generación: lenguajes simbólicos Cada instrucción de la máquina se representa mediante símbolos ADD AX,P1 Tercera generación: lenguajes de alto nivel Una sola instrucción de este tipo representa usualmente varias instrucciones de la máquina P1 = P2 + P3; Ejemplos: FORTRAN, COBOL, LISP, BASIC, C, C++, APL, PASCAL, SMALLTALK, JAVA, ADA, PROLOG 1 Procesadores de lenguaje Los lenguajes simbólicos se traducen mediante ensambladores convierten cada instrucción simbólica en la instrucción máquina equivalente Los programas escritos en lenguajes de alto nivel se traducen mediante traductores o procesadores de lenguaje Tres tipos: Compilador Intérprete Compilador-intérprete Compilador Analiza un programa escrito en un lenguaje de alto nivel (programa fuente) y, si es correcto, genera un código equivalente (programa objeto) escrito en otro lenguaje, que puede ser de primera generación (de la máquina), de segunda generación (simbólico), o de tercera generación. El programa objeto puede guardarse y ejecutarse tantas veces como se quiera, sin necesidad de traducirlo de nuevo. Ejemplos: FORTRAN, COBOL, C, C++, PASCAL y ADA. 2 Notación en T A B C A es el lenguaje fuente B es el lenguaje objeto C es el lenguaje en que está escrito el propio compilador no necesariamente el mismo que el lenguaje fuente o el lenguaje objeto. Intérprete A C Analiza un programa escrito en un lenguaje de alto nivel y, si es correcto, lo ejecuta directamente en el lenguaje de la máquina en que se está ejecutando el intérprete. Cada vez que se desea ejecutar el programa, es preciso interpretarlo de nuevo. Ejemplos: LISP, APL, SMALLTALK, JAVA y PROLOG. De algún lenguaje, como BASIC, existen a la vez compiladores e intérpretes. 3 Compilador-intérprete Traduce el programa fuente a un formato o lenguaje intermedio, que después se interpreta. A B C B es el lenguaje B intermedio D D es el lenguaje en que está escrito el intérprete JAVA es un ejemplo típico primero se compila a BYTECODE, y posteriormente éste se interpreta mediante una máquina virtual de JAVA, que es un intérprete de BYTECODE. Otros conceptos Compilador cruzado Compilador que traduce un lenguaje fuente a objeto, pero el programa objeto es para un ordenador distinto a aquel en que se compila Autocompilador Compilador escrito en el lenguaje fuente que traduce Metacompilador o compilador de compiladores Programa al que se especifica el lenguaje para el que se quiere un compilador y lo genera 4 Compilador de una o varias pasadas Pasada Recorrido total de todo el lenguaje fuente con alguna misión específica Compilador de una pasada Todas las fases se realizan durante un paso único C y Pascal permiten compilación de una pasada Compilador de varias pasadas Imponen menos restricciones al lenguaje fuente Primera pasada: léxico y sintáctico Segunda pasada: semántico y optimización a nivel de fuente Tercera pasada: generación de código y optimización a nivel de objeto Analizador morfológico Programa fuente Analizador sintáctico Tabla de símbolos Analizador semántico Estructura de un compilador Gestión de memoria Optimizador de código Generador de código Programa objeto Proceso de errores 5 Analizador morfológico También llamado analizador léxico, preprocesador o scanner, en inglés. Realiza la primera fase de la compilación. Convierte el programa que va a ser compilado en una serie de unidades más complejas (unidades sintácticas o tokens) Elimina espacios en blanco y comentarios Detecta errores morfológicos Símbolo no permitido Identificador o constante mal construido Usualmente se implementa mediante un autómata finito determinista Analizador morfológico (II) Ejemplo: a[index] = 4+2 Unidades sintácticas a [ index ] = 4 + 2 identificador corchete izquierdo identificador corchete derecho asignación número signo más número 6 Analizador sintáctico También llamado parser, en inglés. Es el elemento fundamental del procesador, pues lleva el control del proceso e invoca como subrutinas a los restantes elementos del compilador. Realiza el resto de la reducción al axioma de la gramática para comprobar que la instrucción es correcta. Usualmente se implementa mediante un autómata a pila o una construcción equivalente. Ejemplo expresión expresión de asignación expresión expresión expresión de subíndice expresión aditiva expresión expresión identificador a [ identificador index expresión ] = número 4 expresión + número 2 7 Analizador semántico Comprueba la corrección semántica de la instrucción, por ejemplo, la compatibilidad del tipo de las variables en una expresión. La información como los tipos de datos que se calculan mediante el analizador semántico se llaman atributos y se agregan al árbol sintáctico como anotaciones Los atributos también se pueden introducir en la tabla de símbolos Ejemplo expresión expresión de asignación expresión expresión entero entero expresión de subíndice expresión expresión identificador a Vector de enteros expresión aditiva [ identificador index entero expresión ] = número 4 entero expresión + número 2 entero 8 Generador y optimizador Generador de código Traduce el programa fuente al lenguaje objeto utilizando toda la información proporcionada por las restantes partes del compilador. Optimizador de código Mejora la eficiencia del programa objeto en ocupación de memoria o en tiempo de ejecución. En un intérprete no existen las fases de generación y optimización de código, que se sustituyen por una fase de ejecución de código. Tabla de símbolos Estructura de datos que mantiene información asociada a los identificadores Tipo Si matriz – número de dimensiones Si función – número y tipo de argumentos Interactúa con casi todos los componentes AM introduce identificadores Asint, Asem agrega tipos de datos y otra información Generador y Optimizador utilizan la información almacenada para generar el código adecuado 9