Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Sumario:
1- Introducción
2- Eliminación de símbolos inútiles
3- Gramática libre de e-producciones
4- Eliminación de producciones sencillas
5- Gramática propia
6- Eliminación de recursividad izquierda
7- Forma normal de Chomsky
8- Forma normal de Greibach
1 - Introducción
Dada una gramática en ocasiones es necesario modificarla con el objetivo de simplificarla o de imponerle cierta
estructura a sus reglas de producción sin modificar el Lenguaje generado. En otras ocasiones se realizan
transformaciones en una gramática con el objetivo de modificar el Lenguaje generado, o sea, se obtiene
producto de la transformación una nueva gramática que genera un lenguaje diferente al original. Este tipo de
transformación puede ser útil, por ejemplo, para eliminar la ambigüedad de una gramática, o para obtener la
precedencia adecuada de los operadores cuando se trata de una gramática para generar expresiones
aritméticas.
Estos algoritmos están definidos para gramáticas libres de contexto (GLC), por ser estas las más adecuadas
para la representación de los lenguajes de programación y por tanto la base para la implementación de la fase
de análisis sintáctico de un compilador.
Definición:
Decimos que un símbolo X N es inútil en una GLC G = ( N, , P, S ) si no existe una derivación
de la forma:
S * wXy * wxy , donde w, x, y *
Esta definición, como se puede apreciar, es aplicable tanto a símbolos no terminales como a símbolos
terminales, y por tanto tiene dos interpretaciones distintas. Para el caso de los símbolos no terminales esta
definición nos dice que el símbolo X es inútil si él no es capaz de generar una cadena de símbolos terminales.
Evidentemente un no terminal que no pueda realizar lo anterior es un símbolo inútil dentro de la gramática
debido a que una vez que él aparezca en una forma sentencial, no podrá generarse una sentencia. La siguiente
interpretación de la definición es aplicable tanto a los símbolos no terminales como a los terminales y nos dice
que un símbolo X es inútil si él nunca va a aparecer en alguna forma sentencial, o sea que el símbolo es
inaccesible.
El algoritmo para eliminar símbolos inútiles de una gramática tiene dos partes: una para eliminar los símbolos
no terminales que no generan cadenas de terminales y otra para eliminar los símbolos inaccesibles.
1. Aplicar el Algoritmo A para eliminar los símbolos no terminales que no generan cadenas de
terminales
2. Aplicar el Algoritmo B para eliminar de la gramática obtenida en el paso 1. los símbolos inaccesibles
Algoritmo A: Eliminación de los no terminales inútiles
Entrada: GLC G = ( N, , P, S )
Salida: Determina si L(G) = , construye G' = (NU, , P', S), tal que L(G) = L(G') y donde NU N, y es el
conjunto de no terminales que generan cadenas de terminales.
1. N0 = , i = 1
5. Si L(G) entonces construir G' = (NU, , P', S). Aquí P' es el conjunto de reglas de producción de P
que solo involucran símbolos de NU .
Este algoritmo construye iterativamente el conjunto NU que contendrá todos los símbolos no terminales capaces
de generar cadenas de terminales. Como consecuencia de este resultado se conocerá, al aplicar el algoritmo, si
el lenguaje generado por la gramática es distinto del vacío, a partir de la pertenencia o no del axioma al
conjunto NU.
1. Sea N0 = { S }, i = 1
Este algoritmo construye iterativamente el conjunto NA que contendrá todos los símbolos, terminales o no, que
podrán aparecer en alguna forma sentencial. Inicialmente este conjunto solo esta formado por el axioma, el cual
es siempre accesible. En el siguiente paso se añaden los símbolos que son accesibles a través del axioma y
luego los accesibles a partir de los recién incluidos, y así sucesivamente, hasta que no es posible agregar mas
símbolos al conjunto.
Ejemplo:
Sea G = ( { S, A, B }, { a, b }, P, S )
Donde P: Sa|A
A AB
Bb
Algoritmo A
1. N0 = , i = 1
2. N1 = { S, B }
2. N2 = { S, B }
3. NU = { S, B }
4. S NU, luego L(G)
5. G' = ({ S, B }, { a, b }, { S a, B b }, S)
Algoritmo B
1. N0 = { S }
2. N1 = { S, a }
2. N2 = { S, a }
3. NA = { S, a }
4. G'' = ( { S }, { a }, { S a }, S )
A partir de este mismo ejemplo puede observarse que el orden de aplicación de los algoritmos A y B es
importante. Si se aplica primero el algoritmo B y luego el A puede obtenerse un resultado diferente, y como
consecuencia la gramática resultante puede aún contener algunos símbolos inútiles. La razón es que puede
darse el caso, como el del ejemplo, de un símbolo que sea accesible en la gramática a través de algún no
terminal inútil. Este es el caso en el ejemplo del símbolo terminal b. Al aplicar los algoritmos en orden inverso la
gramática resultante es:
El siguiente algoritmo permite convertir una GLC a una GLC libre de e-producciones.
Las gramáticas libres de e-producciones son de gran utilidad pues otros tipos de gramáticas como las propias,
las que no son recursivas a la izquierda, etc. pueden ser de esas formas por el hecho de que una vez que un no
terminal aparece en una forma sentencial nunca podrá derivar a la cadena vacía, siempre como mínimo
derivara a un símbolo terminal (excepto quizás la derivación S e, lo cual lo garantiza la definición de
gramática libre de e-producciones.
Salida: G' = ( N', , P', S' ), tal que L(G) = L(G') y G' es libre de e-producciones
1. Construir Ne = { A | A N y A +G e }
Ejemplo:
Sea G = ( { S }, { a, b }, P, S )
P: S aSbS | bSaS | e
1. Ne = { S }
2a. P' = S aSbS | aSb | abS | ab | bSaS | bSa | baS | ba
2b. S Ne luego se añade a P' S' S |
3. G' = ( { S, S' }, , P', S' )
Ejemplo:
Sea GE = ( { E, T, F }, { +, *, (, ), a }, P, E )
Donde P: E E+T | T
T T*F | F
F (E) | a
1. NE = { E, T, F } NT = { T, F } y NF = { F }
2. P' : E E+T | T*F | (E) | a
T T*F | (E) | a
F (E) | a
3. Construir G' = ( { E, T, F }, , P', E )
5- Gramática propia
Un algoritmo muy simple para eliminar los ciclos de una gramática puede ser:
A continuación analizaremos un algoritmo que permite eliminar la recursividad izquierda en una GLC. Este
algoritmo es de gran importancia para la implementación de la fase de análisis sintáctico de un compilador pues
existen métodos para la construcción de analizadores sintácticos a partir de la GLC que genera el lenguaje, que
imponen la restricción a la gramática de que no pueden ser recursivas a la izquierda. Analizaremos
primeramente algunos conceptos.
Una gramática con al menos un no terminal recursivo a la izquierda (derecha) se dice que es recursiva a la
izquierda (derecha).
1. Sean
A A1 | A2 | ... | An | 1 | 2 | ... | m
todas las A-producciones en P y ningún i comienza con A, entonces se construye G' = ( N { A' }, ,
P', S ) donde P' es P con las A-producciones anteriores reemplazadas de la siguiente forma:
A 1 | 2 | ... | m | 1A' | 2A' | ... | mA'
A' 1| 2 | ... | n | 1A' | 2A' | ... | nA'
y A' es un nuevo símbolo no terminal
Otra variante del algoritmo que genera menos reglas de producción pero introduce e-producciones es la
siguiente:
A 1A' | 2A' | ... | nA'
A' 1A'| 2A' | ... | nA' |
Como puede apreciarse, este algoritmo transforma la recursividad a la izquierda en recursividad a la derecha,
pero la recursividad a la derecha por lo general no es un problema para los algoritmos de compilación.
El algoritmo anterior elimina la recursividad izquierda inmediata para un no terminal pero no elimina la
recursividad izquierda general en una GLC.
Definición: Una GLC G = (N, , P, S) se dice que está en Forma Normal de Chomsky (FNC), si cada
producción en P tiene alguna de las formas siguientes:
a) A BC con A, B, C N ó
b) A a con A N, a ó
c) Si L(G), entonces S P y S no aparece en la parte derecha de ninguna regla de producción.
Algoritmo
A partir de una GLC propia G = (N, , P, S) construimos una GLC equivalente expresada en FNC:
1) A P' pertenecen todas las reglas A a P
2) A P' pertenecen todas las reglas A BC P
3) Si S P, entonces añadir S a P'
4) Para cada regla de producción de la forma:
A X1X2…Xk P con k>2, añadir a P' el siguiente conjunto de reglas:
Sustituir Xi por Xi' si Xi y Xi' es un nuevo no terminal
A X1'<X2…Xk>
<X2…Xk> X2'<X3…Xk>
…
donde cada <Xi…Xk> es un nuevo no terminal.
5) Para cada producción de la forma A X1X2 donde X1 o X2 o ambos pertenecen a , añadir a P’ la
producción
A X1'X2'
6) Para cada no temirnal a' introducido en los pasos 4 o 5, añadir a P' la producción
a' a
Finalmente sea N' el conjunto formado por N junto con todos los nuevos no terminales creados. La nueva
gramática será G' = (N', , P', S).
La Forma Normal de Greibach (FNG) tiene gran importancia para el análisis sintáctico, ya que en ella la
gramática tiene la propiedad de que cada una de sus reglas comienza con un terminal en la parte derecha.
Definición: Una GLC G = (N, , P, S) se dice que está en FNG, si es libre de -producciones y cada
producción es de la forma A a, con a y N*.
Lema: Sea G = (N, , P, S) una gramática sin recursividad a la izquierda, entonces existe un orden lineal < en
N, tal que si A B P, entonces A<B.