Anda di halaman 1dari 22

UNIDAD 1.

ANLISIS
SEMNTICO
Instituto Tecnolgico de Tapachula
Ricardo Enrique de la Parra Aguirre
13510644
Ing. Sistemas Computacionales
Lenguajes y Autmatas ll
Lic. Manuel Cedecedo Garca

Contenido
Introduccin.......................................................................................................... 2
Unidad 1. Anlisis semntico................................................................................... 3
1.1 rboles de expresiones.................................................................................. 3
1.2 Acciones semnticas de un analizador sintctico................................................3
1.3 Comprobaciones de tipos de expresiones.........................................................7
Declaraciones................................................................................................. 8
Sentencias...................................................................................................... 9
Expresiones.................................................................................................... 9
1.4 Pila semntica en un analizador sintctico.......................................................10
1.5 Esquema de traduccin................................................................................ 11
1.6 Generacin de la tabla de smbolos y de direcciones........................................13
1.7 Manejo de errores semnticos.......................................................................17
Conclusin.......................................................................................................... 19
Bibliografa.......................................................................................................... 20

Introduccin
La fase de anlisis semntico revisa el programa fuente para tratar de encontrar
errores semnticos y rene la informacin sobre los tipos para la fase posterior de
generacin de cdigo. En ella se utiliza la estructura jerrquica determinada por la
fase de anlisis sintctico para identificar los operadores y operandos de
expresiones y proposiciones.
Un componente importante del anlisis semntico es la verificacin de tipos. Aqu,
el compilador verifica si cada operador tiene operandos permitidos por la
especificacin del lenguaje fuente.

Unidad 1. Anlisis semntico


1.1 rboles de expresiones
El rbol es una estructura de datos fundamental en informtica, muy bien
adaptados a la inteligencia artificial y al anlisis sintctico.
En la inteligencia artificial, las declaraciones de las reglas se efectan segn el
esquema premisas-conclusin, que corresponde al establecimiento de relaciones
de dependencia que se puedan poner en forma arborescente.
Los rboles de expresiones representan el cdigo de nivel del lenguaje en forma
de datos. Los datos se almacenan en una estructura con forma de rbol. Cada
nodo del rbol de expresin representa una expresin, por ejemplo, una llamada al
mtodo o una operacin binaria, como x< y .
La resolucin de un problema se reduce entonces al recorrido de un rbol, con el
objeto de establecer un camino entre las hiptesis y las conclusiones generales.
En el anlisis sintctico, se definen gramticas formales que permiten
descomponer las expresiones. As se puede definir una fase como las
combinaciones de un grupo nominal y de un grupo verbal (verbo y complemento),
este grupo verbal se descompone en un verbo y en un grupo nominal, formado por
un nombre y una frase. La estructura jerrquica de una expresin puede ser
descrita por un esquema arborescente.
Un compilador podr, en el curso del tratamiento del texto de un programa, utilizar
rboles para decodificar tales expresiones.
1.2 Acciones semnticas de un analizador sintctico
Los atributos son informacin personalizada (semntica) de los smbolos. Por lo
que cada tipo de smbolos puede tener atributos diferentes. Esta informacin viaja
a travs del rbol de anlisis sintctico adjunta a cada smbolo. Las acciones
semnticas se encargan de manipular el contenido de los atributos para verificar
que existe un significado correcto en la relacin de los smbolos entre s. Cuando
se habla de smbolos, se hace referencia tanto a terminales como a no terminales.
La escritura de datos formada por los smbolos y sus atributos es parecida a una
estructura de registro. Cada tipo de smbolo es un tipo de registro y cada atributo
es un campo del registro. A la vez, cada atributo puede ser de tipo concreto.
Por ejemplo, se supone que se tiene el smbolo de una variable de tipo entero.
Posiblemente, necesitaremos un atributo para guardar informacin sobre la
direccin en memoria en donde se guardar el valor que tome la variable, tambin
se necesitar saber el tipo de la misma y alguna informacin ms. Por ahora, se
supone que slo se necesita saber, aparte del nombre de la variable, su direccin
3

en memoria y su tipo. Se supone que se va a referenciar su tipo por el nombre del


tipo. Entonces, en Pascal, si se tiene estas reglas:
DeclVar =var nombreVar dospuntos TipoVar puntocoma

TipoVar =enterobooleano
Donde todos los smbolos son terminales excepto DeclVar y TipoVar, que son no
terminales.
var . lexema , nombreVar .lexema ,nombreVar . direccion ,

nombreVar . nombreTipo, dospuntos . lexema , puntocoma . lexema ,


entero . lexema , booleano . lexema

Los lexemas de entero y booleano seran integer y boolean, respectivamente.


Los diferentes atributos seran diferentes tipos; por ejemplo, los lexemas podran
ser de tipo cadena, la direccin de tipo entero y el nombre del tipo de una variable
de tipo cadena.
Hay dos tipos de terminales, los que estn definidos en el anlisis lxico como fijos
y los que siguen un patrn definido, por lo que representan una variedad de
posibles lexemas. En el caso del ejemplo, hay un terminal que no tiene por qu
tener un lexema fijo. Se trata del terminal nombreVar , que representa el nombre
de la variable concreta (acorde con el patrn establecido en el anlisis lxico).
Para poder llenar la tabla de smbolos con la informacin necesaria de cada
smbolo, es preciso que los diferentes atributos tengan sus valores establecidos.
Algunos valores vienen dados por la fase de anlisis lxico, como son el contenido
de los lexemas, pero hay otros valores que se deben calcular en el proceso de
traduccin dirigida por la sintaxis. Una vez conocemos los calores de los atributos,
ya se puede realizar el anlisis semntico.
Para calcular los valores de los atributos, es preciso incluir las llamadas acciones
semnticas, que no son ms que trozos de cdigo en un lenguaje de
programacin concreto, que manipulan los smbolos y sus atributos.
Por ejemplo, en el caso anterior, debemos incluir en la tabla de smbolos la
direccin de la variable declarada y adems su tipo. La direccin se puede calcular
a partir de la informacin que hay en la tabla de smbolos y de la informacin
global que utilicemos, pero el tipo slo se puede obtener de la propia gramtica.
Para pasar la informacin del tipo del no terminal TipoVar al atributo nombreTipo
del terminal nombreVar, se utilizar acciones semnticas inmersas en las reglas.
4

Las acciones semnticas se suelen contener entre llaves (o llaves y dos puntos)
para separarlas de la gramtica. A grandes rasgos se tendr (figura 1.2.1):

Figura 1.2.1. Ejemplo


Se ve que se ha utilizado un atributo para el no terminal TipoVar. Este atributo se
encarga de guardar la informacin necesaria para poder ser utilizada por el
terminal nombreVar.
Reglas para la utilizacin de atributos en acciones semnticas:
1. Las acciones semnticas en las que intervengan atributos de la parte
izquierda de una regla se pondrn al final de la regla.
2. Slo se podrn incluir acciones semnticas en que intervengan atributos de
un smbolo detrs de la aparicin del smbolo en la regla.
En el ejemplo anterior se vio que se ha pasado informacin entre una regla y otra.
Para entender esto, se puede asemejar un no terminal con una funcin de un
lenguaje de programacin. Esa funcin se encarga de leer de la entrada una serie
de lexemas y luego devolver esa serie de lexemas a quien la ha llamado y,
adems, adjuntarle alguna informacin en forma de atributos. En el caso anterior,
cuando se procesa la primera regla y se llega al no terminal TipoVar, es como si
se llamara al procedimiento de la segunda regla. En la segunda regla, se hace una
serie de reconocimiento de lexemas y se devuelve cierta informacin, que en este
caso es el nombre del tipo de la variable. Esa informacin se devuelve en el
atributo del no terminal TipoVar y es utilizada despus para llenar el atributo
nombreTipo del terminal nombreVar. Por eso es necesario que se utilice un
atributo slo despus de que aparezca en una regla.
Dependiendo de la herramienta que se utilizar, los no terminales y los terminales
pueden tener todos sus atributos en una clase (por ejemplo, en Java). De manera
que el terminal o no terminal es un objeto que pertenece a una clase. De esta
manera, al devolver informacin en el caso anterior, se podra devolver no slo un
atributo, sino un objeto completo.
Por ejemplo, para el caso anterior, y utilizando Java, se implementar ms
detalladamente las acciones y los tipos que se utilizarn.
Suponiendo la definicin de la siguiente clase (figura 1.2.2):
5

Figura 1.2.2. Definicin de la clase


Ahora, se supone que se usar una herramienta que permitir utilizar el cdigo
java y reglas de la gramtica. Se tendr algo parecido a la figura 1.2.3.

Figura 1.2.3. Cdigo java


Se ve que delante del nombre del terminal o no terminal se pone el tipo al que
pertenece. En principio, todos son de tipo cadena y slo contendrn un atributo
que es el nombre del lexema.
Ahora, se podr incluir reglas y las acciones semnticas (figura 1.2.4).

Figura 1.2.4. Reglas y acciones semnticas.


Se ha puesto un ejemplo muy simplificado y sin utilizar la sintaxis de ninguna
herramienta de ayuda concreta.
Se ve que se aprovechan las acciones semnticas tanto para verificar la
semntica como para manipular las tablas.
1.3 Comprobaciones de tipos de expresiones
Se procede a la descripcin de un verificador de tipo para un lenguaje simple en
trminos de acciones semnticas, basadas en una representacin de tipos y una
operacin typeEqual. El lenguaje que se usa tiene la gramtica dada en la figura
1.3.1, con un pequeo nmero de expresiones y sentencias agregadas. Tambin
se supone la disponibilidad de una tabla de smbolos que contenga nombres de
variable y tipos asociados, con operaciones de insercin (insert), las cuales
insertan un nombre y un tipo en la tabla, y de bsqueda (lookup), que devuelve el
tipo asociado de un nombre. No se especificarn las propiedades de estas
operaciones en s mismas en la gramtica con atributos. Se analizarn las reglas
de verificacin de tipo y la inferencia de tipo para cada clase de construccin de
lenguaje de manera individual. La lista completa de acciones semnticas se
proporciona en la tabla 3.1.
programa var decls ; sent
var decls var decls ; var declvar decl
var decl id :typeexp
typeexp |bool|array [ num ] of type exp

sents sents ; sentsent

sent if exp then sentid :=exp


Figura 1.3.1. Una gramtica simple para ilustrar la verificacin de tipos.
Declaraciones
Las declaraciones causan que el tipo de un identificador se introduzca en la tabla
de smbolos. De este modo, la regla gramatical var decl id :typeexp tiene la accin
semntica asociada

insert (id . name , type exp .tipe)

que inserta un identificador en

la tabla de smbolos y asocia un tipo al mismo. El tipo asociado en esta insercin


se construye de acuerdo con las reglas gramaticales para typeexp .
Regla gramatical
var decl id :typeexp

Reglas semnticas
insert (id . name , typeexp .tipe)

typeexp

typeexp .type integer

typeexp bool

typeexp .type boolean

2
typeexp array [ num ] of type

1
2
type type makeTypeNode (array , num . type type)

sent if exp then sent

if not typeEqual ( exp . type , boolean )


thentype error (sent )

sent id :=exp

if not typeEqual ( lookup ( id .name ) , exp . type )


thentype error (sent )

exp1 exp 2+ exp3

if not

typeEqual ( exp2 . type , integer )


typeEqual ( exp3 .type , integer )

thentype . error ( exp1 ) ; exp1 . type integer


exp1 exp 2exp3

if not

typeEqual ( exp2 . type , boolean )


typeEqual ( exp3 .type , boolean )

thentype . error ( exp1 ) ; exp1 . type boolean


exp1 exp 2 [exp 3 ]

if isArrayType ( exp2 .type )


typeEqual(exp3 . type ,integer )

thenexp 1 . type exp2 . type . childl


else type . error (exp1 )
exp num

typeexp .type integer

exp true

typeexp .type boolean

exp false

typeexp .type boolean

exp id

typeexp .type lookup (id . name)

Tabla 3.1.1. Gramtica con atributos para verificacin de tipos de la gramtica


simple.
Se supone que los tipos se mantienen como alguna clase de escritura de rbol, de
manera que el tipo estructurado array en la gramtica de la figura 1.3.1
makeTypeNode (array , type)
corresponde a la accin semntica
la cual
construye un nodo de tipo:
Array (size)

Donde el hijo del nodo array (arreglo) es el rbol del tipo dado por el parmetro
type. Se supone que los tipos simples integer y boolean se construyen como
nodos de hoja estndar en la representacin de rbol.
type

Sentencias
Las no tienen tipos en s mismas, sino subestructuras que es necesario verificar
en cuanto a la exactitud de tipo. Situaciones tpicas se muestran mediante las dos
reglas de sentencia en la gramtica simple, la sentencia if y la sentencia de
asignacin. En el caso de la sentencia if, la expresin condicional debe tener tipo
booleano.
Esto
se
indica
mediante
la
regla
if not typeEqual ( exp . type , boolean ) then typeerror (sent ) donde type_error indica un
mecanismo de informe cuyo comportamiento se describir en breve.
En el caso de la sentencia de asignacin, el requerimiento es que la variable que
se est asignando debe tener el mismo tipo que la expresin cuyo valor est por
recibir. Esto depende del algoritmo de equivalencia de tipos, como se expres
mediante la funcin typeEqual.

Expresiones
Las expresiones constantes, tales como nmeros, y los valores booleanos true y
false, tienen tipos implcitamente definidos integer y boolean. Los nombres de
variable tienen sus tipos determinados mediante operadores, tales como el
operador aritmtico +, el operador booleano or y el operador de subndice [ ]. En
cada caso las subexpresiones deben ser del tipo correcto para la operacin
indicada. En el caso de los subndices, esto se indica mediante la regla
if isArrayType ( exp2 .type )typeEqual ( exp3 . type ,integer )
thenexp 1 . type exp2 . type . childl else type . error (exp1 )
Aqu la funcin isArrayType prueba que su parmetro es un tipo arreglo (array),
es decir, que la representacin de rbol del tipo tenga un nodo raz que represente
el constructor de tipo arreglo. El tipo de la expresin del subndice resultante es el
tipo base del arreglo, el cual es el tipo representado por el (primer) hijo child del
nodo raz en la representacin de rbol de un tipo arreglo, y esto se indica
escribiendo exp2 .type . child 1.
El resto describe el comportamiento de un verificador de tipo as en la presencia
de errores, como se indica mediante el procedimiento type_error en las reglas
semnticas de la tabla 3.1.1. Las cuestiones principales son cundo generar un
mensaje de error y cmo continuar la verificacin de tipos en la presencia de
emes. No se debera generar un mensaje de error cada vez que ocurre un error de
tipo; de otro modo, un error simple podra causar que se imprimiera una cascada
de muchos errores (algo que tambin puede pasar con errores de anlisis
sintctico). En su lugar, si el procedimiento type_error puede determinar que un
error de tipo ya debe haber ocurrido en un lugar relacionado, entonces debera
suprimirse la gene- racin de un mensaje de error. Esto se puede sealar teniendo
un tipo de error interno especial (el cual se puede representar mediante un rbol
de tipo nulo). Si typeError encuentra este tipo de error en una subestructura,
entonces no se genera ningn mensaje de error. Al mismo tiempo, si un error de
tipo tambin significa que no se puede determinar el tipo de una estructura,
entonces el verificador de tipo puede usar el tipo de error como su (en realidad
desconocido) tipo.
Por ejemplo, en las reglas semnticas de la tabla 3.1.1, dada una expresin con
subndice exp1 exp 2 [exp 3 ] , si exp2 no es un tipo arreglo, entonces no se
puede asignar a

exp1 , un tipo vlido, y no hay asignacin de un tipo en las

acciones semnticas. Esto supone que los campos de tipo se han inicializado para
algn tipo de error. Por otra parte, en el caso de las operaciones + y or, incluso en
la presencia de un error de tipo, puede hacerse la suposicin de que cl resultado
10

que es significativo es de tipo entero o booleano, y las reglas de la tabla 3.1.1


utilizan ese hecho para asignar un tipo al resultado.
1.4 Pila semntica en un analizador sintctico
Una pila es una coleccin de datos a los cuales se les puede acceder mediante un
extremo, que se conoce generalmente como tope.
Su caracterstica fundamental es que al extraer se obtiene siempre el ltimo
elemento que acaba de insertarse. Por esta razn tambin se le conocen como
estructuras de datos LIFO (del ingls Last In First Out). Una posible
implementacin mediante listas enlazadas sera insertada y extrayendo siempre
por el principio de la lista.
Gracias a las pilas es posible el uso de la recursividad. La variable que llama al
mismo procedimiento en el que est, habr que guardarla, as como el resto de
variables de la nueva llamada, para a la vuelta de la recursividad ir sacndolas,
esto es posible a la implementacin de pilas. Las pilas y colas son estructuras de
datos que se utilizan generalmente para simplificar ciertas operaciones de
programacin.
Las pilas se utilizan en muchas aplicaciones que se usan con frecuencia. Por
ejemplo, la gestin de ventanas en Windows.
Al utilizar arreglos para implementar pilas se tiene la limitacin de que se debe
reservar el espacio en memoria con anticipacin. Una vez dado un mximo de
capacidad a la pila, no es posible insertar un nmero de elementos mayor que el
mximo establecido. Si esto ocurre, en otras palabras, la pila est llena y se
intenta insertar un nuevo elemento, se producir un error conocido como
desbordamiento (overflow). Una posible solucin a este tipo de inconvenientes
consiste en definir pilas de gran tamao, pero esto resultar ineficiente y costoso.
No siempre es viable con exactitud el nmero de elementos a tratar, y siempre
existe la posibilidad de que ocurra un error de desbordamiento.
Operaciones con pilas
-

Insertar un elemento (push)


Eliminar (pop)
Pila vaca
Pila llena

Al decir pila semntica, no se refiere a que hay varios tipos de pila, hace referencia
a que se debe programar nica y exclusivamente en un solo lenguaje, es decir, no
se puede mezclar cdigo C++ con Visual Basic; ya que se trabaja con comandos
similares.
El objetivo terico es construir un rbol de anlisis sintctico, este raramente se
construye como tal, sino que las rutinas semnticas integradas van generando el
rbol de sintaxis abstracta. Las rutinas semnticas deben realizar la evaluacin de
11

los atributos de las gramticas siguiendo las reglas semnticas asociadas a cada
produccin de la gramtica. En definitiva, comprobar que el significado que se va
leyendo es vlido. La salida terica de la fase de anlisis semntico sera un
rbol semntico. Las rutinas semnticas suelen hacer uso de una pila (la pila
semntica) que contiene la informacin semntica asociada a los operandos ( y a
veces a los operadores) en forma de registros semnticos.
1.5 Esquema de traduccin
Un esquema de traduccin es una gramtica de contexto libre en la que se
encuentran intercalados, en el lado derecho de la regla de produccin, fragmentos
de programas a los que hemos llamado acciones semnticas. Un esquema de
traduccin es como una definicin dirigida por sintaxis, con la excepcin de que el
orden de evaluacin de las reglas semnticas se muestra explcitamente. La
posicin en la que se ejecuta alguna accin se da entre llaves y se escribe en el
lado derecho de la regla de produccin. Por ejemplo:
A cd { printf ( c+ d ) } B

Cuando se disea un esquema de traduccin, se deben respetar algunas


limitaciones para asegurarse que el valor de un atributo est disponible cuando
una accin se refiera a l. Estas limitaciones, derivadas del tipo de anlisis
sintctico escogido para construir el rbol, garantizan que las acciones no hagan
referencia a un atributo que an no haya sido calculado.
El ejemplo ms sencillo ocurre cuando slo se necesitan atributos sintetizados. En
este caso, se puede construir el esquema de traduccin creando una accin que
conste de una asignacin para cada regla semntica y colocando esta accin al
final del lado derecho de la regla de produccin asociada. Por ejemplo, la regla de
produccin T T 1F y la accin semntica T . val :=T 1 . valF . val dan como
resultado la siguiente produccin y accin semntica:
T T 1F {T . val T 1 . valF . val }
Si se tienen atributos tanto heredados como sintetizados, se debe ser ms
prudente, de manera que deben cumplirse algunas reglas a la hora de utilizar los
atributos de los smbolos gramaticales:
1. Un atributo heredado para un smbolo en el lado derecho de una regla de
produccin se debe calcular en una accin antes que dicho smbolo.
2. Una accin no debe referirse a un atributo sintetizado de un smbolo que
est a la derecha de la accin.
3. Un atributo sintetizado para el no terminal de la izquierda slo se puede
calcular despus de que se hayan calculado todos los atributos a los que
hace referencia. La accin que calcula dichos atributos se debe colocar,
generalmente, al final del lado derecho de la produccin.
12

Los esquemas de traduccin bien definidos que cumplen estas restricciones se


dice que estn bien definidos. Ejemplo:
D T { L . her=T .tipo } L ;
T {T .tipo=integer }

T real { T . tipo=real }
L { L1 . her =L. her } L1 ,id {aadetipo ( id . pt r tbs , L . her ) }
L id {aadetipo ( id . ptrtbs , L .her ) }
Un traductor divide su labor en dos etapas: una que analiza la entrada y genera
estructuras intermedias y otra que sintetiza la salda a partir de dichas estructuras.
Por tanto, el esquema de un traductor pasa de ser el de la figura 1.5.1, a ser el de
la figura 1.5.2.
Bsicamente los objetos de la etapa de anlisis son:
a) Controlar la correccin del programa fuente
b) Generar las estructuras necesarias para comenzar la etapa de sntesis

Figura 1.5.1. Esquema preliminar de un traductor.


Para llevar esto a cabo, la etapa de anlisis consta de las siguientes fases:
Anlisis lexicogrfico. Divide el programa fuente en los componentes
bsicos del lenguaje a compilar. Cada componente bsico es una
subsecuencia de caracteres del programa fase, y pertenece a una categora
gramatical: nmeros, identificadores de usuario (variables, constantes,
tipos, nombres de procedimientos, ), palabras reservadas, signos de
puntuacin, etc.
Anlisis sintctico. Comprueba que la estructura de los componentes
bsicos sea correcta segn las reglas gramaticales del lenguaje que se
compila.
Anlisis semntico. Comprueba que el programa fuente respeta las
directrices del lenguaje que se compila (todo lo relacionado con el
significado): chequeo de tipos, rangos de valores, existencia de variables,
etc.
13

Figura 1.5.2. Esquema por etapas de un traductor.


Cualquiera de estas tres fases puede emitir mensajes de error derivados de fallos
cometidos por el programador en la redaccin de los textos fuentes. Mientras ms
errores controle un compilador, menos problemas dar un programa en tiempo de
ejecucin. Por ejemplo, el lenguaje C no controla los lmites de un array, lo que
provoca que en tiempo de ejecucin puedan producirse comportamientos del
programa de difcil explicacin.
La etapa de sntesis construye el programa objeto deseado (equivalente
semnticamente al fuente) a partir de las estructuras generadas por la etapa de
anlisis. Para ello se compone de tres fases fundamentales:
Generacin de cdigo intermedio. Genera un cdigo independiente de la
mquina muy parecido al ensamblador. No se genera cdigo mquina
directamente porque as es ms fcil hacer pseudocompiladores y adems
se facilita la optimizacin de cdigo independientemente del
microprocesador.
Generacin del cdigo mquina. Crea un bloque de cdigo mquina
ejecutable, as como los bloques necesarios destinados a contener los
datos.
Fase de optimizacin. La optimizacin puede realizarse sobre el cdigo
intermedio (de forma independiente de las caractersticas concretas del
microprocesador), sobre el cdigo mquina, o sobre ambos. Y puede ser
una aislada de las dos anteriores, o estar integrada con ellas.
1.6 Generacin de la tabla de smbolos y de direcciones
Tambin llamada tabla de nombres o tabla de identificadores, se trata
sencillamente de una estructura de datos de alto rendimiento que almacena toda
la informacin necesaria sobre los identificadores de usuario. Tiene dos funciones
principales:

Efectuar chequeos semnticos.


Generar cdigo.

Adems, esta estructura permanece en memoria slo en tiempo de compilacin,


no de ejecucin, excepto en aquellos casos en que se compila con opciones de
depuracin. Los intrpretes tambin suelen mantener la tabla de smbolos en
memoria durante la ejecucin, ya que sta se produce simultneamente con la
traduccin.
14

La tabla de smbolos almacena la informacin que en cada momento se necesita


sobre las variables del programa; informacin tal como: nombre, tipo, direccin de
localizacin en memoria, tamao, etc. Una adecuada y eficaz gestin de la tabla
de smbolos es muy importante, ya que su manipulacin consume gran parte del
tiempo de compilacin. De ah que su eficiencia sea crtica.
La tabla de smbolos tambin sirve para guardar informacin referente a los tipos
de datos creados por el usuario, los tipos enumerados y, en general, cualquier
identificador creado por el usuario. En estos casos, el desarrollador puede optar
por mezclar las distintas clases de identificadores en una sola tabla, o bien
disponer de varias tablas, donde cada una de ellas albergar una clase distinta de
identificadores: tabla de variables, tabla de tipos de datos, tabla de funciones de
usuario, etc. En lo que sigue nos vamos a centrar principalmente en las variables
de usuario.
La informacin que el desarrollador decida almacenar en esta tabla depender de
las caractersticas concretas del traductor que est desarrollando. Entre esta
informacin puede incluirse:
Nombre del elemento. El nombre o identificador puede almacenarse
limitando o no la longitud del mismo. Si se almacena con lmite empleando
un tamao mximo fijo para cada nombre, se puede aumentar la velocidad
de creacin y manipulacin, pero a costa de limitar la longitud de los
nombres en unos casos y desperdiciar espacio en la mayora. El mtodo
alternativo consiste en habilitar la memoria que necesitemos en cada caso
para guardar el nombre. En C esto es fcil con el tipo char *; si hacemos el
compilador en Modula-2, por ejemplo, habra que usar el tipo ADDRESS.
En el caso de Java, esto no entraa dificultad alguna gracias al tipo String.
Las bsquedas en la tabla de smbolos suelen hacerse por este nombre;
por ello, y para agilizar al mximo esta operacin, la tabla de smbolos
suele ser una tabla de dispersin (hash) en la que las operaciones de
bsqueda e insercin poseen un coste aproximadamente constante (=
O(1)).
Tipo del elemento. Cuando se almacenan variables, resulta fundamental
conocer el tipo de datos a que pertenece cada una de ellas, tanto si es
primitivo como si no, con objeto de poder controlar que el uso que se hace
de tales variables es coherente con el tipo con que fueron declaradas.
Direccin de memoria en que se almacenar su valor en tiempo de
ejecucin. Esta direccin es necesaria, porque las instrucciones que
referencian a una variable deben saber dnde encontrar el valor de esa
variable en tiempo de ejecucin con objeto de poder generar cdigo
mquina, tanto si se trata de variables globales como de locales. En
lenguajes que no permiten la recursin, las direcciones se van asignando
secuencialmente a medida que se hacen las declaraciones. En lenguajes
con estructuras de bloques, la direccin se da con respecto al comienzo del
15

rea de memoria asignada a ese bloque (funcin o procedimiento) en


concreto.
Valor del elemento. Cuando se trabaja con intrpretes sencillos, y dado que
en un intrprete se solapan los tiempos de compilacin y ejecucin, puede
resultar ms fcil gestionar las variables si almacenamos sus valores en la
tabla de smbolos. En un compilador, no obstante, la tabla de smbolos no
almacena nunca el valor.
Nmero de dimensiones. Si la variable a almacenar es un array, tambin
pueden almacenarse sus dimensiones. Aunque esta informacin puede
extraerse de la estructura de tipos, se puede indicar explcitamente para un
control ms eficiente.
Tipos de los parmetros formales. Si el identificador a almacenar pertenece
a una funcin o procedimiento, es necesario almacenar los tipos de los
parmetros formales para controlar que toda invocacin a esta funcin sea
hecha con parmetros reales coherentes. El tipo de retorno tambin se
almacena como tipo del elemento.
Otra informacin. Con objeto de obtener resmenes estadsticos e
informacin varia, puede resultar interesante almacenar otros datos:
nmeros de lnea en los que se ha usado un identificador, nmero de lnea
en que se declar, tamao del registro de activacin, si es una variable
global o local, en qu funcin fue declarada si es local, etc.
Una funcin esencial de un compilador es registrar los identificadores de usuario
(nombres de variables, de funciones, de tipos, etc.) utilizados en el programa
fuente y reunir informacin sobre los distintos atributos de cada identificador. Estos
atributos pueden proporcionar informacin sobre la memoria asignada a un
identificador, la direccin de memoria en que se almacenar en tiempo de
ejecucin, su tipo, su mbito (la parte del programa donde es visible), etc.
Pues bien, la tabla de smbolos es una estructura de datos que posee informacin
sobre los identificadores definidos por el usuario, ya sean constantes, variables,
tipos u otros. Dado que puede contener informacin de diversa ndole, debe
hacerse de forma que su estructura no sea uniforme, esto es, no se guarda la
misma informacin sobre una variable del programa que sobre un tipo definido por
el usuario. Hace funciones de diccionario de datos y su estructura puede ser una
tabla hash, un rbol binario de bsqueda, etc., con tal de que las operaciones de
acceso sean lo bastante eficientes.

16

Figura 1.6.1. Esquema por etapas definitivo de un traductor.


Tanto la etapa de anlisis como la de sntesis accede a esta estructura, por lo que
se halla muy acoplada al resto de fases del compilador. Por ello conviene dotar a
la tabla de smbolos de una interfaz lo suficientemente genrica como para
permitir el cambio de las estructuras internas de almacenamiento sin que estas
fases deban ser retocadas. Esto es as porque suele ser usual hacer un primer
prototipo de un compilador con una tabla de smbolos fcil de construir (y por
tanto, ineficiente), y cuando el compilador ya ha sido finalizado, entonces se
procede a sustituir la tabla de smbolos por otra ms eficiente en funcin de las
necesidades que hayan ido surgiendo a lo largo de la etapa de desarrollo anterior.
Siguiendo este criterio, el esquema general definitivo de un traductor se detalla en
la figura 1.6.1. La figura 1.6.2 ilustra el esquema por fases, donde cada etapa ha
sido sustituida por las fases que la componen y se ha hecho mencin explcita del
preprocesador.

17

Figura 1.6.2. Esquema completo de un compilador por fases con preprocesador.


Por ltimo, es importante recalcar que la tabla de smbolos contiene informacin
til para poder compilar, y por tanto slo existe en tiempo de compilacin, y no de
ejecucin. Sin embargo, en un intrprete dado que la compilacin y la ejecucin se
producen a la vez, la tabla de smbolos permanece en memoria todo el tiempo.
1.7 Manejo de errores semnticos
Un lenguaje con comprobacin fuerte de tipos es capaz de garantizar que los
programas se pueden ejecutar sin errores de tipo, por lo que los errores de tipo se
detectarn siempre en tiempo de compilacin.
Dentro de las comprobaciones estticas (en el momento de la compilacin),
tenemos la deteccin e informacin de errores como:

18

Comprobaciones de tipos: operadores aplicados a operandos


incompatibles, asignacin de tipos incompatibles, llamadas a funciones con
tipos no adecuados, etc.
Comprobaciones de flujo de control: las sentencias que hacen que el flujo
de control abandone una construccin debe tener algn lugar a donde
transmitir el control. Por ejemplo: un break debe estar dentro de una
proposicin while, for o switch en C.
Comprobaciones de unicidad: situaciones en las que solo se puede definir
un objeto una vez exactamente. Por ej: un identificador, las etiquetas casen
dentro de un tt switch.

Como mnimo, ante un error, un comprobador de tipos debe informar de la


naturaleza y posicin del error y recuperarse para continuar con la comprobacin
del
resto
del
programa
a
analizar.
Veamos algunas de las operaciones a tener en cuenta en una comprobacin de
tipos:

19

Conversin de tipos: A veces es necesario transformar el tipo de una


expresin para utilizar correctamente un operador o para pasar de forma
adecuada un parmetro a una funcin.

Coercin: Es una conversin de tipos que realiza de forma implcita el


propio compilador. Si es el programador el que realiza la conversin se
tratar entonces de una conversin explcita.

Sobrecarga de operadores: La sobrecarga se resuelve determinando el tipo


de cada una de las expresiones intervinientes en la sobrecarga.

Funciones polimrficas: Son aquellas que trabajan con argumentos cuyo


tipo puede cambiaren distintas llamadas a la funcin.

Conclusin
Se denomina tradicionalmente anlisis semntico a todo aquello que forma parte
del frontal [front-ent] ms all de lo que la gramtica utilizada nos permite: Tabla
de smbolos, chequeos de tipos, generacin de representacin interna.
La etapa de anlisis semntico detecta la validez semntica de las sentencias
aceptadas por el analizador sintctico, es decir, revisa el conjunto de reglas que
especifican el significado de las sentencias sintcticas y las compara, verificando
su correcta escritura. El analizador semntico suele trabajar simultneamente al
analizador sintctico y en estrecha cooperacin.
El analizador semntico es la fase que sigue al anlisis sintctico.

20

Bibliografa
Snchez Dueas, G., & Valverde Andreu, J. A. (1990). Compiladores e interpretes.
Un enfoque pragmatico. Madrid: Daz de Santos.
V. Aho, A., Sethi, R., & D. Ullman, J. (1990). Compiladores. Principios, tcnicas y
herramientas. Massachusetts, EUA: Addison Wesley Longman.
Glvez Rojas, S. & Mora Mata, M. A. (2005). Traductores y compiladores con
Lex/Yacc, JFlex/Cup y JavaCC. Dpto. de Lenguajes y Ciencias de la
Computacin, E.T.S. de Ingeniera Informtica: Universidad de Mlaga.
Teufel, T., Schmidt, S. & Teufel, B. (1995).
fundamentales. Delaware, EUA: Astro Data.

Compiladores. Conceptos

Kenneth C. Louden (2004). Constrccin de compiladores: principios y prctica.


Ciencias e Ingenieras: Thomson.

21