Está en la página 1de 24

Materia: Autmatas II

Maestro: Ponce
Alumno: Carlos A. Reynosa
Gonzlez

Contenido

Introduccin...............................................................................................................2
Anlisis Semntico.....................................................................................................3
Arboles de expresiones..........................................................................................6
Acciones semnticas de un analizador sintctico................................................11
Comprobaciones de tipos en expresiones...............................................................11
Esquemas de Traduccin........................................................................................15
Generacin de la tabla de smbolo y de direcciones...............................................16
Manejo de errores semnticos.............................................................................20
Conclusiones...........................................................................................................22

Introduccin
Hay determinadas caractersticas de los lenguajes de programacin que no
pueden ser modeladas mediante gramticas contextuales y que es necesario
comprobar en una fase posterior al anlisis sintctico. Por otro lado, las fases
posteriores de la compilacin o interpretacin necesitan una representacin de la
entrada que les permita llevar a cabo sus funciones de manera adecuada. Estas
dos vertientes deteccin de errores y representacin de la informacin estn
muy relacionadas y se solapan en la prctica. Supongamos, por ejemplo, que
nuestro lenguaje permite asignaciones segn la regla Asignacin id:=
Expresin; Es habitual que se impongan ciertas restricciones. En nuestro caso,
estas podran ser:
El identificador de la parte izquierda debe estar declarado previamente. El tipo de
la expresin debe ser compatible con el del identificador. El analizador semntico
deber a comprobar que estas dos restricciones se cumplen antes de declarar que
la sentencia de asignacin est bien formada.
Pero sucede que la informacin necesaria para comprobarlas es til tambin para
generar cdigo. Esto quiere decir que si tuvo ramos una separacin estricta entre
las fases del compilador, para generar cdigo deberamos volver a mirar el
identificador para saber a qu objeto (variable, funcin, constante, etc.)
corresponde y que tipo tiene y tambin deberamos volver a comprobar los tipos
de la expresin para generar el cdigo adecuado.

Anlisis Semntico
Se compone de un conjunto de rutinas independientes, llamadas por los
analizadores morfolgico y sintctico.
El anlisis semntico utiliza como entrada el rbol sintctico detectado por el
anlisis sintctico para comprobar restricciones de tipo y otras limitaciones
semnticas y preparar la generacin de cdigo.
En compiladores de un solo paso, las llamadas a las rutinas semnticas se
realizan directamente desde el analizador sintctico y son dichas rutinas las que
llaman al generador de cdigo. El instrumento ms utilizado para conseguirlo es la
gramtica de atributos.
En compiladores de dos o ms pasos, el anlisis semntico se realiza
independientemente de la generacin de cdigo, pasndose informacin a travs
de un archivo intermedio, que normalmente contiene informacin sobre el rbol
sintctico en forma linealizada (para facilitar su manejo y hacer posible su
almacenamiento en memoria auxiliar).
En cualquier caso, 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.
La fase de anlisis semntico de un procesador de lenguaje es aqulla que
computa la informacin adicional necesaria para el procesamiento de un lenguaje,
una vez que la estructura sintctica de un programa haya sido obtenida. Es por
tanto la fase posterior a la de anlisis sintctico y la ltima dentro del proceso de
sntesis de un lenguaje de programacin.
Sintaxis de un lenguaje de programacin es el conjunto de reglas formales que
especifican la estructura de los programas pertenecientes a dicho lenguaje.
Semntica de un lenguaje de programacin es el conjunto de reglas que
especifican el significado de cualquier sentencia sintcticamente vlida.
Finalmente, el anlisis semntico1 de un procesador de lenguaje es la fase
encargada de detectar la validez semntica de las sentencias aceptadas por el
analizador sintctico.

Ejemplo 1: Dado el siguiente ejemplo de cdigo en C:


Superficie = base * altura / 2;

La sintaxis del lenguaje C indica que las expresiones se pueden formar con un
conjunto de operadores y un conjunto de elementos bsicos. Entre los operadores,

con sintaxis binaria infija, se encuentran la asignacin, el producto y la divisin.


Entre los elementos bsicos de una expresin existen los identificadores y las
constantes enteras sin signo (entre otros). Su semntica identifica que en el
registro asociado al identificador superficie se le va a asociar el valor resultante del
producto de los valores asociados a base y altura, divididos por dos (la superficie
de un tringulo). Finalmente, el anlisis semntico del procesador de lenguaje, tras
haber analizado correctamente que la sintaxis es vlida, deber comprobar que se
satisfacen las siguientes condiciones:

Que todos los identificadores que aparecen en la expresin hayan sido


declarados en el mbito actual, o en alguno de sus mbitos previos.
Que la subexpresin de la izquierda sea semnticamente vlida, es decir,
que sea un value .
Que a los tipos de los identificadores base y altura se les pueda aplicar el
operador de multiplicacin. Un registro en C, por ejemplo, no sera vlido.
Deber inferirse el tipo resultante de la multiplicacin anterior. Al tipo
inferido se le deber poder aplicar el operador de dividir, con el tipo entero
como multiplicando.
Deber inferirse el tipo resultante de la divisin y comprobarse si ste es
compatible con el tipo de superficie para llevar a cabo la asignacin. Como
ejemplo, si superficie fuese entera y division real, no podra llevarse a cabo
la asignacin.

La fase de anlisis semntico obtiene su nombre por requerir informacin relativa


al significado del lenguaje, que est fuera del alcance de la representatividad de
las gramticas libres de contexto y los principales algoritmos existentes de
anlisis; es por ello por lo que se dice que captura la parte de la fase de anlisis
considerada fuera del mbito de la sintaxis. Dentro de la clasificacin jerrquica
que Chomsky dio de los lenguajes, la utilizacin de gramticas sensibles al
contexto (o de tipo 1) permitira identificar sintcticamente caractersticas como
que la utilizacin de una variable en el lenguaje Pascal ha de estar previamente
declarada. Sin embargo, la implementacin de un analizador sintctico basado en
una gramtica de estas caractersticas sera computacionalmente ms compleja
que un autmata de pila.
As, la mayora de los compiladores utilizan una gramtica libre de contexto para
describir la sintaxis del lenguaje y una fase de anlisis semntico posterior para
restringir las sentencias que semnticamente no pertenecen al lenguaje. En el
caso que mencionbamos del empleo de una variable en Pascal que
necesariamente haya tenido que ser declarada, el analizador sintctico se limita a
comprobar, mediante una gramtica libre de contexto, que un identificador forma
parte de una expresin. Una vez comprobado que la sentencia es sintcticamente
correcta, el analizador semntico deber verificar que el identificador empleado
como parte de una expresin haya sido declarado previamente. Para llevar a cabo

esta tarea, es tpica la utilizacin de una estructura de datos adicional denominada


tabla de smbolos. sta poseer una entrada por cada identificador declarado en
el contexto que se est analizando. Con este tipo de estructuras de datos
adicionales, los desarrolladores de compiladores acostumbran a suplir las
carencias de las gramticas libres de contexto.
El objetivo principal del analizador semntico de un procesador de lenguaje es
asegurarse de que el programa analizado satisfaga las reglas requeridas por la
especificacin del lenguaje, para garantizar su correcta ejecucin. El tipo y
dimensin de anlisis semntico requerido vara enormemente de un lenguaje a
otro. En lenguajes interpretados como Lisp o Smalltalk casi no se lleva a cabo
anlisis semntico previo a su ejecucin, mientras que en lenguajes como Ada, el
analizador semntico deber comprobar numerosas reglas que un programa
fuente est obligado a satisfacer.
Vemos, pues, cmo el anlisis semntico de un procesador de lenguaje no modela
la semntica o comportamiento de los distintos programas construidos en el
lenguaje de programacin, sino que, haciendo uso de informacin parcial de su
comportamiento, realiza todas las comprobaciones necesarias no llevadas a cabo
por el analizador sintctico para asegurarse de que el programa pertenece al
lenguaje. Otra fase del compilador donde se hace uso parcial de la semntica del
lenguaje es en la optimizacin de cdigo, en la que analizando el significado de los
programas previamente a su ejecucin, se pueden llevar a cabo transformaciones
en los mismos para ganar en eficiencia.
Existen dos formas de describir la semntica de un lenguaje de programacin:
mediante especificacin informal o natural y formal. La descripcin informal de un
lenguaje de programacin es llevada a cabo mediante el lenguaje natural. Esto
hace que la especificacin sea inteligible (en principio) para cualquier persona. La
experiencia nos dice que es una tarea muy compleja, si no imposible, el describir
todas las caractersticas de un lenguaje de programacin de un modo preciso.
Como caso particular, vase la especificacin del lenguaje ISO/ANSI C++
[ANSIC++]. La descripcin formal de la semntica de lenguajes de programacin
es la descripcin rigurosa del significado o comportamiento de programas,
lenguajes de programacin, mquinas abstractas o incluso cualquier dispositivo
hardware. La necesidad de hacer especificaciones formales de semntica surge
para:

Revelar posibles ambigedades existentes implementaciones de


procesadores de lenguajes o en documentos descriptivos de lenguajes de
programacin.
Ser utilizados como base para la implementacin de procesadores de
lenguaje.
Verificar propiedades de programas en relacin con pruebas de correccin
o informacin relacionada con su ejecucin.

Disear nuevos lenguajes de programacin, permitiendo registrar


decisiones sobre construcciones particulares del lenguaje, as como permitir
descubrir posibles irregularidades u omisiones.
Facilitar la comprensin de los lenguajes por parte del programador y como
mecanismo de comunicacin entre diseador del lenguaje, implementador y
programador. La especificacin semntica de un lenguaje, como documento
de referencia, aclara el comportamiento del lenguaje y sus diversas
construcciones.
Estandarizar lenguajes mediante la publicacin de su semntica de un
modo no ambiguo. Los programas deben poder procesarse en otra
implementacin de procesador del mismo lenguaje exhibiendo el mismo
comportamiento.

Arboles de expresiones.
En muchos problemas de programacin numrica es necesario trabajar con los
valores obtenidos al evaluar una expresin matemtica determinada,
generalmente la solucin a este problema radica en escribir directamente en el
cdigo fuente dicha expresin para luego usarla. La va anterior trae como
inconveniente la recompilacin del cdigo fuente cada vez que se quiera definir
otra expresin matemtica, lo que a su vez nos limita si queremos hacer un
programa que sea genrico en ese sentido. Al usar un intrprete de funciones se
puede solucionar este problema, al poder evaluar de forma dinmica cualquier
expresin matemtica. Sin embargo, prcticamente ningn lenguaje de
programacin trae en su implementacin estndar de funciones y/o clases algn
soporte para interpretar funciones dinmicamente.
Conceptos importantes
Es necesario para una mejor comprensin de este trabajo definir una serie
trminos que sern usados con frecuencia:

Notacin polaca (notacin prefija): Es una forma de notacin de


expresiones matemticas donde los operadores se colocan a la izquierda
de los operandos. Su invencin se debe al matemtico polaco Jan
ukasiewicz, quin la cre alrededor de 1920. Una caracterstica distintiva
de este tipo de notacin es que se puede prescindir del uso de parntesis
como se hace en la notacin infija (notacin tradicional).

Notacin polaca inversa (notacin postfija): Este es el tipo de notacin que


tiene una aplicacin prctica en este trabajo, a diferencia de la notacin

prefija, en la notacin postfija los operadores son colocados a la derecha de


los operandos.
En la siguiente tabla se muestran ejemplos de notacin polaca inversa:

Notacin Tradicional
a+b
(a+b) * c

Notacin Polaca Inversa


ab+
ab +c*

Pila (''stack'' en ingls): es una estructura de datos en la que el modo de acceso a


sus elementos es de tipo LIFO (del ingls Last In First Out, ltimo en entrar,
primero en salir) que permite almacenar y recuperar datos. Cuando se trata de
extraer un elemento almacenado en este tipo de estructura, la extraccin se
realiza en el orden inverso del que fueron almacenados, es decir el ltimo
elemento almacenado es el primero en salir y el primero que fue almacenado es el
ltimo que puede ser extrado.
Las operaciones bsicas que se realizan sobre una pila son las siguientes:

Apilar un elemento: introducir (almacenar) un nuevo elemento en la pila


Despilar un elemento: extraer un elemento de la pila, este elemento ser el
ltimo en ser apilado

Operadores binarios: Acordaremos en llamar operadores binarios a todos aquellos


que acten sobre dos operandos, estos son: suma (+), resta (-), multiplicacin
(*),...., ect.
Operadores unarios: Acordaremos en llamar operadores unarios a todos aquellos
que acten sobre s/slo un operando, estos son las funciones matemticas
bsicas: seno, coseno, tangente, raz cuadrada, logartmo natural,...., ect.

De notacin infija a notacin postfija

Para construir el rbol de expresiones que represente nuestra expresin


matemtica es necesario construir primero la misma expresin pero en la notacin
polaca correspondiente y a partir de esta es que se construye el rbol. El algoritmo
usado para transformar una expresin infija a prefija es explicado a continuacin.
Sea A una expresin infija cualquiera, formada por operadores, parntesis
(izquierdos y derechos) y operandos, tambin se usar una pila para los
operadores.
El procedimiento seguido es el siguiente:
Se lee un elemento de A, si este es un operador o un parntesis izquierdo,
entonces se acta segn la regla I y si es un operando entonces se enva
directamente a la expresin de notacin polaca. Si el elemento ledo de A es un
parntesis derecho, entonces se desapilarn elementos de la pila de operadores
hasta encontrar el correspondiente parntesis izquierdo. Cada elemento
desapilado pasa a formar parte de la notacin polaca, excepto los parntesis.
Cuando no queden elementos en A, entonces se desapilan operadores de la pila,
hasta que esta quede vaca.

Regla I:
Existe un orden de prioridad para los operadores, que de menor a mayor es el
siguiente: suma (+) y resta (-), multiplicacin (*) y divisin (/), exponenciacin (^),
operadores unarios. El parntesis izquierdo lo trataremos como un operador
(aunque no lo es) cuyo orden de prioridad es el mayor de todos cuando se quiera
apilar y el menor de todos cuando est en la cima de la pila.
Cuando se intente apilar algn operador se har lo siguiente: si es un operador
unario entonces se apila, si es un operador binario, se comparar su prioridad con
el ltimo insertado en la pila (el de la cima), si su prioridad es mayor, entonces se
apilar. Si ocurre lo contrario (su prioridad es menor o igual) entonces el operador
de la cima de la pila se desapilar y pasar a formar parte de la notacin polaca.
Se volver a intentar apilar el operador siguiendo la misma regla, hasta que se
pueda apilar, si la pila queda vaca tambin se apila. El parntesis izquierdo
siempre se apilar y no podr ser desapilado por ningn operador y por tanto no
formar parte de la notacin polaca inversa.
El siguiente ejemplo, ayudar a entender mejor lo dicho anteriormente. Sea la
siguiente expresin infija: 2^sin(y+x)ln(x).
En la siguiente tabla se muestra paso a paso la conversin a notacin postfija. Se
usa el color rojo para sealar los casos en que es necesario desapilar operadores
de la pila.

Construccin del rbol binario de expresiones


Una vez obtenida la expresin en notacin postfija, se puede evaluar mediante el
uso nuevamente de una pila. Sin embargo, en nuestro caso se trabaja con una
rbol binario de expresiones, as que lo que se hace es construir el rbol. El
algoritmo usado para construir el rbol no usa como tal la expresin postfija ya
conformada, sino que el rbol se va construyendo usando las mismas reglas con
las que se construye la notacin postfija, una pila para los operadores y otra para
los nodos del rbol, ambas no son necesitadas al terminar el rbol. El algoritmo es
el siguiente:
Se siguen las mismas reglas expuestas anteriormente usando la pila de
operadores, pero cuando se encuentra un operando o un operador es desapilado,
entonces se crea el nodo correspondiente y se acta segn la regla II. Al finalizar
el algoritmo solo debe quedar un nodo apilado en la pila de nodos, el que
constituye el nodo raz de nuestro rbol de expresiones.

Regla II.
Si el nodo corresponde a un operando, entonces se apila. Si el nodo corresponde
a una operador unario entonces se desapila un nodo de la pila de nodos y es
enlazado a la rama izquierda del nodo correspondiente al operador unario y este
ltimo es apilado. Si el nodo corresponde a un operador binario entonces dos
nodos son desapilados de la pila de nodos, el primero es enlazado a la rama
derecha del nodo binario y el segundo a la rama izquierda, nuevamente este nodo
es apilado.
En el siguiente ejemplo se usa la misma expresin infija anterior (2^sin(y+x) ln
(x)) para ilustrar el procedimiento para construir el rbol:

Acciones semnticas de un analizador sintctico


Dependiendo del tipo de sentencias, las acciones semnticas pueden agruparse
en:

Sentencias de Declaracin: Completar la seccin de tipos de la Tabla de


Smbolos.
Sentencias ejecutables: Realizar comprobaciones de tipos entre los
operandos implicados.
Funciones y procedimientos: Comprobar el nmero, orden y tipo de los
parmetros actuales en cada llamada a una funcin o procedimiento.
Identificacin de variables: Comprobar si un identificador ha sido declarado
antes de utilizarlo.
Etiquetas: Comprobar si hay etiquetas repetidas y validacin.
Constantes: Comprobar que no se utilicen en la parte izquierda de una
asignacin.
Conversiones y equivalencias de tipo: Verificacin.
Sobrecarga de operadores y funciones: Detectar y solventar.

Comprobaciones de tipos en expresiones

Sistema de tipos: reglas de un lenguaje que permiten asignar tipos alas


distintas partes de un programa y verificar su correccin.
Formado por las definiciones y reglas que permiten comprobar el dominio
de un identificador, y en qu contextos puede ser usado.
Cada lenguaje tiene un sistema de tipos propio, aunque puede variar de
una a otra implementacin.
La comprobacin de tipos es parte del anlisis semntico.
Funciones principales:
Inferencia de tipos: calcular y mantener la informacin sobre los tipos de
datos.
Verificacin de tipo: asegurar que las partes de un programa tienen sentido
segn las reglas de tipo del lenguaje.

La informacin de tipos puede ser esttica o dinmica:

LISP, CAML o Smalltalk utilizan informacin de tipos dinmica.


En ADA, Pascal o C la informacin de tipos es esttica.
Tambin puede ser una combinacin de ambas formas.

Cuantas ms comprobaciones puedan realizarse en la fase de Compilacin,


menos tendrn que realizarse durante la ejecucin

Mayor eficiencia del programa objeto.

Es parte de la comprobacin de tipos:

Conversin de tipos explcita: transformacin del tipo de una expresin con


un propsito determinado.
Coercin: conversin de tipos que realiza de forma implcita el compilador.

Conversin de tipos explcita: el programador indica el tipo destino.

Funciona como una llamada a funcin: recibe un tipo y devuelve otro.

Conversin de tipos implcita: el compilador convierte automticamente elementos


de un tipo en elementos de otro.

La conversin se lleva a cabo en la accin semntica de la regla donde se


realiza.
Comprobador de tipos seguro: Durante la compilacin (comprobacin
esttica) detecta todos los posibles errores de tipo.
Lenguaje fuertemente tipado: Si un fragmento de cdigo compila es que no
se van a producir errores de tipo.
En la prctica, ningn lenguaje es tan fuertemente tipado que permita una
completa comprobacin esttica.

Informacin de tipos dinmica: El compilador debe generar cdigo que realice la


inferencia y verificacin de tipos durante la ejecucin del programa que se est
compilando.
#let primero (a,b) = a;;
primero : 'a * 'b -> 'a = <fun>

Informacin de tipos esttica:


Se utiliza para verificar la exactitud del programa antes de la ejecucin.
Permite determinar la asignacin de memoria necesaria para cada variable.
function Primero(a,b:integer):integer;
begin

Primero:= a
end;

Tipo de datos = conjunto de valores + operaciones aplicables


En el mbito de los compiladores, un tipo se define mediante una expresin de
tipo (informacin de tipos explcita)

Nombre de tipo: float


Expresin estructurada explcita: set of integer
Estas expresiones se utilizan en la construccin de otros tipos o para
declarar variables.

Tambin es posible incluir informacin de tipos implcita:


const MAX = 10;

La informacin de tipos, implcita o explcita, se mantiene en la tabla de smbolos.


Esta informacin se recupera de la tabla de smbolos mediante el verificador de
tipo cuando se hace referencia al nombre asociado.
Ejemplo:
A[i]
si A es de tipo array [1..10] of real
si i tiene tipo integer
entonces A[i] es correcto y su tipo es real
Saber si i
1..10, no es una verificacin de tipo, sino de si el rango es o no correcto.

Un lenguaje de programacin contiene un conjunto de tipos predefinido


denominados tipos simples.
Algunos lenguajes permiten definir nuevos tipos simples: enumerado, subrango.
Todos los lenguajes permiten crear nuevos tipos complejos a partir de otros ms
simples mediante constructores de tipos:

Matrices, productos, registros, punteros, funciones,


En Pascal: array, set, record,...

En C++: struct, class, union,...

Para analizar los diferentes tipos que intervienen dentro de un programa, el


compilador debe contar con una estructura interna que le permita manejar
cmodamente las expresiones de tipos.
Esta estructura interna:

Debe ser fcilmente manipulable, pues su creacin se realizar conforme


se hace la lectura del programa fuente.
Debe permitir comparar fcilmente las expresiones asignadas a distintos
trozos de cdigo, especialmente a los identificadores de variables.

La forma ms habitual de representacin son los grafos acclicos dirigidos (GADs).

La ventaja de estas representaciones es que ocupan poca memoria y por


tanto la comprobacin de equivalencia se efecta con rapidez.

Como podemos entender un analizador sintctico ascendente utiliza durante el


anlisis una pila. En esta va guardando datos que le permiten ir haciendo las
operaciones de reduccin que necesita.
Para incorporar acciones semnticas como lo es construir el rbol sintctico, es
necesario incorporar a la pila del analizador sintctico ascendente otra columna
que guarde los atributos de los smbolos que se van analizando.

Esquemas de Traduccin
Un analizador sintctico ascendente utiliza durante el anlisis una pila. En esta va
guardando datos que le permiten ir haciendo las operaciones de reduccin que
necesita.
Para incorporar acciones semnticas como lo es construir el rbol sintctico, es
necesario incorporar a la pila del analizador sintctico ascendente otra columna
que guarde los atributos de los smbolos que se van analizando.
Un Esquema de Traduccin Dirigido por Sintaxis

Comienza como una Definicin Dirigida por Sintaxis.


El meta-lenguaje de operaciones es un lenguaje de programacin Turingcompleto despus de todo, es para traducir.
Las acciones pueden ocurrir en cualquier punto de las producciones.
Estn asociadas a un reconocedor concreto.
El resultado producido para el smbolo inicial corresponde con la traduccin.

Siempre se puede
1. Construir el rbol gramatical completo.
2. Recorrer el rbol en DFS de izquierda a derecha.
3. Ejecutar las acciones a medida que se encuentran en este recorrido
En la prctica

No construir todo el rbol gramatical ahorrar espacio.


Garantizar la ejecucin de acciones en el momento oportuno.
Tipo de reconocedor y tipo de atribucin definirn la estrategia.
La Definicin Dirigida por Sintaxis es S-Atribuida.
El reconocedor es ascendente.

Basta ejecutar las acciones al reducir cada regla.

Estas reglas permiten evaluar el resultado justo despus de cada reduccin.

S E# {print(E.val)}
E E1+T {E.val E1.val + T.val}
E T {E.val T.val}
TT1F {T.val T1.val F.val}

TF {T.val F.val}
F (E) {F.val E.val}
F n {F.val n.val}
Atributos de cada smbolo en la pila.

La propia pila LR o una pila paralela.


Si el atributo es simple, contenerlo directamente varios atributos simples en
estructura o registro variante.
Si son muchos atributos diferentes o bien complejos, contener un apuntador
al atributo concreto.

Al momento de reducir A XYZ

Los atributos de X, Y y Z estn en posiciones conocidas en la pila.


Al reducir, se retiran de la pila durante el clculo de los atributos de A.
Los atributos calculados para A quedarn en el nuevo tope de la pila.

Imprime la respuesta

Generacin de la tabla de smbolo y de direcciones


Tambin se la llama tabla de nombres o tabla de identificadores y tiene dos
funciones principales:

Efectuar chequeos semnticos.


Generacin de cdigo.

Permanece slo en tiempo de compilacin, no de ejecucin, excepto en aquellos


casos en que se compila con opciones de depuracin. La tabla almacena la
informacin que en cada momento se necesita sobre las variables del programa,
informacin tal como: nombre, tipo, direccin de localizacin, tamao, etc. La
gestin de la tabla de smbolos es muy importante, ya que consume gran parte del
tiempo de compilacin. De ah que su eficiencia sea crtica. Aunque tambin sirve
para guardar informacin referente a los tipos creados por el usuario, tipos
enumerados y, en general, a cualquier identificador creado por el usuario, nos
vamos a centrar principalmente en las variables de usuario. Respecto a cada una
de ellas podemos guardar:
Almacenamiento del nombre.
Se puede hacer con o sin lmite. Si lo hacemos con lmite, emplearemos una
longitud fija para cada variable, lo cual aumenta la velocidad de creacin, pero
limita la longitud en unos casos, y desperdicia espacio en la mayora. Otro mtodo
es habilitar la memoria que necesitemos en cada caso para guardar el nombre. En
C esto es fcil con los char *. Si hacemos el compilador en MODULA-2, por
ejemplo, habra que usar el tipo ADDRESS.
Direccin de memoria en que se guardar

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, tambin cuando se trata de variables globales. En lenguajes que
no permiten recursividad, 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
bloque de datos de ese bloque, (funcin o procedimiento) en concreto.
El nmero de dimensiones de una variable array, o el de parmetros de una
funcin o procedimiento junto con el tipo de cada uno de ellos es til para el
chequeo semntico. Aunque esta informacin puede extraerse de la
estructura de tipos, para un control ms eficiente, se puede indicar
explcitamente.

Consideraciones sobre la Tabla de Smbolos.


La tabla de smbolos puede iniciarse con cierta informacin til, tal como:

Constantes: PI, E, etc.


Funciones de librera: EXP, LOG, etc.
Palabras reservadas. Esto facilita el trabajo al lexicogrfico, que tras
reconocer un identificador lo busca en la tabla de smbolos, y si es

palabra reservada devuelve un token asociado. Bien estructurado puede


ser una alternativa ms eficiente al lex tal y como lo hemos visto (hash
perfecto).
Conforme van apareciendo nuevas declaraciones de identificadores, el
analizador lxico, o el analizador sintctico segn la estrategia que sigamos,
insertar nuevas entradas en la tabla de smbolos, evitando siempre la
existencia de entradas repetidas.
El analizador semntico efecta las comprobaciones sensibles al contexto
gracias a la tabla de smbolos, y el generador de cdigo intermedio usa las
direcciones de memoria asociadas a cada identificador en la tabla de smbolos,
al igual que el generador de cdigo. El optimizador de cdigo no necesita hacer
uso de ella.

La tabla de smbolos contiene informacin til para poder compilar, por tanto
existe en tiempo de compilacin, y no de ejecucin.
Sin embargo, en un intrprete, dado que la compilacin y ejecucin se
producen a la vez, la tabla de smbolos permanece todo el tiempo.
Suponemos que queremos hacer las siguientes operaciones:
a=7*3
b=3*a
En la segunda instruccin necesitamos saber cunto vale a; es decir el valor
de a debe estar guardado en algn sitio. Para ello utilizaremos una lista de
pares:

De forma que cuando nos encontremos con la instruccin a = 7 * 3, miremos


en la tabla, si no est a en la tabla, creamos un nodo para introducirla

A continuacin nos encontramos con b = 3 * a. Qu es a? Busco en la tabla


de smbolos y vemos que el valor de a es 21.
b = 3 * a Ahora buscamos b en la tabla de smbolos y como no est lo
creamos.

Si ejecutramos ahora la instruccin: a = a + b


Tendramos a a y b en la tabla de smbolos con lo cual solo tendramos que
modificar el valor de a.

La tabla de smbolos consta de una estructura llamada smbolo. Las


operaciones que puede realizar son:

crear: Crea una tabla vaca.


insertar: Parte de una tabla de smbolo y de un nodo, lo que hace es
aadir ese nodo a la cabeza de la tabla.
buscar: Busca el nodo que contiene el nombre que le paso por
parmetro.
imprimir: Devuelve una lista con los valores que tiene los identificadores
de usuario, es decir recorre la tabla de smbolos. Este procedimiento no
es necesario pero se aade por claridad, y a efectos de resumen y
depuracin.

Manejo de errores semnticos.


Un error semntico se produce cuando la sintaxis del cdigo es correcta, pero la
semntica o significado no es el que se pretenda. La construccin obedece las
reglas del lenguaje, y por ello el compilador o intrprete no detectan los errores
semnticos. Los compiladores e intrpretes slo se ocupan de la estructura del
cdigo que se escribe, y no de su significado. Un error semntico puede hacer que
el programa termine de forma anormal, con o sin un mensaje de error. Hablando
en trminos coloquiales, puede hacer que el equipo se quede "colgado".

Tratamiento 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.
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:

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.

Especificacin de un comprobador de tipos bsico


Bsicamente se debern realizar dos tareas:
a)

Asignacin de tipos: en las declaraciones.

b) Evaluacin y comprobacin de tipos: En las expresiones y en las funciones,


as como en las sentencias.

Otras comprobaciones semnticas y recuperacin de errores semnticos

Dentro de las comprobaciones estticas (en el momento de la compilacin),


tenemos la deteccin e informacin de errores como:

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 alg un lugar a donde
transmitir el control. Por ejemplo: Unbreak 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 ejemplo: Un identificador, las etiquetas
case dentro de un switch.

Conclusiones
El analizador semntico tiene dos objetivos:
Hacer comprobaciones que no se hagan durante el anlisis lxico o sintctico.
Crear una representacin adecuada para fases posteriores.
Implementaremos el anlisis semntico en dos partes:
Mediante esquemas de traduccin dirigidos por la sintaxis.
Recorriendo el AST.
Un esquema de traduccin dirigido por la sintaxis aade a las gramticas:
Acciones intercaladas en las partes derechas de las reglas.
Atributos asociados a los no terminales.
Dos tipos de atributos: heredados y sintetizados.
Las acciones deben garantizar que se evalan correctamente los atributos.
Se pueden implementar los esquemas de traduccin sobre los analizadores
sintcticos interpretando los atributos como parmetros y aadiendo el cdigo de
las acciones al cdigo del analizador.
El clculo de algunos atributos y algunas comprobaciones semnticas son ms
fciles sobre el AST

Bibliografa
http://di002.edv.uniovi.es/~ortin/publications/semantico.pdf
http://www.giaa.inf.uc3m.es/docencia/ITIG/Semantico.pdf
http://www.gramaticas.net/2012/05/ejemplos-de-analisis-semantico.html
http://arantxa.ii.uam.es/~alfonsec/docs/compila5.htm