Cuando se habla de compiladores (bajo el marco lógico de la teoría de compiladores y sobre el contexto de la ingeniería en informática) nos referimos a un tipo de programa de sistema conocido como procesador de lenguaje. Los procesadores de lenguaje mas conocidos son los compiladores y los interpretes (mas no son todos), y la diferencia entre estos radica en la forma como procesan en lenguaje y la salida que se obtiene.
En lineas generales, un compilador (como procesador de lenguaje) es un programa que recibe como entrada un programa escrito en un lenguaje fuente y que da como salida la traducción de ese programa a un lenguaje destino. Normalmente la mayoría de los compiladores usan como lenguaje destino el código maquina, que no es otra sino el lenguaje que entienden las computadoras.
ENTRADA -> [COMPILADOR] -> SALIDA
Un compilador no es un programa aislado sino que para lograr el objetivo de traducir un programa al lenguaje maquina necesita la ayuda de otros programas. La tarea de recolectar los archivos que conforman el programa de origen es llevado a cabo por el pre-procesador. Este a su vez se encarga de expandir fragmentos de código conocidos como macros. La salida del pre-procesador es la entrada del compilador, que dará como salida el programa en lenguaje ensamblador. Esta salida del compilador pasara a un programa conocido como Ensamblador y este producirá codigo maquina a partir del código ensamblador y por ultimo si el programa ha sido compilado en partes el Enlazador es el ultimo programa en realizar su labor al unir las distintas partes del programa en código maquina.
Por tanto el proceso de compilación en general esta representado de la siguiente forma:
Codigo Fuente -> [Pre-procesador] -> [Compilador] -> [Ensamblador] -> [Enlazador] -> Programa.
Ahora bien, el compilador mas que ser un programa que realiza un trabajo mágico como si de una caja negra se tratara, consta en realidad de dos grandes sub-procesos: El Análisis y la Síntesis.
En el famoso libro del dragon ("Compiladores. Principios, Tecnicas y Herramientas" de Alfred. Aho, Monica Lam, Ravi Sethi y Jeffrey Ullman, 2da Edición 2008) se nos explica bajo el apartado 1.2 Estructura de un compilador lo siguiente:
La parte de análisis divide el programa fuente en componentes e impone una estructura gramatical sobre ellas. Después utiliza esta estructura para crear una representación intermedia del programa fuente [...]. La parte del análisis tambien recolecta información sobre el programa fuente y la almacena en una estructura de datos llamada tabla de símbolos, la cual se pasa junto con la representación intermedia a la parte de síntesis.
María del Mar Aguilera Sierra y Sergio Gálvez Rojas en su obra "Traductores, Compiladores e Intérpretes" en el tema "Tabla de Símbolos" explican en que consiste esta particular estructura de datos:
La tabla almacena la información que en cada momento se necesita sobre las variables del programa, información tal como: nombre, tipo, dirección de localización, tamaño, etc. La gestión de la tabla de símbolos es muy importante, ya que consume gran parte del tiempo de compilación. De ahí que su eficiencia sea crítica. Aunque también sirve para guardar información referente a los tipos creados por el usuario, tipos enumerados y, en general, a cualquier identificador creado por el usuario.
Permanece sólo en tiempo de compilación, no de ejecución, excepto en aquellos casos en que se compila con opciones de depuración.
En el libro del dragón (citado anteriormente) se nos da información adicional:
La tabla de símbolos es una estructura de datos que contiene un registro para cada nombre de variable, con campos para los atributos del nombre. La estructura de datos debe estar diseñada de tal forma que permita al compilador buscar el registro para cada nombre o almacenar u obtener los datos de ese registro con rapidez.
De forma que, tenemos como salidas del proceso de análisis dos estructuras de datos: La tabla de símbolos y representación intermedia del programa fuente. El árbol sintáctico es normalmente la estructura de datos usada para representar de forma intermedia el código fuente. Ambas estructuras pasan al proceso de síntesis que según los autores Aho, Lam, Sethi y Ullman consiste en:
contru[ir] el programa destino deseado a partir de la representación intermedia y de la información de la tabla de símbolos. A la parte de análisis se le llama comúnmente el front-end del compilador; la parte de síntesis (propiamente la traducción es el back-end.
Observando con más detalle el proceso de compilación podemos notar que esta compuesto de fases teóricamente definidas pero que en la practica pueden solaparse y agruparse. Estas fases transforman una representación del programa fuente en otro. La tabla de símbolos es usada es todas las fases de compilación.
En otra vertiente podemos preguntarnos: ¿Cuales son cada una de estas fases?, ¿Como realizan su trabajo? ¿Cuales son sus entradas y salidas? y ¿En que consiste el agrupamiento de fases en pasadas?.
Todas interrogantes serán respondidas en la segunda parte de esta serie sobre teoría de compiladores: Teoría de Compiladores (2da Parte) - Fases de un compilador