Title: Lenguajes Libres de Contexto
1Lenguajes Libres de Contexto
Curso de Compiladores
- Preparado por
- Manuel E. Bermúdez, Ph.D.
- Profesor Asociado
- University of Florida
2Gramáticas Libres de Contexto
- Definición Una gramática libre de contexto
(GLC) es una tupla G (?, ?, P, S), donde todas
las producciones son de la forma - A ? ?, donde A ? ? y ? ? (?u? ).
- Derivación Izquierda En cada paso, el símbolo
no-terminal más a la izquierda es el que se
re-escribe. - Derivación Derecha En cada paso, el símbolo
no-terminal más a la derecha es el que se
re-escribe. -
3(No Transcript)
4Árboles de Derivación
- Un árbol de derivación describe las
re-escrituras, en forma independiente del orden
(izquierdo o derecho). - Cada rama del árbol corresponde a una producción
en la gramática.
5(No Transcript)
6Árboles de Derivación
- Notas
- Hojas en el árbol son símbolos terminales.
- El contorno inferior es la sentencia.
- Recursividad izquierda causa ramificación a la
izquierda. - Recursividad derecha causa ramificación a la
derecha.
7Metas del Análisis Sintáctico
- Examinar la hilera de entrada ?, y determinar si
es legal o no en el lenguaje, i.e. si S gt ?. - Esto es equivalente a (intentar) construir el
árbol de derivación. - Beneficio adicional si el inento es exitoso, el
árbol refleja la estructura sintáctica de la
hilera de entrada. - Por lo tanto, el árbol debiera ser único (para
una hilera dada).
8Ambigüedad en Gramáticas
- Definición Una GLC es ambigua si existen dos
derivaciones derechas (o izquierdas, pero no
ambas) para alguna sentencia z. - Definición (equivalente) Una GLC es ambigua si
existen dos árboles de derivación diferentes,
para alguna sentencia z.
9Ambigüedad en Gramáticas
- Dos ambigüedades clásicas (al menos en lenguajes
de programación) - Recursividad simultánea izquierda/derecha
- E ? E E
- Problema del else colgante
- S ? if E then S
- ? if E then S else S
10(No Transcript)
11Reducción de Gramáticas
- Qué lenguaje genera esta gramática ?
- S ? a D ? EDBC
- A ? BCDEF E ? CBA
- B ? ASDFA F ? S
- C ? DDCF
- Respuesta L(G) a
- Problema Algunos no-terminales (y producciones)
son inútiles no se pueden usar en la
generación de ninguna sentencia.
12Reducción de Gramáticas
- Definición Una GLC es reducida sii para todo A ?
?, - a) S gt aAß, para algunos a, ß ? V,
- (decimos que A es generable), y
- b) A gt z, para algún z ? S
- (decimos que A es terminable)
- G es reducida sii todo símbolo no-terminal A es
generable y también terminable.
13Reducción de Gramáticas
- Ejemplo S ? BB A ? aA
- B ? bB ? a
- B no es terminable, porque
- B gt z, para ningún z ? S.
- A no es generable, porque
- S gt aAß, para ningunos a,ß?V.
14Reducción de Gramáticas
- Para encontrar cuáles no-terminales son
generables - Construir el grafo (?, d), donde (A, B) ? d sii
- A ? aBß es una producción.
- Verificar que todos los nodos son alcanzables
desde S.
15Reducción de Gramáticas
- Ejemplo S ? BB A ? aA
- B ? bB ? a
- A no es generable,
- porque no
es alcanzable - desde S.
S
B
A
16Reducción de Gramáticas
- Algoritmo 1 Calcular no-terminales generables
- Generable S
- while(Generable cambia) do
- para cada A ? ?Bß do
- if A ? Generable then
- Generable Generable U B
- od
- Ahora, Generable contiene los
- no-terminales que son generables
-
17Reducción de Gramáticas
- Para encontrar cuáles no-terminales son
terminables - Construir el grafo (2?, d), donde
- (N, N U A) ? d sii
- A ? X1 Xn es una producción, y para
- todo i,
- Xi ? S o bien Xi ? N.
- Verificar que el nodo ? (todos los no-terminales)
es alcanzable desde el nodo ø (vacío).
18Reducción de Gramáticas
- Ejemplo S ? BB A ? aA
- B ? bB ? a
- A, S, B no es alcanzable desde ø ! Solo A es
alcanzable desde ø. Conclusión S y B no son
terminables.
19Reducción de Gramáticas
- Algoritmo 2 Calcular no-terminales terminables
- Terminable
- while (Terminable cambia) do
- para cada A ? X1Xn do
- if todo no-terminal entre los Xs
- está en Terminable then
- Terminable Terminable U A
- od
- Ahora, Terminable contiene los
- no-terminales que son terminables.
-
20Reducción de Gramáticas
- Algorithmo 3 Reducción de una gramática
- Encontrar todos los no-terminales generables.
- Encontrar todos los no-terminales terminables.
- Eliminar cualquier producción A ? X1 Xn
- si a) A is not generable
- o si b) algún Xi no es terminable.
- Si la nueva gramática no es reducida, repetir el
proceso.
21Reducción de Gramáticas
- Ejemplo E ? E T F ? not F
- ? T Q ? P / Q
- T ? F T P ? (E)
- ? P ? i
- Generable E, T, F, P, no Generable Q
-
- Terminable P, T, E, no Terminable F,Q
- Entonces, se elimina toda producción para Q, y
toda producción cuya parte derecha contiene F ó
Q.
22Reducción de Gramáticas
- Nueva Gramática
- E ? E T
- ? T
- T ? P
- P ? (E)
- ? i
-
- Generable E , T, P Ahora, la gramática
- Terminable P, T, E está reducida.
23Reducción de Gramáticas
- Ejemplo Resultado
- S ? AB S ? a
- ? a B ? b
- A ? aA
- B ? b GenerableS
-
TerminableS,B - GenerableS,A,B
- no TerminableA Se elimina B ? b
-
- Se elimina toda producción Resultado final
- que contiene A. S ? a
24Precedencia y Asociatividad de Operadores
- Construyamos una GLC (gramática libre de
contexto) para expresiones, que consista de - El identificador i.
- , - (operadores binarios) con baja precedencia
y asociativos por la izquierda. - , / (operadores binarios) con precedencia
media, y asociativos por la derecha. - y - (operadores unarios) con la más alta
precedencia, y asociativos por la derecha.
25Gramática para Expresiones
E ? E T ? E - T ? T T ? F T ? F
/ T ? F F ? - F ? F ?
P P ? ( E ) ? i
E consiste de T's, separados
por s y 's, asociativos a la
izquierda, con precedencia baja. T consiste de
F's, separados por 's y /'s, asociativos a
la derecha, con precedencia media. F consiste
de un solo P, precedido por 's y -'s,
asociativos a la derecha, con precedencia alta.
P consiste de una E entre paréntesis, o una
i .
26Precedencia y Asociatividad de Operadores
- Precedencia
- Cuanto más abajo en la gramática, más alta la
precedencia. - Asociatividad
- Recursividad izquierda en la gramática, causa
asociatividad izquierda del operador, y causa
ramificación izquierda en el árbol. - Recursividad derecha en la gramática cause
asociatividad derecha del operador, y causa
ramificación derecha en el árbol.
27Árboles de Derivación
- Hilera de Entrada
- - i - i ( i i ) / i i
- Construcción (humana) del árbol de derivación
- Método Ascendente.
- En cada pasada se procesan los operadores de
mayor precedencia. - Los operadores de baja precedencia son los
últimos, en la parte superior del árbol.
28(No Transcript)
29Precedencia y Asociatividad de Operadores
- Ejercicio Escribir una gramática para
expresiones - El identificador i.
- , , (operadores binarios) con baja
precedencia y asociativos por la izquierda. - , (operadores binarios) con precedencia
media, y asociativos por la derecha. - _at_, ! (operadores binarios) con la más alta
precedencia, y asociativos por la izquierda. - Paréntesis sobrellevan la precedencia y la
associatividad.
30Precedencia y Asociatividad de Operadores
- Gramática E0 ? E0 E1
- ? E0 E1
- ? E0 E1
- ? E1
- E1 ? E2 E1
- ? E2 E1
- ? E2
- E2 ? E2 _at_ E3
- ? E2 ! E3
- ? E3
- E3 ? (E0)
- ? i
31Precedencia y Asociatividad de Operadores
- Ejemplo Construir el árbol de derivación para
- i i _at_ i i ( i i i ! i) ( i i ) i
_at_ i
32Árbol de Derivación
33Gramáticas de Traducción
- Definición Una gramática de traducción (o
esquema de traducción dirigido por sintaxis) es
como una GLC, pero con la siguiente
generalización - Cada producción es una tupla (A, ß, ?) ? ? x V x
V, llamada una regla de traducción, denotada - A ? ß gt ?, donde
- A es la parte izquierda,
- ß es la parte derecha, y
- ? es la parte de traducción.
34Gramáticas de Traducción
- Ejemplo Traducción de infijo a postfijo para
expresiones. - E ? E T gt E T
- ? T gt T
- T ? P T gt P T
- ? P gt P
- P ? (E) gt E Nota ()s se eliminan
- ? i gt i
- La parte de traducción describe cómo se genera la
salida, conforme se deriva la entrada.
35Gramáticas de Traducción
- Se deriva un par (?, ß), donde ? y ß son las
formas sentenciales de la entrada y salida. - ( E, E )
- gt ( E T, E T )
- gt ( T T, T T )
- gt ( P T, P T )
- gt ( i T, i T )
- gt ( i P T, i P T )
- gt ( i i T, i i T )
- gt ( i i i, i i i )
36Traducción de Hileras a Árboles
- Notación lt N t1 tn gt denota
- Gramática de traducción de hileras a árboles
- E ? E T gt lt E T gt
- ? T gt T
- T ? P T gt lt P T gt
- ? P gt P
- P ? (E) gt E
- ? i gt i
37Traducción de Hileras a Árboles
- Ejemplo
- (E, E)
- gt (E T, lt E T gt)
- gt (T T, lt T T gt)
- gt (P T, lt P T gt)
- gt (i T, lt i T gt)
- gt (i P T, lt i lt P T gt gt)
- gt (i i T, lt i lt i T gt gt)
- gt (i i P, lt i lt i P gt gt)
- gt (i i i, lt i lt i i gt gt)
38Gramáticas de Traducción
- Definición Una gramática de traducción es simple
si para cada regla A ? ? gt ß, la secuencia de
no-terminales en ? es idéntica a la secuencia que
aparece en ß. - Ejemplo E ? E T gt lt E T gt
- ? T gt T
- T ? P T gt lt P T gt
- ? P gt P
- P ? (E) gt E
- ? i gt i
39Traducción de Hileras a Árboles
- Si la gramática es simple, eliminamos los
no-terminales y la notación de árboles en las
partes de traducción - E ? E T gt
- ? T
- T ? P T gt
- ? P
- P ? (E)
- ? i gt i Suena familiar ?
-
Notación del TWS
40Árboles de Sintaxis Abstracta
- ASA es una versión condensada del árbol de
derivación. - Sin ruido (nodos intermedios).
- Es el resultado de usar una gramática de
traducción de hilera-a-árbol. - Reglas de la forma A ? ? gt 's'.
- Se construye un nodo 's', con un hijo por cada
símbolo no-terminal en ?. - Traducimos del vocabulario de entrada (símbolos
en ?), al vocabulario de nombres de nodos del
árbol (e.g. s)
41Ejemplo de ASA
G
Entrada - i - i ( i i ) / i i
Árbol de Derivación
ASA
42El Juego de Dominó Sintáctico
- La gramática
- E ? ET T ? PT P ? (E)
- ? T ? P ? i
- Las piezas de juego Una cantidad ilimitada de
cada pieza. Una pieza por cada regla en la
gramática. - El tablero de juego
- El dominó inicial arriba.
- Los dominós abajo son la hilera de entrada.
43(No Transcript)
44El Juego de Dominó Sintáctico
- Reglas del juego
- Se agregan piezas al tablero.
- Deben coincidir las partes planas, y los
símbolos. - Las líneas son infinitamente elásticas, pero no
se pueden cruzar. - Objetivo del juego
- Conectar el dominó de inicio con los dominós de
entrada. - Que no sobren partes.
45Estrategias de Análisis Sintáctico
- Las mismas que para el juego de dominó
sintáctico. - Descendente (top-down) se comienza con el
dominó inicial, se trabaja hacia la hilera de
entrada. - Ascendente (bottom-up) se comienza con la
hilera de entrada, se trabaja hacia el dominó
inicial. - En ambas estrategias, se puede procesar la
entrada de izquierda-a-derecha ? , o de
derecha-a-izquierda ? .
46Análisis Sintáctico Descendente
- Se intenta una derivación izquierda, prediciendo
la regla que hará coincidir lo que queda de la
hilera de entrada. - Se usa una hilera (una pila, en realidad) de la
cual se pretende derivar la hilera de entrada.
47Análisis Sintáctico Descendente
- Se comienza con S en la pila.
- A cada paso, dos alternativas
- ? (la pila) comienza con un símbolo terminal t.
Debe coincidir con el siguiente símbolo de
entrada. - ? comienza con un símbolo no-terminal A. Se
consulta con un oráculo FOP (Función Omnisciente
de Parsing) para determinar cuál producción de A
llevaría a coincidir con el siguiente símbolo de
entrada. - La FOP es la parte predictiva del analizador.
48(No Transcript)
49Algoritmo Clásico de Análisis Sintáctico
Descendente
- Push (Stack, S)
- while not Empty (Stack) do
- if Top(Stack) ??
- then if Top(Stack) Head(input)
- then input tail(input)
- Pop(Stack)
- else error (Stack, input)
- else P OPF (Stack, input)
- Push (Pop(Stack), RHS(P))
- od
- if (not empty(input)) then error
-
50(No Transcript)
51Análisis Sintáctico Descendente
- La mayoría de los métodos imponen cotas al número
de símbolos de la pila y de la hilera de entrada,
que se usan para escoger la producción. Para los
lenguajes de programación, la escogencia común es
(1,1). - Debemos definir FOP (A,t), donde A es el primer
símbolo en la pila, y t es el primer símbolo de
la entrada. - Requerimientos de almacenamiento O(n2), donde n
es el tamaño del vocabulario de la gramática,
O(1002).
52Análisis Sintáctico Descendente
A
?
t
- FOP (A, t) A ? ? si
- ? gt t?, para algún ?,
- ? gt e, y S gt ?A?t?, para algunos
- ?, ?, donde ? gt e.
ó
53Análisis Sintáctico Descendente
- Ejemplo S ? A B ? b
- (ilustrando 1) A ? BAd C ? c
- ? C
- FOP b c d
- B B ? b B ? b B ? b
- C C ? c C ? c C ? c
- S S ? A S ? A S ? A
- A A ? BAd A ? C ???
- OPF (A, b) A ? BAd porque BAd gt bAd
- OPF (A, c) A ? C porque C gt c
- i.e., B comienza con b, y C comienza con c.
Elementos de color café son opcionales. También
el elemento ???
54Análisis Sintáctico Descendente
- Ejemplo (ilustrando 2) S ? A A ? bAd
-
? - OPF b d ?
- S S ? A S ? A
- A A ? bAd A ? A ?
- OPF (S, b) S ? A , porque A gt bAd
- OPF (S, d) -------- , porque S gt
aS?dß - OPF (S, ? ) S ? A , porque S? es legal
- OPF (A, b) A ? bAd , porque A gt bAd
- OPF (A, d) A ? , porque S gt bAd
- OPF (A, ? ) A ? , porque S? gtA?
55Análisis Sintáctico Descendente
- Definición
- First (A) t / A gt t?, para algún ?
- Follow (A) t / S gt ?Atß, para algún ?, ß
- Cálculo de Conjuntos First
- Construir grafo (?, d), donde (A,B) ? d si
- B ? ?A?, ? gt e (i.e. First(A) ? First(B))
- Agregar a cada nodo un conjunto vacío de
terminales. - Agregar t a First(A) si A ? ?t?, ? gt e.
- Propagar los elementos de los conjuntos a lo
largo de las aristas del grafo.
56Análisis Sintáctico Descendente
- Ejemplo S ? ABCD A ? CDA C ? A
- B ? BC ? a D ? AC
- ? b ?
- Anulables A, C, D
b
a, b
Paso 1 Grafo
a
Paso 2 Conjuntos
a
Paso 3 Agregar t
a
Paso 4 Propagar
57Análisis Sintáctico Descendente
- Cálculo de Conjuntos Follow
- Construir grafo (?, d), donde (A,B) ? d si
- A ? ?B?, ? gt e.
-
- Follow(A) ? Follow(B), porque cualquier símbolo
X que sigue después de A, también sigue después
de B, porque A puede terminar en B.
58Análisis Sintáctico Descendente
- Agregar a cada nodo un conjunto vacío de
terminales. Agregar ? a Follow(S). - Agregar First(X) a Follow(A) si
- B ? ?A?X?, ? gt e.
- Nota First(t)t.
- Propagar los elementos de los conjuntos a lo
largo de las aristas del grafo.
59Análisis Sintáctico Descendente
- Ejemplo S ? ABCD A ? CDA C ? A
- B ? BC ? a D ? AC
- ? b ?
- Nullable A, C, D First(S) a, b
- First(C) a
- First(A) a
- First(D) a
- First(B) b
a
-
,
S
B
-
a
,
b,
A
C
a,b,
-
-
Blanco Paso 3
Café Paso 4
a
,
b,
D
-
60Análisis Sintáctico Descendente
- Resumiendo,
- Follow(S) ?
- Follow(A) Follow(C) Follow(D) a, b, ?
- Follow(B) a, ?
61Análisis Sintáctico Descendente
- Regresando al análisis sintáctico
- Deseamos que OPF(A, t) A ? ? si
- t ? First(?),
- i.e. ? gt tß
- ó
- ? gt e and t ? Follow(A),
- i.e. S gt ?A?
- gt ?Atß
A a
?
t ß
A a
?
e
t ß
62Análisis Sintáctico Descendente
- Definición Select (A? ?)
- First(?) U
- if ? gt e then Follow(A)
- else ø
- Así, PT(A, t) A ? ? si t ? Select(A ? ?)
- Parse Table (PT), en lugar de FOP, porque ya no
es omnisciente.
63Análisis Sintáctico Descendente
- Ejemplo First (S) a, b Follow (S) ?
- First (A) a Follow(A) a, b, ?
- First (B) b Follow(B) a, ?
- First (C) a Follow (C) a, b, ?
- First (D) a Follow(D) a, b, ?
- Gramática Conjuntos
Select
S ? ABCD a, b B ? BC b
? b b A ? CDA a, b, ? ? a a
? a, b, ? C ? A a, b, ? D ? AC a, b,
?
Gramática NO es LL(1)
64Análisis Sintáctico Descendente
Gramática no-LL(1) elementos múltiples en PT.
S ? ABCD a, b C ? A
a, b, ? B ? BC b D ? AC
a, b, ? ? b b A ? CDA a, b,
? ? a a ? a, b,
?
- a b -
- S S ? ABCD S ? ABCD
- A A ? CDA, A? a, A ? A ? CDA, A ? A ?
CDA,A ? - B B ? BC, B ? b
- C C ? A C ? A C ? A
- D D ? AC D ? AC D ? AC
65Gramáticas LL(1)
- Definición Una GLC G es LL(1)
- ( Left-to-right, Left-most, (1)-symbol lookahead)
- sii pata todo A? ?, y para todo par de
producciones - A??, A ?? con ? ? ?,
- Select (A ? ?) n Select (A ? ?) ?
- Ejemplo previo gramática no es LL(1).
- Qué hacer ? Más tarde.
66Ejemplo de gramática LL(1)
- S ? A b,?
- A ? bAd b
- ? d, ?
Disjuntos! Gramática es LL(1) !
d b ?
S S ? A S ? A
A A ? A ? bAd A ?
A lo sumo una producción en cada posición de la
tabla.
67Ejemplo
- Construir la tabla de análisis sintáctico para la
siguiente gramática. - S ? begin SL end begin
- ? id E id
- SL ? SL S begin,id
- ? S begin,id
- E ? ET (, id
- ? T (, id
- T ? PT (, id
- ? P (, id
- P ? (E) (
- ? id id
No es LL(1)
68(No Transcript)
69Ejemplo (contd)
- Lemma Rescursividad izquierda siempre produce
una gramática no-LL(1) - (e.g., SL, E)
- Prueba Considere
- A ? A? First (?) or Follow (A)
- ? ? First (?) Follow (A)
70Problemas con nuestra Gramática
- SL tiene recursividad izquierda.
- E tiene recursividad izquierda.
- T ? P T comienzan con una ? P
secuencia en común (P).
71Solución al Problema 3
- Cambiar T ? P T (, id
- ? P (, id
- a T ? P X (, id
- X ? T
- ? , , )
- Follow(X)
- Follow(T) porque T ? P X
- Follow(E) porque E ? ET , E ? T
- , , ) porque E ? ET, S ? id E
- y P ? (E)
Disjuntos!
72Solución al Problema 3 (contd)
- En general, cambiar
- A ? ??1
- ? ??2
- . . .
- ? ??n
- a A ? ? X
- X ? ?1
- . . .
- ? ?n
Con suerte, todos los ?s comienzan con símbolos
distintos
73Solución a los Problemas 1 y 2
- Queremos (((( T T) T) T))
- En su lugar, (T) (T) (T) (T)
- Cambiar E ? E T (, id
- ? T (, id
- a E ? T Y (, id
- Y ? T Y
- ? , )
- Follow(Y) ? Follow(E)
- , )
Ya no contiene , porque eliminamos la
producción E ? E T
74Solución a los Problemas 1 and 2 (contd)
- En general,
- Cambiar A ? A?1 A ? ? 1
- . . . . . .
- ? A?n ? ? m
- a A ? ?1 X X ? ?1 X
- . . . . . .
- ? ?m X ? ?n X
- ?
75Solución a los Problemas 1 and 2 (contd)
- En nuestro ejemplo,
- Cambiar SL ? SL S begin, id
- ? S begin, id
- a SL ? S Z begin, id
- Z ? S Z begin, id
- ? end
76Gramática Modificada
- S ? begin SL end begin
- ? id E id
- SL ? S Z begin,id
- Z ? S Z begin,id
- ? end
- E ? T Y (,id
- Y ? T Y
- ? ,)
- T ? P X (,id
- X ? T
- ? ,,)
- P ? (E) (
- ? id id
-
Disjuntos. La gramática es LL(1)
77(No Transcript)
78(No Transcript)
79Parsing de Descenso Recursivo
- Estrategia descendente, apropiada para
geramáticas LL(1). - Una rutina por cada no-terminal.
- Contenido de pila embebido en la secuencia de
llamadas recursivas. - Cada rutina escoge y recorre una producción,
basado en el siguiente símbolo de entrada, y los
conjuntos Select. - Buena técnica para escribir un analizador
sintáctico a mano.
80Parsing de Descenso Recursivo
- proc S S ? begin SL end
- ? id E
- case Next_Token of
- T_begin Read(T_begin)
- SL
- Read (T_end)
- T_id Read(T_id)
- Read (T_)
- E
- Read (T_)
- otherwise Error
- end
- end
Read (T_X) verifica que el siguiente token es
X, y lo consume.
Next_Token es el siguiente token.
81Parsing de Descenso Recursivo
- proc SL SL ? SZ
- S
- Z
- end
- proc E E ? TY
- T
- Y
- end
Técnicamente, debimos insistir que Next_Token
fuera T_begin o T_id, pero S hará eso de todas
maneras. Revisión temprana ayuda en la
recuperación de errores.
Lo mismo para T_( y T_id.
82Parsing de Descenso Recursivo
- proc ZZ ? SZ
- ?
- case Next Token of
- T_begin, T_id SZ
- T_end
- otherwise Error
- end
- end
83Parsing de Descenso Recursivo
Se puede usar un case
- proc Y Y ? TY
- ?
- if Next Token T_ then
- Read (T_)
- T
- Y
- end
- proc T T ? PX
- P
- X
- end
Se pudo haber insistido que Next_Token fuera T_(
o T_id.
84Parsing de Descenso Recursivo
- proc XX ? T
- ?
- if Next Token T_ then
- Read (T_)
- T
- end
85Parsing de Descenso Recursivo
- proc P P ?(E)
- ? id
- case Next Token of
- T_( Read (T_()
- E
- Read (T_))
- T_id Read (T_id)
- otherwise Error
- end
- end
86Traducción hilera-a-árbol
- Podemos obtener el árbol de derivación o el ASA.
- El árbol puede ser generado en forma ascendente o
descendente. - Mostraremos cómo obtener
- Árbol de derivación en forma descendente.
- ASA para la gramática original, en forma
ascendente.
87Generación Descendente del AD
- En cada rutina, y para cada alternativa, escribir
la producción escogida EN CUANTO HAYA SIDO
ESCOGIDA.
88Generación Descendente del AD
- proc S S ? begin SL end
- ? id E
- case Next_Token of
- T_begin Write(S ? begin SL end)
- Read(T_begin)
- SL
- Read(T_end)
- T_id Write(S ? id E)
- Read(T_id)
- Read (T_)
- E
- Read (T_)
- otherwise Error
- end
- end
89Generación Descendente del AD
- proc SL SL ? SZ
- Write(SL ? SZ)
- S
- Z
- end
- proc E E ? TY
- Write(E ? TY)
- T
- Y
- end
90Generación Descendente del AD
- proc Z Z ? SZ
- ?
- case Next_Token of
- T_begin, T_id Write(Z ? SZ)
- S
- Z
- T_end Write(Z ? )
- otherwise Error
- end
- end
91Generación Descendente del AD
- proc Y Y ? TY
- ?
- if Next_Token T_ then
- Write (Y ? TY)
- Read (T_)
- T
- Y
- else Write (Y ? )
- end
- proc T T ? PX
- Write (T ? PX)
- P X
- end
92Generación Descendente del AD
- proc XX ? T
- ?
- if Next_Token T_ then
- Write (X ? T)
- Read (T_)
- T
- else Write (X ? )
- end
93Generación Descendente del AD
- proc PP ? (E)
- ? id
- case Next_Token of
- T_( Write (P ? (E))
- Read (T_()
- E
- Read (T_))
- T_id Write (P ? id)
- Read (T_id)
- otherwise Error
- end
94Notas
- La colocación de las instrucciones Write es obvia
precisamente porque la gramática es LL(1). - El árbol puede ser construido conforme procede el
algoritmo, o puede ser construido por un
post-procesador.
95S ? begin SL end SL ? SZ S ? id E E ? TY T ?
PX P ? (E) E ? TY T ? PX P ? id X ? Y ? TY T ?
PX P ? id X ? Y ? X ? T T ? PX P ? id X ? Y ?
Z ?
96Generación Ascendente del AD
- Pudimos haber colocado las instrucciones Write al
FINAL de cada frase, en lugar del principio. De
ser así, generamos el árbol en forma ascendente. - En cada rutina, y para cada alternativa,
escribimos la producción escogida A ? ? DESPUÉS
de reconocer ?.
97Generación Ascendente del AD
- proc SS ? begin SL end
- ? id E
- case Next_Token of
- T_begin Read (T_begin)
- SL
- Read (T_end)
- Write (S ? begin SL end)
- T_id Read (T_id)
- Read (T_)
- E
- Read (T_)
- Write (S ? idE)
- otherwise Error
- end
98Generación Ascendente del AD
- proc SL SL ? SZ
- S
- Z
- Write(SL ? SZ)
- end
- proc E E ? TY
- T
- Y
- Write(E ? TY)
- end
99Generación Ascendente del AD
- proc Z Z ? SZ
- ?
- case Next_Token of
- T_begin, T_id S
- Z
- Write(Z ? SZ)
- T_end Write(Z ? )
- otherwise Error
- end
- end
100Generación Ascendente del AD
- proc Y Y ? TY
- ?
- if Next_Token T_ then
- Read (T_)
- T
- Y
- Write (Y ? TY)
- else Write (Y ? )
- end
101Generación Ascendente del AD
- proc T T ? PX
- P
- X
- Write (T ? PX)
- end
- proc XX ? T
- ?
- if Next_Token T_ then
- Read (T_)
- T
- Write (X ? T)
- else Write (X ? )
- end
102Generación Ascendente del AD
- proc PP ? (E)
- ? id
- case Next_Token of
- T_( Read (T_()
- E
- Read (T_))
- Write (P ? (E))
- T_id Read (T_id)
- Write (P ? id)
- otherwise Error
- end
103Notas
- La colocación de las instrucciones Write sigue
siendo obvia. - Las producciones se emiten conforme las rutinas
terminan, en lugar de hacerlo al empezar. - Las producciones son emitidas en orden inverso,
i.e., la secuencia de producciones debe ser
utilizada en orden inverso para producir una
derivación derecha. - Nuevamente, el árbol puede ser construido
conforme procede el algoritmo (usando una pila de
árboles), o puede ser construido por un
post-procesador.
104Ejemplo
- Hilera de Entrada
- begin id (id id) id end
- Salida
-
P ? id X ? T ? P X P ? id X ? T ? P X Y ? Y ? T
Y E ? T Y P ? ( E )
P ? id X ? T ? PX X ? T T ? PX Y ? E ? TY S ?
idE Z ? SL ? SZ S ? begin SL end
105P ? id X ? T ? P X P ? id X ? T ? P X Y ? Y ?
T Y E ? T Y P ? ( E ) P ? id X ? T ? P X X ?
T T ? P X Y ? E ? T Y S ? id E Z ? SL ? S
Z S ? begin SL end
106Recursividad vs. Iteración
- No todos los símbolos no-terminales son
necesarios. - La recursividad de SL, X, Y y Z se puede
reemplazar con iteración.
107Recursividad vs. Iteración
SL ? S Z Z ? S Z ?
- proc S S ? begin SL end
- ? id E
-
- case Next_Token of
- T_begin Read(T_begin)
- repeat
- S
- until Next_Token ? T_begin,T_id
- Read(T_end)
- T_id Read(T_id)
- Read (T_)
- E
- Read (T_)
- otherwise Error
- end
- end
SL
Reemplaza llamado a SL.
Reemplaza recursividad de Z, porque L(Z)S
108Recursividad vs. Iteración
Reemplaza recursividad de Y, porque L(Y)(T).
- proc E E ? TY
- Y ? TY
- ?
- T
- while Next_Token T_ do
- Read (T_)
- T
- od
- end
109Recursividad vs. Iteración
- proc T T ? PX
- X ? T
- ?
- P
- if Next_Token T_
- then Read (T_)
- T
- end
Reemplaza llamado a X, porque L(X)(T)? No hay
iteración, porque X no es recursivo.
110Recursividad vs. Iteración
- proc PP ? (E)
- ? id
- case Next_Token of
- T_( Read (T_()
- E
- Read (T_))
- T_id Read (T_id)
- otherwise Error
- end
- end
111Construcción Ascendente del AD, para la gramática
original
- proc S (1)S ? begin SL end (2)S ? begin SL
end - ? id E ? id E
- SL ? SZ SL ? SL S
- Z ? SZ ? S
- ?
- case Next_Token of
- T_begin Read(T_begin) S Write(SL ? S)
- while Next_Token in T_begin,T_id do
- S Write(SL ? SL S)
- od
- Read(T_end) Write(S ? begin SL end)
- T_id Read(T_id)Read (T_)ERead (T_)
- Write(S ? id E)
- otherwise Error
- end
- end
112Construcción Ascendente del AD, para la gramática
original
- proc E (1)E ? TY (2) E ? ET
- Y ? TY ? T
- ?
- T
- Write (E ? T)
- while Next_Token T_ do
- Read (T_)
- T
- Write (E ? ET)
- od
- end
while, porque Y es recursivo
113Construcción Ascendente del AD, para la gramática
original
- proc T (1)T ? PX (2) T ? PT
- X ? T ? P
- ?
- P
- if Next_Token T_
- then Read (T_)
- T
- Write (T ? PT)
- else Write (T ? P)
- end
if, porque X no es recursivo
114Construcción Ascendente del AD, para la gramática
original
- proc P(1)P ? (E) (2)P ? (E)
- ? id ? id
-
- // IGUAL QUE ANTES
- end
115P ? id T ? P E ? T P ? id T ? P E ? ET P ? (E) P
? id T ? P
T ? PT E ? T S ? idE SL? S S ? begin SL end
T ? PT E ? T S ? idE SL? S S ? begin SL end
116Generación ascendente del ASA, para la gramática
original
- proc S S ? begin S end ? 'block'
- ? id E ? 'assign'
- var Ninteger
- case Next_Token of
- T_begin Read(T_begin)
- S
- N1
- while Next_Token in T_begin,T_id do
- S
- NN1
- od
- Read(T_end)
- Build Tree ('block',N)
- T_id Read(T_id)
- Read (T_)
- E
- Read (T_)
- Build Tree ('assign',2)
- otherwise Error
Build Tree (x,n) saca n árboles de la pila,
construye un nodo x como su padre, y entra el
árbol resultante en la pila.
Asumimos que se construye un nodo.
117Generación ascendente del ASA, para la gramática
original
- proc E E ? ET ?''
- ? T
- T
- while Next_Token T_ do
- Read (T_)
- T
- Build Tree ('',2)
- od
- end
Ramificación izquierda en el árbol !
118Generación ascendente del ASA, para la gramática
original
- proc T T ? PT ?''
- ? P
- P
- if Next_Token T_
- then Read (T_)
- T
- Build Tree ('',2)
- end
Ramificación derecha en el árbol !
119Generación ascendente del ASA, para la gramática
original
- proc PP ? (E)
- ? id
- // IGUAL QUE ANTES,
- // i.e.,no se construye árbol
- // encima de E o id.
- end
120Ejemplo
- Hilera de Entrada
- begin id1 (id2 id3) id4 end
- Secuencia de eventos
id1
id4
id2
BT('',2) BT('assign',2) BT('block',1)
id3
BT('',2)
121(No Transcript)
122Resumen
- Construcción ascendente o descendente del árbol
deseado. - Gramática original o modificada.
- Árbol de derivación, o árbol de sintaxis
abstracta. - Técnica de escogencia
- Parser de descenso recursivo,
- Construcción ascendente del ASA, para la
gramática original.
123Parsing LR
- Las rutinas en el parser de descenso recursivo
pueden ser anotadas con items. - Item una producción con un marcador . en la
parte derecha. - Podemos usar los items para describir la
operación del parser de descenso recursivo. - Existe un NFA (un estado por cada item) que
describe todas las secuencias de llamadas en el
código de descenso recursivo.
124Parser de Descenso Recursivo con items
- Ejemplo
- proc E E ? .E T, E ?.T
- T E ? E. T, E ? T.
- while Next_Token T_ do
- E ? E. T
- Read(T_) E ? E .T
- T E ? E T.
- od
- E ? E T. E ? T.
- end
T
T
T
125NFA que conecta items
- NFA M (PP, V, ?, S ? .S?, S ? S?.)
- PP conjunto de todos los items posibles (PP
producciones con punto), y ? se define tal que - simula un llamado a B
-
- simula la ejecución de la rutina X,
- si X es no-terminal, o
- Read(X), si X es un terminal.
?
1
A ? a.Bß
B ? . ?
X
2
A ? a.Xß
A??X.ß
126NFA que conecta items
- Ejemplo E ? E T T ? i S ? E ?
- ? T T ? (E)
E
-
S ? . E?
S ? E ? .
S ? E . ?
e
T
E ? . T
E ? T .
e
e
e
i
e
T ? . i
T ? i .
e
(
E
T ? . (E)
T ? (E) .
T ? (.E)
)
e
T ? (E.)
e
e
e
E
T
E ? .E T
E ? E. T
E ? E . T
E ? E T.
127NFA que conecta items
- Hay que usar esta máquina con una pila (la
secuencia de llamadas recursivas). - Para regresar de A ? ?., retrocedemos ? 1
estados, y avanzamos sobre A. - Problema de esta máquina es no-determnística.
- No problem. Be happy ?.
- Transformémosla a una DFA !
128DFA que conecta items
-
E
-
-
-
S ? . E
S ? E .
S ? E .
E ? .E T
E ? E. T
E ? . T
T ? . i
i
i
T
E ? E T.
E ? E . T
T ? i .
T ? . (E)
T ? .i
(
T ? .(E)
i
T
(
T
E ? T .
T ? (.E)
E ? .E T
E
)
T ? (E.)
(
T ? (E) .
E ? .T
E ? E. T
T ? .i
T ? .(E)
- ESTE ES UN AUTÓMATA LR(0)
129Parsing LR
- LR significa Left-to-Right, Right-most
Derivation. - Necesitamos una pila de estados para operar el
parser. - Se requieren 0 símbolos de look-ahead, por lo
que se denomina LR(0). - El DFA describe todas las posiciones posibles en
el código de descenso recursivo. - Una vez construido el automáta, se pueden
descartar los items (como siempre con NFA ?DFA).
130Parsing LR
- Operación de un parser LR
- Dos movimientos shift y reduce.
- Shift Avanzar desde el estado actual sobre
Next_Token, y agregar el estado nuevo a la pila. - Reduce (sobre A ? ?). Remover ? estados de la
pila. Avanzar desde el nuevo estado, sobre A.
131Parsing LR
- Pila Entrada Árbol deDerivación
- 1 i (i i) - i (
i i ) - 14 (i i) -
- 13 (i i) -
- 12 (i i) -
- 127 (i i) -
- 1275 i i) -
- 12754 i) -
- 12753 i)-
- 12758 i) -
- 127587 i) -
- 1275874 ) -
- 1275879 ) -
- 12758 ) -
- 12758 10 -
- 1279 -
- 12
- - 126 ---------
E ? T
T
1
3
T
(
T
E
i
E
(
i
2
4
5
T?i
T
i
E
(
-
E
6
7
8
T
E
)
T
T
E
9
10
T ? (E)
E ? ET
132Parsing LR
- Representación de Parsers LR
- Dos Tablas
- Acción indexada por estado y símbolo terminal.
Contiene los movimientos shift y reduce. - GOTO indexada por estado y símbolo no-terminal.
Contiene las transiciones sobre símbolos
no-terminales.
133Parsing LR
ACCIÓN GOTO
i ( ) E T
-
E ? T
1 S/4 S/5 2 3
2 S/7 S/6
3 R/E?T R/E?T R/E?T R/E?T R/E?T
4 R/T? i R/T? i R/T? i R/T? i R/T? i
5 S/4 S/5 8 3
6 Accept Accept Accept Accept Accept
7 S/4 S/5 9
8 S/7 S/10
9 R/ E ?ET R/ E ?ET R/ E ?ET R/ E ?ET R/ E ?ET
10 R/ T ? (E) R/ T ? (E) R/ T ? (E) R/ T ? (E) R/ T ? (E)
T
1
3
(
T
E
i
(
2
4
5
T?i
i
i
E
(
-
6
7
8
)
T
9
10
T ? (E)
E ? ET
134Parsing LR
- Algoritmo Driver_LR
- Push(Start_State, S)
- while ACTION (Top(S), ?) ? Accept do
- case ACTION (Top(S), Next_Token) of
- Shift/r Read(Next_Token)
- Push(r, S)
- Reduce/A ? ? Pop(S) ? veces
- Push(GOTO (Top(S), A), S)
- empty Error
- end
- end
135Parsing LR
- Construcción Directa del Autómata LR(0)
- PT(G) Closure(S ? .S ? ) U
- Closure(P) P ? Successors(P), P ? PT(G)
- Closure(P) P U A ? .w B ? a.Aß ? Closure(P)
- Successors(P) Nucleus(P, X) X ? V
- Nucleus(P, X) A ? aX .ß A ? a.Xß ? P
136Parsing LR
E ? E T T ? i S ? E ? ? T T ? (E)
- Construcción Directa del Autómata LR(0) previo
-
)
E
E
T ? (E.) E ? E. T
S ? .E E ? .E T E ? .T T ? .i T ? .(E)
T ? (.E) E ? .E T E ? .T T ? .i T ? .(E)
2
8
10
1
5
8
E
E
2
8
7
T
T
E ? E T.
3
3
9
i
i
4
4
T ? (E).
10
(
(
5
5
-
-
S ? E . E ? E. T
S ? E?.
2
6
6
7
T
E ? E .T T ? .i T ? .(E)
9
7
i
E ? T.
4
3
(
5
T ? i.
4
137Parsing LR
- Notas
- Esta gramática es LR(0) porque no tiene
conflictos. - Un conflicto ocurre cuando un estado contiene
- a. Conflicto shift-reduce un item final (A ?
?.) - y un item no-final (A ? a.ß), o
- b. Conflicto reduce-reduce Dos o más items
- finales (A ? ?. y B ? ?.).
138Parsing LR
- Ejemplo E ? E T T ? P T P ? i
- ? T ? P P ? (E)
-
E
E
T
T ? P .T T ? .P T T ? .P P ? .i P ? .(E)
S ? .E E ? .E T E ? .T T ? .P T T ? .P P ?
.i P ? .(E)
P ? (.E) E ? .E T E ? .T T ? .P T T ? .P P ?.
i P ? .(E)
2
10
12
1
6
9
E
E
P
2
10
4
P
T
T
4
3
3
i
P
P
5
4
4
(
P
P
4
6
4
i
i
5
5
)
P ? (E.) E ? E. T
13
10
(
(
6
8
6
-
-
-
S ? E .
S ? E . E ? E. T
E ? E T.
7
11
2
7
T
E ? E .T T ? .P T T ? .P P ? .i P ? .(E)
11
8
8
T ? P T .
12
E ? T.
P
4
3
P
P ? (E).
4
13
T ? P. T T ? P.
9
4
i
5
La gramática no es LR(0).
(
6
P ?i.
5
139Parsing LR
- El conflicto aparece en la table ACCIÓN, como
entradas múltiples. - i ( )
- 1 S/5 S/6
- 2 S/8
S/7 - 3 R/E?T
- 4
- 5 R/P?i
- 6 S/5 S/6
- 7 Accept
- 8 S/5 S/6
- 9 S/5 S/6
- 10 S/8
S/13 - 11 R/E?ET
- 12 R/T?PT
- 13 R/P?(E)
-
ACCIÓN
R/T?P S/9,R/T?P R/T?P
140Parsing LR
- Solución Utilizar lookahead, tomando en cuenta
el siguiente símbolo de entrada en la decisión de
parsing. - En LL(1), lookahead se usa al principio de la
producción. - En LR(1), lookahead se usa al final de la
producción. - Usaremos SLR(1) Simple LR(1)
- LALR(1) LookAhead LR(1)
141Parsing LR
- SLR(1)
- Calculamos Follow(A) para cada producción A ??
que causa un conflicto. Luego, se coloca R/A ?
? en ACCIÓNp,t solo si t ? Follow(A). - Aquí, Follow(T) ? Follow(E) , ), ? .
- i ( )
- - 4 (antes) R/T?P S/9,R/T?P R/T?P
R/T?P R/T?P R/T?P - 4 (después) R/T?P S/9 R/T?P
R/T?P
Problema resuelto. La gramática es SLR(1)
142Parsing LR
- Ejemplo S ? aSb anbn/ n gt 0
- ?
-
S
4
-
1
2
4
S
S ? .S S ? .aSb S ? .
2
S ?
1
a
3
a
b
S
3
5
6
S ? aSb
-
-
S ?
S ? S .
a
4
2
a b ? S
1 S/3 R/S? R/S? R/S? 2
2 S/4
3 S/3 R/S? R/S? R/S? 5
4 Accept Accept Accept
5 S/6
6 R/S?aSb
S ? a.Sb S ? .aSb S ? .
S
5
3
a
3
-
S ? S .
4
b
S ? aS.b
6
5
S ? aSb.
6
La gramática no es LR(0)
143Parsing LR
- Análisis SLR(1)
- Estado 1 Follow(S)b, ?. Ya que a ?
Follow(S), el conflicto shift/reduce queda
resuelto. - Estado 3 La misma historia.
- Las filas 1 y 3 resultantes
- a b - S
- 1 S/3 R/S ? R/S ? 2
- 3 S/3 R/S ? R/S ? 5
-
- Conflictos resueltos. La gramática es SLR(1).
144Parsing LR
- Gramáticas LALR(1)
- Ejemplo S ? AbAa A ? a
- ? Ba B ? a
- Autómata
- LR(0)
S
?
1
2
6
A
a
b
3
7
10
A ? a
A
a
A ? AbAa
9
11
B
a
4
8
S ? Ba
a
A ? a
5
Conflicto reduce-reduce. La gramática no es LR(0).
B ? a
145Parsing LR
- Análisis LR(0)
- a b -
- R/A?a,R/B?a R/A?a,R/B?a R/A?a,R/B?a
-
- La gramática no es LR(0).
-
Análisis SLR(1) Follow(A)a,b, No
disjuntos. Follow(B)a Conflicto no
resuelto. a b - 5
R/A?a,R/B?a R/A?a
La gramática no es SLR(1).
146Parsing LR
- Técnica LALR(1)
- I. Para cada reducción conflictiva A ? ? en cada
estado inconsistent q, hayar todas las
transiciones no-terminales (pi, A) tales que -
- II. Calcular Follow(pi, A) (ver abajo), para
todo i, y unir los resultados. El conjunto que
resulta es el conjunto de lookahead LALR(1)
para la reducción A ? ? en q.
A
p1
?
q
A ? ?
?
A
pn
147Parsing LR
- Cálculo de Follow(p, A)
- Es el cálculo ordinario Follow, en otra
gramática, llamada G. Para cada transición (p,
A), y cada producción A?w1 w2wn, tenemos -
- En esta situación, G contiene esta producción
- (p, A) ? (p, w1)(p2, w2)(pn, wn)
- G Consiste de las transiciones en el autómata
LR(0). Refleja la estructura de G, y la del
autómata LR(0).
A
p
w1
Wn
Wn-1
w2
p2
A ? w1wn
p3
pn
148Parsing LR
- En nuestro ejemplo G S ? AbAa A ? a
- ? Ba B ? a
-
-
-
- G (1, S) ? (1, A)(3, b)(7, A)(9, a)
- ? (1, B)(4, a)
- (1, A) ? (1, a)
- (7, A) ? (7, A)
- (1, B) ? (1, a)
S
?
1
2
6
A
a
b
3
7
10
A ? a
A
a
A ? AbAa
9
11
B
a
4
8
S ? Ba
a
A ? a
5
B ? a
Estos se separaron !
149Parsing LR
- Para el conflicto en el estado 5, necesitamos
- Follow(1, A) (3, b)
- Follow(1, B) (4, a). Se extraen los
símbolos terminales -
- a b -
- 5 R/B ? a R/A ? a Conflicto
resuelto. - La gramática es LALR(1).
A ? a b
a
5
B ? a a
150Parsing LR
- Ejemplo S ? bBb B ? A
- ? aBa A ? c
- ? acb
- Autómata
- LR(0)
?
S
1
2
5
8
A ? c
c
b
B
b
11
6
3
S ? bBb
A
7
B ? A
A
S ? aBa
a
a
B
4
12
9
c
b
10
13
S ? acb
A ? c
Estado 10 es inconsistente (conflicto
shift-reduce).
La gramática no es LR(0)
151Parsing LR
- Análisis SLR(1), estado 10
- Follow(A) ? Follow(B) a, b.
- La gramática no es SLR(1).
- Análisis LALR(1) Se necesita Follow(4, A).
- G (1,S) ? (1, b)(3, B)(6, b) (3, B) ? (3,
A) - ? (1, a)(4, B)(9, a) (4, B) ? (4,
A) - ? (1, a)(4, c)(10, b) (3, B) ? (3,
c) - (4, A) ? (4, c)
- Así, Follow(4, A) ? Follow(4, B) (9, a).
- El conjunto lookahead es a. La gramática es
LALR(1).
152Resumen de Parsing
- Parsing Descendente (top-down)
- Escrito a mano o dirigido por tabla LL(1)
S
Parte conocida
Parte conocida
pila
w
Parte por predecir
ß
a
Entrada por procesar
Entrada procesada
153Resumen de Parsing
- Parsing Ascendente (bottom-up)
- Dirigida por tabla LR(0), SLR(1), LALR(1).
S
Parte conocida
Parte desconocida
pila
w
Parte conocida
ß
a
Entrada por procesar
Entrada procesada
154Lenguajes Libres de Contexto
Curso de Compiladores
- Preparado por
- Manuel E. Bermúdez, Ph.D.
- Profesor Asociado