2010-08-02 9 views
6

Estoy tomando un curso de principios de los lenguajes de programación en este momento, pero no puedo por la vida de mí resolver esto. Esta no es tarea solo una pregunta conceptual general.¿Cómo se relaciona una tabla de símbolos con las cadenas estáticas y el alcance?

En nuestra clase hemos hablado de cadenas estáticas y pantallas. Creo que entiendo por qué los necesitamos. De lo contrario, cuando tengamos métodos anidados, no podremos determinar de qué variable estamos hablando cuando tengamos métodos anidados.

Mi prof también ha hablado de una tabla de símbolos. Mi pregunta es ¿para qué sirve la tabla de símbolos? ¿Cómo se relaciona con las cadenas estáticas?

Voy a dar algunos antecedentes (por favor corríjanme si me equivoco).


(Voy a definir algunas cosas sólo para hacer explicaciones más fácil)

Supongamos que tenemos este código:

main(){ 
    int i; 
    int j; 
    int k; 
    a(){ 
     int i; 
     int j; 
     innerA(){ 
      int i = 5; 
      print(i); 
      print(j); 
      print(k); 
     } 
    } 

    b(){ 
     ... 
    } 
    ... 
} 

Y esta pila:

| innerA | 
| a  | 
| b  | 
| main | 
-----------    

Descripción rápida de las cadenas estáticas como repaso.

Las cadenas estáticas se utilizan para encontrar qué variable se debe usar cuando las variables se redefinen dentro de una función interna. En la pila que se muestra arriba, cada cuadro tendrá un puntero al método que lo contiene. Por lo tanto:

| innerA | \\ pointer to a 
| a  | \\ pointer to main 
| b  | \\ pointer to main 
| main | \\ pointer to global variables 
-----------   

(Suponiendo alcance estático, para el ámbito dinámico creo que cada marco de pila solo apuntará a la de abajo)

Creo que cuando ejecutamos print(<something>) dentro del método innerA este que va a pasar:

currentStackframe = innerAStackFrame; 
while(true){ 
    if(<something> is declared in currentStackFrame) 
     print(<something>); 
     break; 
    else{ 
     currentStackFrame = currentStackFrame.containedIn(); 
    } 
} 

repaso rápido de symbo l tabla

No estoy seguro de para qué sirve una tabla de símbolos. Pero esto es lo que parece:

Index is has value, 
Value is reference. 
__ 
| | 
|--|      -------------------------------------------------- 
| | --------------------> | link to next | name | type | scope level | other | 
|--|      -------------------------------------------------- 
| |        | 
|--|    --------------- 
| |    |  
|--|    |    -------------------------------------------------- 
| |     -------> | link to next | name | type | scope level | other | 
|--|        -------------------------------------------------- 
| | 
|--| 
  • enlace a lado - si hay más de una cosa tiene el mismo tiene valor hash se trata de un nombre de enlace
  • - nombre del elemento (ejemplos: i, j, a, int)
  • tipo - de qué se trata (ejemplos: variable, función, parámetro)
  • nivel de alcance - no es 100% seguro de cómo se define esto.Creo que:
    • 0 sería construido-ins
    • 1 sería globales
    • 2 sería principal método
    • 3 habría una y b
    • 4 sería innerA

Sólo para reiterar mis preguntas:

  • ¿Para qué sirve la tabla de símbolos?
  • ¿Cómo se relaciona con las cadenas estáticas?
  • ¿Por qué necesitamos cadenas estáticas ya que la información del alcance está en la tabla de símbolos?
+0

Estas son preguntas muy amplias sobre cómo funcionan los compiladores. –

Respuesta

5

Tenga en cuenta que "tabla de símbolos" puede significar dos cosas diferentes: podría significar la estructura interna utilizada por el compilador para determinar qué alias de una variable tiene ámbito donde, o podría significar la lista de símbolos exportados por biblioteca a sus usuarios en el momento de la carga. Aquí, estás usando la definición anterior.

La tabla de símbolos se utiliza para determinar a qué dirección de memoria se está refiriendo un usuario cuando emplea un nombre determinado. Cuando dices "x", ¿qué alias de "x" quieres?

La razón por la que necesita mantener una cadena estática y una tabla de símbolos es la siguiente: cuando el compilador necesita determinar qué variables son visibles en un determinado ámbito, debe "desenmascarar" las variables previamente alias en el ámbito interno . Por ejemplo, al pasar de innerA a a, la variable i cambia su dirección de memoria. Lo mismo ocurre nuevamente al pasar de a a main. Si el compilador no mantuvo una cadena estática, tendría que atravesar toda la tabla de símbolos. Eso es caro si tienes muchos nombres. Con las cadenas estáticas, el compilador solo mira el nivel actual, elimina la última definición de cada variable contenida en él, y luego sigue el enlace hasta un alcance. Si, por otro lado, no tenía la tabla de símbolos, entonces cada acceso variable no en el ámbito local haría que el compilador tuviera que recorrer la cadena estática.

En resumen, puede reconstruir la tabla de símbolos de la cadena estática, y viceversa. Pero realmente quiere tener ambas cosas para hacer que las operaciones comunes sean rápidas. Si no dispone de la tabla de símbolos, la compilación llevará más tiempo porque cada acceso variable de ámbito no local requerirá escalar la cadena estática. Si carece de la cadena estática, la compilación llevará más tiempo porque para dejar un ámbito será necesario recorrer la tabla de símbolos para eliminar las entradas ahora desaparecidas.

Por cierto, si usted no está usando ya el Programming Language Pragmatics de Michael Scott, échele un vistazo. Es de lejos el mejor libro de texto sobre este tema que he visto.

1

Esto, obviamente, se refiere a una implementación de clase específica, y para entenderlo recomiendo encarecidamente hablar con alguien relacionado con la clase.

La tabla de símbolos es lo que traduce los identificadores de código fuente en algo que el compilador puede usar. Mantiene las descripciones necesarias. Tiende a ser utilizado durante todo el proceso de compilación.El "tipo" que mencionas parece que sería para analizar, y sin duda habría más entradas (en el "otro") para las etapas posteriores.

Es difícil saber cómo se relaciona con las cadenas estáticas, o por qué son necesarias, ya que ni siquiera sabe cuál es el "nivel de alcance". Sin embargo, tenga en cuenta que tanto a() como b() pueden tener una variable i, parece que cree que tienen el mismo nivel de alcance, por lo que necesita algo para diferenciarlos.

Además, la cadena estática es con frecuencia una optimización, por lo que el compilador sabe qué entradas de la tabla de símbolos aceptar. Sin una cadena estática, el compilador tendría que hacer algunas búsquedas para rechazar una entrada en b por algo encontrado en innerA.

Para obtener algo más útil, tendrá que explicar más acerca de lo que está sucediendo (sugiero encarecidamente hablar con el instructor o las TA o lo que sea) y probablemente tenga preguntas más específicas.

Cuestiones relacionadas