Capítulo 4: Algoritmos usados por el Generador de Analizadores Sintácticos

Documentos relacionados
Analizadores sintácticos LR(0) y SLR

Analizador Sintáctico Ascendente

Tema 5. Análisis sintáctico ascendente

ANÁLISIS SINTÁCTICO II SLR

Compiladores: Análisis Sintáctico. Pontificia Universidad Javeriana Cali Ingenieria de Sistemas y Computación Prof. Gloria Inés Alvarez V.

Capítulo 1: Presentación del Trabajo

ANÁLISIS SINTÁCTICO II LR1

Capítulo 3: Algoritmos Usados por el Generador de Autómatas Finitos Determinísticos

UNIVERSIDAD NACIONAL DE EDUCACIÓN A DISTANCIA Escuela Técnica Superior de Ingeniería Informática Procesadores de Lenguajes. Tema 4

Compiladores: Análisis Sintáctico. Pontificia Universidad Javeriana Cali Ingenieria de Sistemas y Computación Prof. Gloria Inés Alvarez V.

Tema 4: Análisis sintáctico ascendente. Análisis sintáctico ascendente: un ejemplo

ANÁLISIS SINTÁCTICO I ANÁLISIS SINTÁCTICO DESCENDENTE LL(1)

22, 23 y 24 Análisis sintáctico V Compiladores - Profr. Edgardo Adrián Franco Martínez

Controla el flujo de tokens reconocidos por parte del analizador léxico. 4.2 Introduccion a las gramaticas libres de contexto y arboles de derivacion

Universidad Nacional del Santa Facultad de Ingeniería E.A.P. de Ingeniería de Sistemas e Informática TEORIA DE COMPILADORES ANALISIS SINTACTICO

LR(1) - LALR. Alejandro Grinberg. 30 de Octubre de (agradecimiento a Juan Manuel Pérez) Alejandro Grinberg () LR(1) - LALR 1 / 16

Procesadores de Lenguaje

Tema 4: Gramáticas independientes del contexto. Teoría de autómatas y lenguajes formales I

Ciencias de la Computación I

MODELOS DE COMPUTACION I Preguntas Tipo Test. 1. El lema de bombeo puede usarse para demostrar que un lenguaje determinado es regular.

Lenguajes y Compiladores Aspectos Formales (Parte 1) Compiladores

Procesadores de lenguaje Tema Análisis sintáctico (Parte II)

Procesadores de lenguaje

Procesadores de Lenguaje

Tema: Análisis Sintáctico LR

ANÁLISIS SINTÁCTICO II LALR

Procesadores de Lenguajes. Análisis sintáctico. Analizadores descendentes

PROCESADORES DE LENGUAJE EXAMEN FINAL 8-JUNIO-07

GRAMATICAS LIBRES DEL CONTEXTO

5 Autómatas de pila 5.1 Descripción informal. 5.2 Definiciones

La Forma Normal de Chomsky

Departamento de Tecnologías de la Información. Tema 4. Máquinas de Turing. Ciencias de la Computación e Inteligencia Artificial

16 Análisis sintáctico I

Gramáticas tipo 0 o Estructura de frase En este tipo de gramáticas no hay restricción en su producciones y tienen la forma siguiente.

Procesadores de Lenguaje

Construcción de tablas de análisis sintáctico LL(1)

ANÁLISIS SINTÁCTICO I ANALIZADORES SINTÁCTICOS

4 o Ingeniería Informática

Convertir un AFND a un AFD

ANÁLISIS SINTÁCTICO. Comprobar que la secuencia de componentes léxicos cumple las reglas de la gramática Generar el árbol sintáctico

AUTÓMATAS DE PILA Y LENGUAJES INDEPENDIENTES DEL CONTEXTO

LENGUAJES Y GRAMÁTICAS

GRAMÁTICAS LIBRES DE CONTEXTO

MÁQUINAS DE TURING Y LENGUAJES ESTRUCTURADOS POR FRASES

Lenguajes y Compiladores Aspectos Formales (Parte 2) Compiladores

Las Gramáticas LL. Gramáticas con Parsing Eficiente. Universidad de Cantabria

1. Cadenas EJERCICIO 1

Unidad II: Análisis semántico

Capítulo 9. Introducción a los lenguajes formales. Continuar

Departamento de Tecnologías de la Información. Tema 5. Decidibilidad. Ciencias de la Computación e Inteligencia Artificial

18 Análisis sintáctico III Compiladores - Profr. Edgardo Adrián Franco Martínez. Clasificación de métodos de análisis sintáctico Análisis descendente

El análisis descendente LL(1) 6, 7 y 13 de abril de 2011

UNIVERSIDAD NACIONAL DE EDUCACIÓN A DISTANCIA Escuela Técnica Superior de Ingeniería Informática Procesadores de Lenguajes.

Contenido. Capítulo 1. Teoría de conjuntos. 1. Capítulo 2. Lenguaje. 39. Capítulo 3. Lenguajes formales. 55

PROGRAMACIÓN II AÑO 2009 TALLER 3: TEORÍA DE LENGUAJES Y AUTÓMATAS

Universidad de Valladolid

Software para la Enseñanza de las Fases de Análisis Léxico y Análisis Sintáctico en Procesadores de Lenguajes

Proyecto Intermedio Algoritmo de Earley

UNIVERSIDAD NACIONAL DE EDUCACIÓN A DISTANCIA Escuela Técnica Superior de Ingeniería Informática Procesadores de Lenguajes. Tema 2.

Compiladores. Análisis Sintáctico Ascendente. Adrian Ulises Mercado Martínez. Facultad de Ingeniería, UNAM. 5 de septiembre de 2013

Análisis léxico. Formalización y desarrollo. Procesadores de Lenguajes. Ingeniería Técnica superior de Ingeniería Informática

Tema 5. Análisis semántico

Lenguajes y Compiladores Análisis Sintáctico Parte I. Teoría Lenguajes 1

GRAMMAR Aplicación de apoyo para el aprendizaje de los lenguajes formales.

TIPOS DE GRAMATICAS JERARQUIAS DE CHOMSKY

Computabilidad y lenguajes formales: Sesión 19. Gramáticas Incontextuales (Context Free Grammars)

ANÁLISIS LÉXICO Ing. Ronald Rentería Ayquipa

Nombre de la asignatura: Lenguajes y Autómatas I. Créditos: Aportación al perfil

Tema 1. Introducción

UNIVERSIDAD NACIONAL DE EDUCACIÓN A DISTANCIA Escuela Técnica Superior de Ingeniería Informática Procesadores de Lenguajes. Tema 3.

Unidad 4. Autómatas de Pila

Unidad 4. Autómatas de Pila

Agenda. Introducción Analizador léxico Analysis El problema de analizar sintácticamente Analizador sintáctico descendeterecursivo

TEORIA DE AUTOMATAS.

Procesadores de lenguaje

Análisis sintáctico Analizadores descendentes

Tema 5 (2 a parte): Traductores ascendentes. Algoritmo de análisis ascendente. Procesamiento de Lenguajes. E E op T E T T num

Cátedra Sintaxis y Semántica del Lenguaje

Traductores Push Down

1. Define que es un Autómatas finitos determinanticos y cuáles son sus elementos constitutivos (explique cada uno de ellos).

Conceptos básicos sobre gramáticas

Pontificia Universidad Católica del Ecuador

DEFINICIONES BÁSICAS E INTRODUCCIÓN A LENGUAJES FORMALES

Tema: Autómata de Pila

Modelos De Computación. Guía Modelos de Computación. Tema I: Lenguajes y Gramáticas

DEL AUTÓMATA FINITO A LA EXPRESIÓN REGULAR

La Representación de las Gramáticas

SSL Guia de Ejercicios

Tema 3: Gramáticas regulares. Teoría de autómatas y lenguajes formales I

Tres versiones de Pal. Sesión 19. Una máquina para aceptar Pal El lenguaje: Tabla de transición para Pal. Más de un siguiente estado.

Compiladores. Curso: 2001/2002 Alumna: Laura M. Castro Souto Profesores: Bernardino Arcay Varela José Carlos Dafonte Vázquez

Análisis sintáctico 1

Gramáticas libres de contexto

Un autómata con pila no determinista (APND) es una septupla Q A B F en la que

Cadenas de Caracteres

Autómatas Finitos Deterministicos (DFA)

Autómatas Finitos Deterministicos (DFA)

Introducción. Las gramáticas definen las reglas que definen a los lenguajes Las reglas pueden tener una diversa variedad de esquemas

Compiladores: Parsing ascendente

Autómatas de Pila. Descripciones instantáneas o IDs. El Lenguaje de PDA. Equivalencia entre PDAs y CFGs INAOE (INAOE) 1 / 50

Transcripción:

Capítulo 4: Algoritmos usados por el Generador de Analizadores Sintácticos 4.1 Introducción En este capítulo se presentan los algoritmos usados por el Generador de Analizadores Sintácticos SLR. Se tratará de clarificar bien los conceptos teóricos utilizados, lo que no hace la bibliografía que se utilizó (luego de la lectura de la bibliografía, en el mejor de los casos quedan muchos conceptos flotando y sin relación alguna, y lo más común es que no se los entienda). Los analizadores sintácticos generados trabajan con la técnica SLR(1) o SLR para simplificar, la que es un caso especial de LR(k). A diferencia de la técnica LR(1) canónica y de la técnica LALR, esta técnica genera tablas mucho más pequeñas (se minimiza el número de estados del autómata de pila). Se la puede aplicar a casi todas las gramáticas de contexto libre que pueda necesitar un programador (el desarrollo de lenguajes de programación con gramáticas complejas puede requerir trabajar con la técnica LALR, pero si la técnica SLR es aplicable entonces el analizador será más eficiente). La técnica LR ha sido descripta por Knuth [1965], pero no resultó práctica porque el tamaño de las tablas que se debían construir eran demasiado grandes (recordar que en ese tiempo 16 kbytes era mucha memoria). En 1969 Korenjak mostró que mediante esa técnica se podían producir analizadores sintácticos de tamaño razonable para las gramáticas de los lenguajes de programación. En 1969 y 1971, DeRemer inventó los métodos "LR simples" (SLR por Simple LR) y "LR con símbolo de anticipación" (LALR por lookahead-lr) que son más simples que los de Korenjak. La utilización de la técnica SLR (y del resto de las LR) simplifica mucho el trabajo del desarrollo de un traductor, siempre y cuando se disponga de un programa generador de las tablas de análisis sintáctico. Si no se dispone de un generador de las tablas, la construcción de las mismas puede llegar a desalentar la construcción del traductor puesto que se requiere un dominio profundo de los algoritmos de construcción y de la teoría en la que se basan. Una persona puede entender bien los algoritmos de construcción de las tablas, y aún así cometer muchos errores. 28

El analizador SLR es uno solo para todas las posibles gramáticas. Es un autómata de pila determinístico, y su funcionamiento es análogo al autómata finito determinístico. El algoritmo se lo ilustra en la sección siguiente. La tabla construida para un analizador SLR se llama tabla SLR, la gramática para la cual se pueda construir una tabla SLR se llamará gramática SLR. Una gramática para la cual la construcción de la tabla SLR genere conflictos no es SLR, aunque se puedan resolver a mano los conflictos. 4.2 Análisis sintáctico por la técnica SLR (LR Simple) Antes de explicar cómo se construyen las tablas es necesario ver primero cómo se las usa. 4.2.1 Algoritmo de análisis sintáctico SLR Se dispone de una pila en la que se pueden almacenar estados (enteros no negativos) o símbolos de la gramáticas (terminales o no terminales). También se dispone de un par de tablas a las que se les da el nombre de acción e ir_a. La tabla acción contiene las acciones que puede ejecutar el autómata. Las acciones se especifican con una letra que especifica la acción y el número de estado al que debe ir el autómata luego de ejecutarla. Las mismas pueden ser: 1. Desplazamiento: se simboliza con la letra d y un número que indica el estado al que debe pasar el autómata. 2. Reducción: se simboliza con la letra r y un número que indica el número de regla por la cual se reduce. 3. Aceptar: se simboliza con la letra a. No tiene un número de sufijo puesto que no hace falta; el autómata se detiene automáticamente al encontrar esa orden. 4. Nada: si una entrada en esta tabla no contiene alguna de las tres alternativas anteriores entonces en la posición actual hay error de sintaxis. 29

La tabla ir_a contiene números enteros no negativos que son los estados a los que tiene que ir el autómata luego de ejecutar una reducción. La figura siguiente muestra el algoritmo de análisis sintáctico LR simple: Se dispone de una pila vacía en la cual se coloca 0 como estado inicial. Sea pt el puntero al primer terminal de la cadena de entrada. Salir = No Repetir Sea E el estado en el tope de la pila y t el terminal apuntado por pt. Si acción[e, t] = dy entonces Apilar primero t y luego Y. Avanzar pt al siguiente terminal. Sino, si acción[e, t] = rx entonces X es el número de regla por la que hay que reducir, entonces desapilar 2 veces el número de símbolos de la parte derecha de la regla número X. Sea Y el estado que ahora está en el tope de la pila y A el no terminal de la parte derecha de la regla número X. Apilar primero A y luego ir_a[x, A]. Sino, si acción[e, t] = a entonces Sino FinSi Se ha llegado al estado de aceptación. Salir = Si. Aceptar = Si. Salir = Si. Hasta que Salir = Si. Aceptar = No; hay error de sintaxis. Si Aceptar = Si entonces La oración de entrada cumple con la estructura definida por la gramática, esto es, es gramatical. Sino La oración de entrada no es gramatical. 30

Fig. 10 Algoritmo de análisis sintáctico SLR 4.2.2 Ejemplo del funcionamiento del analizador sintáctico SLR Para ejemplificar el funcionamiento del analizador sintáctico trabajaremos con la gramática siguiente (las reglas han sido numeradas): 1: P --> D I 2: D --> 'Var' L ':' 'Tipo' ';' 3: D --> 4: L --> L ',' 'Id' 5: L --> 'Id' 6: I --> I 'Instr' ';' 7: I --> Las tablas de análisis sintáctico SLR para la gramática dada son las siguientes: acción(estado, símbolo terminal) ir_a(estado, símbolo no terminal) Est 'Var' ':' 'Tipo' ';' ',' 'Id' 'Instr' FA P D L I ----+--------------------------------------------+----------------------- 0 d1 r3 r3 2 3 1 d4 5 2 a 3 r7 r7 6 4 r5 r5 5 d7 d8 6 d9 r1 7 d10 8 d11 9 d12 10 d13 11 r4 r4 12 r6 r6 13 r2 r2 Fig. 11 Tabla de análisis sintáctico SLR para la gramática de un lenguaje simple. En la tabla acción el símbolo FA significa Fin de Archivo. Aunque no forma parte del texto de entrada, su inclusión fue realizada durante la construcción de las tablas; el símbolo Fin de Archivo es un símbolo terminal de la gramática ampliada (ver más adelante qué es una gramática ampliada). Sea el texto de entrada el siguiente: Var Id : Tipo ; Instr ; 31

El análisis sintáctico se ilustra en el cuadro siguiente. Se utiliza un espacio como separador de elementos de la pila. Si se ha llegado al fin de archivo (FA) en la columna Entrada no habrán terminales. Paso Pila Entrada Acción 1 0 Var Id : Tipo ; Instr ; d1 2 0 Var 1 Id : Tipo ; Instr ; d4 3 0 Var 1 Id 4 : Tipo ; Instr ; r5 4 0 Var 1 L : Tipo ; Instr ; Ir a 5 5 0 Var 1 L 5 : Tipo ; Instr ; d7 6 0 Var 1 L 5 : 7 Tipo ; Instr ; d10 7 0 Var 1 L 5 : 7 Tipo 10 ; Instr ; d13 8 0 Var 1 L 5 : 7 Tipo 10 ; 13 Instr ; r2 9 0 D Instr ; Ir a 3 10 0 D 3 Instr ; r7 11 0 D 3 I Instr ; Ir a 6 12 0 D 3 I 6 Instr ; d9 13 0 D 3 I 6 Instr 9 ; d12 14 0 D 3 I 6 Instr 9 ; 12 r6 15 0 D 3 I Ir a 6 16 0 D 3 I 6 r1 17 0 P Ir a 2 18 0 P 2 Acepta r Fig. 12 Ejemplo de análisis sintáctico con la técnica SLR. La pila del analizador puede quedar con muchos elementos y aún así haber llegado al estado de aceptación. 4.2.3 Clasificación de los errores que se pueden producir durante el análisis sintáctico El algoritmo de análisis sintáctico SLR presentado en la figura 10 no especifica qué tipos de errores pueden aparecer ni cómo tratarlos. En esta 32

sección se dará una definición de los tipos de errores que pueden aparecer ya que la bibliografía no da una definición rigurosa de los mismos. Error lexicográfico: se dará este nombre al error que se produce al intentar buscar un símbolo terminal siguiente al actual y se encontró un símbolo que no es parte del conjunto de símbolos terminales de la gramática. El Fin de Archivo (FA) no es error lexicográfico, sino que simplemente no hay más símbolos terminales de entrada. Error semántico: si la implementación del analizador sintáctico incluye la posibilidad de ejecutar acciones semánticas (ver sección 2.3.8 y 12.3.3), durante la ejecución de esas acciones se pueden producir errores. A esos errores se les dará el nombre de errores semánticos. Error sintáctico: si no es error lexicográfico ni error semántico entonces es sintáctico. El autómata en este caso se queda sin saber qué acción ejecutar (la entrada de la tabla acción no está definida para el estado actual y el terminal de entrada). Las definiciones precedentes son aplicables a todas las técnicas de análisis que hay esta el momento de la escritura de este trabajo. En el contexto de las técnicas LR(k), un error semántico puede ser ignorado sin que se produzcan efectos indeseados. No ocurre lo mismo con los errores lexicográficos y sintácticos (nadie sabe con certeza lo que quiso escribir el autor del texto fuente), aunque los efectos colaterales pueden reducirse previo estudio y modificación "a mano" de las tablas. 4.3 Fundamentos de la construcción de las tablas de análisis SLR Antes de explicar la construcción de las tablas se darán primero algunas definiciones, se explicarán algoritmos usados por el algoritmo de construcción de las tablas de análisis sintáctico SLR y se explicarán los fundamentos de la construcción de las tablas del analizador SLR. 4.3.1 Elemento del análisis sintáctico LR(0) Se denominará elemento del análisis sintáctico LR(0) (elemento para abreviar) de una gramática G a una regla de G con un punto en alguna posición de la parte derecha. 33

Una regla que derive en la cadena nula (A --> ) genera un solo elemento que es "A -->. ". Intuitivamente, un elemento indica hasta dónde se ha visto una producción en un momento dado del proceso de análisis sintáctico. Por ejemplo, la regla A --> B C D genera cuatro elementos: A --->. B C D A ---> B. C D A ---> B C. D A ---> B C D. El primer elemento indica que a continuación se espera ver en la entrada una cadena derivable de "B C D". El segundo elemento indica que se acaba de ver en la entrada una cadena derivable de B, y que a continuación se espera ver una cadena derivable de "C D". 4.3.2 Operación Cerradura Sea I un conjunto de elementos para una gramática G, Cerradura(I) es el conjunto de elementos construidos a partir de I y de G mediante las dos siguientes reglas: 1. Inicialmente, todo elemento de I se agrega a Cerradura(I). 2. Si A --> α. B β está en Cerradura(I) y B --> γ es una regla, entonces se agrega B -->. γ a Cerradura(I), si todavía no fue agregado. Se aplica esta regla hasta que no se puedan agregar más elementos a Cerradura(I). Intuitivamente, si A --> α. B β está en Cerradura(I) es porque en algún momento del proceso de análisis sintáctico se cree que es posible ver a continuación una cadena derivable de B como entrada. Si B --> γ es una regla, también se espera ver una subcadena derivable de B --> γ en éste punto, y por esta razón se incluye B -->. γ en Cerradura(I). Ejemplo: para la gramática utilizada en el punto 4.2.2, sea I = { (P --> D I) } entonces Cerradura(I) contiene los siguientes elementos: P ---> D I D ---> 'Var' L ':' 'Tipo' ';' D ---> 34

Otro ejemplo: para la gramática utilizada en el punto 4.2.2, sea I = { ( D ---> 'Var' L ':' 'Tipo' ';' ) }, entonces Cerradura(I) contiene los siguientes elementos: D ---> 'Var' L ':' 'Tipo' ';' L ---> L ',' 'Id' L ---> 'Id' 4.3.3 Mangos Informalmente, un mango de una cadena es una subcadena que concuerda con el lado derecho de una regla y cuya reducción al no terminal del lado izquierdo de la regla representa un paso a lo largo de la inversa de una derivación por la derecha. Formalmente, un mango de una forma de frase derecha γ es una regla A-->β y una posición de γ donde la cadena β podría encontrarse y sustituirse por A para producir la forma de frase derecha previa en una derivación por la derecha de γ. Es decir, si O ==>* αaω ==>* αβω, entonces A-->β si la posición que sigue de α es un mango de αβω. La cadena ω a la derecha del mango contiene sólo símbolos terminales. Si la gramática no es ambigua entonces toda forma de frase derecha de la gramática tiene exactamente un mango. Para la gramática del ejemplo dado en la sección 4.2.2, obsérvesen la figura 12, la fila correspondiente al paso 14: la forma de frase derecha es D I Instr ; la operación que se va a ejecutar en ese paso es r6 y el mango es "I Instr ;", que concuerda con la parte derecha de la regla 6 ( I --> I 'Instr' ';' ). En este caso, a la derecha del mango no hay símbolos terminales. 4.3.4 Prefijo Viable Los prefijos de las formas de frase derecha que pueden aparecer en la pila de un analizador sintáctico por desplazamiento y reducción se denominan prefijos viables. Una definición equivalente de un prefijo viable es la de que es un prefijo de una forma de frase derecha que no continúa más allá del extremo derecho del mango situado más a la derecha de esta forma de frase. Con esta 35

definición, siempre es posible añadir símbolos terminales al final de un prefijo viable para obtener una forma de frase derecha. Por lo tanto, aparentemente no hay error siempre que la porción examinada de la entrada hasta un punto dado pueda reducirse a un prefijo viable. Por ejemplo, para la gramática del ejemplo dado en la sección 4.2.2, obsérvese en la figura 12, la fila correspondiente al paso 8, la forma de frase derecha es: Var L : Tipo ; Instr ; y se reduce por regla 2 el mango "Var L : Tipo ;" para obtener la forma de frase derecha siguiente: D Instr ; Aquí, D es un prefijo viable. 4.3.5 Operación ir_a La función ir_a(i, X) donde I es un conjunto de elementos y X es un símbolo de la gramática (terminal o no terminal) se define como la cerradura del conjunto de todos los elementos A --> α X. β tales que A --> α. X β esté en I. Intuitivamente, si I es el conjunto de elementos válidos para algún prefijo viable, entonces ir_a(i, X) es el conjunto de elementos válidos para el prefijo viable γx. Por ejemplo, para la gramática del ejemplo dado en la sección 4.2.2, para el conjunto de elementos I igual a: P ---> D I D ---> 'Var' L ':' 'Tipo' ';' D ---> entonces ir_a(i, D) consta de: P ---> D I I ---> I 'Instr' ';' I ---> 36

4.3.6 Colección Canónica de Conjuntos de Elementos del Análisis Sintáctico LR(0) La construcción de la colección canónica de conjunto de elementos LR(0) se aplica a una gramática aumentada G' obtenida a partir de G por el agregado de la siguiente regla: O' --> O donde O es el símbolo inicial de la gramática G. Ahora O' es el símbolo inicial de la gramática G', a la que se llamará gramática aumentada. El objetivo de esta regla es la de indicar al analizador cuándo debe detener el análisis sintáctico y anunciar la aceptación de la cadena. La aceptación se produce únicamente cuando el analizador está por reducir O' --> O. El algoritmo se muestra en la siguiente figura, en donde C es conjunto de conjuntos de elementos (la colección canónica LR(0) ): Sea C = { Cerradura( { O' -->. O } ) } Repetir Para cada conjunto de elementos I en C y cada símbolo gramatical X tal que ir_a(i, X) no esté vacío y no esté en C hacer FinPara Agregar ir_a(i, X) a C. Hasta que no se puedan agregar más conjuntos de elementos a C. Fig. 13 Construcción de la Colección Canónica LR(0) En adelante, a cada I se lo llamará indistintamente conjunto de elementos LR(0) o estado. Ejemplo: para la gramática dada en la sección 4.2.2, la gramática aumentada es: P' --> P P ---> D I D ---> 'Var' L ':' 'Tipo' ';' D ---> L ---> L ',' 'Id' L ---> 'Id' I ---> I 'Instr' ';' I ---> 37

y la colección canónica es: Estado 0 (I 0 ): P' ---> P P ---> D I D ---> 'Var' L ':' 'Tipo' ';' D ---> Estado 1 (I 1 ): D ---> 'Var' L ':' 'Tipo' ';' L ---> L ',' 'Id' L ---> 'Id' Estado 2 (I 2 ): P' ---> P Estado 3: P ---> D I I ---> I 'Instr' ';' I ---> Estado 4: L ---> 'Id' Estado 5: D ---> 'Var' L ':' 'Tipo' ';' L ---> L ',' 'Id' Estado 6: P ---> D I I ---> I 'Instr' ';' Estado 7: D ---> 'Var' L ':' 'Tipo' ';' Estado 8: L ---> L ',' 'Id' Estado 9: I ---> I 'Instr' ';' Estado 10: D ---> 'Var' L ':' 'Tipo' ';' Estado 11: L ---> L ',' 'Id' Estado 12: I ---> I 'Instr' ';' Estado 13: D ---> 'Var' L ':' 'Tipo' ';' 4.3.7 Idea Central del Método SLR Los elementos del análisis sintáctico LR(0) pueden considerarse como los estados del autómata finito no determinista que reconoce los prefijos viables. Para poder convertir el autómata en determinista hace falta agrupar los 38

elementos en conjuntos. Los conjuntos serían entonces los estados del autómata finito determinista que reconoce los prefijos viables. La idea central del método SLR es construir primero a partir de la gramática un AFD que reconozca los prefijos viables. Se construye la colección canónica de elementos LR(0). Cada conjunto de elementos dentro de la colección canónica pasan a ser los estados del analizador sintáctico SLR (del AFD que el mismo usa). Para el ejemplo dado en el punto anterior, el AFD que reconoce prefijos viables se muestra en la figura siguiente: 'Id' 4 'Var' 1 L ':' 7 'Tipo' 10 ';' 13 0 P D 2 5 ',' 8 'Id' 11 3 I 6 'Instr' ';' 9 12 Fig. 14 AFD que reconoce prefijos viables de la gramática del ejemplo. El AFD de la figura precedente tiene dos problemas: no tiene estados finales y tiene transiciones con símbolos no terminales. El hecho de tener transiciones con no terminales hace necesario disponer de una pila para la implementación del autómata. El autómata resultante se pasa a llamar autómata de pila, que como ya se mencionó en el punto 2.2.5, son los que implementan analizadores sintácticos para gramáticas del Tipo 2 de la clasificación de Chomsky. 4.3.8 Función Anulable La función Anulable se aplica a un símbolo no terminal de una gramática y devuelve Verdadero si ese símbolo es anulable. Un símbolo no terminal A es anulable si de alguna forma, mediante derivaciones sucesivas con las reglas de la gramática, se transforma A en la 39

cadena nula ( A ==>* λ ). (λ representa a la cadena nula. En este trabajo cuando en una regla se quiere denotar la presencia de la cadena nula no se pone nada puesto que es más claro.) Definiremos primero una versión simple de Anulable a la que se le llamará AnulableSimple. Esta función devolverá Verdadero si hay una regla que derive el no terminal directamente en la cadena nula ( A --> ). A partir de la función de AnulableSimple se define la función Anulable de la siguiente manera: un símbolo no terminal X de una gramática G es anulable si: 1. X es Anulable Simple ( X --> ). 2. Si existe alguna regla X --> Y Z, con Y y Z anulables. El punto 2 hace que la definición sea recursiva, por lo tanto un algoritmo que la implemente podrá ser recursivo, lo que no es aconsejable debido a la cantidad de veces que se puede repetir el cálculo de Anulable para algunos símbolos no terminales. Ejemplo: para la gramática siguiente O ---> A B C A ---> a B A ---> B ---> b C B ---> C C ---> c O C ---> El cálculo de AnulableSimple para cada uno de los símbolos daría el siguiente resultado: O: no es anulable simple. A: si es anulable simple. B: no es anulable simple. C: si es anulable simple. El cálculo de Anulable arroja el siguiente resultado: O: si es anulable porque A, B y C son anulables. A: si es anulable porque es anulable simple. B: si es anulable porque hay una regla B --> C, y C es anulable. C: si es anulable porque es anulable simple. 4.3.9 La operación Primero Si α es una cadena de símbolos gramaticales, se considera Primero(α) como el conjunto de terminales que inician las cadenas derivadas de α. 40

Si α ==>* λ, entonces λ también está en Primero(α). El resultado de la función Primero es un conjunto de símbolos terminales, que obviamente es un subconjunto de T (el conjunto de símbolos terminales de la gramática). Para calcular Primero(X) para todos los símbolos gramaticales X, se proponen las siguientes reglas: 1. Si X es terminal, entonces Primero(X) es { X }. 2. Si X -- > λ es una regla, entonces agregar λ a Primero(X). 3. Si X es no terminal y X --> Y 1 Y 2... Y k entonces se agrega b a Primero(X) si, para alguna i, b está en Primero(Y i ) y λ está en todos los conjuntos Primero(Y 1 ),..., Primero(Y i - 1 ); esto es, la cadena Y 1...Y i - 1 ==>* λ. Si λ está en Primero(Y j ) para toda j = 1, 2,..., k, entonces se agrega λ a Primero(X); esto es, la cadena Y 1...Y k ==>* λ. Por ejemplo, todo lo que está en Primero(Y 1 ) sin duda estará en Primero(X). Si Y 1 no deriva en λ, entonces no se agrega nada más a Primero(X), pero si Y 1 ==>* λ, entonces se agrega Primero(Y 2 ), y así sucesivamente. 4. Se repetirán las tres primeras reglas hasta que no se puedan agregar Fig. 15 Cálculo de Primero(X). Observando la regla 1, se concluye que el cálculo de Primero(X) para X terminal no tiene sentido, puesto que es un axioma. A los efectos de la utilización de la función Primero en la generación de las tablas de análisis sintáctico SLR, el agregado de λ no es necesario. En los ejemplos siguientes no se incluye λ en donde se debiera. Ejemplo 1: para la gramática dada en la sección anterior (4.3.8) los conjuntos Primero sin Lambda (λ) son: Primero(O) = { a b c } Primero(A) = { a } Primero(B) = { b c } Primero(C) = { c } 41

Ejemplo 2: para la gramática dada en la sección (4.2.2) los conjuntos Primero sin Lambda (λ) son: Primero(P) = { 'Var' 'Instr' } Primero(D) = { 'Var' } Primero(L) = { 'Id' } Primero(I) = { 'Instr' } 4.3.10 La operación Siguiente La función Siguiente se calcula para los símbolos no terminales de la gramática, únicamente. Para calcular Siguiente(X) para todos los símbolos no terminales X, se proponen las siguientes reglas: 1. Agregar FA (Fin de Archivo) a Siguiente(O), donde O es el símbolo inicial y FA es el delimitador derecho de la entrada. 2. Si hay una regla A ---> α B β, entonces todo lo que esté en Primero(β) excepto λ se agrega a Siguiente(B). 3. Si hay una regla A ---> α B o una regla A ---> α B β, donde Primero(β) contenga λ (es decir, β ==>* λ), entonces todo lo que esté en Siguiente(A) se agrega a Siguiente(B). Fig. 16 Cálculo de Siguiente(X). Obsérvese las reglas 2 y 3, al decir Primero(β) se está hablando en realidad de la unión de varios conjuntos Primero(X i ) para i = 1,..., k y todos los Primero(X i ) excepto Primero(X k ) contiene a λ. Por lo tanto, se deberá tener esto en cuenta al implementar el algoritmo. Obsérvese también que en la regla 2, al agregar todo lo que esté en Primero(β) excepto λ a Siguiente(B) justifica el hecho de que en este trabajo se calcula Primero(X) sin λ. Ejemplo 1: para la gramática dada en la sección anterior (4.3.8) los conjuntos Siguiente(X) son los siguientes: Siguiente(O) = { c b } Siguiente(A) = { b c } 42

Siguiente(B) = { c b } Siguiente(C) = { c b } Ejemplo 2: para la gramática dada en la sección (4.2.2) los conjuntos Siguiente(X) son: Siguiente(P) = { } Siguiente(D) = { 'Instr' } Siguiente(L) = { ':' ',' } Siguiente(I) = { 'Instr' } 4.4 Construcción de las tablas de análisis SLR La construcción de las tablas de análisis sintáctico SLR (similar a la mostrada en la figura 11 de la sección 4.2.2) se resume en el algoritmo mostrado en la figura siguiente. Si los 3 primeros pasos generan acciones contradictorias, se dice que la gramática no es SLR(1) porque el algoritmo no consigue producir las tablas para el análisis sintáctico. En este caso no se ejecutan los pasos siguientes. 43

1. Construir G', la gramática aumentada, a partir de G, por el agregado de la regla O' --> O, donde O era el símbolo inicial de G. O' pasa a ser el símbolo inicial en G'. 2. Construir C = { I 0, I 1,..., I n }, la colección canónica de conjuntos de elementos del análisis sintáctico LR(0) para la gramática aumentada G'. 3. El estado i se construye a partir de I i. Las acciones de análisis sintáctico para el estado i se determinan como sigue: a. Si A --> α. x β está en I i con x terminal e ir_a(i i, x) = I j, entonces asignar "desplazar j" a accion[i, x]. b. Si A --> α. está en I i, con A distinto de O' entonces asignar "reducir por A --> α" a accion[i, x] para todo x perteneciente a Siguiente(A). c. Si O' ---> O. está en I i, entonces asignar "aceptar" a accion[i, FA] (FA es el Fin de Archivo). 4. La tabla ir_a(i, X) para el estado i y el no terminal X se construyen utilizando la regla: si ir_a[i i, X] = I j entonces ir_a[i, X] = j 5. Todas las entradas de las tablas no definidas por las reglas 3 y 4 son consideradas "error". 6. El estado inicial del analizador es el que se construye a partir del conjunto de elementos que contiene a S' --->. S Fig. 17 Construcción de las tablas de análisis sintáctico SLR. Ejemplo 1: para la gramática dada en la sección 4.2.2, las tablas se muestran en la figura 12 que se encuentra en la misma sección. La colección canónica de elementos LR(0) los encontrará en la sección 4.3.6. Los conjuntos Siguiente(X) los encontrará en la sección 4.3.10. Ejemplo 2: para la gramática dada en la sección 4.3.8, los conjuntos Siguiente(X) los encontrará en la sección 4.3.10. La colección canónica de 44

elementos LR(0) es la siguiente (aquí a los terminales se los encierra entre comillas simples para que no queden dudas): Estado 0: O' ---> O O ---> A B C A ---> 'a' B A ---> Estado 1: A ---> 'a' B B ---> 'b' C B ---> C C ---> 'c' O C ---> Estado 2: O' ---> O Estado 3: O ---> A B C B ---> 'b' C B ---> C C ---> 'c' O C ---> Estado 4: B ---> 'b' C C ---> 'c' O C ---> Estado 5: C ---> 'c' O O ---> A B C A ---> 'a' B A ---> Estado 6: A ---> 'a' B Estado 7: B ---> C Estado 8: O ---> A B C C ---> 'c' O C ---> Estado 9: B ---> 'b' C Estado 10: C ---> 'c' O Estado 11: O ---> A B C Al construir la tabla acción obtenemos lo siguiente, en la que se detectará 6 conflictos de desplazamiento-reducción: acción(e, x) 'a' 'b' 'c' FA ir_a(e, X): O A B C 45

0 d1 r3 r3 r3 2 3 1 d4 d5 r7 6 7 2 a 3 d4 d5 r7 8 7 4 r7 d5 r7 9 5 d1 r3 r3 r3 10 3 6 r2 r2 r2 7 r5 r5 r5 8 r7 d5 r7 11 9 r4 r4 r4 10 r6 r6 r6 11 r1 r1 r1 Los conflictos los generó el paso 3.b del algoritmo y son los siguientes: 1. En el estado 1, con el terminal 'c' hay que elegir entre d5 o r7. 2. En el estado 1, con el terminal 'b' hay que elegir entre d4 o r7. 3. En el estado 3, con el terminal 'c' hay que elegir entre d5 o r7. 4. En el estado 3, con el terminal 'b' hay que elegir entre d4 o r7. 5. En el estado 4, con el terminal 'c' hay que elegir entre d5 o r7. 6. En el estado 8, con el terminal 'c' hay que elegir entre d5 o r7. Debido a que esta gramática genera conflictos en la construcción de las tablas SLR se dirá que la misma no es SLR. Una definición equivalente es decir que la gramática es ambigua para la técnica de análisis SLR, lo que no significa que sea ambigua a secas (la construcción unívoca de un árbol de análisis sintáctico no es posible con la técnica SLR, esto es, el algoritmo de construcción de las tablas se comporta en este caso como una función no inyectiva porque puede generar varias tablas accion alternativas para la misma gramática). Más ejemplos de construcción de tablas las puede encontrar en el capítulo 11 y 12 en donde se muestran ejemplos de ejecución de SLR1. 46