Você está na página 1de 8

128 CAPÍTULO 4.

GRAMÁTICAS Y LENGUAJES LIBRES DE CONTEXTO

1. S → aBT c 6. Y X → AX
2. T → ABT c 7. AX → AB
3. T → ABc 8. aA → aa
4. BA → BX 9. aB → ab
5. BX → Y X 10. bB → bb

En esta gramática, las reglas 1 a 3 generan A, a, B y c no necesariamente en orden (las


A y B van a estar alternadas). Luego las reglas 4 a 7 permiten reordenar las A y B, para que
todas las A queden antes que todas las B, 17 y finalmente las reglas 8 a 10 permiten generar
los terminales solamente cuando las letras están en el orden correcto. Como un ejemplo, la
palabra aaabbbccc se puede generar de la forma siguiente:

S ⇒1 aBT c ⇒2 aBABT cc ⇒3 aBABABccc ⇒4 aBXBXBccc ⇒5 aY XY XBccc


⇒6 aAXAXBccc ⇒7 aABABBccc ⇒4 aABXBBccc ⇒5 aAY XBBccc ⇒6 aAAXBBccc
⇒7 aAABBBccc ⇒8 aaABBBccc ⇒8 aaaBBBccc ⇒9 aaabBBccc ⇒10 aaabbBccc ⇒10
aaabbbccc.

4.8. Transformación de las GLC y Formas Normales

En muchas situaciones se considera conveniente modificar las reglas de la gramática,


de manera que cumplan las reglas con propiedades tales como no producir la cadena vacı́a
del lado derecho, o bien simplemente por cuestiones de estandarización o facilidad de im-
plementación computacional. Desde luego, cuando hablamos de “modificar las reglas de la
gramática”, se entiende que esto debe hacerse sin modificar el lenguaje generado.

Por ejemplo, la presencia de reglas que producen vacı́o en la gramática puede ser fuente de
dificultades tales como la ambigüedad, o la posibilidad de tener derivaciones arbitrariamente
largas. Tomemos por ejemplo la siguiente gramática para los paréntesis bien balanceados
(damos sólo las reglas):

1. S → SS

2. S → (S)

3. S → ε

Con esta gramática es posible hacer derivaciones arbitrariamente largas de una palabra
tan sencilla como “()”(el subı́ndice de las flechas indica la regla utilizada):
17
De hecho bastarı́a con una regla BA → AB, salvo que ésta no cumple con el formato de las gramáticas
sensitivas al contexto.
4.8. TRANSFORMACIÓN DE LAS GLC Y FORMAS NORMALES 129

S ⇒1 SS ⇒1 SSS ⇒1 . . . ⇒3 SSS ⇒3 SS ⇒3 S ⇒2 (S) ⇒3 ()

Si pudiéramos tener una gramática equivalente, pero sin reglas que produzcan la cadena
vacı́a, ya no serı́a posible hacer derivaciones arbitrariamente largas. Esto puede ser una
ventaja a la hora de determinar si una palabra se deriva o no de una gramática (ver sección
4.10).

4.8.1. Eliminación de reglas A → ε

Consideremos nuevamente la gramática para los paréntesis bien balanceados. Si queremos


una GLC equivalente, pero sin emplear producciones vacı́as (como S → ε), una idea serı́a
analizar “en reversa” la derivación de donde viene la S que queremos cambiar por ε. Sólo
hay otras dos reglas en la gramática, de modo que esa S tuvo que ser generada ya sea por
S → (S) o por S → SS. En el caso de S → (S), una solución serı́a, en vez de hacer la
derivación

S ⇒ . . . ⇒ αSβ ⇒ α(S)β ⇒ α()β, α ∈ Σ∗ , β ∈ (Σ ∪ V )∗


mejor hacer directamente la derivación

S ⇒ . . . ⇒ αSβ ⇒ α()β
agregando una regla S ⇒ () a la gramática. Y en caso de que la S provenga de la regla
S → SS, se puede cambiar la derivación

S ⇒ . . . ⇒ αSβ ⇒ αSSβ ⇒ αSβ


por la derivación

S ⇒ . . . ⇒ αSβ ⇒ αSβ
usando una nueva regla S → S, o mejor aún, simplemente reemplazarla por

S ⇒ . . . ⇒ αSβ
sin ninguna regla adicional (la parte de la derivación αSβ ⇒ αSSβ ⇒ αSβ desaparece por
completo, pues no sirve de nada).

Resumiendo, la idea que permite eliminar las reglas A → ε es la de irse un paso atrás,
para examinar de dónde provino el no-terminal A que queremos eliminar, y por cada regla
B → αAβ de la gramática agregar una regla B → αβ , en que directamente ya se reemplazó A
130 CAPÍTULO 4. GRAMÁTICAS Y LENGUAJES LIBRES DE CONTEXTO

por ε. Una vez hecho esto, se pueden suprimir todas las reglas de la forma A → ε, pues
resultan redundantes.

Por ejemplo, sea la GLC de los paréntesis bien balanceados:

S → (S), S → SS, S → ε.

Aplicando mecánicamente la transformación a dicha gramática, se tiene:

S → (S), S → SS, S → (), S → S

La regla S → S es evidentemente inútil y se puede eliminar, pero dejemos esto para el


siguiente párrafo, en que nos ocuparemos de la eliminación de reglas de esa forma.

Otra cuestión más importante aún debe haber saltado a la vista escrutadora del lector
perspicaz: ¡la nueva GLC no es exactamente equivalente a la anterior! En efecto, la GLC
original generaba la palabra vacı́a ε, mientras que la GLC transformada no la genera. Desde
luego, el hecho de que una GLC contenga reglas de la forma A → ε no significa que el lenguaje
contenga forzosamente a la palabra vacı́a; considérese por ejemplo la siguiente gramática:

S → (A), A → (A), A → AA, A → ε

cuyo lenguaje no contiene a la palabra vacı́a.

En caso de que el lenguaje en cuestión realmente contenga a la palabra vacı́a, no es


posible estrictamente eliminar todas las producciones vacı́as sin alterar el significado de la
gramática. En estos casos vamos a expresar el lenguaje como la unión {ε} ∪ L(G ), donde G
es la gramática transformada. Este pequeño ajuste no modifica los resultados que obtuvimos
arriba.

4.8.2. Eliminación de reglas A → B

Supongamos ahora que se tiene la gramática con las reglas siguientes:

S → (S), S → BB, S → (), B → S

Claramente esta GLC es equivalente a la gramática dada anteriormente para generar los
paréntesis bien balanceados. La única diferencia es que, en vez de utilizar la regla S → SS, se
tiene una regla S → BB, y luego las B se transforman en S por la regla B → S. Pero, ¿para
que usar esos intermediarios, como B en este caso, cuando es posible generar directamente
SS a partir de S? La idea de eliminar las reglas de la forma A → B viene de observar que
dichas reglas no producen nada útil, simplemente introducen sı́mbolos intermediarios, que
es posible eliminar. A continuación veremos cómo.
4.8. TRANSFORMACIÓN DE LAS GLC Y FORMAS NORMALES 131

Supongamos que hay reglas A → B y B → Γi en la gramática, entonces es posible añadir


reglas A → Γi sin modificar el lenguaje. Ahora bien, si hacemos esto siempre que sea posible,
las reglas de la forma A → B se vuelven inútiles, pues toda derivación:

. . . ⇒ αAβ ⇒ αBβ ⇒ αΓi β ⇒ . . .


puede transformarse en:

. . . ⇒ αAβ ⇒ αΓi β ⇒ . . .
sin modificar el lenguaje. Esto prueba que la gramática modificada es equivalente a la original.

Por ejemplo, aplicando esta transformación a la gramática del ejemplo, la regla “inútil”,
que tratamos de eliminar, es B → S. Se producen las nuevas reglas siguientes:

B → (S), al combinar B → S con S → (S)


B → BB, al combinar B → S con S → BB
B → (), al combinar B → S con S → ()

La gramática queda entonces con las reglas:


S → (S), S → BB, S → (), B → (S), B → BB, B → ()

4.8.3. Eliminación de reglas inaccesibles

Considérese una gramática con reglas:


S → aXbb, X → bSa, Y → SX

Es fácil comprender que la tercera regla es inútil, porque no hay nadie que produzca la
Y necesaria para que dicha regla se aplique. A reglas como éstas se les llama inaccesibles.

Definición.- Una regla X → α de una gramática (V, Σ, R, S) es inaccesible si no hay una


derivación S ⇒ α1 Xα2 , donde α1 , α2 ∈ (V ∪ Σ)∗ .

En términos prácticos, si vemos que una variable X no aparece en el lado derecho de


ninguna regla de la gramática, podemos asegurar sin arriesgarnos que la regla X → α es
inaccesible.

Para eliminar una regla inaccesible no se necesita hacer ninguna otra modificación a
la gramática mas que simplemente borrarla. La equivalencia de la gramática sin la regla
inaccesible y la original está garantizada por el hecho de que dicha regla no participa en
ninguna derivación.
132 CAPÍTULO 4. GRAMÁTICAS Y LENGUAJES LIBRES DE CONTEXTO

4.8.4. Formas Normales

En ocasiones es necesario expresar una GLC siguiendo un formato más preciso de las
reglas que la simple forma A → α. Estos “estándares” reciben el nombre de formas normales.
Vamos a estudiar una de las formas normales más conocidas, la forma normal de Chomsky
(FNCH).

La FNCH consiste en que las reglas pueden tener dos formas:

1. A → a, a ∈ Σ

2. A → BC, con B, C ∈ V

Esta forma normal, aparentemente tan arbitraria, tiene por objeto facilitar el análisis
sintáctico de una palabra de entrada, siguiendo la estrategia siguiente: Se trata de construir
el árbol de derivación de w de arriba hacia abajo (llamada “top-down” en inglés), y por
consiguiente se supone inicialmente que el sı́mbolo inicial S puede producir la palabra w. En
seguida se procede a dividir la palabra de entrada w en dos pedazos, w = αβ , para luego
tomar alguna regla S → AB , y tratar de verificar si se puede derivar a a partir de A y b a
partir de B, es decir: S ⇒ . . . ⇒ w ssi:

1. w ∈ Σ, hay una regla S → w

2. w = αβ, hay una regla S → AB, con A ⇒ . . . ⇒ α, y B ⇒ . . . ⇒ β

Por ejemplo, considérese la siguiente gramática para el lenguaje de los paréntesis bien
balanceados, en forma normal de Chomsky (damos sus reglas): 18

1. S → XY

2. X → (

3. Y → SZ

4. Z →)

5. S → SS

6. S → XZ

Supongamos que tenemos una palabra como (())(), y queremos verificar si se puede derivar
a partir de esta gramática. Hay que “partir” dicha palabra en dos pedazos, y escoger alguna
18
Luego veremos cómo calcular esta forma normal.
4.8. TRANSFORMACIÓN DE LAS GLC Y FORMAS NORMALES 133

S S

X Y X Z

( S Z ( )

X Z )

( )

Figura 4.3: Arbol de la palabra (())()

regla que produzca dos variables. Escogemos la quinta regla, S → SS, y partimos la palabra
en los pedazos (()) y (). Para que SS pueda generar (())() ahora se necesitará que la primera
S pueda generar (()), y la segunda pueda generar (). Estos son subproblemas muy similares
al problema inicial. Tomemos el primero, es decir, a partir de S generar (()). Escogemos la
regla S → XY , y partimos la palabra en ( y ()). Ahora X tiene la responsabilidad de generar
( y Y la de generar ()). Por la segunda regla, X genera directamente (. Ahora tomamos el
problema de generar ()) a partir de Y . Escogemos la regla S → SZ, y la separación en los
pedazos () y ). Entonces Z produce directamente ), y queda por resolver cómo S produce ().
Para ello, escogemos la regla S → XZ, y finalmente X produce ( y Z se encarga de ), con
lo que terminamos el análisis. El árbol de compilación se presenta en la figura 4.3.

Esta manera de generar dos nuevos problemas similares al problema inicial, pero con
datos más pequeños, es tı́picamente un caso de recursión. Este hecho permite pensar en
un sencillo procedimiento recursivo para “compilar” palabras de un LLC. Sea CC(A, u) la
función que verifica si A ⇒ . . . ⇒ u. Entonces un algoritmo de análisis sintáctico serı́a el
siguiente:

CC(A, w) :

1. Si |w| > 1, dividirla en u y v, w = uv;


Para cada regla de la forma A → U V , intentar CC(U, u) y CC(V, v)

2. Si |w| = 1, buscar una regla A → w.

Si en el punto 1 la división de la palabra no nos llevó a una compilación exitosa (es decir,
los llamados recursivos CC(U, u) y CC(V, v) no tuvieron éxito), puede ser necesario dividir
la palabra de otra manera. Dicho de otra forma, puede ser necesario ensayar todas las formas
134 CAPÍTULO 4. GRAMÁTICAS Y LENGUAJES LIBRES DE CONTEXTO

posibles de dividir una palabra en dos partes, antes de convencerse de que ésta pertenece o
no a nuestro lenguaje. Aún cuando esto puede ser muy ineficiente computacionalmente, es
innegable que el algoritmo es conceptualmente muy sencillo.

El siguiente problema a examinar es si efectivamente es posible transformar una GLC


cualquiera G en otra GLC G que está en la FNCH. Vamos a efectuar esta transformación en
dos etapas: en una primera etapa, llevaremos G a una forma intermedia Gtemp , para pasar
después de Gtemp a G .

En Gtemp las reglas son de las formas:

1. A → a, con a ∈ Σ

2. A → β, con β ∈ V V ∗

En Gtemp , los lados derechos de las reglas son, ya sea un terminal, o una cadena (no vacı́a)
de no-terminales. La manera de llevar una GLC cualquiera a la forma intermedia consiste en
introducir reglas A → a, B → b, etc., de modo que podamos poner, en vez de un terminal
a, el no-terminal A que le corresponde, con la seguridad de que después será posible obtener
a a partir de A. Por ejemplo, considérese la siguiente GLC:

1.- S → aX

2.- S → bY

3.- X → Y a

4.- X → ba

5.- Y → bXX

6.- Y → aba

Como se ve, el obstáculo para que esta GLC esté en la forma intermedia es que en los
lados derechos de varias reglas (1, 2, 3, 5) se mezclan los terminales y los no-terminales.
Por otra parte, hay reglas (4, 6) que en el lado derecho tienen varios terminales. Entonces
añadimos las reglas:

7.- A → a
4.8. TRANSFORMACIÓN DE LAS GLC Y FORMAS NORMALES 135

8.- B → b

y modificamos las reglas (1,2,3,5), reemplazando a por A y b por B:

1 .- S → AX

2 .- S → BY

3 .- X → Y A

4 .- X → BA

5 .- Y → BXX

6 .- Y → ABA

con lo que la gramática ya está en la forma intermedia. La equivalencia de la nueva


gramática con respecto a la original es muy fácil de probar.

Luego, para pasar de Gtemp a la FNCH, puede ser necesario dividir los lados derechos
de algunas reglas en varias partes. Si tenemos una regla X → X1 X2 . . . Xn , la dividimos
en dos reglas, una X → X1 W y otra W → X2 . . . Xn , donde W es una nueva variable,
es decir, no debe formar previamente parte de la gramática. Cada vez que se aplica esta
transformación, el lado derecho de la regla afectada se reduce en longitud en una unidad,
por lo que, aplicándola repetidas veces, se debe poder llegar siempre a reglas cuyo lado
derecho tiene exactamente dos no-terminales. Para el ejemplo visto arriba, la regla 5 se
convierte en:

5 .- Y → BW

5 .- W → XX

Similarmente se puede transformar la regla 6 , dejando la gramática (reglas 1 , 2 , 3 , 4 ,


5 , 5 , 6 , 6 , 7, 8) en la FNCH.


Você também pode gostar