Automatas Semantico
Automatas Semantico
Automatas Semantico
INGENIERIA DE SISTEMAS
ANALIZADOR SEMANTICO
DOCENTE:
CURSO:
Autómatas y Compiladores
ALUMNOS:
GUADALUPE – LA LIBERTAD
2019
ANALIZADOR SEMANTICO
1
ÍNDICE
INTRODUCCIÓN ..................................................................................................................... 5
Etiquetas: ........................................................................................................................ 10
Constantes:...................................................................................................................... 10
2
Conversión de tipos explícita: ........................................................................................ 15
Vectores (arrays)............................................................................................................. 17
Punteros .......................................................................................................................... 17
Funciones ........................................................................................................................ 17
Clases: ............................................................................................................................. 18
atributos .......................................................................................................................... 19
Gramáticas S-Atribuidas................................................................................................. 23
3
MANEJO DE ERRORES SEMÁNTICOS ............................................................................. 24
RECUPERACION DE ERRORES.......................................................................................... 24
CONCLUSIONES ................................................................................................................... 25
BIBLIOGRAFÍA ..................................................................................................................... 26
4
INTRODUCCIÓN
Los programas que se compilan no son solamente cadenas de símbolos sin significado
alguno que pueden ser aceptadas como correctas o no por una máquina abstracta. El lenguaje
no es más que el vehículo por el cual se intenta transmitir una serie de instrucciones a un
procesador para que éste las ejecute produciendo unos resultados. Por ello, la tarea del
compilador requiere la extracción del contenido semántico incluido en las distintas sentencias
del programa.
Por esto, se hace necesario dotar al compilador de una serie de rutinas auxiliares que
permitan captar todo aquello que no se ha expresado mediante la sintaxis del lenguaje y todo
aquello que hace descender a nuestro lenguaje de programación de las alturas de una máquina
abstracta hasta el nivel de un computador real. A todas estas rutinas auxiliares se les denomina
genéricamente análisis semántico.
5
EL ANÁLISIS SEMÁNTICO
Se trata de determinar el tipo de los resultados intermedios, comprobar que los argumentos que
tiene un operador pertenecen al conjunto de los operadores posibles, y si son compatibles entre
sí, etc. En definitiva, comprobará que el significado de lo que se va leyendo es válido.
También en el análisis semántico se detectan errores relacionados con la validez del programa.
Se puede decir que estos errores son de tipo sintáctico-semántico, pero no pueden ser
detectados por el analizador sintáctico, ya que se relacionan con interdependencias entre las
diferentes partes de un programa que no son reflejadas en un análisis gramatical. El analizador
semántico recibe la información resultado del análisis sintáctico que puede ser un árbol
jerárquico con la información relativa a la organización de los tokens en la instrucción que se
está analizando.
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.
El análisis semántico, a diferencia de otras fases, no se realiza claramente diferenciado del resto
de las tareas que lleva a cabo el compilador, más bien podría decirse que el análisis semántico
completa las dos fases anteriores de análisis léxico y sintáctico incorporando ciertas
comprobaciones que no pueden asimilarse el reconocimiento de una cadena dentro de un
lenguaje.
6
ÁRBOL SEMÁNTICO
Es una estructura jerárquica en la cual se registran las operaciones que implica u opera dentro
del programa fuente, en cada una de las ramas del árbol se registra el valor o significado que
este debe tener y el análisis analiza cuál de los valores registrado en las ramas es aplicable.
Los árboles de expresiones representan el código de nivel del lenguaje en forma de datos. Los
datos se almacenan en una estructura con forma de árbol. Cada nodo del árbol de expresión
representa una expresión.
En los árboles de expresión, la sucesión del preorden de etiquetas nos da lo que se conoce como
la forma prefijo de una expresión.
7
Análogamente, la sucesión postorden de las etiquetas de un árbol expresión nos da lo que se
conoce como la representación postfija de una expresión
FUNCIONES PRINCIPALES
Lenguaje natural
Especificación formal: Semántica Operacional, semántica denotacional, semántica
Axiomática, Gramáticas con Atributos.
8
RECORRIDOS EN ÁRBOLES
Recorrido en Preorden:
En este tipo de recorrido se realiza cierta acción (quizás simplemente imprimir por pantalla el
valor de la clave de ese nodo) sobre el nodo actual y posteriormente se trata el hijo izquierdo y
cuando se haya concluido, el hijo derecho.
Recorrido en Postorden:
En este caso se trata primero el hijo izquierdo, después el derecho y por último el nodo actual.
Recorrido en Inorden:
En este caso se trata primero el hijo izquierdo, después el nodo actual y por último el hijo
derecho.
En este caso el recorrido se realiza en orden por los distintos niveles del árbol. Así, se
comenzaría tratando el nivel 1, que sólo contiene el nodo raíz, seguidamente el nivel 2, el 3 y
así sucesivamente.
En los árboles de expresión, la sucesión del preorden de etiquetas nos da lo que se conoce como
la forma prefija de una expresión.
9
ACCIONES SEMÁNTICAS
Dependiendo del tipo de sentencias, las acciones semánticas pueden agruparse en:
Sentencias de Declaración:
Sentencias ejecutables:
Funciones y procedimientos:
Comprobar el número, orden y tipo de los parámetros actuales en cada llamada a una función
o procedimiento.
Identificación de variables:
Etiquetas:
Constantes:
10
PILA SEMÁNTICA
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.
La estructura que puede realizar estas operaciones de manera eficiente es la tabla hash. La
implementación habitual es una tabla que asocia cada identificador a información tal como su
naturaleza (constante, variable, nombre de función, etc.), su tipo (entero, real, booleano, etc.),
su valor (en el caso de constantes), su dirección (en el caso de variables y funciones), etc.
Es importante tener únicamente una tabla; si tenemos varias, por ejemplo, una para constantes
y otra para variables, el acceso se hace más difícil ya que para comprobar las propiedades de
un identificador hay que hacer varias consultas en lugar de una.
11
Una cuestión importante es cómo se relacionan la tabla y el AST. Tenemos distintas
posibilidades, que explicaremos sobre el siguiente ´árbol, correspondiente a la sentencia a=
a+c:
La primera posibilidad es dejar el árbol tal cual, y cada vez que necesitemos alguna
información, por ejemplo, el valor de a, consultar la tabla. Esta opción sería la más adecuada
para situaciones en las que se vaya a recorrer el árbol pocas veces, por ejemplo, en una
calculadora donde se evalúe cada expresión una sola vez. Otra posibilidad es ir decorando cada
una de las hojas con toda la información que se vaya recopilando. Por ejemplo, si durante el
análisis averiguamos el tipo y dirección de las variables, pasaríamos a almacenar la nueva
información:
Esto tiene costes muy elevados en tiempo —tendremos que actualizar repetidamente un
número de nodos que puede ser elevado— y espacio —hay mucha información que se
almacena repetida—. Podemos reducir estos costes guardando en cada nodo un puntero a la
entrada correspondiente en la tabla:
12
Finalmente, la opción más adecuada cuando tenemos lenguajes que presenten ámbitos anidados
(veremos en otro tema cómo representar los ámbitos en la tabla) es guardar la información
sobre los objetos en otra estructura de datos a la que apunta tanto la tabla como los nodos del
árbol:
13
VERIFICACIÓN DE TIPOS DE EXPRESIONES
Funciones Principales:
Reglas de un lenguaje que permiten asignar tipos a las distintas partes de un programa
y verificar su corrección.
Inferencia de tipos: calcular y mantener la información sobre los tipos de datos.
Verificación de tipo: asegurar que las partes de un programa tienen sentido según las
reglas de tipo del lenguaje.
Comprobación de tipos:
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 detectarán 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.
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.
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.
14
Funciones polimórficas: Son aquellas que trabajan con argumentos cuyo tipo puede
cambiaren distintas llamadas a la función.
Conversión de tipos
Hay situaciones en las cuales se tiene un valor de un tipo dado y se desea almacenar ese valor
en una variable de un tipo diferente.
Durante la compilación (comprobación estática) detecta todos los posibles errores de tipo.
En la práctica, ningún lenguaje es tan fuertemente tipado que permita una completa
comprobación estática.
15
Información de tipos dinámica: El compilador debe generar código que realice la
inferencia y verificación de tipos durante la ejecución del programa que se está compilando.
Todos los lenguajes permiten crear nuevos tipos complejos a partir de otros más simples
mediante constructores de tipos:
Para analizar los diferentes tipos que intervienen dentro de un programa, el compilador debe
contar con una estructura interna que le permita manejar cómodamente las expresiones de tipos.
La forma más habitual de representación son los grafos acíclicos dirigidos (GADs).
16
EXPRESIÓN DE TIPO
Vectores (arrays)
Punteros
Funciones
Una variable de tipo función denota una transformación de elementos de un tipo, a elementos
de otro tipo. En los lenguajes funcionales, las funciones son elementos de primera categoría,
entendiendo que pueden ser pasados y devueltos como parámetros de otras funciones, o
17
aparecer incluso ubicados en cualquier estructura de datos. En determinados lenguajes
imperativos, esta facilidad aparece gracias a los punteros a funciones. De este modo, es factible
poseer variables de tipo (puntero a) función. Será por tanto necesario representar dicha
expresión de tipo al procesar estos lenguajes. La operación principal a aplicar sobre una función
es requerir la transformación que denota, es decir, invocarla.
Clases: Las clases denotan un tipo de objetos que posee una estructura y comportamiento
común. La mayoría de los lenguajes orientados a objetos poseen el concepto de clase para
indicar un tipo de objeto. A la hora de representar este tipo por parte de un procesador de
lenguaje, es necesario tener en cuenta un conjunto de características propias de los modelos
computacionales orientados a objetos. Centrándonos en el análisis semántico, las
características principales a tener en cuenta a la hora de representar.
SISTEMA DE TIPOS
Un sistema de tipos es un conjunto de reglas para asignar expresiones de tipos a las distintas
construcciones de un lenguaje. Para ello, un sistema de tipos deberá definir sus expresiones de
tipos, asignar éstas a las distintas construcciones sintácticas del lenguaje, y comprobar que las
reglas semánticas de los tipos del lenguaje se cumplan ante cualquier programa de entrada. Si
no fuere así, generará un error de tipo (type clash), continuando el procesamiento del programa
o finalizando, en función del tipo del mecanismo de manejo de errores que implemente
COMPROBADOR DE TIPOS
Una vez el sistema de tipos infiera el tipo de cada expresión, el comprobador de tipos, en la
producción expresiones, verificará si el tipo inferido es error. En ese caso, mostrará por la salida
estándar de error el número de línea y el mensaje de error, y seguirá llevando a cabo el análisis
del código fuente. Uno de los beneficios de emplear esta expresión de tipo especial (error) es
18
que, de un modo sencillo, se puede implementar un procesador de lenguaje capaz de
recuperarse ante los errores de tipo.
En el caso de que el tipo inferido en cada expresión sea correcto, a modo de ejemplo se muestra
el número de línea, la expresión de tipo de tipo inferida, y el número de bytes que el generador
de código emplearía para albergar en memoria el valor de la expresión. Los métodos
expresionTipo y getBytes son implementados por cada tipo específico de un modo recursivo,
haciendo uso de la estructura del patrón Composite.
atributos
Ejemplos de atributos:
Una gramática de atributos es una gramática independiente del contexto en la cual a sus
símbolos terminales y no terminales se les dota de unos atributos y a sus producciones de unas
funciones de evaluación que hacen que dichos atributos se propaguen a través de la gramática.
Su fin es conocer un determinado valor de un atributo en cualquier parte del árbol de derivación
y tomar la decisión oportuna.
Un atributo es una propiedad asociada a una estructura sintáctica. Si una estructura sintáctica
representada por el símbolo gramatical X tiene asociado un atributo a lo representaremos por
𝑥𝑎 (Nombre símbolo. Nombre atributo)
19
Gramáticas Atribuidas
Las gramáticas atribuidas fueron definidas originalmente por Knuth. como un método para
describir la semántica de un lenguaje de programación. Una gramática atribuida (GA) es una
tripleta GA= {G, A, R}, donde:
las reglas semánticas establecen relaciones entre los valores de los atributos de una gramática
atribuida, expresadas mediante una función matemática. Desde el punto de vista más estricto
de definición de gramática atribuida, las reglas semánticas únicamente pueden recibir como
parámetros otros atributos de la gramática (no están permitidas las constantes, variables o
llamadas a funciones que generen efectos colaterales) y devolver, sin generar un efecto
colateral, un único valor que será asignado a otro atributo de la producción actual.
20
Los atributos heredados se calculan “descendentemente” en el árbol sintáctico. se
asigna un valor a un atributo del nodo hijo 𝑥2 para que, en aquellas reglas en las que
éste aparezca en la parte izquierda de la producción, herede el valor asignado.
Como hemos visto, las gramáticas atribuidas ofrecen un modo de decorar o anotar un árbol
sintáctico (concreto o abstracto) de un modo declarativo, sin identificar explícitamente el modo
en el que deban ejecutarse las reglas semánticas –en el caso de que realmente se puedan
ejecutar. En función de las propiedades que cumpla una gramática atribuida, podremos decir si
se puede evaluar cualquier árbol asociado a un programa de entrada e incluso podremos
determinar un orden específico de ejecución de las reglas semánticas.
Los atributos calculados en una producción p de la gramática libre de contexto asociada a una
gramática atribuida son los que cumplan la siguiente condición:
Los atributos calculados asociados a una producción son, pues, aquéllos cuyo valor es
calculado en una regla semántica asociada a dicha producción.
21
Gramática Atribuida Completa
Una gramática es bien si para todas las sentencias del lenguaje generado por su gramática libre
de contexto, es posible calcular los valores de los atributos de todos sus símbolos gramaticales.
Este proceso decoración o anotación del árbol sintáctico ante un programa de entrada se
denomina evaluación de la gramática. Para que una gramática sea bien definida (no circular),
deberá ser posible encontrar un modo de calcular la gramática ante cualquier programa de
entrada. Esto implica saber en qué orden se han de ejecutar las reglas semánticas ante cualquier
programa, para poder evaluar la gramática. Así, una gramática es completa si asigna
correctamente valores a sus atributos y será bien definida si, además, es posible encontrar un
orden de ejecución de sus reglas semánticas ante cualquier programa de entrada. Por lo tanto,
toda gramática atribuida bien definida es completa.
22
Gramáticas S-Atribuidas
Una gramática es S-atribuida si todos sus atributos son sintetizados. Esta característica
específica de determinadas gramáticas atribuidas es empleado para preestablecer un orden de
ejecución de sus rutinas semánticas.
Gramáticas L-Atribuidas
para que una gramática sea L-atribuida, los atributos heredados de la parte derecha de toda
producción han de calcularse en función de los heredados del no terminal de la izquierda y/o
en función de los atributos de los símbolos gramaticales de la parte derecha de la producción,
ubicados a su izquierda. En el caso de que la condición se satisfaga para una definición dirigida
por sintaxis, se dice que ésta es con atributos por la izquierda.
Grafo de Dependencias
Para calcular el valor de un atributo es necesario calcular en primer lugar los valores de los
atributos de los que depende, para lo cual se deberá establecer una dependencia entre atributos
mediante un Grafo de Dependencias.
Ejemplo: Analizar la forma sentencial real id1, id2, id3 a partir de la siguiente definición
dirigida por la sintaxis:
23
MANEJO DE ERRORES SEMÁNTICOS
Es una de las misiones más importantes del compilador. Se utiliza más en el análisis, pero los
errores pueden darse en cualquier fase. El manejo de errores es una tarea difícil.
RECUPERACION DE ERRORES
24
CONCLUSIONES
El analizador semántico es una parte fundamental del proceso que tiene un autómata. Este se
diferencia de un analizador sintáctico porque no solo busca que las palabras estén bien escritas,
sino que tenga un significado dentro de un compilador.
El analizador semántico tiene la tarea La implantación de todos los casos posibles de operación
con tipos de datos.
25
BIBLIOGRAFÍA
1. Moguel. Analisis Semantico. Analisis Semantico. [En línea] 20 de Enero de 2016. [Citado
el: 14 de junio de 2019.] http://analisissemantico.blogspot.mx/.
2. Atom. Gramaticas. Analisis Semantico. [En línea] 2 de Abril de 2014. [Citado el: 14 de Junio
de 2019.] https://www.gramaticas.net/2012/05/ejemplos-de-analisis-semantico.html.
3. Marquez. Lenguajes y automatas II. Analisis. [En línea] 17 de Octubre de 2013. [Citado el:
14 de Junio de 2019.] http://elvismqz4.blogspot.com/2013/10/analisis-semantico.html.
4. Hopcroft, John E., Motwani, Rajeev y Ullman, Jeffrey D. Teoris de Automatas Lenguajes
y computacion. Tercera Edicion. Madrid : Pearson Educación, 2007. pág. 458.
ISBN:9788478290888.
26