La aplicación de los operadores y operandos deben ser compatibles
Comprobaciones del flujo del control
Las proposiciones que hacen que se abandone el flujo del control de una construcción debe transferirse a otro punto. (break, exit)
Comprobaciones de unicidad
Hay situaciones en los que un objeto solo puede definirse una vez exclusivamente. Las etiquetas de una sentencia case no deben repetirse, declaraciones de objetos,..
Comprobaciones relacionadas con nombre
El mismo nombre debe aparecer dos o más veces. En Ada el nombre que aparece en un bloque puede aparecer al principio y final, el compilador debe comprobar que se utiliza el mismo el ambos sitios
Análisis Semántico
Además de comprobar que un programa cumple con las reglas de la gramática, hay que comprobar que lo que se quiere hacer tiene sentido.
Esta fase también modifica la tabla de símbolos y suele estar mezclada con la generación de código intermedio.
Las gramáticas independientes del contexto (G2) no son suficientes para realizar el análisis semántico.
Por ejemplo, no hay forma de comprobar si una variable ha sido definida ya, o si existe una determinada etiqueta.
Es necesario definir un tipo de gramática más rica como las gramáticas de atributo.
Definición
Definición
Las gramáticas de atributo son gramáticas G2 a las que se añaden atributos y reglas de evaluación de atributos (funciones/reglas semánticas)
Traducción dirigida por sintaxis
Traducción dirigida por sintáxis
Notaciones
Definición dirigida por la sintaxis (DDS)
Esquema de Traducción (EDT)
Evaluación de una acción
Generación de código
Guardar/Consultar información de la Tabla de Símbolos
Si un atributo b en un nodo depende de un atributo c, entonces se debe evaluar la regla semántica para b después de la regla semántica que define a c
Las interdependencias entre atributos heredados y sintetizados de un árbol de análisis sintáctico se pueden representar mediante un grafo dirigido llamado Grafo de Dependencias
Grafos de dependencias
Algoritmo de Construcción
Para cada nodo n en el árbol de análisis sintáctico hacer
No necesita construir un grafo de dependencias de forma explícita
Métodos “sin recuerdo”
Para realizar el orden de evaluación no tiene en cuenta las reglas semánticas. Por ejemplo en el momento de análisis sintáctico.
No necesita construir un grafo de dependencias de forma explícita
Evaluación Ascendente de Definiciones con Atributos Sintetizados (I)
Los atributos sintetizados se pueden evaluar con un analizador sintáctico ascendente conforme la entrada es analizada
El analizador sintáctico conserva en su pila los valores de los atributos sintetizados asociados a los símbolos gramaticales
Cuando se hace una reducción se calculan los valores de los nuevos atributos sintetizados a partir de los atributos de la pila para los símbolos gramaticales del lado derecho de la producción.
Evaluación Ascendente de Definiciones con Atributos Sintetizados (II)
Ejemplo
Producción Fragmento de Código
L->E n print (val [tope])
E->E1 + T val [ntope] := val [tope-2] + val [tope]
E->T
T->T1 * F val [ntope] := val [tope-2] * val [tope]
T->F
F-> ( E ) val [ntope] := val [tope-1]
F->dígito F.val := dígito.valex
Definiciones con Atributos por la Izquierda
Si la traducción ocurre durante el análisis sintáctico, el orden de evaluación de los atributos se corresponde con el orden en el que se “crean” los nodos de un árbol de análisis sintáctico
Un orden natural para los métodos de traducción descendente y ascendente es el “orden de evaluación en profundidad”
Un atributo heredado para un símbolo en el lado derecho de una producción debe calcularse en una acción antes que dicho símbolo.
Una acción no debe referirse a un atributo sintetizado de un símbolo que esté a la derecha de la acción
Un atributo sintetizado para el NO terminal de la izquierda solo puede calcularse después de que se hayan calculado todos los atributos a los que hace referencia. (La acción se sitúa al final del lado derecho de la producción).
Generación de código intermedio
Proceso de Síntesis
Lenguaje Intermedio
Generación de Código
Ventajas del código intermedio
Facilitar la fase de optimización
Aumentar la portabilidad del compilador de una máquina a otra
Se puede utilizar el mismo analizador para diferentes generadores
Se pueden utilizar optimizadores independientes de la máquina
El código se genera cuando se encuentra el operador.
Generación de Código Intermedio en el Análisis Sintáctico Recursivo
Se pueden utilizar las rutinas de árboles de sintaxis abstracta, incorporándolas al código
Supongamos que se genera con el análisis un árbol binario con tres campos por nodo: info (información del nodo); izda (puntero al subárbol izquierdo; dcha (puntero al subárbol derecho)