Compilador Diseño - Tabla de Símbolos



Tabla de símbolos es una importante estructura de datos creada y mantenida por los compiladores con el fin de almacenar información acerca de la ocurrencia de diversas entidades, tales como nombres de variables, nombres de funciones, objetos, clases, interfaces, etc. tabla de símbolos se utiliza en el análisis y la síntesis de un compilador.

Una tabla de símbolos pueden servir los fines siguientes en función del idioma de la mano:

  • Para almacenar los nombres de todas las entidades de forma estructurada en un solo lugar.

  • Para verificar si se ha declarado una variable.

  • Comprobación del tipo de implemento, comprobando las cesiones y las expresiones en el código fuente son semánticamente correcto.

  • Para determinar el alcance de un nombre (alcance de la resolución).

Una tabla de símbolos es simplemente una tabla que puede ser lineal o una tabla hash. Mantiene una entrada para cada uno de los nombres con el formato siguiente:

<symbol name,  type,  attribute>

Por ejemplo, si tiene una tabla de símbolos para almacenar información acerca de la siguiente declaración de variables:

static int interest;

A continuación, debe almacenar la entrada como la siguiente:

<interest, int, static>

El atributo cláusula contiene las entradas relacionadas con el nombre.

Aplicación

Si un compilador es manejar una pequeña cantidad de datos, a continuación, la tabla de símbolos puede ser implementado como una lista desordenada, que es muy fácil de código, sino que sólo es adecuado para pequeñas mesas. Una tabla de símbolos se puede implementar en una de las siguientes formas:

  • Lineal (ordenadas o desordenadas) lista
  • Árbol de búsqueda binaria
  • Tabla Hash

Entre todos, tablas de símbolos son en su mayoría implementadas como tablas hash, en el que el código fuente propio símbolo es tratada como un elemento clave para la función de hash y el valor de retorno es la información sobre el símbolo.

Operaciones

Una tabla de símbolos, ya sea lineal o hash, debe proporcionar las siguientes operaciones.

Insert()

Esta operación es el que se utiliza con más frecuencia en fase de análisis, es decir, la primera mitad del compilador en donde los testigos son identificados y los nombres se almacenan en la tabla. Esta operación se utiliza para añadir información en la tabla de símbolos de nombres únicos que ocurren en el código fuente. El formato o estructura en la que los nombres se almacenan depende del compilador en mano.

Un atributo de un símbolo en el código fuente es la información asociada con ese símbolo. Esta información contiene el valor, el estado, el alcance y el tipo sobre el símbolo. El insertar() toma el símbolo y sus atributos como argumentos y almacena la información en la tabla de símbolos.

Por ejemplo:

int a;

Debe ser procesada por el compilador como:

insert(a, int);

Lookup()

Lookup() es utilizado para buscar un nombre en la tabla de símbolos para determinar:

  • Si el símbolo existe en la tabla.
  • Si se declara antes de que se utilice.
  • Si el nombre se usa en el ámbito de aplicación.
  • Si el símbolo está inicializado.
  • Si el símbolo declarado varias veces.

El formato de búsqueda() varía según el lenguaje de programación. El formato básico debe coincidir con el siguiente:

Lookup(símbolo)

Este método devuelve el valor 0 (cero) si el símbolo no existe en la tabla de símbolos. Si el símbolo existe en la tabla de símbolos, se devuelve sus atributos almacenados en la tabla.

Ámbito Gestión

Un compilador mantiene dos tipos de tablas de símbolos: a global tabla de símbolos que puede ser accedida por todos los procedimientos y el alcance tablas de símbolos que se crean para cada ámbito en el programa.

A fin de determinar el alcance de un nombre, símbolo mesas están dispuestas en estructura jerárquica que se muestra en el ejemplo siguiente:

. . . 
int value=10;
void pro_one()
   {
   int one_1;
   int one_2;
      {              \
      int one_3;      |_  inner scope 1 
      int one_4;      | 
      }              /
   int one_5; 
     {              \   
      int one_6;      |_  inner scope 2
      int one_7;      |
      }              /
   }
void pro_two()
   {
   int two_1;
   int two_2;
      {              \
      int two_3;      |_  inner scope 3
      int two_4;      |
      }              /
   int two_5;
   }
. . . 

El programa anterior se puede representar en una estructura jerárquica de tablas de símbolos:

Tabla de Símbolos

La tabla de símbolos global contiene los nombres de una variable global (int valor) y dos nombres de procedimiento, que debe estar disponible para todos los nodos secundarios se muestra arriba. Los nombres mencionados en la tabla de símbolos pro_one (y todos sus niños tablas) no están disponibles para símbolos pro_two tablas y su hijo.

Este símbolo jerarquía en la estructura los datos de la tabla se almacena en el analizador semántico y cada vez que un nombre se debe buscar en una tabla de símbolos, se busca mediante el siguiente algoritmo:

  • En primer lugar, un símbolo se buscará en el ámbito actual, es decir tabla de símbolos.

  • Si un nombre se encuentra, entonces, otra cosa que se buscará en la tabla de símbolos hasta que padre,

  • O bien se encuentra el nombre o símbolo mundial tabla se ha buscado para el nombre.

Advertisements