Tema 6: Compiladores e intérpretes

Anuncio
Tema 6:
Compiladores e intérpretes
Teoría de autómatas y lenguajes formales I
Bibliografía
• Sudkamp, T. A. “Languages and machines: an
introduction to the theory of computer science”. Addison Wesley. 1997.
– capítulos 4, 15 y 16
• Aho A., Sethi R. and Ullman J. “Compiladores. Principios, técnicas y herramientas”. Addison‐
Wesley. 1990. – capítulo 1
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
2
Introducción
• Un compilador es un programa que lee un programa escrito en
un lenguaje (fuente) y lo traduce a un programa equivalente en
otro lenguaje (objeto)
• El primer compilador FORTRAN necesitó de 18 años de trabajo
para su implantación
• Hoy en día existen técnicas sistemáticas para manejar muchas
de las tareas que surgen en la compilación, y herramientas
software que facilitan el diseño
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
3
Sistema para procesamiento de un lenguaje
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
4
Fases de un compilador
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
5
Traducción de una proposición
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
6
Análisis sintáctico
• Tres tipos generales de analizadores sintácticos
– métodos universales de análisis sintáctico
• algoritmos de Cocke-Younger-Kasami y de Early
– descendentes
• construyen árboles de análisis sintáctico desde arriba (raíz) hasta abajo
(hojas)
– ascendentes
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
7
Análisis descendente en anchura
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
8
Análisis descendente en anchura
•
•
Se obtiene una derivación si la entrada pertenece al lenguaje
Puede no ser capaz de determinar si una cadena no está en el lenguaje
– camino infinito: recursividad por la izquierda
– solución: conocer la longitud de la cadena
• para ello son necesarios analizadores de varias pasadas
•
Implementación práctica: crecimiento exponencial del árbol
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
9
Análisis descendente en profundidad
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
10
Análisis descendente en profundidad (II)
• No está garantizado que se encuentre una derivación para
todas las cadenas del lenguaje
– se puede entrar en caminos infinitos
• Ejemplo: cadena de entrada (b) + b
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
11
Análisis ascendente
•
•
•
Se construirán las derivaciones más a la derecha
Reducción: dada w=u1qu2, y A
q, entonces v=u1Au2
Ejemplo: reducción de la cadena (b) + b a S
•
Generación de todas las posibles reducciones de una cadena
– w=uv
q, se produce la reducción de w a u1Av
– si u=u1q y A
– hay que probar con todas las posibles combinaciones de u y v
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
12
Análisis ascendente en anchura
•
•
Si la cadena forma parte del lenguaje, siempre se encontrará su derivación más a la derecha
Para gramáticas cuyas reglas tengan todas una longitud de su parte derecha mayor que 1, está
garantizado que la longitud del árbol no puede exceder la de la cadena, asegurando la terminación
del análisis con una derivación o un fallo
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
13
Análisis ascendente en profundidad
•
•
En la pila se almacena [u, i, v], donde uv es la forma sentencial que se va a
reducir, e i el identificador de la regla usada en la reducción
El axioma de la gramática debe ser no recursivo
– cualquier GIC se puede transformar a una equivalente con axioma no recursivo
– otra posibilidad es eliminar la condición que restringe las reducciones con S, y
cambiar la condición de finalización del lazo desde (u=S) a (u=S y v=λ)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
14
Análisis ascendente en profundidad (II)
•
Ejemplo: construir la derivación para (b + b) para la gramática AE
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
15
Predicción en analizadores descendentes
• Construcción de la derivación más a la izquierda para p
– las derivaciones serán de la forma S
* uAv
• u es el prefijo de p
– analizando lo que resta de cadena de entrada se puede reducir el
número de reglas de A que es necesario examinar
• Se asumirá que las gramáticas no tienen símbolos inútiles
• Ejemplo: derivación de la cadena acbb para la gramática
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
16
Predicción en analizadores descendentes (II)
•
Sea G = (V, Σ, P, S) una GIC, y A∈ V
– conjunto predictivo de la variable A: LA( A) = {x | S →* uAv →* ux ∈ Σ*}
– conjunto predictivo de la regla A
w:
LA( A → w) = {x | wv →* x ∈ Σ* , donde S →* uAv}
• Los conjuntos LA(A wi) satisfacen:
n
– LA( A) = U LA( A → wi )
i =1
• para cualquier GIC
– LA( A → wi ) ∩ LA( A → w j ) = ∅ para todo 1 <= i <= j <= n
• para una GIC fuertemente LL(k)
•
Ejemplo: cadena ab: predicción de tres símbolos
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
17
Predicción en analizadores descendentes (III)
• Ejemplo: cadena abc: predicción de cuatro símbolos
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
18
Predicción en analizadores descendentes (IV)
• Sea G = (V, Σ, P, S) una GIC, y k>0 un número natural
– trunck ( X ) = {u | u ∈ X con u ≤ k , o uv ∈ X con u = k}
– LAk(A) = trunck(LA(A))
– LAk(A w) = trunck(LA(A w))
• Ejemplo: conjuntos predictivos de longitud 3
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
19
FIRST
• Sea G una GIC. Para cada cadena u ∈ (V ∪ Σ)* y k>0
– FIRSTk (u ) = trunck ({x | u →* x, u ∈ Σ*})
• Ejemplo:
• Para cada k>0,
–
–
–
–
–
FIRSTk(λ) = {λ}
FIRSTk(a) = {a}
FIRSTk (au ) = {av | v ∈ FIRSTk −1 (u )}
FIRSTk(uv) = trunck(FIRSTk(u) FIRSTk(v))
si A w es una regla de G, entonces FIRSTk ( w) ⊆ FIRSTk ( A)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
20
FOLLOW
• Sea G una GIC. Para cada variable A∈ V y k>0
*
– FOLLOWk ( A) = trunck ({x | S → uAv, y x ∈ FIRSTk (v)})
• Ejemplo:
• Para todo k>0, FOLLOWk(S) contiene λ (S es el axioma de
G)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
21
Conjunto predictivo
• Sea G una GIC. Para todo k>0, A∈ V y regla A
u1u2 . . . un
– LAk(A) = trunck(FIRSTk(A) FOLLOWk(A))
– LAk(A w) = trunck(FIRSTk(w)FOLLOWk(A)) =
trunck(FIRSTk(u1)...FIRSTk(un)FOLLOWk(A))
• Ejemplo:
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
22
Gramáticas fuertemente LL(k)
• Las gramáticas fuertemente LL(k) (Left –la cadena se lee de
izqda. a dcha.- Left –derivación más a la izqda.-) garantizan
que los conjuntos predictivos LAk(A) están particionados por los
conjuntos LAk(A wi) para cada variable A∈ V
• Cuando se predice con k símbolos, es útil concatenar un
marcador de final de cadena, #k, al final de cada cadena del
lenguaje
– si S (axioma) es no recursivo, se añade #k al final de cada regla de S
– en caso contrario, se crea un nuevo axioma S’ y la regla S’ S#k
• Sea G una GIC con marcador final #k. G es fuertemente LL(k)
si siempre que existan dos derivaciones más a la izquierda
– S * u1Av1 * u1xv1 * u1zw1
– S * u2Av2 * u2yv2 * u2zw2
– donde ui, wi, z ∈ Σ* y |z|=k. Entonces x = y
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
23
Construcción de FIRSTk
• Ejemplo: First2
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
24
Construcción de FOLLOWk
Para A
u1 ... un
FL(ui) = FL(ui) U trunck { Firstk (ui+1) ...
Firstk (un) FL´(A) }
• Ejemplo:
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
25
Un ejemplo
• Ejemplo: conjuntos predictivos de longitud 2 para la
gramática
– LAk(A
w) = trunck(FIRSTk(u1)...FIRSTk(un)FOLLOWk(A))
• G es fuertemente LL(2), pues los conjuntos LAk(A
cada variable A∈ V
© Manuel Mucientes
wi) particionan LAk(A) para
Tema 6: Compiladores e intérpretes
26
Una gramática fuertemente LL(1)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
27
Analizador fuertemente LL(k)
• Ejemplo: análisis de la cadena (b + b)# para la siguiente
gramática fuertemente LL(1)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
28
Gramáticas LL(k)
• Sea G una GIC con marcador final #k. G es LL(k) si siempre
que existan dos derivaciones más a la izquierda
– S * uAv * uxv * uzw1
– S * uAv * uyv * uzw2
– donde ui, wi, z ∈ Σ* y |z|=k. Entonces x = y
• Las gramáticas fuertemente LL(k) requieren que exista una
única regla de A que pueda derivar la cadena predictiva z
desde cualquier forma sentencial que contenga A
• Las gramáticas LL(k) sólo requieren que la regla sea única
para una forma sentencial dada, uAv
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
29
Gramáticas LL(k) (II)
• Sea G una GIC, y uAv una forma sentencial de G
– el conjunto predictivo de la forma sentencial uAv es
LAk(uAv)=FIRSTk(Av)
– el conjunto predictivo de la forma sentencial uAv y la regla A
LAk(uAv, A w)=FIRSTk(wv)
w es
• Para seleccionar de forma única una regla para la forma
sentencial uAv , el conjunto LAk(uAv) debe estar particionado
por los conjuntos LAk(uAv, A wi)
– si la gramática es fuertemente LL(k), esto está garantizado y la
gramática también será LL(k)
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
30
Gramáticas LL(k) (III)
• Ejemplo: una gramática LL(k) no necesita ser fuertemente
LL(k)
– es fuertemente LL(3), es LL(2), pero no fuertemente LL(2)
• Ejemplo: la siguiente gramática es LL(3), pero no es
fuertemente LL(k) para ningún k
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
31
Gramáticas LL(k) (IV)
• El análisis determinístico con gramáticas LL(k) requiere la
construcción de los conjuntos predictivos para las formas
sentenciales generadas durante el análisis
• LAk(uAv, A w) donde w=w1 ... wn y v=v1 ... vm será:
– LAk(uAv, A
© Manuel Mucientes
w)=trunck(FIRSTk(w1)...FIRSTk(wn)FIRSTk(v1)...FIRSTk(vm))
Tema 6: Compiladores e intérpretes
32
Gramáticas LR(k)
• Analizadores ascendentes
• LR
– left: se lee la cadena de entrada de izquierda a derecha
– right: se selecciona la derivación más a la derecha
• Un analizador ascendente determinista trata de reducir la
cadena de entrada al símbolo inicial de la gramática
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
33
Problemas finales
• Dada la gramática G=({a, b}, {S, A, B}, P, S), donde P viene
dada por:
•
•
•
•
S→C
C → aC | AB | B
A → abA | ab
B → ba | BB
– Obtener el árbol de derivación para el análisis descendente en
profundidad con la cadena “aababa”. Mostrar la configuración del
árbol y de la pila en cada instante.
– ¿Es la gramática fuertemente LL(2)? Para probarlo es obligatorio
construir los conjuntos FIRST y FOLLOW (para todas las variables).
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
34
Problemas finales (II)
• Dada la gramática G=({a, b}, {S, A, B}, P, S), donde P viene
dada por:
• S → aAbB | bAbB
• A → ab | a
• B → aB | b
– Obtener el árbol de derivación para el análisis descendente en
profundidad con la cadena “babab”. Mostrar la configuración del
árbol y de la pila en cada instante.
– ¿Es la gramática fuertemente LL(2)? Para probarlo es obligatorio
construir los conjuntos FIRST y FOLLOW (para todas las variables).
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
35
Problemas finales (III)
• El lenguaje {aiabci | i > 0} es generado por las gramáticas:
– Construir los conjuntos FIRST y FOLLOW de todas las variables, así
como los conjuntos predictivos para cada una de las reglas.
– Determinar cuántos símbolos son necesarios para realizar la
predicción en cada una de las variables.
– Estimar si la gramática es fuertemente LL(k) para algún valor de k.
© Manuel Mucientes
Tema 6: Compiladores e intérpretes
36
Descargar