Sei sulla pagina 1di 17

qwertyuiopasdfghjklzxcvbnmqwer tyuiopasdfghjklzxcvbnmqwertyuiopa sdfghjklzxcvbnmqwertyuiopasdfghjkl zxcvbnmqwertyuiopasdfghjklzxcvbn Procesadores de Lenguajes I mqwertyuiopasdfghjklzxcvbnmqwert Tablas de smbolos yuiopasdfghjklzxcvbnmqwertyuiopas dfghjklzxcvbnmqwertyuiopasdfghjklz xcvbnmqwertyuiopasdfghjklzxcvbnm qwertyuiopasdfghjklzxcvbnmqwerty uiopasdfghjklzxcvbnmqwertyuiopasd fghjklzxcvbnmqwertyuiopasdfghjklzx

cvbnmqwertyuiopasdfghjklzxcvbnmq wertyuiopasdfghjklzxcvbnmqwertyui opasdfghjklzxcvbnmqwertyuiopasdfg hjklzxcvbnmrtyuiopasdfghjklzxcvbn mqwertyuiopasdfghjklzxcvbnmqwert yuiopasdfghjklzxcvbnmqwertyuiopas


1 04/01/2008 Francisco Charte Ojeda

Tabla de contenido
1. Utilidad de una tabla de smbolos ................................................................................ 3 2. Estructura lgica de una tabla de smbolos.................................................................. 4 3. Operaciones fundamentales en la tabla de smbolos .................................................. 7 4. Estructuras de datos subyacentes ................................................................................ 8 4.1. Listas o tablas sin orden ........................................................................................ 9 4.2. Listas o tablas con orden ..................................................................................... 10 4.3. rboles binarios ................................................................................................... 10 4.4. Tablas hash .......................................................................................................... 11 4.5. Cmo abordar el problema de los mbitos ......................................................... 13 4.6. Tablas de smbolos locales .................................................................................. 16 5. Contenido de la tabla de smbolos ............................................................................. 16 6. Referencias ................................................................................................................. 17

Pgina 2 de 17

1. Utilidad de una tabla de smbolos


Los compiladores e intrpretes son programas que analizan un cdigo de entrada, el cdigo fuente, a fin de generar un cdigo de salida ejecutable que puede ser escrito en un archivo, en el caso de los compiladores, o utilizado de forma inmediata en memoria, en el de los intrpretes. Para ello pasan por varias fases, siendo preciso en algunas de ellas determinar qu significado (tipo de elemento y atributos asociados) tienen los identificadores que se encuentran en el cdigo fuente. Las tablas de smbolos se crean en las primeras fases del proceso, durante el anlisis lxico y sintctico, permitiendo a las siguientes asociar un contexto a cada uno de los smbolos que haga posible saber, por ejemplo, si un identificador representa una variable o el nombre de un procedimiento, cul es el tipo de dato de la variable o la lista de argumentos que precisa ese procedimiento, cul es el mbito que les corresponde en el caso de los lenguajes con estructura de bloques y orientados a objetos, etc. Mediante la tabla de smbolos un compilador (la mayora de lo dicho sera aplicable tambin a un intrprete) puede, dependiendo de la fase en que se encuentre, determinar: Si un identificador es una variable, conociendo su tipo o la direccin relativa que se le ha asignado. Si una variable o un procedimiento ha sido declarado antes de utilizarse la primera vez. Si un identificador es una palabra reservada y por tanto no debe permitir su redefinicin. Los identificadores que son visibles dependiendo de su mbito y el bloque que se est procesando en cada momento.

La tabla de smbolos es una estructura de datos temporal en el caso de los compiladores, ya que una vez generado el cdigo objeto se descarta al no tener mayor utilidad. Algunos compiladores, no obstante, tienen la capacidad para incluirla en el ejecutable a fin de facilitar la depuracin, de forma que el programador puede ir inspeccionando las variables por su nombre, no como posiciones de memoria, y de igual forma identificar los procedimientos a los que se invoca, argumentos de entrada y salida, etc. Los intrpretes emplean la tabla de smbolos durante todo el proceso de traduccin y ejecucin del programa, lo cual les permite, por ejemplo, saber qu valor contiene una cierta variable en cada momento y actuar sobre ste. Puede afirmarse, por tanto, que la tabla de smbolos es una de las piezas fundamentales en el funcionamiento de los compiladores, de ah que sea importante su estudio en una asignatura como Procesadores de lenguajes: operaciones que contempla, estructura de datos subyacente, evolucin a lo largo de las distintas fases de compilacin, etc. Dado que la tabla de smbolos es una estructura de datos relativamente compleja, en la que se contemplan varios tipos de operaciones posibles, lo habitual es que exista una lgica Pgina 3 de 17

independiente encargada de gestionarla. En el diagrama siguiente se han representado los distintos pasos de un hipottico compilador y cules seran las operaciones que solicitaran al gestor de la tabla de smbolos:

2. Estructura lgica de una tabla de smbolos


Sin entrar en un principio a detallar la estructura de datos subyacente, la estructura lgica de una tabla de smbolos podra ser la siguiente: Smbolo Edad DifFecha Nombre ... Atributos Var, Entero, $02 Func, Entero,2,Fecha,Fecha Var, Cadena, $06 ...

La primera columna contendra el identificador de cada smbolo: nombre de variable, funcin, etc. En la segunda habra una lista de atributos mediante los que se obtiene informacin sobre el smbolo: categora (variable, funcin, constante ...), tipo, direccin de almacenamiento, lista de argumentos, tipo de retorno, etc. Pgina 4 de 17

Dependiendo de las caractersticas de cada lenguaje, el compilador puede almacenar directamente en la tabla de smbolos la secuencia de caracteres que componen cada identificador o, en su lugar, mantener una estructura paralela. En el primer caso es obvio que existe una longitud mxima para los identificadores, adems de un desperdicio de espacio. Hasta no hace mucho haba compiladores, recuerdo algunos de la firma Borland, en los que los identificadores podan tener cualquier longitud pero solamente eran significativos los primeros 32 caracteres, de forma que dos nombres de variable que coincidiesen en esos 32 caracteres (no era habitual) el compilador los identificaba como un mismo smbolo. Supongo que esa limitacin se deba a que en la tabla de smbolos de estos compiladores los identificadores se almacenaban en la propia tabla, donde haba reservados 32 bytes para tal fin. La alternativa, utilizada por la mayora de los compiladores actuales, consiste en guardar los identificadores en una estructura paralela, almacenando en la propia tabla de smbolos nicamente un puntero a la posicin del identificador y su longitud, por ejemplo: Smbolo $00,4 $04,8 $12,6 ...
00 E 01 d 02 a 03 d 04 D 05 i 06 f 07 F 08 e 09 c

Atributos Var, Entero, $02 Func, Entero,2,Fecha,Fecha Var, Cadena, $06 ...
10 h 11 a 12 N 13 o 14 m 15 b 16 r 17 e 18 19

Otra posibilidad sera almacenar como smbolo en la tabla principal solamente el puntero, sin especificar la longitud, usando un delimitador de final de cadena en la tabla donde se guarden los identificadores. Sera el caso representado en el siguiente diagrama:

Pgina 5 de 17

En cuanto a los atributos se refiere, cada smbolo tendr unos u otros dependiendo de la categora a que pertenezca: variable, constante, procedimiento, etc. Algunos habituales son: Categora: Determina a qu pertenece el smbolo asociado. Tipo: En el caso de las variables, establece el tipo de informacin que contendrn. Si el smbolo es una funcin, este mismo atributo indicara el tipo de valor devuelto. Argumentos: Para los procedimientos, funciones o mtodos indicar la lista de parmetros que precisa y sus tipos. Posicin: Para las variables es habitual contar con una posicin relativa de memoria asociada. Los intrpretes utilizarn dicha posicin a medida que ejecuten el cdigo para leer y modificar el valor. Valor: Si el smbolo es una constante este atributo contendra el valor que representa. mbito: En los lenguajes orientados a objetos y con estructura de bloques pueden existir mltiples smbolos con el mismo identificador en mbitos distintos, sirviendo este atributo para determinar el mbito a que pertenecen.

Otros atributos que podran existir sera la indicacin de si una variable es un array o matriz, el nmero de dimensiones con que cuenta y el nmero de elementos de cada dimensin, si los parmetros de entrada a un procedimiento tienen asociado un valor por defecto y cul es ste, si un cierto mtodo de un objeto est vinculado estticamente o de forma dinmica (late-binding) en cuyo caso hay que buscar durante la ejecucin en las vtable de mtodos virtuales, etc. En los lenguajes ms evolucionados, con orientacin a objetos y a componentes como pueden ser C# o Java, la tabla de smbolos llega a ser una estructura realmente compleja por la cantidad de atributos que pueden existir. Esto no implica, sin embargo, unas necesidades de almacenamiento muy grandes en la tabla de smbolos, ya que suelen utilizarse paquetes de bits en los que se resume toda la informacin asociada a cada identificador. Con los primeros dos o tres bits se indica la categora y, dependiendo de sta, los paquetes siguientes tienen un significado u otro. Mientras que el identificador asociado a un smbolo es algo que no cambia a lo largo del proceso de compilacin, la lista de atributos asociados a dicho smbolo s que puede experimentar alteraciones a medida que se va pasando de una fase a otra dentro de ese proceso. Asimismo en determinados casos pueden existir en la tabla mltiples copias de un mismo conjunto de smbolos en diferentes mbitos o niveles. Es lo que ocurre, por ejemplo, si el lenguaje tiene una estructura de bloques como la de C, en la que un mismo identificador puede hacer referencia a distintos smbolos en un cierto punto del programa dependiendo del contexto.

Pgina 6 de 17

3. Operaciones fundamentales en la tabla de smbolos


Una vez que se conoce cul es la estructura lgica de la tabla de smbolos y su contenido, para justificar qu estructura de datos fsica es la ms adecuada es necesario analizar las operaciones fundamentales que se llevarn a cabo sobre ella. En las primeras fases del compilador, principalmente durante el anlisis lxico y semntico, se introducen en la tabla de smbolos los identificadores y la lista de atributos que los describen. Las operaciones ms usuales en ese momento son la insercin y actualizacin de smbolos, si bien la ltima conlleva siempre una operacin previa de bsqueda. En las fases posteriores, en la generacin de cdigo intermedio y cdigo objeto, la tabla de smbolos se utiliza para comprobar si un identificador existe o no y saber cules son sus atributos, no producindose nuevas inserciones y quedando la modificacin de atributos como algo puntual. La operacin que se ejecuta continuamente es la bsqueda/consulta sobre la tabla de smbolos. El proceso que acaba de describirse es el empleado por los compiladores de una sola pasada, pero existen otros que efectan varias pasadas sobre el cdigo fuente y generan la tabla de smbolos al inicio del anlisis semntico, en lugar de en el anlisis lxico. En este tipo de compiladores las operaciones de insercin, actualizacin de atributos y consultas de smbolos tienen lugar a lo largo de toda la fase de anlisis semntico y generacin de cdigo. Cuando se trabaja con lenguajes que tienen estructura de bloques, durante el proceso de compilacin tambin puede darse el caso de que ciertos smbolos, al cerrar un bloque, tengan que ser eliminados de la tabla de smbolos al dejar de existir. El borrado es una operacin que implica una bsqueda en la tabla y la invalidacin de la entrada correspondiente. En resumen, las operaciones que debern ejecutarse sobre la tabla de smbolos durante el proceso de compilacin sern las siguientes: Bsqueda/Consulta: Es la operacin que ms se repite en todas las fases, a fin de comprobar si un smbolo ya existe o ha de insertarse como nuevo, encontrar los atributos asociados a un smbolo para leerlos o modificarlos o borrar un smbolo de la tabla. Las otras tres operaciones normalmente siempre implican una bsqueda previa. Actualizacin: En los compiladores de una sola pasada la fase de anlisis lxico se encarga de crear la tabla de smbolos e introducir en ella los identificadores, pero la asociacin de la mayora de los atributos queda en manos del anlisis semntico, que debe localizar cada smbolo y actualizarlo. Insercin: Una vez creada la tabla de smbolos hay que introducir en ella las parejas (identificador, atributos) a medida que se analiza el cdigo fuente, tarea de la que se ocupa el analizador lxico o el semntico, dependiendo de los casos. Segn el tipo de lenguaje es posible que en la tabla existan varios smbolos con un mismo identificador pero con distintos atributos. Borrado: Se produce cuando un smbolo queda fuera de mbito y, por tanto, deja de existir.

Pgina 7 de 17

4. Estructuras de datos subyacentes


La tabla de smbolos de un compilador puede ser implementada utilizando diferentes estructuras de datos: listas, rboles, tablas hash, etc. De la eficiencia de las operaciones sobre dichas estructuras depender en gran parte la eficiencia del propio compilador, tanto en velocidad como en uso de memoria. Desde una perspectiva algortmica, dejando de lado la funcin asociada en el proceso de compilacin, una tabla de smbolos no es ms que una coleccin de pares (clave, valor) en la que la clave es el identificador de cada smbolo y el valor es el conjunto de atributos que tiene en un momento dado. Sobre esa coleccin se insertarn, modificarn y eliminarn entradas, pero la operacin ms usual, como se apuntaba en el apartado 3, ser la bsqueda/consulta, por lo que ser la que mayor influencia tenga en la eficiencia al trabajar con la tabla de smbolos. Otro aspecto que influir en la estructura a usar para mantener la tabla de smbolos ser el tipo de lenguaje para el que se escribe el compilador. Si es un lenguaje con un nico mbito y sin bloques no puede darse el caso de que existan varios smbolos con el mismo identificador, por lo que la estructura de datos subyacente no tiene que mantener duplicados. En caso contrario, en lenguajes que s cuentan con esas caractersticas, la tabla de smbolos debe estar preparada para mantener identificadores duplicados asociando cada uno de ellos al smbolo adecuado segn el bloque o contexto que corresponda al punto del cdigo que se est procesando. En cuanto a la eficiencia en el uso de recursos, la tabla de smbolos puede tener un tamao fijo, crecer a medida que sea necesario, establecer una longitud mxima para las claves (los identificadores) o bien permitir claves de cualquier valor. Como suele ser habitual, al incrementar la eficiencia en el uso de recursos se ver afectada la eficiencia en velocidad y viceversa. Un compilador con una tabla de smbolos de tamao fijo, lo suficientemente grande como para poder procesar cualquier programa, no ser eficiente en el uso de recursos pero, a cambio, no tendr la necesidad de ir aumentando la tabla a medida que se agregan smbolos o reducindola cuando se eliminen. Con los identificadores ocurre otro tanto, ya que si se opta por permitir cualquier longitud se ocupar exactamente el espacio necesario para guardar las claves, pero a la hora de realizar una bsqueda se emplear ms tiempo al tener que acceder desde la tabla de smbolos a la estructura que mantiene los identificadores. Lo fundamental, en consecuencia, a la hora de decidirse sobre la estructura de datos subyacente que se emplear para mantener la tabla de smbolos ser: El tipo de lenguaje a procesar porque de ello depender que se tenga que trabajar con claves duplicadas que tendrn asociado un mbito o nivel. La eficiencia en la bsqueda de claves, al ser sta la operacin que se ejecuta con mayor frecuencia sobre la tabla de smbolos.

Sobre estas premisas, en los puntos siguientes se analiza la idoneidad de algunas estructuras de datos tpicas para su uso como tabla de smbolos en un compilador. Pgina 8 de 17

4.1. Listas o tablas sin orden


Una de las estructuras de datos ms sencillas que pueden utilizarse es una lista o una tabla (vector) en la que no se mantiene orden, de manera que las operaciones pueden ejecutarse con los siguientes rdenes de eficiencia: Insercin: O(1) si se inserta siempre al final de la lista/vector sin comprobacin previa de si la clave existe o no. No hay ms que mantener un puntero al final de la lista, como se indica en el diagrama de ms abajo, para poder insertar de manera inmediata. Bsqueda: Al no haber orden la bsqueda es necesariamente secuencial (flechas rojas en el diagrama), por lo que el orden de eficiencia ser O(1) en el mejor de los casos y O(n) en el peor (siendo n el nmero de smbolos existentes). La eficiencia esperada sera, por tanto, de O(n+1)/2. Actualizacin y Borrado: Puesto que son operaciones que precisan una bsqueda previa, en principio tendramos una eficiencia esperada de O(n+1)/2. En el caso del borrado, si implica una reestructuracin de la lista/vector para no dejar huecos, habra que sumar el tiempo empleado en trasladar los elementos que estn tras el eliminado.

Teniendo en cuenta que una tabla de smbolos contendr habitualmente varios cientos de claves, incluso miles en los programas grandes, salta a la vista que esta estructura de datos no resulta adecuada salvo en los casos ms sencillos (con programas muy pequeos), ya que cada bsqueda empleara mucho tiempo y el proceso de compilacin se dilatara considerablemente en el tiempo. Otro problema que plantea el uso de una lista/vector es el mantenimiento de claves duplicadas si el lenguaje lo permitiese, ya que por la simplicidad de la estructura la nica forma de saber qu smbolos son vlidos en el mbito actual sera recorriendo toda la lista de forma secuencial, buscando las distintas coincidencias de la clave, a fin de leer un atributo que identificara el bloque al que pertenece el smbolo.

Pgina 9 de 17

4.2. Listas o tablas con orden


En lugar de usar listas o vectores sin orden, podra utilizarse la clave para mantener los elementos ordenados a fin de mejorar la eficiencia en la bsqueda de smbolos. La existencia de orden permitira utilizar un algoritmo de bsqueda dicotmica o binaria, cuyo orden de eficiencia es logartmico: O(log n). Puesto que la bsqueda es una operacin previa a todas las dems, esta mejora influira globalmente en la gestin de la tabla de smbolos.

El principal problema de este tipo de estructura es que la insercin y el borrado son operaciones que implicarn un trabajo adicional para mantener ese orden, lo cual traslada el problema de la falta de eficiencia de un punto a otro. Si con la lista sin ordenar la operacin ms lenta era la bsqueda, que afecta a todas las fases pero especialmente al anlisis semntico y la generacin de cdigo, con la lista ordenada es la fase de anlisis lxico la perjudicada al emplearse un tiempo muy superior en la insercin. En cuanto al mantenimiento de claves duplicadas necesaria para los lenguajes con bloques o mbitos, el problema sigue siendo exactamente el mismo que en el caso anterior pero con un problema aadido. Al realizar una bsqueda binaria es posible que smbolos con la misma clave, con el mismo identificador, hayan quedado tanto delante como detrs de la posicin en que se ha encontrado, lo obligara a efectuar comprobaciones adicionales y un recorrido secuencial en ambos sentidos.

4.3. rboles binarios


Se trata de una estructura con una eficiencia aceptable para las distintas operaciones que se necesitan siempre que se mantenga equilibrado, ya que de lo contrario pueden terminar convirtindose en una lista y la bsqueda sera secuencial. Los ms apropiados seran los rboles AVL o los rboles rojo-negro. El tiempo de bsqueda en un rbol perfectamente equilibrado siempre es logartmico. El resto de las operaciones se efectan prcticamente en el mismo orden de eficiencia, con una pequea penalizacin cuando son precisos ajustes como puede ser una doble rotacin tras un borrado para mantener el equilibrio. Al igual que las listas, ordenadas y sin ordenar, un rbol puede crecer dinmicamente a medida que se inserten smbolos sin ms lmite, en principio, que el de la propia memoria disponible en el sistema. Pgina 10 de 17

La clave de cada nodo del rbol sera el identificador de un smbolo, pudiendo mantenerse el conjunto de atributos en la propia estructura de rbol o bien en una tabla independiente, de forma que en el rbol estaran solamente las claves y un puntero a la informacin del smbolo asociado. Para los lenguajes con bloques o mbitos el rbol no es la mejor opcin. Aunque pueden seguirse una serie de reglas que permitan la duplicidad de claves, la bsqueda de los smbolos del nivel ms interno y la eliminacin de los smbolos cuando un mbito deja de existir, algunas de las operaciones requerirn que se recorra el rbol completo, desde la raz hasta las hojas, perdiendo la eficiencia que se obtendra en un principio.

4.4. Tablas hash


Las tcnicas de hashing hacen posible mantener tablas de datos con acceso por clave con un orden de eficiencia terico de O(1) para todas las operaciones, lo que les hace ideales para el mantenimiento de una tabla de smbolos. Ese orden de eficiencia terico se alcanzar en mayor o menor medida dependiendo del algoritmo de hashing que se emplee y de que ste resulte adecuado para el tipo de claves utilizadas. Teniendo en cuenta que la mayora de los lenguajes permiten utilizar en la composicin de identificadores letras minsculas y maysculas, dgitos numricos y algunos smbolos, una funcin de dispersin de cadenas como la siguiente (Pearson) resultara adecuada. int f_hash(char* C) { int h = 0, i = 0; while(C[i]) h = T[h ^ C[i++]]; return h; }

Pgina 11 de 17

La variable T sera un array que contendra una serie de nmeros aleatorios, su tamao depender de las necesidades de cada caso, y las ventajas del algoritmo es que pequeas variaciones de entrada producen grandes diferencias en el resultado, de forma que smbolos con identificadores parecidos no provocaran colisiones. El uso de una tabla hash, por tanto, resultar mucho ms eficiente a la hora de realizar bsquedas en la tabla de smbolos, as como a la hora de insertar, actualizar o borrar. El tiempo no depender del tamao de la tabla, es decir, de lo grande que sea el programa a compilar, sino que se mantendr aproximadamente constante. Existen, no obstante, dos dificultades a superar: las colisiones y el tamao de la tabla hash.

Una colisin se produce cuando dos claves distintas producen el mismo resultado al ser procesadas por la funcin de hashing, por lo que les correspondera la misma posicin en la tabla. Obviamente no pueden almacenarse dos smbolos en una misma posicin, por lo que se recurre a diferentes tcnicas para solventar el problema. Una de ellas consiste en definir cada posicin de la tabla hash no como un elemento, sino como una cubeta en la que pueden almacenarse varios elementos. Para evitar el desbordamiento de las cubetas pueden implementarse de forma que sean extensibles o bien enlazables. Es obvio que cuanto mejor sea el algoritmo de hashing menor ser la posibilidad de que se produzcan colisiones, pero dicha circunstancia es algo que debe tenerse en cuenta. El otro aspecto importante es el tamao de la tabla ya que, a diferencia de lo que ocurre con otras estructuras de datos, ese tamao suele influir en el algoritmo que determina la posicin de los smbolos y, adems, no es fcil cambiarlo. En el caso ms extremo al crecer el nmero de elementos almacenados podra tener que recurrirse al rehashing tras adecuar el Pgina 12 de 17

tamao de la tabla, redistribuyendo nuevamente todos los smbolos lo cual no es deseable por la influencia que dicha operacin tendra en la eficiencia global. Tanto para la gestin de colisiones como para determinar cul es el tamao adecuado de la tabla y facilitar su crecimiento, si fuese preciso, habra que recurrir a las tcnicas y algoritmos que se estudian en la asignatura Estructuras de datos I, correspondiente al segundo curso de esta titulacin, y en cuyos detalles creo innecesario profundizar aqu.

4.5. Cmo abordar el problema de los mbitos


Los primeros lenguajes de programacin, como FORTRAN o el BASIC ancestral, contaban con un nico mbito de existencia de los smbolos y, en consecuencia, todas las variables eran globales. No existan funciones o procedimientos, aunque era posible crear lo que se denominaban subrutinas gracias a nmeros de lnea o identificadores e instrucciones del tipo GOSUB/RETURN. En este tipo de lenguajes, y otros igualmente simples, no hay que preocuparse por el mbito de los smbolos, de forma que al realizar una bsqueda, con independencia de cul sea el punto del cdigo fuente que est analizndose en cada momento, si el smbolo est en la tabla existe y de lo contrario no, as de sencillo. No puede darse el caso de que haya dos smbolos con el mismo identificador sin que se produzca un error durante la compilacin. La mayora de los lenguajes utilizados en la actualidad, especialmente los que cuentan con mayor difusin, no son tan simples, ya que el cdigo puede estructurarse en mbitos o bloques a distintos niveles: mdulos, clases, funciones, bloques asociados a estructuras de repeticin o condicionales, etc. En cada uno de esos mbitos existirn los identificadores definidos en el mismo y los correspondientes a los bloques exteriores al actual, por lo que durante el anlisis del cdigo fuente es necesario controlar cundo se entra y sale de un mbito, as como asociar algn tipo de informacin a los smbolos para saber a qu mbito pertenecen. Existen distintas tcnicas para abordar este problema, siendo unas adecuadas para compiladores de una sola pasada y otras para los que efectan mltiples pasadas sobre el cdigo fuente. En cualquier caso siempre existir una estructura de datos base, que en ocasiones establecer el tipo de los elementos de otra estructura superior. En los prrafos siguientes se asume siempre que la estructura base es una tabla hash, pero tambin sera factible utilizar otras como rboles o vectores. En compiladores de una sola pasada, en los que todas las fases se efectan prcticamente en paralelo a medida que se recorre el cdigo fuente, puede utilizarse una pila de tablas de smbolos. Cada vez que se entra en un nuevo bloque se crea una tabla de smbolos, una tabla hash en la que se almacenaran los smbolos de ese mbito, y se coloca en el tope de la pila. Al llegar al final del bloque actual, que fue el ltimo que se coloc en la pila, se extrae de sta y se descarta, puesto que ya no va a volver a ser til. Al encontrar en el cdigo un identificador ste se buscara en la tabla hash que est en el tope de pila, a continuacin en la tabla que se encuentra justo debajo que representa el mbito que acta como contenedor del actual y as sucesivamente, hasta llegar al primer nivel que sera el global.

Pgina 13 de 17

En el diagrama siguiente se ha representado cul sera el estado de la pila de tablas de smbolos en cuatro momentos del procesamiento de un programa sencillo. Entre las lneas 5 y 7, por ejemplo, si se hiciese referencia al smbolo a se encontrara en la tabla de smbolos 2, correspondiente al bloque interno de la sentencia if, mientras que si se hace referencia a b, al no encontrarse en dicha tabla de smbolos se continuara buscando en la siguiente, segn el orden en que se han apilado.

Para los compiladores de mltiples pasadas, que tienen que mantener la tabla de smbolos completa durante las distintas fases hasta que se genere el cdigo final, en lugar de una pila habra que utilizar una lista o vector de tablas hash, asociando a cada uno de los mbitos un nmero nico que actuara como ndice. En ningn momento se eliminaran elementos de ese vector, sino que dependiendo del bloque que est analizndose se recurrira a uno u otro para buscar los smbolos en la tabla hash correspondiente. Una pila simple de enteros, mantenida en paralelo, permitir saber al compilador qu mbitos estn abiertos y, por tanto, tiene que examinar, as como el orden en que tiene que recorrerlos, a la hora de encontrar un smbolo. El mayor inconveniente de estas implementaciones es que, en ambos casos, para localizar un determinado smbolo es necesario recorrer varias estructuras de datos: por una parte la pila o lista de tablas hash y, por otra, cada una de las tablas correspondientes a los mbitos abiertos en ese instante. La alternativa es mantener todos los smbolos de todos los mbitos, incluyendo los que cuentan con identificadores duplicados, en una misma estructura de datos. Lgicamente ser preciso agregar un atributo que permita dilucidar a qu mbito pertenece cada uno de ellos. Una posibilidad, asumiendo que se utiliza una tabla hash como estructura de datos subyacente, sera asociar a cada posicin de la tabla no un elemento sino una lista invertida de elementos. La funcin de hashing generara siempre la misma posicin para los identificadores duplicados, posicin en la que estara la lista con los distintos smbolos de forma que el primero correspondera al mbito actual, el siguiente al mbito abierto contenedor del actual y as sucesivamente. En el diagrama de la pgina siguiente se ha representado cul sera el estado de esa tabla hash en los mismos cuatro momentos del diagrama anterior (con pilas de tablas de smbolos), tomando como base el mismo programa. Entre las lneas 5 y 7 puede verse cmo al Pgina 14 de 17

resolver la referencia para el smbolo a se tendra acceso directamente a la informacin que corresponde al mbito 2. Al cerrarse ese bloque de cdigo se eliminan sus smbolos de la tabla, recuperando el acceso al mismo smbolo del mbito previo. No es necesario, por tanto, ir recuperando tablas de smbolos de una pila y despus buscar en ellas los identificadores, dando como resultado operaciones ms eficientes.

Es un mecanismo rpido para determinar la existencia de un smbolo y obtener sus atributos, si bien habra que complementarlo con algn algoritmo que determinase qu mbito es el actual y qu mbitos hay abiertos en cada momento. En compiladores de una sola pasada el procedimiento sera simple, ya que al entrar en un bloque se agregaran los smbolos al principio de la lista de los elementos respectivos de la tabla hash, mientras que al salir de un bloque se procedera a eliminarlos. Es una tcnica similar a la de la pila de tablas hash descrita antes, pero en este caso las pilas se encontraran como elementos de la tabla y no a la inversa. Para los compiladores multipasada sera preciso mantener una estructura independiente, como la pila de nmeros de mbito abiertos citada anteriormente, para conocer cules de los smbolos de la tabla seran vlidos en cada fase del proceso.

Pgina 15 de 17

4.6. Tablas de smbolos locales


En los lenguajes orientados a objetos no solamente existe un mbito actual y una serie de mbitos abiertos, a los que podra pertenecer un cierto smbolo, sino que tambin estn presentes los mbitos locales asociados a cada uno de los objetos. Cuando en el cdigo fuente se encuentra el nombre de un objeto y un punto, el compilador debe cambiar el contexto del analizador para operar sobre una tabla de smbolos local a la clase a la que pertenece dicho objeto. La tabla de smbolos local de una clase o de cualquier otra estructura de datos compleja, como puede ser un registro en Pascal, se genera en el momento en que se analiza la definicin de ese nuevo tipo de dato. Al utilizar la notacin objeto.identificador (o equivalente segn el lenguaje) el compilador debe localizar el identificador no en la tabla de smbolos general, sino en la tabla local que corresponde al tipo de ese objeto. En un lenguaje orientado a objetos actual, con atributos de visibilidad, mtodos y otros elementos como miembros, las tablas de smbolos locales pueden llegar a ser tan complejas como las de un programa completo, por lo que se recurrira a las mismas estructuras de datos y algoritmos que ya se han mencionado en apartados previos para gestionar la tabla de smbolos asociada.

5. Contenido de la tabla de smbolos


Una vez abordada cul es la utilidad de la tabla de smbolos, su estructura lgica, las operaciones que se efectan habitualmente sobre ellas, su eficiencia y las estructuras de datos ms apropiadas para su implementacin, nos quedara abordar cul sera el contenido de esta herramienta de apoyo de los compiladores. Es obvio, por lo ya dicho, que en una tabla de smbolos irn almacenndose durante el proceso de compilacin los identificadores y atributos de las variables, procedimientos, constantes y, en general, cualquier tipo de elemento definido por el programador en el cdigo fuente. sta, sin embargo, es una visin limitada de las tablas de smbolos tal y como las implementan y utilizan la mayora de los compiladores utilizados actualmente. Antes de que se inicie la primera fase de la compilacin, el compilador puede cargar la tabla de smbolos con algunos elementos que resultan de utilidad durante el anlisis lxico y la generacin de cdigo. Algunas posibilidades son: Palabras reservadas: Si el lenguaje para el que se escribe el compilador cuenta con palabras reservadas, su inclusin en la tabla de smbolos permitir al analizador lxico identificarlas y facilitar al sintctico los token correspondientes, al tiempo que se impide su redefinicin. Constantes predefinidas: Un compilador especfico para un lenguaje cientfico, por poner un ejemplo, podra agregar a la tabla de smbolos una serie de constantes de utilidad (PI, velocidad de la luz, nmero de Avogadro, etc.) de forma que estuviesen disponibles durante toda la compilacin.

Pgina 16 de 17

Tipos de datos: Los identificadores que representan a los tipos de datos bsicos del lenguaje, los intrnsecos, tambin pueden formar parte del contenido inicial de la tabla de smbolos.

Tambin es posible, dependiendo del lenguaje, que a la tabla de smbolos vayan aadindose durante el anlisis del cdigo fuente smbolos generados por el propio compilador. En Java y C#, por ejemplo, es posible definir mtodos annimos asociados a un cierto evento, bloques de cdigo para los que el programador no establece explcitamente un nombre. El compilador, sin embargo, s genera un identificador que se agrega a la tabla de smbolos. Por ltimo, mencionar que los compiladores de ciertos lenguajes, como es el caso de C++, modifican los identificadores que el programador crea para ciertos elementos, como las funciones y mtodos, segn el nmero y tipo de los parmetros. Es una tcnica conocida como name mangling o decorado de smbolos y que hace posible lo que se conoce como sobrecarga, de forma que pueden tenerse varios mtodos con el mismo nombre siempre que la lista de argumentos difiera. En la tabla de smbolos realmente cada mtodo aparecera como un smbolo distinto, aadindose al identificador original una serie de caracteres adicionales que lo diferencian del resto de versiones sobrecargadas.

6. Referencias
Para la realizacin de este trabajo he recurrido a los apuntes de la propia asignatura Procesadores de lenguajes I, el libro Compiladores e intrpretes de Manuel Alfonseca et al., la pgina del profesor Alfonseca sobre compiladores en http://arantxa.ii.uam.es/~alfonsec, el libro Compiladores del profesor Sergio Glvez Rojas y los apuntes sobre hashing de la asignatura Estructuras de datos I.

Pgina 17 de 17

Potrebbero piacerti anche