Pila Semántica en Un Analizador Sintáctico
Short Description
Pila semantica...
Description
TECNOLÓGICO NACIONAL DE MÉXICO INSTITUTO TECNOLÓGICO DE ACAPULCO
INGENIERÍA EN SISTEMAS COMPUTACIONALES
LENGUAJES Y AUTÓMATAS II
INVESTIGACIÓN: PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
PROFESOR: MARIO GIMÉNEZ VÁZQUEZ
ALUMNO: RAÚL AXEL MARISCAL ESCOBAR NO. CONTROL: 12320775
HORA: 7:00 – 8:00 AULA: 712
ACAPULCO, GRO. GRO.
5 - SEPTIEMBRE - 2016 2016
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Índice Definición y descripción ........................................................................................... 2 Características ........................................................................................................ 4 Ventajas .................................................................................................................. 5 Desventajas............................................................................................................. 6 Ejemplos (Como trabaja la pila semántica con las expresiones) ............................. 6 Bibliografía ............................................................................................................ 11
1|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Definición y descripción Las pilas semánticas son estructuras de datos que se utilizan generalmente para simplificar ciertas operaciones de programación. Estas estructuras pueden implementarse mediante arrays o listas enlazadas. También podemos definirlas como una colección de dato s a los cuales se les puede acceder mediante un extremo, que se conoce generalmente como tope. Las pilas semánticas tienen dos operaciones básicas:
Push (para introducir un elemento) Pop (para extraer un elemento)
La pila semántica en un analizador sintáctico juega un papel fundamental en el desarrollo de cualquier analizador semántico. Dentro de cada elemento de la pila se guardan los valores que pueden tener una expresión. Como podemos entender un analizador sintáctico ascendente utiliza durante el análisis una pila semántica. 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.
Bottom up Es un principio de muchos años del estilo de programación utilizado para realizar una pila semántica. Los elementos funcionales de un programa no deben ser demasiado grandes. Si un cierto componente de un programa crece más allá de la etapa donde está fácilmente comprensible, se convierte en una masa de la complejidad que encubre errores tan fácilmente como una ciudad grande encubre a fugitivos. 2|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Top-down Este método consiste en dividir los problemas en subproblemas más sencillos para conseguir una solución más rápida. El diseño descendente es un método para resolver el problema que posteriormente se traducirá a un lenguaje comprensible por la computadora.
class TPila { public: TPila( ); TPila( TPila & ); ~TPila( ); TPila& operator=( TPila &); TItem& Cima( ); void Apilar( TItem& ); . . . private: struct TNodo { TItem dato; TNodo *sig; }; TNodo *fp; }; TPila::TPila( ) { fp = NULL; } void TPila::Desapilar( ) { TNodo *aux; aux = fp; fp = fp -> sig; delete aux;
Ejemplo de implementacion en codigo C++ de una pila semantica.
Reglas semánticas Son el conjunto de normas y especificaciones que definen al lenguaje de programación y están dadas por la sintaxis del lenguaje, las reglas semánticas asignan un significado lógico a ciertas expresiones definidas en la sintaxis del lenguaje. La evaluación de las reglas semánticas define los valores de los atributos en los nodos del árbol de análisis sintáctico para la cadena de entrada. Una regla semántica también puede tener efectos colaterales, por ejemplo, imprimir un valor o actualizar una variable global. 3|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Compatibilidad de tipos Durante la fase de análisis semántico, el compilador debe verificar que los tipos y valores asociados a los objetos de un programa se utilizan de acuerdo con la especificación del lenguaje. Además, debe detectar conversiones implícitas de tipos para efectuarlas o insertar el código apropiado para efectuarlas, así como almacenar información relativa a los tipos de los objetos y aplicar las reglas de verificación de tipos.
Características Sus características fundamentales es que al extraer se obtiene siempre el último elemento que acabe de insertarse. Por esta razón también se conoce como estructuras de datos LIFO, una posible implementación mediante listas enlazadas seria insertando y extrayendo siempre por el principio de la lista. Una pila semántica ayuda al compilador a reconocer la estructura de una cadena de componentes léxicos. Al decir pila semántica 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 podemos mezclar código de C++ con Visual Basic. Con el uso de las pilas semánticas es posible construir un árbol de análisis sintáctico, este raramente se construye como tal, sino que las rutinas semánticas integradas van generando el árbol de Sintaxis abstracta. Se especifica mediante una gramática libre de contexto. Para incorporar acciones semánticas como lo es construir el árbol sintáctico, es necesario incorporar a la pila del parser otra columna que guarde los atributos de los símbolos que se van analizando. En general una pila semántica hace posible al analizador sintáctico: Acceder a la tabla de símbolos (para hacer parte del trabajo del analizador semántico).
Chequeo de tipos (del analizador semántico). Generar código intermedio. Generar errores cuando se producen. 4|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
En definitiva, realiza casi todas las operaciones de la compilación. Este método de trabajo da lugar a los métodos de compilación dirigidos por sintaxis.
Ventajas Al utilizar una pila semántica en un analizador sintáctico podemos obtener los siguientes beneficios:
Detecta la validez semántica de las sentencias aceptadas por el analizador sintáctico. El analizador semántico suele trabajar simultáneamente al analizador sintáctico y en estrecha cooperación. Se entiende por semántica como el conjunto de reglas que especifican el significado de cualquier sentencia sintácticamente correcta y escrita en un determinado lenguaje. Las rutinas semánticas deben realizar la evaluación de los atributos de las gramáticas siguiendo las reglas semánticas asociadas a cada p roducción de la gramática. Permite agilizar la fase del análisis sintáctico en la que se trata de determinar el tipo de los resultados intermedios, comprobar que los argumentos que tiene un operador pertenecen al conjunto de los operad ores posibles, y si son compatibles entre sí, etc. El análisis semántico utiliza como entrada el árbol sintáctico detectado por el análisis sintáctico para comprobar restricciones de tipo y otras limitaciones semánticas y preparar la generación de código. Las rutinas semánticas suelen hacer uso de una pila que contiene la información semántica asociada a los operadores en forma de registros semánticos. Permiten guardar el estado de las variables o tokens en el momento en que se hace la llamada, para seguir ocupándolas al regresar del analizador. Su implementación suele ser relativamente fácil.
5|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Desventajas
Los problemas de integración entre los subsistemas son sumamente costosos y muchos de ellos no se solucionan hasta que la programación alcanza la fecha límite para la integración total del sistema. Se necesita una memoria auxiliar que nos permita guardar los datos para poder hacer la comparación. Un grave error que puede ocurrir es tratar de eliminar un elemento de una pila semántica vacía. Este tipo de error se le conoce como subdesbordamiento (underflow ) y puede ocasionar que el analizador sintáctico se detenga repentinamente y con ello se aborte este proceso. El tamaño de la pila puede ser un problema, en caso de que esta crezca hasta tal punto de sobrepasar la memoria disponible. A veces un error provoca una avalancha de muchos errores que se solucionan con el primero.
Ejemplos (Como trabaja la pila semántica con las expresiones) 1. Sea la gramática simplificada que analiza las instrucciones de asignación: ::= id #PId := #RAs ::= + #RS | ::= id #PId | Ct #PCt
Se observará que hemos hecho uso de cuatro símbolos de acción:
#PId: PUSH a la pila semántica el registro asociado al identificador. #PCt: PUSH a la pila semántica el registro asociado a la constante. #RS: Realizar suma: POP los dos registros superiores de la pila; comprobar que es posible sumarlos; realizar la suma (mediante una llamada al generador de código) o generar representación intermedia (si es una compilación en dos o más pasos); PUSH registro semántico del resultado en la pila semántica. #RAs: Realizar asignación: POP los dos registros superiores de la pila; comprobar que es posible realizar la asignación; realizarla (mediante una 6|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
llamada al generador de código) o generar representación intermedia (si es una compilación en dos o más pasos). En los analizadores sintácticos top-down basados en gramáticas LL(1), la introducción de los símbolos de acción en las rutinas correspondientes es trivial. En los analizadores bottom-up basados en gramáticas SLR(1) es más delicado, pues los estados del análisis se mueven simultáneamente sobre varias reglas. Sólo en el momento de realizar una reducción sabemos exactamente dónde estamos. Por ello, se suele introducir la restricción de que los símbolos de acción deben estar situados únicamente al final de una regla. Cuando no se cumple esto (como en el ejemplo anterior) es trivial conseguirlo, introduciendo símbolos no terminales adicionales.
::= ::= ::= ::=
:= #RAs id #PId + #RS | id #PId | Ct #PCt
Poner un ejemplo del análisis sintáctico-semántico bottom-up de la instrucción A := B + 1. Otro ejemplo: instrucciones condicionales con las reglas ::= If #S2 then #S1 | If #S2 then else #S3 #S1 ::= If then #S1 | If then #S1 ::= #S2 ::= else #S3
2. Sea la expresión int a,b,c; a/(b+c^2)
El árbol sintáctico es: / --------| | a + --------| | b ^ --------| | c 2
7|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
De la instrucción declarativa, la tabla de símbolos y el analizador morfológico obtenemos los atributos de los operandos: / --------| | a + int --------| | b ^ int --------| | c 2 int int
Propagando los atributos obtenemos: / int --------| | a + int int --------| | b ^ int int --------| | c 2 int int
Si la expresión hubiera sido a/(b+c^-2)
El árbol sintáctico sería el mismo, sustituyendo 2 por -2. Sin embargo, la propagación de atributos sería diferente: / real --------| | a + real int --------| | b ^ real int --------| | c -2 int int
En algún caso podría llegar a producirse error (p.e. si / representara sólo la división entera).
8|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Si la expresión hubiera sido int a,b,c,d; a/(b+c^d)
El árbol sintáctico sería el mismo, sustituyendo 2 por d. Sin embargo, la propagación de atributos sería incompleta: / {int,real} --------| | a + {int,real} int --------| | b ^ {int,real} int --------| | c d int int
El analizador semántico podría reducir los tipos inseguros al tipo máximo (real) o utilizar un tipo interno nuevo (ej. arit={int,real}, una unión). Lo anterior es un ejemplo de propagación bottom-up. La propagación top-down también es posible: lo que se transmite son las restricciones y los tipos de las hojas sirven de comprobación. Por ejemplo, si la división sólo puede ser entera, transmitimos hacia abajo la restricción de que sus operandos sólo pueden ser enteros. La implantación de todos los casos posibles de operación con tipos mixtos podría ser excesivamente cara. En su lugar, se parte de operaciones relativamente simples (ej. int+int, real+real) y no se implementan las restantes (ej. int+real, real+int), añadiendo en su lugar operaciones monádicas de cambio de tipo (ej. int->real). Esta decisión puede introducir ambigüedades. Por ejemplo, sea el programa real a; int b,c; a:=b+c
9|Página
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Existen dos conversiones posibles: := real --------| | a + real real --------| | b c int int
:= real --------| | a + int real --------| | b c int int
El problema es que no tenemos garantía de que los dos procedimientos sean equivalentes. El segundo puede dar overflow de la pila, el primero pérdida de precisión. La definición del lenguaje debe especificar estos casos. Las transformaciones posibles se pueden representar mediante un grafo cuyos nodos son los tipos de datos y cada arco indica una transformación. Dado un operando de tipo A que se desea convertir al tipo B, se trata de encontrar una cadena de arcos que pase de A a B en el grafo anterior. Podría haber varios grafos, cada uno de los cuales se aplicará en diferentes condiciones, por ejemplo, uno para las asignaciones, otro para las expresiones, etc.
3. Con la producción A!i:=E, se asocia una acción de agregar el valor de E a i.
10 | P á g i n a
PILA SEMÁNTICA EN UN ANALIZADOR SINTÁCTICO
Bibliografía 1. Alfred V. Aho, J. D. (2000). Compiladores Principios, tecnicas y herramientas. Mexico: Addison Wesley. 2. Alfred V. Aho, M. S. (2008). Compiladores: principios, técnicas y herramientas. Mexico: Pearson Adisson Wesley. 3. N., E. W. (2006). Compiler Construction. New York: Addison Wesley. 4. Terry, P. (1997). Compilers and Compiler Generators: an introduction with C++. Boston: International Thomson Computer Press.
11 | P á g i n a
View more...
Comments