July 21, 2017 | Author: Cristal De Leon Gonzalez | Category: Compiler, Programming Language, Parsing, Areas Of Computer Science, Computer Programming

#### Description

AUTOMATAS II UNIDAD 1: ANALISIS SEMANTICO

Integrantes: - Escobar Castillo Diana Carmina. - De León González Cristal Idtzayany. - García Guzmán Suriel Tonaiuh. -

1

CONTENIDO INTRODUCCIÓN ....................................................................................................................................................3 1.

ANALISIS SEMÁNTICO ...................................................................................................................................4 1.1

ARBOLES DE EXPRESIONES ...................................................................................................................4

1.1.1

ARBOLES EN INFORMATICA ..........................................................................................................6

1.1.2

DEFINICION RECURSIVA. ...............................................................................................................7

1.1.3

REPRESENTACION DE UN ARBOL GENERAL ..................................................................................8

1.1.4

ARBOL BINARIO ..........................................................................................................................10

1.1.5

NOTACION POLONESA. ...............................................................................................................11

1.2

ACCIONES SEMÁNTICAS DE UN ANALIZADOR ....................................................................................12

1.3

COMPROBACIONES DE TIPOS EN EXPRESIONES ................................................................................13

1.4

PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO...........................................................................14

1.4.1

TEORÍA DE COLAS Y PILAS ...........................................................................................................14

1.5

1.6

GENERACIÓN DE LA TABLA DE SÍMBOLOS Y DE DIRECCIONES...........................................................17

1.6.1 1.7

CONTENIDO DE LA TABLA DE SÍMBOLOS ...................................................................................19

MANEJO DE ERRORES SEMÁNTICOS ..................................................................................................21

CONCLUSIÓN ......................................................................................................................................................22 BIBLIOGRAFÍA .....................................................................................................................................................23

2

INTRODUCCIÓN

3

1. ANALISIS SEMÁNTICO La fase de análisis semántico revisa el programa fuente para tratar de encontrar errores semánticos y reúne la información sobre los tipos para la fase posterior de generación de código. En ella se utiliza la estructura jerárquica determinada por la fase de análisis sintáctico para identificar los operadores y operandos de expresiones y proposiciones. Un componente importante del análisis semántico es la verificación de tipos. Aquí, el compilador verifica si cada operador tiene operandos permitidos por la especificación del lenguaje fuente. Por ejemplo, las definiciones de muchos lenguajes de programación requieren que el compilador indique un error cada vez que se use un número real como índice de una matriz. Sin embargo, la especificación del lenguaje puede permitir ciertas coerciones a los operandos, por ejemplo, cuando un operador aritmético binario se a plica a un número entero y a un número real. En este caso, el compilador puede necesitar convertir el número entero real.

1.1 ARBOLES DE EXPRESIONES Expresión: secuencia de tokens. Token: puede ser un operando o un operador. Operador: +, -, *, /. Propiedades:  Cada hoja es un operando.

4

 El nodo raíz o los nodos internos son operadores.  Los subárboles son subexpresiones en los nodos que el nodo raíz es un operador. Reglas de precedencia: + (positivo), - (negativo). *, /, % +, Ejemplo: a*(b+c)+d  los paréntesis están implícitos en el árbol.  La prioridad se determina solo por paréntesis.  La expresión completa se sitúa con paréntesis.

Figura 1. Diagrama de expresiones usando notación polonesa.

5

1.1.1 ARBOLES EN INFORMATICA El árbol es una estructura de datos fundamental en informática, muy bien adaptados a la inteligencia artificial y al análisis sintáctico. En la inteligencia artificial, las declaraciones de las reglas se efectúan según

el

esquema

premisas-conclusión,

que

corresponde

al

establecimiento de relaciones de dependencia que se puedan poner en forma arborescente. La resolución de un problema se reduce entonces al recorrido de un árbol, con el objeto de establecer un camino entre las hipótesis y las conclusiones generales. En el análisis sintáctico, se definen gramáticas 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 jerárquica de una expresión 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.

6

1.1.2 DEFINICION RECURSIVA. Un árbol T es un conjunto finito de uno a más nudos tales que:  Existe un nudo especial denominado raíz del árbol.  Los otros nudos son particiones en m>0 conjuntos disjuntos T1, T2,…TM y cada conjunto es un árbol. Se dice entonces que T1, T2,….TM son sub arboles de la raíz. Esta definición recursiva, es decir que se define un árbol en términos de árboles. El número de subárboles de un nudo terminal se le llama nivel del nudo. Un nudo de grado cero se designa nudo terminal u hoja. El nivel de un nudo con relación al árbol T se define de la siguiente forma:  La raíz de T es de nivel 0  Los otros nudos tienen el nivel de la raíz del subárbol que los contiene más. Ejemplo: Sea un árbol T que consta de siete nudos A, B, C, D, E, F, G, donde A es la raíz del árbol y tal que los grados de los diversos nudos son: grado de A=2, grado de C=m, grado de F=1, grado de los otros nudos=0 (hojas).

7

1.1.3 REPRESENTACION DE UN ARBOL GENERAL La representación y nomenclatura de los árboles se realiza con las típicas notaciones de las relaciones familiares en los árboles genealógicos:

NIVELES DE UN ARBOL NIVEL 0: A = RAIZ NIVEL 1: {B}, {C, D, F, G} = 2 subárboles. NIVEL 2: {D}, {E}, {F, G}= 3 subárboles NIVEL 3: {G}= 1 subárbol.

Figura 2. Niveles de un árbol. Padre, hijo, hermano, ascendente, descendente, etc. Un ejemplo es el árbol general de la figura 2. Las definiciones a considerar son:  Raíz del árbol, todos los árboles que no están vacíos tienen un único nudo raíz. Todos los demás elementos o nudos derivan o descienden de él. El nudo raíz no tiene padre, es decir, no es hijo de ningún nudo.

8

 Nudo son los vértices o elementos del árbol.  Nudo terminal u hoja, es aquel nudo que no contiene ningún subárbol, en la figura son hojas los nudos E, F, K, L, H, I y J.

Figura 3. Árbol general.  A cada nudo que no es hoja se le asocia a uno o varios subárboles llamados descendientes o hijos. De igual forma, cada uno tiene asociado un antecesor o ascendiente llamado padre.  Los nudos de un mismo padre se le llaman hermanos.  Los nudos con uno o dos subárboles no son hojas ni raíz se llaman nudos internos.  Un conjunto con dos o más árboles se llama bosque.  Se denomina camino el enlace entre dos nudos consecutivos, y rama es un camino que termina en una hoja.  Altura de un árbol es el número máximo de nudos de una rama. Equivale al nivel más alto de los nudos más uno.  El peso de un árbol es el número de nudos terminales.

9

1.1.4 ARBOL BINARIO Existe un tipo de árbol denominado árbol binario que puede ser implementado fácilmente en un ordenador. Un árbol binario es un conjunto finito de cero o más nudos tales que:  Existe un nudo llamado raíz del árbol.  Cada nudo puede tener 0, 1 o 2 subárboles, conocidos como subárbol izquierdo y subárbol derecho. Estos dos subárboles son bien diferenciados. (Fig.3) Sean dos árboles binarios: Subárbol izquierdo: tiene una raíz A y una hoja B. Subárbol derecho: tiene una raíz A y una hoja B

(a)

(b) Figura 4. a) Subárbol izquierdo, b) Subárbol derecho.

Estos dos subárboles binarios son diferentes, mientras que es cualquier árbol serán idénticos.

10

1.1.5 NOTACION POLONESA. Como ejemplo de aplicación de los métodos considerados, evaluaremos la expresión algebraica. (

)

Que se encuentra representada por el árbol de la figura 5. El primer árbol está construido de la siguiente forma: Cada operador binario (+, -, *, /,..) constituye una raíz de un árbol. Cada operador (1n,..) constituye la raíz de un árbol cuya rama es el operando. Las constantes y las variables forman las hojas del árbol. Si se recorre el árbol, se obtendrá las listas de los nudos en el orden siguiente: x

Si se recorre el sentido contrario obtendremos la lista de los nudos en el orden siguiente: √

/

+

11

+

*

/

6

tg

√⬚

*

X

3

X

Figura 5. Ejemplo de notación polonesa.

1.2 ACCIONES SEMÁNTICAS DE UN ANALIZADOR Dependiendo del tipo de sentencias, las acciones semánticas pueden agruparse en:  Sentencias de declaración: completar la sección de tipos de la tabla de símbolos.  Sentencias “ejecutables”: realizar comprobaciones de tipos entre los operandos.  Funciones y procedimientos: comprobar el número, orden y tipo de los parámetros actuales en cada llamada a una función o procedimiento.

12

 Identificación de variables: comprobar si un identificador ha sido declarado antes de utilizarlo.  Etiquetas: comprobar si hay etiquetas repetidas y validación.  Constantes: comprobar que no se utilicen en la parte izquierda de una asignación.  Conversiones y equivalencias de tipo: verificación.  Sobrecarga de operadores y funciones: detectar y solventar.

1.3 COMPROBACIONES DE TIPOS EN EXPRESIONES Un aspecto importante del análisis semántico es la comprobación de los tipos de las expresiones. Un lenguaje con comprobación 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 detectaran siempre en tiempo de compilación. Como mínimo, ante un error, un comprobador de tipos debe informar de la naturaleza y posición del error y recuperarse para continuar con la comprobación del resto del programa a analizar. Algunas operaciones en una comprobación de tipos son las siguientes:  Conversión de tipos: a veces es necesario transformar el tipo de una expresión para utilizar correctamente un operador o para pasar de forma adecuada un parámetro a una función.

13

 Coerción: es una conversión de tipos que realiza de forma implícita el propio compilador. Si es el programador el que realiza la conversión se tratará entonces de una conversión explícita.  Sobrecarga

de

la

sobrecarga

se

resuelve

determinando el tipo de cada una de las expresiones intervinientes en la sobrecarga.  Funciones polimórficas: son aquellas que trabajan con argumentos cuyo tipo puede cambiar en distintas llamadas a la función.

1.4 PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO Como podemos entender un analizador sintáctico ascendente utiliza durante el análisis una pila. En esta va guardando datos que le permiten ir haciendo las operaciones de reducción que necesita. Para incorporar acciones semánticas como lo es construir el árbol sintáctico, es necesario incorporar a la pila del analizador sintáctico ascendente otra columna que guarde los atributos de los símbolos que se van analizando

1.4.1 TEORÍA DE COLAS Y PILAS Son estructuras de datos que se utilizan principalmente para simplificar ciertas

operaciones

de

programación

estas

estructuras

pueden

implementarse mediante arrays o listas enlazadas

14

Pila: Una colección de datos a los cuales se les puede acceder mediante un extremo, que se conoce generalmente como tope Las pilas tienen 2 operaciones básicas:  Push (para insertar un elemento).  Pop (para extraer un elemento). Su característica principal es que al extraer se obtiene siempre un último elemento que acaba de insertarse por esta razón por eso se conocen como estructuras de datos lifo gracias a la pila es posible el uso de la recursividad la variable a la que llama al mismo procedimiento en el que esta, habrá que guardarla así como el reto de las variables de la nueva llamada para huella de la recursividad.

1.5 ESQUEMAS DE TRADUCCIÓN Un esquema de traducción es una gramática atribuida en la que hay intercalados en el lado derecho de las reglas de producción, fragmentos de código en un lenguaje de programación, que implementan acciones semánticas. Un ETDS es una Definición Dirigida por Sintaxis (DDS) en que se da un orden en la ejecución de las acciones semánticas. Las acciones semánticas se sitúan a la derecha de los símbolos a lo que se refieren y entre llaves. Esta regla de situar las acciones semánticas después de los símbolos que utilizan da un orden en su ejecución.

15

Una característica fundamental de un ETDS es que la traducción pueda realizarse de una sola pasada. Por lo tanto, un ETDS no permite herencia de los atributos desde la derecha hacia la izquierda. Por todo ello, un ETDS es una Gramática con Atributos por la Izquierda (GAI) en que se insertan acciones semánticas. Los ETDS se utilizan a menudo para convertir un formato de un lenguaje en el formato de otro lenguaje. Si tenemos una gramática y queremos que sea un ETDS, deberemos decidir los atributos necesarios y asignarlos a los símbolos de la gramática. Luego, debemos insertar las acciones semánticas necesarias. En este segundo paso debemos tener en cuenta que se deben cumplir las restricciones de un ETDS, es decir: a) Si todos los atributos son sintetizados, pondremos las acciones semánticas después de los atributos implicados. Lo mejor es situarlas al final de la regla de producción. Para cada atributo sintetizado, siempre hay que calcularlo después de que hayan tomado valor todos los demás atributos que intervienen en el cálculo. b) Si hay atributos heredados: 

Un atributo heredado A.h debe calcularse antes de que aparezca el símbolo A.

16

Un atributo sintetizado A.s no debe usarse antes de que aparezca el símbolo A.

c) Una acción semántica no debe referirse a un atributo sintetizado de un símbolo que esté a la derecha de la acción.

1.6 GENERACIÓN DE LA TABLA DE SÍMBOLOS Y DE DIRECCIONES Las tablas de símbolos (también llamadas tablas de identificadores y tablas de nombres), realizan dos importantes funciones en el proceso de traducción: verificar que la semántica sea correcta y ayudar en la generación apropiada de código. Ambas funciones se realizan insertando o recuperando desde la tabla de símbolos los atributos de las variables usadas en el programa fuente. Estos atributos, tales como: el nombre, tipo, dirección de almacenamiento y dimensión de una variable, usualmente se encuentran explícitamente en las declaraciones o más implícitamente a través del contexto en que aparecen los nombres de variables en el programa. Una de las estructuras de datos que se encuentran relacionadas con las fases del proceso de compilación es la tabla de símbolos, la cual tiene como propósito registrar información que se comparte entre varias etapas y que permite administrar los recursos asociados a las entidades que manipulará el programa. La tabla de símbolos tiene típicamente la siguiente estructura:

17

Figura 6. Estructura típica de una tabla de símbolos. En donde vemos la designación de la entidad y su token -derivados del análisis de léxico- así como una serie de atributos (tipo de dato, dirección en memoria) que emanan de otras fases (análisis gramatical y semántico). Las consultas a la tabla de símbolos se realizan por medio del lexema con que se designa a la entidad. Esta concepción de la tabla de símbolos es demasiado simple para fines prácticos si consideramos que el lexema de la entidad es de longitud variable y se desea que la estructura sea homogénea. Una solución es considerar que en el campo lexema se tiene un apuntador (que siempre ocupa el mismo espacio) hacia donde se registrarán propiamente los lexemas. Eso evitará el desperdicio de memoria al tener el espacio justo para representar a cada lexema.

18

Figura 7. Representación de direcciones en una tabla de símbolos. La creación de la tabla de símbolos compete inicialmente al analizador de léxico, quien registrará a las entidades (reconocidas bajo el patrón de Identificador) de manera única, por medio del binomio de operaciones Búsqueda-Inserción. En el contexto de un programa las entidades pueden describir propiamente objetos manipulables por el lenguaje (por ejemplo variables, constantes o funciones) o descriptores de acciones (las palabras reservadas); ambas situaciones son reconocidas bajo el mismo patrón de identificador y la tabla de símbolos se emplea para hacer su discriminación.

1.6.1 CONTENIDO DE LA TABLA DE SÍMBOLOS Una tabla de símbolos puede conceptualizarse como una serie de renglones, cada uno de los cuales contiene una lista de valores de atributos que son asociados con una variable en particular. Las clases de los atributos que aparecen en una tabla de símbolos dependen en algún

19

grado de la naturaleza del lenguaje de programación para el cual se escribe el compilador. Por ejemplo, un lenguaje puede ser sin tipos, y por lo tanto el atributo tipo no necesita aparecer en la tabla. Similarmente, la organización de la tabla de símbolos variará dependiendo de las limitaciones de memoria y tiempo de acceso. A continuación se presenta un ejemplo de una tabla de símbolos típica.

Los atributos que se manejan en la tabla anterior y que se describen enseguida, no son estrictamente necesarios para todos los compiladores; sin embargo, cada uno de tales atributos deberá ser considerado para la implementación de un compilador de un compilador en particular.  Nombre de la variable.  Dirección del código objeto.  Tipo.  Valor (o número de parámetros para uno procedimiento).

20

 Número de línea fuente donde fue declarada la variable.  Números de línea fuente donde se hace referencia a la variable.  Liga. Campo cuyos valores sirven para listar las variables en orden alfabético.

1.7 MANEJO DE ERRORES SEMÁNTICOS Los errores que puede detectar el analizador sintáctico son aquellos que violan las reglas de una gramática independiente del contexto. Algunas de las características de un lenguaje de programación no pueden enunciarse con reglas independientes del contexto, ya que dependen de él; por ejemplo, la restricción de que los identificadores deben declararse previamente. Por lo tanto, los principales errores semánticos son:  Identificadores no definidos.  Operadores y operandos incompatibles. La mayoría de los errores semánticos pueden ser detectados mediante la revisión de la tabla de símbolos, suponiendo un tipo que se base en el contexto donde ocurra o un tipo universal que permita al identificador ser un operando de cualquier operador del lenguaje. Al hacerlo, evitamos la producción de un mensaje de error cada vez que se use la variable no definida. Si el tipo de un operando no concuerda con los requisitos de tipo del operador, también es conveniente reemplazar el operando con una variable ficticia de tipo universal.

21

CONCLUSIÓN

22

BIBLIOGRAFÍA Arbones, M., & E.A. (1992). Tecnicas graficas en productica. Barcelona, España: MARCOMBO. Catalán, J. R. (2010). Compiladores. Teoría e implementación. Madrid, España: Alfaomega. Malisani Arbones, E. A. (1992). Tecnicas graficas en productica. Barcelona, España: MARCOMBO. Sánchez Dueñas, G., & Valverde Andreu, J. A. (1990). Compiladores e interpretes. Un enfoque pragmatico. Madrid: Díaz de Santos. V. Aho, A., Sethi, R., & D. Ullman, J. (1990). Compiladores. Principios, técnicas y herramientas. Massachusetts, EUA: Addison Wesley Longman.

23