Investigacion 1.4 pila semantica en un analizador sintactico 1.5 esquema de traduccion 1.6 generacion de la tabla de simbolo y tabla de direcciones
1.4 Pila semántica en un analizador sintáctico
Las pilas y colas son estructuras de datos que se utilizan generalmente para simplificar ciertas operaciones de programación. Estas estructuras pueden implementarse mediante arrays o listas enlazadas. Pila: colección de datos a los cuales se les puede acceder mediante un extremo, que se conoce generalmente como tope. Las pilas tienen dos operaciones básicas:
· Push (para introducir un elemento)
· Pop (para extraer un elemento) 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. Las pilas se utilizan en muchas aplicaciones que utilizamos con frecuencia. Las pilas y colas son estructuras de datos que se utilizan generalmente para simplificar ciertas operaciones de programación. Estas estructuras pueden implementarse mediante arrays o listas enlazadas. Un analizador sintáctico es un autómata de pila que reconoce la estructura de una cadena de componentes léxicos. En general, el analizador sintáctico inicializa el compilador y para cada símbolo de entrada llama al analizador morfológico y proporciona el siguiente símbolo de entrada. 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.
Ventajas
· 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. Objetivo teórico Es 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. El
análisis semántico 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 producción
de la gramática. El análisis sintáctico es la fase 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 operadores posibles, y si
son compatibles entre sí, etc. En definitiva, comprobará que el significado de
la que se va leyendo es válido. La salida teórica de la fase de análisis
semántico sería un árbol semántico. Consiste en un árbol sintáctico en el que
cada una de sus ramas ha adquirido el significado que debe tener. Se compone de
un conjunto de rutinas independientes, llamadas por los analizadores
morfológico y sintáctico. 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. 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. 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. Analizadores descendentes: Parten
del axioma inicial de la gramática, se va descendiendo utilizando las
derivaciones izquierdas, hasta llegar a construir la cadena analizada. Se va
construyendo el árbol desde sus nodos terminales. Es decir, se construye desde
los símbolos de cadena hasta llegar al axioma de la gramática. Bottom up Es un
principio de muchos años del estilo de programación que 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. 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 compresible por la
computadora. Un parser 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 parser otra columna que
guarde los atributos de los símbolos que se van analizando. Estos atributos
estarían ligados a la correspondiente producción en la tabla de parsing. La
pila 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.
1.5 Esquema de traducción
Un esquema de traducción es una gramática independiente de contexto en la que se asocian atributos con los símbolos gramaticales y se insertan acciones semánticas encerradas entre llaves { } dentro de los lados derechos de las producciones. Los esquemas de traducción pueden tener tantos atributos sintetizados como heredados. Cuando se diseña un esquema de traducción, se deben respetar algunas limitaciones para asegurarse de que el valor de un atributo esté disponible cuando una acción se refiera a él. Estas limitaciones, motivadas por las definiciones con atributos por la izquierda, garantizan que las acciones no hagan referencia a un atributo que aún no haya sido calculado. El ejemplo más sencillo ocurre cuando sólo se necesitan atributos sintetizados, en este caso, se puede construir el esquema de traducción creando una acción que conste de una asignación para cada regla semántica y colocando esta acción al final del lado derecho de la producción asociada. Traducción descendente Se trabaja con esquema de traducción en lugar de hacerlo con definiciones dirigidas por sintaxis, así que se puede ser explícito en cuanto al orden en que tienen que lugar las acciones y las evaluaciones de los atributos. Eliminacion de la recursividad izquierda de un esquema de traducción Como la mayoría de los operadores aritméticos son asociativos por la izquierda, es natural utilizar gramáticas recursivas por la izquierda para las expresiones. La transformación se aplica a esquemas de traducción con atributos sintetizados. Para el análisis sintáctico descendente, se supone que una acción se ejecuta en el mismo momento en que se expandiría un símbolo en la misma posición. Un atributo heredado de un símbolo debe ser calculado por una acción que aparezca antes que el símbolo, y un atributo sintetizado del no terminal de la izquierda se debe calcular después de que hayan sido calculados todos los atributos de los que depende. Un atributo heredado de un símbolo debe ser calculado por una acción que aparezca antes que el símbolo, y un atributo sintetizado del no terminal de la izquierda se debe calcular después de que hayan sido calculados todos los atributos de los que depende. Los fragmentos de código así insertados se denominan acciones semánticas. Dichos fragmentos actúan, calculan y modifican los atributos asociados con los nodos del árbol sintáctico. El orden en que se evalúan los fragmentos es el de un recorrido primero-profundo del árbol de análisis sintáctico. Obsérvese que, en general, para poder aplicar un esquema de traducción hay que construir el árbol sintáctico y después aplicar las acciones empotradas en las reglas en el orden de recorrido primero-profundo. Por supuesto, si la gramática es ambigua una frase podría tener dos árboles y la ejecución de las acciones para ellos podría dar lugar a diferentes resultados. Si se quiere evitar la multiplicidad de resultados (interpretaciones semánticas) es necesario precisar de qué árbol sintáctico concreto se está hablando.
1.6 Generación de la tabla de símbolo 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: 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 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.
Comentarios
Publicar un comentario