6.2 rbol de derivacin. 6.3 Formas normales de Chomsky. 6.4 Diagramas de sintaxis 6.5 Eliminacin de la ambigedad 6.6 Generacin de matriz predictiva (clculo first y follow) 6.7 Tipos de analizadores sintcticos 6.8 Manejo de errores. 6.9 Generadores de analizadores sintcticos
Unidad 6: Anlisis Sintctico. 6.1 GLC. Gramticas Libres de Contexto (GLC), o de tipo 2: las reglas son de la forma X , donde X es una variable y es una cadena que puede contener variables y constantes. Estas gramticas producen los lenguajes Libres de Contexto (abreviado LLC) Capturan la nocin de constituyente sintctico y la nocin de orden. Herramienta formal que puede ser vista tanto desde un punto de vista generador como estructurador. Propiedades computacionales interesantes: se puede reconocer en tiempo polinmico. Una Gramtica Libre de Contexto es una tupla con 4 parmetros: G = (V, T, P, S) V conjunto de smbolos variables T conjunto de smbolos terminales S V, smbolo inicial P conjunto de reglas de produccin: A , con sucesin de smbolos de V U T, eventualmente vaca ( = ) Una GLC es un dispositivo generador. Definimos el lenguaje LG generado por una gramtica G del siguiente modo: G = { w / S * w } , siendo * una especie de clausura transitiva de y w una tira de terminales.
6.2 rbol de derivacin. Es una representacin grfica (en forma de rbol invertido) de un proceso de derivacin en una gramtica. Se define el rbol de derivacin como sigue: la raz del rbol ser el smbolo inicial de la gramtica los nodo interiores del rbol estn etiquetados por los smbolos no terminales las hojas estn etiquetadas por smbolos terminales si un nodo interior etiquetado por A, posee como hijos los nodos etiquetados por X1,X2, Xn , entonces A X1,X2, Xn es una produccin de la gramtica, en donde Xi , representa smbolo terminal o no terminal. Sea la siguiente gramtica: G=( ={a, b}, N={S,A,B},S P ) P: SaABAa , A |aA , B|bB la construccin de un rbol de derivacin en el proceso de la generacin de la palabra aa es el siguiente:
Propiedades de un rbol de derivacin.
Sea G = (N, T, S, P) una gramtica libre de contexto, sea A N una variable. Diremos que un rbol TA= (N, E) etiquetado es un rbol de derivacin asociado a G si verifica las propiedades siguientes: La raz del rbol es un smbolo no terminal Cada hoja corresponde a un smbolo terminal o . Cada nodo interior corresponde a un smbolo no terminal. Para cada cadena del lenguaje generado por una gramtica es posible construir (al menos) un rbol de derivacin, en el cual cada hoja tiene como rtulo uno de los smbolos de la cadena.
rbol de derivacin.
Ejemplo:
Sea G=(N, T, S, P) una GLC con P: S ab|aSb
La derivacin de la cadena aaabbb ser: S aSb aaSbb aaabbb y el rbol de derivacin:
6.3 Formas normales de Chomsky.
Una gramtica formal est en Forma normal de Chomsky si todas sus reglas de produccin son de alguna de las siguientes formas:
A BC o A a o
donde A, B y C son smbolos no terminales (o variables) y es un smbolo terminal.
Todo lenguaje independiente del contexto que no posee a la cadena vaca, es expresable por medio de una gramtica en forma normal de Chomsky (GFNCH) y recprocamente. Adems, dada una gramtica independiente del contexto, es posible algortmicamente producir una GFNCH equivalente, es decir, que genera el mismo lenguaje.
Sea G = ( N, T, P, $) una gramtica con P N X (N U T)* y X N un smbolo no-terminal (o una variable). Podemos clasificar tales smbolos X en tres clases: Variables accesibles: Si existe una derivacin desde el smbolo inicial que contiene X, es decir, existe $ * X donde , * Variables generativas: Si existe una derivacin desde el la variable que produce una sentencia , es decir, existe X * donde *T. Variables tiles: Si existe una derivacin desde el smbolo inicial usando que produce una sentencia , es decir, existe $ * X * donde , * y *T.
6.4 Diagramas de sintaxis
Los diagramas sintcticos, de sintaxis o diagramas del ferrocarril son una forma de representar una gramtica libre de contexto. Representan una alternativa grfica para la Forma de Backus-Naur (BNF, por sus siglas en ingls) o la Forma Extendida de Backus- Naur (EBNF, por sus siglas en ingles).
Los diagramas de ferrocarril son ms comprensibles para la mayora de la gente. Alguna parte de la popularidad del formato de intercambio de datos JSON se debe a su representacin en los diagramas de ferrocarril.
Un segundo mtodo alternativo para desplegar las producciones de ciertas gramticas de tipo 2 es el diagrama de sintaxis. sta es una imagen de las producciones que permite al usuario ver las sustituciones en forma dinmica, es decir, verlas como un movimiento a travs del diagrama. En la figura 10.5 se ilustrar los diagramas que resultan de la traduccin de conjuntos de producciones tpicos, que son, por lo general, todas las producciones que aparecen en el lado derecho de algn enunciado BNF.
6.5 Eliminacin de la ambigedad
Una GLC es ambigua si existe una cadena w L(G) que tiene ms de una derivacin por la izquierda o ms de una derivacin por la derecha o si tiene dos o ms arboles de derivacin .
En casi de y que toda cadena w L (G) tenga un nico rbol de derivacin no es ambigua.
Ejemplo: La gramtica S aS| Sa | a es ambigua porque aa tiene dos derivaciones por la izquierda S aS aa S Sa aa.
Tipos de Ambigedad
Dentro del estudio de gramticas existen dos tipos fundamentales de ambigedad, los cuales son:
Ambigedad Inherente:
Las gramticas que presentan este tipo de ambigedad no pueden utilizarse para lenguajes de programacin, ya que por ms transformaciones que se realicen sobre ellas, nunca se podr eliminar completamente la ambigedad que presentan:
Un lenguaje L es inherentemente ambiguo si todas sus gramticas; si existe cuando menos una gramtica no ambigua para L, L no es ambiguo. El lenguaje de las expresiones no es Ambiguo Las expresiones regulares no son ambiguas Ejemplo de un lenguaje inherentemente ambiguo:
La gramtica es ambigua: hay cadenas con ms de una derivacin ms izquierda:
6.6 Generacin de matriz predictiva (clculo first y follow)
FIRST: Sea G := (V; ; Q0; P) una gramtica libre de contexto. Para cada forma sentencial (V U )* y para cada k N definiremos la funcin.
En otras palabras, el operador F IRST k asocia a cada forma sentencial los primeros k smbolos de cualquier forma terminal alcanzable desde mediante derivaciones masa la izquierda".
FOLLOW: Con las mismas notaciones anteriores, para cada forma sentencial (V U )* definiremos la funcin FOLLOWG GK () del modo siguiente.
De nuevo nos ocuparemos solamente de FOLLOW: = FOLLOW1. Obsrvese que FOLLOW k () * y que para cada x FOLLOW (), Ixl k. Obsrvese que para cada variable A V, FOLLOW(A) son todos los smbolos terminales que pueden aparecer a la derecha de A en alguna forma sentencial de la gramtica.
6.7 Tipos de analizadores sintcticos
Analizador Descendente:
Se construye el rbol de anlisis sinttico partiendo del smbolo inicial y aplicando las producciones mediante derivaciones por la izquierda, el smbolo a expandir es el que esta mas a la izquierda.
Analizador Ascendente:
Se construye el rbol de anlisis sinttico partiendo de la frase a reconocer y aplicando las producciones mediante reducciones hasta llegar al smbolo inicial de la gramtica. Ejemplo:
G= ({+,*, ID, (,)}, {E, T, P},E, P)P={E:=E+T | T; T:=T*P | P; P:= ID | (E) }FraseID + ( ID * ID )
Ejemplo:
G= ({+,*, ID, (,)}, {E, T, P},E, P)P={E:=E+T | T; T:=T*P | P; P:= ID | (E) }FraseID + ( ID * ID )
6.8 Manejo de errores.
Un compilador es un sistema que en la mayora de los casos tiene que manejar una entrada incorrecta. Sobre todo en las primeras etapas de la creacin de un programa, es probable que el compilador se utiliza para efectuar las caractersticas que debera proporcionar un buen sistema de edicin dirigido por la sintaxis, es decir, para determinar si las variables han sido declaradas antes de usarla, o si faltan corchetes o algo as.
Por lo tanto, el manejo de errores es parte importante de un compilador y el escritor del compilador siempre debe tener esto presente durante su diseo.
Hay que sealar que los posibles errores ya deben estar considerados al disear un lenguaje de programacin. Por ejemplo, considerar si cada proposicin del lenguaje de programacin comienza con una palabra clave diferente (excepto la proposicin de asignacin, por supuesto). Sin embargo, es indispensable lo siguiente:
El compilador debe ser capaz de detectar errores en la entrada; El compilador debe recuperarse de los errores sin perder demasiada informacin; Y sobre todo, el compilador debe producir un mensaje de error que permita al programador encontrar y corregir fcilmente los elementos (sintcticamente) incorrectos de su programa.
Errores Sintcticos. Muchos errores de naturaleza sintctica Recuperacin: Al producirse un error el compilador debe ser capaz de informar del error y seguir compilando. (Ideal).
El manejo de errores de sintaxis es el ms complicado desde el punto de vista de la creacin de compiladores. Nos interesa que cuando el compilador encuentre un error, se recupere y siga buscando errores. Por lo tanto el manejador de errores de un analizador sintctico debe tener como objetivos: Indicar los errores de forma clara y precisa. Aclarar el tipo de error y su localizacin. Recuperarse del error, para poder seguir examinando la entrada. No ralentizar significativamente la compilacin. Un buen compilador debe hacerse siempre teniendo tambin en mente los errores que se pueden producir; con ello se consigue: Simplificar la estructura del compilador. Mejorar la respuesta ante los errores.
Errores semnticos. Un lenguaje con comprobacin 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 detectarn siempre en tiempo de compilacin. Como mnimo, ante un error, un comprobador de tipos debe informar de la naturaleza y posicin del error y recuperarse para continuar con la comprobacin del resto del programa a analizar.
Veamos algunas de las operaciones a tener en cuenta en una comprobacin de tipos: Conversin de tipos: A veces es necesario transformar el tipo de una expresin para utilizar correctamente un operador o para pasar de forma adecuada un parmetro a una funcin. Coercin: Es una conversin de tipos que realiza de forma implcita el propio compilador. Si es el programador el que realiza la conversin se tratar entonces de una conversin explcita. Sobrecarga de operadores: La sobrecarga se resuelve determinando el tipo de cada una de las expresiones intervinientes en la sobrecarga. Funciones polimrficas: Son aquellas que trabajan con argumentos cuyo tipo puede cambiaren distintas llamadas a la funcin.
6.9 Generadores de analizadores sintcticos
ANTLR: (ANother Tool for Language Recognition; en espaol "otra herramienta para reconocimiento de lenguajes") es una herramienta creada principalmente por Terence Parr, que opera sobre lenguajes, proporcionando un marco para construir reconocedores (parsers), intrpretes, compiladores y traductores de lenguajes a partir de las descripciones gramaticales de los mismos (conteniendo acciones semnticas a realizarse en varios lenguajes de programacin).
GNU bison: Es un programa generador de analizadores sintcticos de propsito general perteneciente al proyecto GNU disponible para prcticamente todos los sistemas operativos, se usa normalmente acompaado de flex aunque los analizadores lxicos se pueden tambin obtener de otras formas.
Grammatica: Es un generador de analizadores sintcticos de C# y Java libre. Es similar a otras herramientas como Yacc o ANTLR. Grammatica soporta el algoritmo LL(k) para gramticas con un nmero ilimitado de tokens de anticipacin. Est bastante bien probado, y ha sido auto compilado desde la versin 0.1. La documentacin contiene una lista completa de caractersticas, as como una comparacin con otros generadores de analizadores.
JavaCC: (Java Compiler Compiler) es un generador de analizadores sintcticos de cdigo abierto para el lenguaje de programacin Java. JavaCC es similar a Yacc en que genera un parser para una gramtica presentada en notacin BNF, con la diferencia de que la salida es en cdigo Java. A diferencia de Yacc, JavaCC genera analizadores descendentes (top-down), lo que lo limita a la clase de gramticas LL (K) (en particular, la recursin desde izquierda no se puede usar). El constructor de rboles que lo acompaa, JJTree, construye rboles de abajo hacia arriba (bottom-up).
Yacc: Es un programa para generar analizadores sintcticos. Las siglas del nombre significan Yet Another Compiler-Compiler, es decir, "Otro generador de compiladores ms". Genera un analizador sintctico (la parte de un compilador que comprueba que la estructura del cdigo fuente se ajusta a la especificacin sintctica del lenguaje) basado en una gramtica analticaescrita en una notacin similar a la BNF. Yacc genera el cdigo para el analizador sintctico en el Lenguaje de programacin C.