Vous êtes sur la page 1sur 10

Uso de la normalizacin de gramticas para el diseo de compiladores El diseo de gramtica se ha usado con xito para la descripcin de lenguajes de programacin.

Las gramticas expresadas permiten especificar la sintaxis y la semntica de un lenguaje de programacin y enfatizar la relacin entre sintaxis y las acciones necesarias para realizar una orden.

Anlisis sintctico descendente predictivo

Traductores, Compiladores e Intrpretes 16 Anlisis Sintctico Realizados por: Mara del Mar Aguilera Sierra y Sergio Glvez Rojas

Anlisis Descendente sSSAnlisis

descendente de gramticas LL(1) gramtica LL(1) es aquella en la que su tabla de chequeo de sintaxis no posee entradas mltiples, o sea, es suficiente con examinar slo un smbolo a la entrada, parasaber quregla aplicar. Toda gramtica reconocible mediante el mtodo de los diagramasde Conway es LL(1)El mtodo consiste en seguir un algoritmo partiendo de:La cadena a reconocer, junto con un apuntador, que nos indica cual es el token actual.- Una pila de smbolos ( terminales y no terminales)- Una tabla asociada de forma unvoca a una gramtica. En esta asignatura no vamos a vercomo calcular dicha tabla.

Dada una gramtica libre de contexto G= (, N, P, S) y una frase de entrada w *, un Analizador Sintctico Descendente (Top-Down Parser) intenta encontrar una derivacin izquierda de la frase partiendo del smbolo no-terminal inicial S y reemplazando el no-terminal ms a la izquierda por el lado derecho de una produccin que tenga a ese no-terminal por lado izquierdo.

En la introduccin al Anlisis sintctico descendente (ASD) vimos como las implementaciones de los analizadores sintcticos recursivos con retroceso (ASDRR) podan producir programas sumamente ineficientes por el carcter no determinista de la solucin subyacente. Por ejemplo, en la siguiente gramtica:
1. A BC 2. B e 3. B DB 4. C abb 5. D a 6. D b

Observamos que, ante una configuracin: (w$, Ba$) para hacer el anlisis eficiente debamos hacer la sustitucin B e solo si los siguientes cuatro smbolos en la entrada eran abb$, y la sustitucin B DB de lo contrario. Es posible transformar la gramtica en una equivalente de manera que el analizador recursivo resultante sea eficiente:
1. A abb$ 2. A DA 3. D a 4. D b

Ante esta situacin, debemos preguntarnos:


1. Es siempre posible decidir cul es la produccin (substitucin) correcta mirando

los siguientes k smbolos de la secuencia entrada?


2. Cmo sabemos cuntos smbolos debemos mirar (el valor de k)?

Gramticas LL El analizador sintctico LL es un analizador sintctico descendente, por un conjunto de gramtica libre de contexto En ste analizador las entradas son de izquierda a derecha, y construcciones de derivaciones por la izquierda de una sentencia o enunciado. La clase de gramtica que es analizable por este mtodo es conocida como gramtica LL. El resto de este artculo se describe en el cuadro de base del tipo de analizador sintctico, la alternativa comienza con ser un intrprete de ascendencia recursiva que normalmente son codificados a mano (aunque no siempre; por ejemplo, ANTLR para un LL (*) - (generador de analizador ascendencia recursiva).
Un analizador LL es llamado un analizador LL (k) si usa k tokens cuando el analizador ve hacia delante de la sentencia. Si existe tal analizador para cierta gramtica y puede analizar sentencias de sta gramtica sin marcha atrs, entonces es llamada una gramtica LL (k). De sta gramticas, la gramtica LL (1), aunque es bastante restrictiva, stas son muy populares porque los analizadores LL correspondientes slo necesita ver el siguiente token para hacer el anlisis de sus decisiones. Lenguajes mal diseados usualmente suelen tener gramticas con un alto nivel de k, y requieren un esfuerzo considerable a analizar. Otra fuente:

En general no es posible (no sabemos cmo) construir analizadores sintcticos eficientes para cualquier gramtica. A pesar de eso, dada una gramtica independiente del contexto y un entero k especfico, si podemos hacer lo siguiente:
1. Determinar si para dicha gramtica es posible decidir la produccin correcta en casa

paso de una derivacin mirando solo los k smbolos siguientes en lo que resta de la secuencia de entrada.
2. Si la respuesta a lo anterior es si, podemos construir de manera sistemtica una

analizador sintctico descendente determinista para esa gramtica.

Las gramticas para las cuales podemos decidir de manera ambigua la produccin a utilizar en cada paso de una derivacin mirando solo k smbolos de entrada se llaman gramticas LL(k) y los lenguajes generados por esas gramticas se llaman lenguajes LL(k). El nombre LL (k) significa lo siguiente:

L: La entrada se examina de izquierda a derecha (Left to right). L: El anlisis produce una derivacin izquierda (Left derivation). k: El anlisis se hace mirando a lo sumo k smbolos de lo que resta de la secuencia de entrada.

La mayora de los lenguajes de programacin de uso comn se describen mediante gramticas LL (1). Se puede demostrar que para que una gramtica G sea LL (k), G debe ser:
1. No-ambigua 2. Carente de recursin por la izquierda.

Anlisis sintctico ascendente usando SLD, LALR O LR (1)

El anlisis sintctico ascendente es una tcnica de anlisis sintctico que intenta comprobar si una cadena x pertenece al lenguaje definido por una gramtica L (G) aplicando los siguientes criterios

Partir de los elementos terminales de la frase x Escoger reglas gramaticales estratgicamente Aplicar a la inversa derivaciones por la derecha (Right Most Derivation) Procesar la cadena de izquierda a derecha Intentar alcanzar el axioma para obtener el rbol de anlisis sintctico o error

Los diferentes tipos de analizadores sintcticos ascendentes LR (0), SLR, LALR, LR (1) y LR (k) slo se diferencian entre s por el procedimiento de construccin de las tablas accin e ir A. En esta seccin abordaremos su estudio.

Condiciones SLR
Se comprueban al construir el analizador

LR1

El conjunto de gramticas que pueden ser analizadas mediante un anlisis

ascendente lineal se denomina LR(1) El conjunto LR(1) es mucho ms amplio que el de las gramticas LL(1

El mtodo SLR (1) (del ingls Simple LR). Usa ya un smbolo de pre anlisis. El mtodo LR (1). Es el ms poderoso y costoso. El tamao del autmata a pila para el reconocimiento se incrementa considerablemente. El mtodo LALR (1) (del ingls Look-Ahead LR, con smbolo de anticipacin). Es una versin simplificada del LR (1), que combina el coste en tamao (eficiencia) de los mtodos SLR con la potencia del LR (1).

Herramientas automatizadas para el desarrollo de un Analizador Sintctico

Plan de desarrollo
Etapas: 1. 2. Elegir el tipo del analizador sintctico. Trasformar el lenguaje al tipo correspondiente. Calcular las

tablas correspondientes. 3. Escribir el programa del analizador sintctico sin acciones ni

produccin de cdigo. 4. Aadir al analizador atributos y acciones (en la parte del

analizador sintctico -- solo la produccin de la salida, tal como se explica en los requisitos de prueba). 5. Aadir al analizador generador de cdigo.

Propiamente hablando, slo el segundo y el tercer punto forman el analizador sintctico por s. El resto es analizador semntico y el generador de cdigo. En todos los modos se requiere una vista general al definir como vamos a realizar el analizador sintctico.

Diferentes notaciones para especificar la estructura o sintaxis de un lenguaje de programacin y la tabla de smbolos.

La tabla de smbolos es la estructura de datos usada por el compilador para asociar a cada smbolo del programa fuente (identificadores, constantes, etc... ) un contenido semntico. Esta formada por registros que en general tienen una longitud fija. Los campos que tienen estos registros varan dependiendo del lenguaje a compilar y de la estructura del compilador. En general, estos campos pueden contener la informacin misma para la que estan destinados, o bien un puntero a posiciones de memoria en las que se guarda esta informacin. Algunos de los campos que pueden definirse para los registros de la tabla de smbolos son:

1. Nombre del smbolo. En la tabla de smbolo deben aparecer todos los lexemas correspondientes a los smbolos usados en el texto fuente, los smbolos sern todos aquellos trozos de cdigo que representen identificadores, constantes nmericas, o cualquier otro elemento que el lenguaje sea capaz de manejar. Para el almacenamiento en la tabla de smbolos de los lexemas pueden utilizarse las tcnicas: Interna. El campo de la tabla de smbolos se define como de tipo cadena de caracteres de dimensin fija (por ejemplo 16). El inconveniente de esta tcnica es que la longitud mxima de los identificadores esta restringida al valor fijado Externa. El campo de la tabla de smbolos contiene un puntero a una zona de memoria en la que se almacena el lexema.

2. Direccin en memria. En este campo se almacenan las direcciones de memoria en la que se guardarn los valores de las variables correspondientes a cada smbolo, durante la ejecucin del programa. Normalmente el dato que interesa almacenar aqu no es la direccin absoluta, sino la relativa a una determinada zona de memoria de las que el programa usar en su ejecucin. Por ejemplo, la direccin relativa al comienzo de la memria estatica, la direccion relativa al comienzo del registro de activacin cotrrespondiente al procedimiento, etc... Es importante recordar que la tabla de smbolos no contiene los valores de las variables, sino simplemente la direccin en la que se almacenarn cuando el programa objeto se ejecute. Esto es obvio, ya que la tabla de smbolos es una estructura de datos que se utiliza en la fase de compilacin, y por lo general, desaparece una vez terminada la compilacin, no incorporandose al programa objeto. Por otra parte, slo durante la ejecucin del programa es cuando se computan los valores de las variables. Excepcionalmente, cuando queremos disponer de un depurador simblico durante la fase de ejecucin, no tenemos mas remedio que incorporar la tabla de smbolos al programa objeto. Esto ocurre tambin en los interpretes, ya que compilacin y ejecucin se alternan. 3. Tipos.En este campo se almacenar el cdigo correspondiente al tipo de datos representado por el smbolo, o bien un puntero a la estructura de datos correspondiente, segn se ve en el capitulo dedicado a los sistemas de tipos. 4. Nmero de linea de la declaracon o nmeros de linea en los que se usa el smbolo. Esta es una informacin auxiliar que ser de utilidad para producir un listado de referencias cruzadas que ayuden a la depuracin de los programas. Puede utilizarse una lista encadenada de nmeros de lineas, siendo la cabeza de esta lista la linea en donde aparece la declaracin del smbolo. Lenguaje de programacin

SINTAXIS(BNF + EBNF + DIAGRAMAS DE SINTAXIS)+SEMNTICA OPERACIONAL (APROXIMACIN UTULIZADA AQU)FORMAL (A TRAVS DE MECANSMOS RIGUROSOS Y EXACTOS) SEMANTICA OPERACIONAL: Se describe el significado de cada construccin del lenguaje en trminos de las operaciones correspondientes en un proceso abstracto CONVERSIN ENTRE LENGUAJESDE ALTO NIVEL a--> DE MAQUINA que interpreta que interpreta un programador la Computadora ALTERNATIVAS INTERPRETACIN: Ejecucin paso a paso de cada instruccin de un programa. CICLO: LECTURA DECODIFICACIN EJECUCUIN Menor velocidad Relativo aprovechamiento de memoria (solo se carga una instruccin por vez) COMPILACION: Conversin completa de un programa antes de su ejecucin. FASES : COMPILACIN ENSAMBLADOR LINKEADO CARGADO EJECUCIN

Procedimientos para la generacin de la tabla de anlisis sintctico (primero, siguiente, ir a y otros)

Construccin de tablas de anlisis sintctico LALR


Es mucho ms fcil construir tablas SLR y LALR que tablas LR. Ya que las tablas LR pueden tener muchos estados que la tabla LALR reducira. Primero para construir la tabla necesitamos que la gramtica est aumentada. Luego podemos seguir los siguientes pasos: 1. 2. 3. Construir C = ,I0, I1, , In-, la coleccin de conjuntos de elementos LR(1). Para cada corazn presente entre el conjunto de elementos LR(1), buscar todos los conjuntos que tengan ese corazn y sustituir estos conjuntos por su unin. Dejar que C = ,J0, J1, , Jn- sean los conjuntos resultantes de elementos LR(1). Las acciones de anlisis sintctico para el estado i se construyen a partir de Ji. Si hay conflicto de acciones en el anlisis sintctico, el algoritmo no produce un analizador sintctico y decimos que la gramtica no es LALR(1).

4.

La tabla ir_A se construye de la siguiente manera. Si J es la unin de uno o ms conjuntos de elementos LR(1), es decir, J = I1 I2 Ik, entonces los corazones de ir_A(I1, X), hasta ir_A(Ik, X) son iguales, ya que I1, I2, , Ik tienen el mismo corazn. Dejar que K sea la unin de todos los conjuntos de elementos que tienen el mismo corazn que ir_A(I1, X). Entonces, ir_A(J, X) = K. Sin embargo este algoritmo para la construccin de tablas LALR no es tan eficiente como el que veremos a continuacin.

Construccin eficiente de tablas LALR


Podemos hacer varias modificaciones al algoritmo anterior para evitar construir la coleccin completa de conjuntos de elementos LR(1), en el proceso de crear una tabla de anlisis sintctico LALR(1). 1. Podemos representar cualquier conjunto de elementos I mediante su corazn, es decir, mediante aquellos elementos que sean el elementos inicial , *S->.S+ o *S, -> .S, $], o que tengan el punto en algn lugar que no sea el principio del cuerpo de la produccin. Podemos construir los corazones de los elementos LALR(1) a partir de los corazones de los elementos LR(0), mediante un proceso de propagacin y generacin espontnea de lecturas adelantadas. Si tenemos los corazones LALR(1), podemos generar la tabla de anlisis sintctico LALR(1) cerrando cada corazn, usando la funcin CERRADURA y despus calculando las entradas en la tabla, como si los conjuntos de elementos LALR(1) fueran conjuntos de elementos LR(1) cannicos. Despus de realizar el algoritmo de construccin no quedara un autmata como el siguiente para una gramtica G= S- > S S -> E1 S-> 2E3 S-> X3 S-> 2X1 E->4 X-> 4

2.

3.

Implementacin de un analizador sintctico t o t o implementacio t t or t o t r r o, o os t r or s t t o -sis que presentamos en 5.2. Bastaria con buscar una t S r o, st t o t o t o o ss t s to o s

s s, or o

st

r os t o t r t codificadirectamente en forma de programa.

Podemos reflejar la tabla de analisis (o la gramatica) directamente en un programa. La idea basica es tener una funcion (o un metodo si decidimos hacer que el analizador sea un objeto)por cada uno de los no terminales. As al no terminal A le asociaramos la funcion (metodo) Analiza_A. De momento, no utilizaremos parametros. El resultado de la llamada sera el valor cierto si hemos encontrado en la entrada una secuencia que se pueda derivar de A y falso en caso contrario. El analisis se hara mediante una llamada a Analiza_S: si devuelve cierto, se comprobara que hemos llegado al final de la entrada; si no, ha habido un error.