Procesadores de Lenguaje Tema 4: Analizador sintáctico ...
Procesadores de Lenguaje Tema 4: Analizador sintáctico ...
Procesadores de Lenguaje Tema 4: Analizador sintáctico ...
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Procesadores</strong> <strong>de</strong> <strong>Lenguaje</strong><br />
<strong>Tema</strong> 4: <strong>Analizador</strong> <strong>sintáctico</strong><br />
3 er curso<br />
2º cuatrimestre<br />
Alfonso Ortega: alfonso@ii.uam.es<br />
<strong>Analizador</strong> <strong>sintáctico</strong><br />
Conceptos<br />
• Se ocupa específicamente <strong>de</strong>l tratamiento <strong>de</strong> la parte <strong>de</strong>l lenguaje <strong>de</strong> programación<br />
que es in<strong>de</strong>pendiente <strong>de</strong>l contexto<br />
• Recuer<strong>de</strong> el alumno la <strong>de</strong>finición que vio en TALF <strong>de</strong> gramáticas in<strong>de</strong>pendientes <strong>de</strong>l<br />
contexto<br />
• < Σ T<br />
, Σ N<br />
, axioma, reglas ><br />
• Don<strong>de</strong><br />
• axioma ∈ Σ N<br />
• reglas ∈ ℘(Σ N<br />
×Σ * ),, Σ * = Σ T<br />
∪Σ N<br />
• Es <strong>de</strong>cir, las reglas <strong>de</strong> producción tienen la forma<br />
A→v,,A ∈ Σ N<br />
∧ v ∈ (Σ T<br />
∪Σ N<br />
) *<br />
• También recibe el nombre <strong>de</strong> “parser”<br />
• Suele ser el que gobierna todo el proceso <strong>de</strong> análisis.<br />
• El proceso <strong>de</strong> análisis pue<strong>de</strong> enten<strong>de</strong>rse como el mecanismo para obtener el “árbol<br />
<strong>sintáctico</strong> <strong>de</strong> <strong>de</strong>rivación <strong>de</strong>l programa (en caso <strong>de</strong> ser correcto) que es una manera<br />
<strong>de</strong> po<strong>de</strong>r reducir el programa completo al axioma <strong>de</strong> la gramática.<br />
• Recuér<strong>de</strong>se que, tras el paso <strong>de</strong> análisis morfológico, los símbolos terminales para<br />
este paso son las unida<strong>de</strong>s sintácticas reconocidas por el analizador morfológico<br />
Construcciones <strong>de</strong> lenguajes no in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Declaración <strong>de</strong> i<strong>de</strong>ntificadores antes <strong>de</strong> su uso [Aho]<br />
• Considérese el siguiente lenguaje<br />
L={wcw|w∈(a|b)*}<br />
• Al analizar alguna <strong>de</strong> sus palabras:<br />
• aabcaab<br />
• aca<br />
• bcb<br />
• Po<strong>de</strong>mos interpretar que abstrae la circunstancia <strong>de</strong> utilizar un i<strong>de</strong>ntificador que ha<br />
sido previamente <strong>de</strong>clarado:<br />
• En aabcaab el i<strong>de</strong>ntificador sería aab<br />
• En aca el i<strong>de</strong>ntificador sería a<br />
• En bcb el i<strong>de</strong>ntificador sería b<br />
• En cualquiera <strong>de</strong> las situaciones, la primera aparición <strong>de</strong>l i<strong>de</strong>ntificador representa su<br />
<strong>de</strong>claración y la segunda su uso.<br />
• Observe que el lenguaje supone una simplificación bastante gran<strong>de</strong> <strong>de</strong> la situación<br />
real <strong>de</strong>scrita (ausencia <strong>de</strong> tipo en la <strong>de</strong>claración necesaria en muchos lenguajes, por<br />
ejemplo<br />
3<br />
4
Construcciones <strong>de</strong> lenguajes no in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Declaración <strong>de</strong> i<strong>de</strong>ntificadores antes <strong>de</strong> su uso [Aho]<br />
• Se pue<strong>de</strong> <strong>de</strong>mostrar, no es objeto <strong>de</strong> este curso, que el lenguaje anterior no es<br />
in<strong>de</strong>pendiente <strong>de</strong>l contexto.<br />
• Cualquier lenguaje real que tenga esta característica necesitará reglas todavía más<br />
complicadas (el lenguaje anterior es una simplificación <strong>de</strong>l problema)<br />
• Por lo tanto, ninguno <strong>de</strong> los lenguajes <strong>de</strong> programación en los que haya que <strong>de</strong>clarar<br />
los i<strong>de</strong>ntificadores antes <strong>de</strong> su uso sean in<strong>de</strong>pendientes <strong>de</strong>l contexto.<br />
• Posibles soluciones:<br />
• Utilizar una arquitectura abstracta más potente que los autómatas a pila para<br />
gestionar los lenguajes<br />
• Intentar añadir a la gramática algún mecanismo que permita solucionar el<br />
problema:<br />
• Por ejemplo la tabla <strong>de</strong> símbolos.<br />
• Es la opción utilizada<br />
Construcciones <strong>de</strong> lenguajes no in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Declaración <strong>de</strong> i<strong>de</strong>ntificadores antes <strong>de</strong> su uso [Aho]<br />
• Considérese el siguiente lenguaje<br />
L={a n b m c n d m |n≥1, m≥1}<br />
• Al analizar alguna <strong>de</strong> sus palabras:<br />
• aaabcccd<br />
• abbcdd<br />
• aaaaabbcccccdd<br />
• La coinci<strong>de</strong>ncia <strong>de</strong> número <strong>de</strong> repeticiones <strong>de</strong> la ca<strong>de</strong>na <strong>de</strong> aes y <strong>de</strong> ces y <strong>de</strong> la<br />
ca<strong>de</strong>na <strong>de</strong> bes y <strong>de</strong> <strong>de</strong>s se pue<strong>de</strong> interpretar como la comprobación en la llamada <strong>de</strong><br />
una subrutina <strong>de</strong> que se tiene el mismo número <strong>de</strong> parámetros que en la <strong>de</strong>claración<br />
• En aaabcccd el número <strong>de</strong> parámetros <strong>de</strong> la pareja aaa···ccc··· es 3 y el<br />
<strong>de</strong> la pareja ···b···d es 1.<br />
• En abbcdd el número <strong>de</strong> parámetros <strong>de</strong> la pareja a···c··· es 1 y el <strong>de</strong> la<br />
pareja ···bb···dd es 2.<br />
• En aaaabbcccccdd el número <strong>de</strong> parámetros <strong>de</strong> la pareja<br />
aaaaa···ccccc··· es 5<br />
• En cualquiera <strong>de</strong> las situaciones, la primera ca<strong>de</strong>na representa la <strong>de</strong>claración <strong>de</strong> la<br />
subrutina y la segunda una llamada<br />
• Observe que el lenguaje supone una simplificación bastante gran<strong>de</strong> <strong>de</strong> la situación<br />
real <strong>de</strong>scrita (ausencia <strong>de</strong> nombre <strong>de</strong> función y tipo <strong>de</strong> los argumentos)<br />
5<br />
6<br />
Construcciones <strong>de</strong> lenguajes no in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Declaración <strong>de</strong> i<strong>de</strong>ntificadores antes <strong>de</strong> su uso [Aho]<br />
• Se pue<strong>de</strong> <strong>de</strong>mostrar, no es objeto <strong>de</strong> este curso, que el lenguaje anterior no es<br />
in<strong>de</strong>pendiente <strong>de</strong>l contexto.<br />
• Cualquier lenguaje real que tenga esta característica necesitará reglas todavía más<br />
complicadas (el lenguaje anterior es una simplificación <strong>de</strong>l problema)<br />
• Por lo tanto, ninguno <strong>de</strong> los lenguajes <strong>de</strong> programación en los que tenga subrutinas<br />
con argumentos (en todos ellos las llamadas tienen que proporcionar el mismo<br />
número <strong>de</strong> argumentos <strong>de</strong>clarados) es in<strong>de</strong>pendientes <strong>de</strong>l contexto.<br />
• Posibles soluciones:<br />
• Utilizar una arquitectura abstracta más potente que los autómatas a pila para<br />
gestionar los lenguajes<br />
• Intentar añadir a la gramática algún mecanismo que permita solucionar el<br />
problema:<br />
• Por ejemplo la tabla <strong>de</strong> símbolos.<br />
• Es la opción utilizada<br />
Construcciones <strong>de</strong> lenguajes in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Construcciones <strong>de</strong> la programación estructurada:<br />
• Consi<strong>de</strong>re el siguiente fragmento <strong>de</strong> la gramática <strong>de</strong> ASPLE que tiene para este año<br />
7 : ::= <br />
8 : | ; <br />
22 : ::= if then fi<br />
23 : | if then else fi<br />
24 : ::= while do end<br />
25 : | repeat until <br />
• Estas reglas representan respectivamente las construcciones <strong>de</strong> control <strong>de</strong> flujo <strong>de</strong><br />
programa <strong>de</strong> la programación estructurada:<br />
• Bloque <strong>de</strong> sentencias<br />
• Sentencia <strong>de</strong> control <strong>de</strong> flujo condicional<br />
• Sentencia <strong>de</strong> control <strong>de</strong> flujo iterativa<br />
• La existencia <strong>de</strong> estas reglas muestra que son construcciones in<strong>de</strong>pendientes <strong>de</strong>l<br />
contexto<br />
7<br />
8
Construcciones <strong>de</strong> lenguajes in<strong>de</strong>pendientes <strong>de</strong>l contexto<br />
Conclusiones<br />
• Es suficiente el uso <strong>de</strong><br />
• Gramática in<strong>de</strong>pendiente <strong>de</strong>l contexto<br />
• Tabla <strong>de</strong> símbolos<br />
<strong>Analizador</strong> <strong>sintáctico</strong><br />
Conceptos: clases <strong>de</strong> estrategias <strong>de</strong> análisis <strong>sintáctico</strong><br />
• Segundo enfoque:<br />
• A partir <strong>de</strong> la ca<strong>de</strong>na <strong>de</strong> “tokens” <strong>de</strong>vueltos por el analizador morfológico, se<br />
comienza a leer intentando i<strong>de</strong>ntificar las partes <strong>de</strong>rechas <strong>de</strong> las reglas <strong>de</strong> la<br />
gramática.<br />
• Cuando esto ocurre se sustituye la ca<strong>de</strong>na <strong>de</strong> “tokens” por el no terminal <strong>de</strong> la<br />
parte izquierda <strong>de</strong> la regla y se continúa el mismo análisis teniendo en cuenta<br />
esta sustitución<br />
• Si en algún momento ninguna secuencia <strong>de</strong> la ca<strong>de</strong>na se correspon<strong>de</strong> con la<br />
parte <strong>de</strong>recha <strong>de</strong> ninguna regla tal vez se tenga que <strong>de</strong>shacer alguna elección<br />
para probar si con otra <strong>de</strong>cisión se consigue terminar el análisis<br />
• Cuando se han probado sistemáticamente todas las opciones sin po<strong>de</strong>r terminar<br />
el análisis se concluye que el programa es sintácticamente incorrecto.<br />
• La otra forma <strong>de</strong> terminar el análisis es cuando se consigue obtener por el<br />
mecanismo <strong>de</strong>scrito el axioma <strong>de</strong> la gramática.<br />
• En este último caso se concluye que el programa es sintácticamente correcto.<br />
9<br />
10<br />
<strong>Analizador</strong> <strong>sintáctico</strong><br />
Conceptos: clases <strong>de</strong> estrategias <strong>de</strong> análisis <strong>sintáctico</strong><br />
• Las diferentes técnicas para resolver el problema se pue<strong>de</strong>n agrupar <strong>de</strong> la siguiente<br />
forma:<br />
• Primer enfoque<br />
• A partir <strong>de</strong>l axioma <strong>de</strong> la gramática y el programa (transformado en secuencia<br />
<strong>de</strong> “tokens” por el analizador morfológico):<br />
• Probar con las distintas opciones <strong>de</strong> <strong>de</strong>rivación para cada no terminal que<br />
encontremos<br />
• Ir avanzando simultáneamente en el programa y en las hojas <strong>de</strong>l árbol <strong>de</strong><br />
<strong>de</strong>rivación que estamos construyendo, cuando haya coinci<strong>de</strong>ncia entre el<br />
terminal actual en el programa y el terminal <strong>de</strong> la hoja actual <strong>de</strong>l árbol.<br />
• Hasta que<br />
• O bien se recorra por completo la ca<strong>de</strong>na y coincida con las hojas <strong>de</strong>l árbol<br />
y, por tanto, el programa es sintácticamente correcto<br />
• O bien se intentan todas las opciones posibles para cada no terminal<br />
(incluido el axioma) y no se pue<strong>de</strong> completar el análisis por lo que el<br />
programa es sintácticamente incorrecto.<br />
<strong>Analizador</strong> <strong>sintáctico</strong><br />
Conceptos: clases <strong>de</strong> estrategias <strong>de</strong> análisis <strong>sintáctico</strong><br />
• Al primer enfoque, por la manera y el or<strong>de</strong>n en que proce<strong>de</strong> se le conoce también<br />
como análisis <strong>de</strong>scen<strong>de</strong>nte o “top down”.<br />
• Por la misma razón al segundo enfoque se le conoce también como análisis<br />
ascen<strong>de</strong>nte o “bottom up”.<br />
11<br />
12
Análisis <strong>sintáctico</strong> <strong>de</strong>scen<strong>de</strong>nte<br />
Introducción<br />
• El alumno pue<strong>de</strong> imaginar alguna solución a este problema con las herramientas que<br />
ha adquirido en otras materias <strong>de</strong> la carrera.<br />
• Se está ante una situación en la que se <strong>de</strong>be encontrar una <strong>de</strong>rivación (secuencia <strong>de</strong><br />
aplicación <strong>de</strong> reglas <strong>de</strong> la gramática en lugares concretos) que lleve <strong>de</strong>s<strong>de</strong> el no<br />
terminal inicial (el axioma) hasta la situación final (el programa proporcionado como<br />
entrada)<br />
• A<strong>de</strong>más, el número <strong>de</strong> posibles <strong>de</strong>rivaciones es muy gran<strong>de</strong> (potencialmente infinito)<br />
• Esta situación pue<strong>de</strong> a los problemas <strong>de</strong> búsqueda <strong>de</strong> un camino que llevara <strong>de</strong> una<br />
situación inicial a otra final atravesando un espacio enorme <strong>de</strong> posibles situaciones.<br />
• Ya se ha estudiado en asignaturas como IA la existencia <strong>de</strong> estrategias generales<br />
(para cualquier problema) <strong>de</strong> búsqueda ciega y sus propieda<strong>de</strong>s <strong>de</strong> las que se<br />
mencionan algunas:<br />
• Las dos estrategias básicas son en anchura y en profundidad<br />
• En anchura siempre se pue<strong>de</strong> conseguir encontrar la solución óptima (aquella<br />
para la que se requiere un menor número <strong>de</strong> pasos)<br />
• En profundidad, excepto árboles infinitos, se suele tener oportunidad <strong>de</strong><br />
encontrar alguna solución con menos esfuerzo<br />
Análisis <strong>sintáctico</strong> <strong>de</strong>scen<strong>de</strong>nte<br />
“Top-down” con vuelta atrás lenta: conceptos<br />
• Podríamos consi<strong>de</strong>rar el análisis <strong>sintáctico</strong> top-down con vuelta atrás lenta como un<br />
caso particular <strong>de</strong> búsqueda ciega en profundidad (se <strong>de</strong>sempate <strong>de</strong> izquierda a<br />
<strong>de</strong>recha)<br />
• El criterio para <strong>de</strong>cidir si una regla es aplicable en una posición es la coinci<strong>de</strong>ncia <strong>de</strong><br />
esa posición con el no terminal que está en la parte izquierda <strong>de</strong> la regla.<br />
• No podremos continuar por un camino cuando tengamos terminales que discrepen<br />
con el programa (po<strong>de</strong>mos suponer el or<strong>de</strong>n <strong>de</strong> recorrido natural <strong>de</strong>l programa (<strong>de</strong><br />
izquierda a <strong>de</strong>recha)<br />
• Habremos terminado el proceso en dos situaciones:<br />
• Si el árbol <strong>de</strong> <strong>de</strong>rivación “se cierra” porque se ha llegado a eliminar todos los no<br />
terminales y se obtiene la misma secuencia <strong>de</strong> terminales <strong>de</strong>l programa. En este<br />
caso se ha construido un árbol <strong>sintáctico</strong> para el programa que resulta ser<br />
correcto<br />
• Si no se ha podido “cerrar” el árbol <strong>de</strong> <strong>de</strong>rivación pero se ha probado todas las<br />
reglas en cada posición y no se pue<strong>de</strong> aplicar ninguna otra opción. En ese caso<br />
se ha <strong>de</strong>mostrado que el programa es sintácticamente incorrecto.<br />
• Describiremos esta técnica mediante los siguientes ejemplos<br />
13<br />
14<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
• Análisis <strong>sintáctico</strong> <strong>de</strong> la palabra aaabbb<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
15<br />
16
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
17<br />
18<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
S<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a S b a S<br />
b<br />
19<br />
20
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
S<br />
a<br />
S<br />
b<br />
S<br />
S<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
b<br />
a<br />
S<br />
b<br />
a b a b<br />
21<br />
22<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
S<br />
a<br />
S<br />
b<br />
S<br />
a<br />
S<br />
b<br />
a<br />
S<br />
ba<br />
S<br />
b<br />
a<br />
S<br />
b<br />
a<br />
b<br />
23<br />
24
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
• La siguiente palaba<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
a<br />
S<br />
S<br />
S<br />
b<br />
b<br />
aaabbb<br />
G=<br />
a<br />
a<br />
S<br />
S<br />
S<br />
b<br />
b<br />
aaabbb<br />
a<br />
b<br />
a<br />
b<br />
25<br />
26<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
• Análisis <strong>sintáctico</strong> <strong>de</strong> la palabra abbb<br />
G=<br />
a<br />
a<br />
S<br />
S<br />
S<br />
b<br />
b<br />
aaabbb<br />
G=<br />
S<br />
abbb<br />
a<br />
b<br />
ACEPTADA<br />
27<br />
28
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
a<br />
S<br />
b<br />
29<br />
30<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
S<br />
b<br />
S<br />
a S b a S<br />
b<br />
a<br />
b<br />
a<br />
S<br />
b<br />
31<br />
32
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a S b a S<br />
b<br />
a<br />
b<br />
a<br />
S<br />
b<br />
a b<br />
33<br />
34<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
a<br />
b<br />
a<br />
S<br />
b<br />
35<br />
36
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
• Análisis <strong>de</strong> la palabra i+--i<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
RECHAZADA<br />
37<br />
38<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
- E<br />
- E<br />
39<br />
40
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
i<br />
i<br />
- E<br />
41<br />
42<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E +<br />
- E<br />
E<br />
i<br />
- E<br />
43<br />
44
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E<br />
- E<br />
E<br />
i<br />
+<br />
E<br />
i<br />
- E<br />
45<br />
46<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E<br />
- E<br />
E +<br />
i -<br />
E<br />
i - E<br />
E<br />
47<br />
48
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E<br />
- E<br />
E +<br />
i -<br />
E<br />
i - E<br />
E<br />
- E<br />
49<br />
50<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E<br />
- E<br />
E +<br />
i -<br />
E<br />
i - E<br />
E<br />
- E<br />
- E<br />
E<br />
- E<br />
- E<br />
- E<br />
51<br />
52
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
G=<br />
E<br />
- E<br />
E<br />
E +<br />
i -<br />
E<br />
E E<br />
i - E<br />
E<br />
i+--i<br />
G=<br />
E<br />
- E<br />
E<br />
E +<br />
i -<br />
E<br />
E E<br />
i - E<br />
E<br />
i+--i<br />
- E E<br />
- E E<br />
i<br />
- E<br />
i<br />
- E<br />
ACEPTADA<br />
53<br />
54<br />
Análisis “top-down”, vuelta atrás lenta<br />
Ejemplos previos<br />
• Consi<strong>de</strong>rar el análisis para i++i<br />
G=<br />
E<br />
i+--i<br />
Análisis “top-down”, vuelta atrás lenta<br />
Conclusiones<br />
• Como el alumno habrá observado, la presencia en la gramática <strong>de</strong> reglas recursivas<br />
por la izquierda hace que este tipo <strong>de</strong> análisis encuentre bucles infinitos <strong>de</strong> los que<br />
no pue<strong>de</strong> salir.<br />
• En las siguientes transparencias se sacará provecho <strong>de</strong> este <strong>de</strong>scubrimiento y se<br />
presentará otras propieda<strong>de</strong>s <strong>de</strong> las gramáticas interesantes para la construcción <strong>de</strong><br />
analizadores <strong>sintáctico</strong>s <strong>de</strong>scen<strong>de</strong>ntes eficientes.<br />
55<br />
56
Propieda<strong>de</strong>s <strong>de</strong> las gramáticas para los analizadores <strong>de</strong>scen<strong>de</strong>ntes<br />
Propieda<strong>de</strong>s<br />
• Uno <strong>de</strong> los objetivos <strong>de</strong> este tema es <strong>de</strong>mostrar que se pue<strong>de</strong> construir fácilmente<br />
analizadores <strong>de</strong> tipo LL(1) (la entrada se lee <strong>de</strong>s<strong>de</strong> la izquierda – left – las<br />
<strong>de</strong>rivaciones en el árbol se hacen <strong>de</strong> izquierda – left – a <strong>de</strong>recha y se necesita<br />
conocer sólo 1 símbolo <strong>de</strong> la entrada por anticipado) si la gramática se pue<strong>de</strong><br />
expresar en forma a<strong>de</strong>cuada<br />
• Propieda<strong>de</strong>s necesarias para expresar la gramática <strong>de</strong> esa forma<br />
• Eliminar recursividad por la izquierda (por su relación suele consi<strong>de</strong>rarse un<br />
paso auxiliar para la cuarta propiedad)<br />
• Eliminar símbolos inaccesibles (por su relación suele consi<strong>de</strong>rarse un paso<br />
auxiliar para la cuarta propiedad)<br />
• Eliminar reglas <strong>de</strong>l tipo A→λ<br />
• Expresión <strong>de</strong> la gramática en forma normal <strong>de</strong> Greibach<br />
• Factorización por la izquierda (que es una condición necesaria para LL(1))<br />
G=<br />
E<br />
E<br />
+<br />
i -<br />
E<br />
Forma normal <strong>de</strong> Greibach<br />
Eliminación <strong>de</strong> recursividad a izquierdas: ejemplo previo<br />
• Analícese el siguiente ejemplo<br />
E<br />
- E<br />
i+--i<br />
E<br />
i E’<br />
+ E E’<br />
- E E’<br />
- E E’<br />
i E’<br />
G=<br />
i<br />
λ<br />
57<br />
58<br />
Forma normal <strong>de</strong> Greibach<br />
Eliminación <strong>de</strong> recursividad a izquierdas: conclusiones previas<br />
Forma normal . <strong>de</strong> Greibach<br />
Eliminación <strong>de</strong> recursividad a izquierdas: ejemplo 1<br />
• Del ejemplo anterior no parece po<strong>de</strong>r <strong>de</strong>ducirse i<strong>de</strong>a intuitiva alguna<br />
• Sin embargo la técnica se pue<strong>de</strong> generalizar<br />
G=<br />
A→Aα 1<br />
|...|Aα n<br />
|β 1<br />
|...|β m<br />
A→β 1<br />
X|...|β m<br />
X<br />
X→α 1<br />
X|...|α n<br />
X|λ<br />
G’=<br />
59<br />
60
Forma normal <strong>de</strong> Greibach<br />
Lema: eliminación <strong>de</strong> recursividad a izquierdas<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: modificación <strong>de</strong> reglas y gramáticas equivalentes<br />
Toda gramática in<strong>de</strong>pendiente <strong>de</strong>l contexto pue<strong>de</strong> reducirse a otra equivalente sin<br />
reglas recursivas a izquierdas<br />
• Una regla recursiva a izquierdas tiene el siguiente aspecto<br />
A→Ax,,A ∈ Σ N<br />
∧ x ∈ (Σ T<br />
∪Σ N<br />
) *<br />
• El lema se <strong>de</strong>muestra <strong>de</strong> forma constructiva realizando para cada regla recursiva el<br />
siguiente tratamiento:<br />
• Sea < Σ T<br />
, Σ N<br />
, S, P > una gramática que tiene reglas recursivas <strong>de</strong> la siguiente<br />
forma:<br />
• A→Aα 1<br />
|...|Aα n<br />
|β 1<br />
|...|β m<br />
• Don<strong>de</strong> {β i<br />
} n i=1 representa todas las partes <strong>de</strong>rechas no recursivas<br />
• Se sustituye el subconjunto anterior <strong>de</strong> reglas por<br />
• A→β 1<br />
X|...|β m<br />
X<br />
• X→α 1<br />
X|...|α n<br />
X|λ<br />
Se pue<strong>de</strong> modificar una gramática sustituyendo una regla por el<br />
conjunto <strong>de</strong> reglas obtenido al sustituir en su parte <strong>de</strong>recha todas<br />
las apariciones <strong>de</strong> un no terminal por todas las partes <strong>de</strong>rechas <strong>de</strong><br />
ese no terminal. La gramática obtenida genera el mismo lenguaje<br />
que la <strong>de</strong> partida<br />
61<br />
62<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
G’=<br />
F→i (i sustituye las F <strong>de</strong>)<br />
T→FT’<br />
G’=<br />
G’=<br />
T→iT’ (iT’ sustituye<br />
las T <strong>de</strong>) E→TE’<br />
G’=<br />
63<br />
64
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
Se pue<strong>de</strong>n eliminar reglas <strong>de</strong> una gramática siempre que se<br />
sustituya, la parte izquierda <strong>de</strong> la regla que se elimina por su parte<br />
<strong>de</strong>recha, en todas las apariciones en otras partes <strong>de</strong>rechas<br />
• Un caso <strong>de</strong> especial interés es la posibilidad <strong>de</strong> eliminar reglas <strong>de</strong> las llamadas<br />
lambda<br />
• Una regla lambda es <strong>de</strong> la forma<br />
A→λ,,A ∈ Σ N<br />
• Y se utiliza para borrar símbolos <strong>de</strong> una palabra<br />
G’=<br />
G’=<br />
65<br />
66<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
• Comprobemos algunas <strong>de</strong>rivaciones<br />
G’=<br />
G’=<br />
G=<br />
E<br />
T<br />
E<br />
+<br />
E<br />
+ T<br />
T F<br />
F i<br />
i+i+i<br />
E<br />
i E’<br />
+ T E’<br />
G’=<br />
F<br />
i<br />
i+<br />
T<br />
i<br />
i<br />
67<br />
68
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
• Comprobemos algunas <strong>de</strong>rivaciones<br />
Forma normal <strong>de</strong> Greibach<br />
Observación: eliminación <strong>de</strong> reglas y gramáticas equivalentes, ejemplos<br />
• Comprobemos algunas <strong>de</strong>rivaciones<br />
G=<br />
T<br />
E<br />
T<br />
*<br />
F<br />
i*i*i<br />
* F T’<br />
T * F i i* F T’<br />
E<br />
i T’<br />
G’=<br />
G=<br />
T<br />
F<br />
E<br />
*<br />
E<br />
+ T<br />
F F<br />
i i<br />
i*i+i<br />
E<br />
i T’ E’<br />
* F+<br />
T<br />
G’=<br />
F<br />
i<br />
i*<br />
F<br />
i<br />
i<br />
i<br />
i<br />
i<br />
69<br />
70<br />
Forma normal <strong>de</strong> Greibach<br />
Definición<br />
Forma normal <strong>de</strong> Greibach<br />
Enunciado teorema: existencia <strong>de</strong> forma normal <strong>de</strong> Greibach<br />
• Informalmente<br />
Se dice que una gramática in<strong>de</strong>pendiente <strong>de</strong>l contexto está en forma normal <strong>de</strong><br />
Greibach si y sólo si la parte <strong>de</strong>recha <strong>de</strong> todas las reglas empieza por un símbolo<br />
terminal seguido, opcionalmente, <strong>de</strong> no terminales<br />
Todo lenguaje in<strong>de</strong>pendiente <strong>de</strong>l contexto que no contenga la palabra vacía,<br />
pue<strong>de</strong> representarse mediante una gramática en forma normal <strong>de</strong> Greibach<br />
• Formalmente:<br />
< Σ T<br />
, Σ N<br />
, S, P > in<strong>de</strong>pendiente <strong>de</strong>l contexto está en forma normal <strong>de</strong> Greibach<br />
⇔(<strong>de</strong>f)<br />
∀ r∈P r=A→ax ,, a∈Σ T<br />
∧ x∈Σ * N<br />
71<br />
72
Forma normal <strong>de</strong> Greibach<br />
Demostración teorema: existencia <strong>de</strong> forma normal <strong>de</strong> Greibach<br />
• Se realizará una <strong>de</strong>mostración constructiva mostrando el algoritmo para la<br />
transformación<br />
• La transformación consiste en los siguientes pasos:<br />
1. Si el lenguaje contiene la palabra vacía, se aña<strong>de</strong> la regla (S es el axioma)<br />
S→λ<br />
2. Se elimina todas las reglas recursivas a izquierdas aplicando el lema <strong>de</strong>scrito<br />
previamente (se han visto ejemplos previamente)<br />
3. Se establece, entre los no terminales, la siguiente relación <strong>de</strong> or<strong>de</strong>n (parcial)<br />
<strong>de</strong>ducida <strong>de</strong>l estudio <strong>de</strong> las reglas <strong>de</strong> producción<br />
• Si no hay bucles<br />
A i<br />
Forma normal <strong>de</strong> Greibach<br />
Demostración teorema: existencia <strong>de</strong> forma normal <strong>de</strong> Greibach<br />
5. Se elimina las reglas <strong>de</strong> tipo 3 (comenzando por aquella cuya parte izquierda<br />
es la primera <strong>de</strong>l or<strong>de</strong>n parcial)<br />
• Grupo 3: Reglas <strong>de</strong> la forma<br />
A→Bx,, A,B∈Σ N<br />
, x∈Σ * ∧ B
Forma normal . <strong>de</strong> Greibach<br />
Ejemplo <strong>de</strong> paso 6<br />
Forma normal . <strong>de</strong> Greibach<br />
Ejemplo <strong>de</strong> paso 6<br />
G’=<br />
G’=<br />
• Reglas <strong>de</strong> tipo 2, con el or<strong>de</strong>n E
Forma normal <strong>de</strong> Greibach<br />
Demostración teorema: existencia <strong>de</strong> forma normal <strong>de</strong> Greibach<br />
8. Queda pendiente el tratamiento <strong>de</strong> las reglas lambda<br />
• La forma normal <strong>de</strong> Greibach prohíbe estas reglas excepto para el axioma<br />
(cuando el lenguaje incluye la palabra vacía)<br />
• Habría que eliminarlas utilizando el resultado que se estudió previamente<br />
• El objetivo <strong>de</strong> este curso es el paso <strong>de</strong> la gramática a una forma<br />
compatible para analizadores <strong>sintáctico</strong>s LL(1).<br />
• Aplicaremos el siguiente tratamiento práctico:<br />
• Analizar si las reglas lambda molestan para LL(1)<br />
• En caso afirmativo se eliminarán y, en el mejor <strong>de</strong> los casos, se<br />
terminará el proceso<br />
• Pue<strong>de</strong> ser difícil cumplir todas las condiciones para LL(1) al eliminar<br />
las reglas lambda.<br />
• Pue<strong>de</strong> tenerse la habilidad para pasar a la forma compatible LL(1)<br />
• Se pue<strong>de</strong> refinar la gramática <strong>de</strong> partida para expresarla <strong>de</strong> una<br />
manera que permita llegar hasta el final<br />
G=<br />
Forma normal . <strong>de</strong> Greibach<br />
Ejemplo 1<br />
1. El lenguaje no contiene la palabra vacía, no hay que hacer nada<br />
2. Se elimina todas las reglas recursivas a izquierdas<br />
A→Aα 1<br />
|...|Aα n<br />
|β 1<br />
|...|β m<br />
A→β 1<br />
X|...|β m<br />
X<br />
X→α 1<br />
X|...|α n<br />
X|λ<br />
G’=<br />
85<br />
86<br />
Forma normal . <strong>de</strong> Greibach<br />
Ejemplo 1<br />
3. Se establece, entre los no terminales, la siguiente relación <strong>de</strong> or<strong>de</strong>n (parcial), en<br />
este caso las nuevas reglas no aportan nada al or<strong>de</strong>n. En general se pue<strong>de</strong><br />
establecer el or<strong>de</strong>n con la gramática <strong>de</strong> partida e ir completándolo si proce<strong>de</strong><br />
G=<br />
• De las reglas anteriores se <strong>de</strong>duce el siguiente or<strong>de</strong>n<br />
• De E→E+T no se <strong>de</strong>duce nada<br />
• De E→T se <strong>de</strong>duce E
6. Se elimina las reglas <strong>de</strong> tipo 2<br />
Forma normal . <strong>de</strong> Greibach<br />
Ejemplo 1<br />
G’=<br />
• Reglas <strong>de</strong> tipo 2, con el or<strong>de</strong>n E
G’=<br />
Forma normal <strong>de</strong> Greibach<br />
Ejemplo1<br />
G’=<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• No todas las reglas lambda son perjudiciales para conseguir expresar la<br />
gramática <strong>de</strong> una manera compatible para LL(1)<br />
• Ya que el objetivo es utilizar LL(1) parece más a<strong>de</strong>cuado tratar sólo aquellas<br />
reglas lambda que realmente molesten<br />
• Se seguirá un tratamiento práctico basado en las siguientes reflexiones:<br />
• Cuando un no terminal tiene una regla lambda, como la siguiente<br />
X→λ<br />
• Podría generarse la siguiente situación:<br />
• Que el mismo no terminal tuviera otra parte <strong>de</strong>recha (todas comenzaran<br />
por un símbolo terminal porque todas son reglas <strong>de</strong> tipo 1)<br />
X→aα,, a∈Σ T<br />
∧ α∈Σ *<br />
Y se habría terminado el proceso<br />
93<br />
94<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• Imaginemos un árbol genérico <strong>sintáctico</strong> para una palabra concreta (se<br />
representa en rojo los terminales).<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• Imagínese que se intenta realizar análisis <strong>sintáctico</strong> <strong>de</strong>scen<strong>de</strong>nte para esa<br />
palabra, y que se está justamente en el símbolo previo a la a<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
X<br />
t i<br />
t j<br />
t l<br />
t k<br />
t b<br />
t a<br />
t s<br />
t n<br />
• Si sólo queda X como no terminal se pue<strong>de</strong> seguir el árbol:<br />
X→λ<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
X→aα<br />
aα<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
X<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
XY 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
• Intuitivamente la eficiencia por la que LL(1) mejora al “top down” con vuelta<br />
lenta, se basa en la “in<strong>de</strong>xación” <strong>de</strong> las partes <strong>de</strong>rechas <strong>de</strong> cada no terminal<br />
mediante el próximo terminal que hay que analizar<br />
• Esto se ocurre si cada no terminal tiene sólo una parte <strong>de</strong>recha que<br />
comience con ese terminal.<br />
• Si en esta situación no existieran reglas lambda (X→λ) se continuaría el<br />
análisis <strong>de</strong>scen<strong>de</strong>nte sin incertidumbre:<br />
t i<br />
t j<br />
t l<br />
t k<br />
t b<br />
t a<br />
t s<br />
t n<br />
t i<br />
t j<br />
t l<br />
t k<br />
t b<br />
t a<br />
t s<br />
t n<br />
95<br />
96
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• Ya que se tendría el siguiente conjunto <strong>de</strong> partes <strong>de</strong>rechas para X:<br />
X→ t 1<br />
β 1<br />
···<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
X→ t i-1<br />
β i-1<br />
X→ aα<br />
X→ t i+1<br />
β i+1<br />
···<br />
X→ t k<br />
β k<br />
,,{t 1<br />
,...,t i-1<br />
,a,t i+1<br />
,...,t k<br />
}⊆Σ T<br />
∧t p<br />
≠t q<br />
≠a ∀∈p,q∈{1,...,i-1,i+1,...k}<br />
∧{β 1<br />
,...,β i-1<br />
,a,β i+1<br />
,...,β k<br />
}⊆Σ N<br />
*<br />
• Sólo se podría elegir la resaltada y se continuaría el análisis:<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
aα<br />
Y 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
• ¿Cuándo son problemáticas las reglas lambda?<br />
• Cuando originan incertidumbre sobre cuál es la siguiente regla que<br />
se tiene que aplicar<br />
97<br />
98<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• ¿Qué pasaría si existieran a la vez X→aα, X→λ y Y 1<br />
→aγ 1<br />
?<br />
• Se confun<strong>de</strong>n las a’s <strong>de</strong>rivadas por X (X→aα) y por Y 1<br />
, que sigue a X<br />
Borrado <strong>de</strong> X Y 1<br />
→aγ 1<br />
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• Así que necesitaremos conocer<br />
• Cuál es el primer terminal que <strong>de</strong>riva X (en nuestro caso a)<br />
• Cuál es el primer terminal que es <strong>de</strong>rivado por lo que sigue a X y,<br />
por lo tanto, ¿quién sigue a X?<br />
• Las siguientes gráficas muestran los dos casos posibles<br />
Y 1<br />
→aγ 1<br />
100<br />
XY 1<br />
...Y m<br />
λ<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
X→λ<br />
XY 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
Y 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
aγ 1<br />
X→aα<br />
Y 2<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
Y 1<br />
...Y m<br />
B→σXY 1<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
X Y 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
σ<br />
B<br />
λ<br />
V→τIWω<br />
W→Y 1<br />
...Y m<br />
I→ξX<br />
τ IW<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
X Y 1<br />
...Y m<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
ξ<br />
λ<br />
V<br />
ω<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
aα<br />
t 1<br />
t 2<br />
t 3<br />
t 4<br />
t 5<br />
t 6<br />
t 7<br />
t 8<br />
at i<br />
...t n<br />
99
Ajustes a la forma normal <strong>de</strong> Greibach para LL(1)<br />
Cambios en el paso 8<br />
• X es seguido por el primer símbolo <strong>de</strong>l resto (a partir <strong>de</strong> él) <strong>de</strong> las partes<br />
<strong>de</strong>rechas don<strong>de</strong> aparece (en este caso, sólo se tiene B→σXY 1<br />
y es seguido<br />
por Y 1<br />
)<br />
• Si es el último no terminal <strong>de</strong> la parte <strong>de</strong>recha, se mirará quién sigue a su<br />
padre (en este caso I→ξX, y si I sólo aparece en V→τIWω se estudiará el<br />
primer terminal que <strong>de</strong>riva <strong>de</strong> W)<br />
• Por tanto, si el primer terminal que <strong>de</strong>riva <strong>de</strong> Y 1<br />
no es a, la regla lambda no<br />
da problemas.<br />
• En otro caso sí los da y se intentará eliminarla.<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
8. Si sólo se quiere utilizar la gramática para generar un analizador <strong>sintáctico</strong><br />
<strong>de</strong>scen<strong>de</strong>nte con la técnica LL(1) tendremos que estudiar si molestan las reglas λ<br />
G’=<br />
¿Quién sigue a E’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando E’<br />
• Comencemos por la primera regla lambda<br />
101<br />
102<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
8. (cont.)<br />
8. (cont.)<br />
G’=<br />
¿Quién sigue a E’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando E’.<br />
En las dos reglas aparece como último símbolo <strong>de</strong> la<br />
parte <strong>de</strong>recha.<br />
A E’le seguirá quien siga a las partes izquierdas <strong>de</strong><br />
esas dos reglas:<br />
G’=<br />
¿Quién sigue a E’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando E’.<br />
En las dos reglas aparece como último símbolo <strong>de</strong> la<br />
parte <strong>de</strong>recha.<br />
A E’le seguirá quien siga a las partes izquierdas <strong>de</strong><br />
esas dos reglas:<br />
• E<br />
• E’<br />
En general, pue<strong>de</strong> terminarse el estudio cuando se<br />
llega:<br />
• Al axioma<br />
• Al mismo símbolo que se está estudiando<br />
• Po<strong>de</strong>mos concluir que la primera regla lambda no molesta<br />
103<br />
104
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
8. (cont.)<br />
8. (cont.)<br />
G’=<br />
¿Quién sigue a T’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T’.<br />
G’=<br />
¿Quién sigue a T’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T’.<br />
En una regla aparece seguido por E’.<br />
En dos reglas aparece como último símbolo <strong>de</strong> la<br />
parte <strong>de</strong>recha.<br />
A T’le seguirá quien siga a las partes izquierdas <strong>de</strong><br />
esas dos reglas:<br />
• Continuemos con la segunda regla lambda<br />
105<br />
106<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
8. (cont.)<br />
8. (cont.)<br />
G’=<br />
¿Quién sigue a T’?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T’.<br />
En una regla aparece seguido por E’.<br />
En dos reglas aparece como último símbolo <strong>de</strong> la<br />
parte <strong>de</strong>recha.<br />
A T’le seguirá quien siga a las partes izquierdas <strong>de</strong><br />
esas dos reglas:<br />
• T’<br />
• T<br />
Pue<strong>de</strong> terminarse el estudio cuando se llega al<br />
mismo símbolo<br />
G’=<br />
¿Quién sigue a T?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T.<br />
• Continuemos con los símbolos no terminales que siguen a T<br />
107<br />
108
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Forma normal <strong>de</strong> Greibach para LL(1)<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
Nuevo final <strong>de</strong>l ejemplo 1<br />
8. (cont.)<br />
8. (cont.)<br />
G’=<br />
¿Quién sigue a T?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T.<br />
En la regla aparece seguido por E’.<br />
Recapitulando sólo tenemos que estudiar E’<br />
G’=<br />
¿Quién sigue a T?<br />
Consultemos las partes <strong>de</strong>rechas <strong>de</strong> las reglas<br />
buscando T.<br />
En la regla aparece seguido por E’.<br />
Recapitulando sólo tenemos que estudiar E’<br />
Comprobemos<br />
• El primer terminal <strong>de</strong>rivado por T’ es *.<br />
• El primer terminal <strong>de</strong>rivado por E’es +.<br />
• Como los terminales son distintos (* y +) po<strong>de</strong>mos concluir que la segunda regla<br />
lambda tampoco molesta<br />
109<br />
110<br />
Forma normal <strong>de</strong> . Greibach / LL(1)<br />
Ejemplo 2<br />
• Obtener, si es posible, la expresión a<strong>de</strong>cuada para LL(1) <strong>de</strong> la siguiente gramática<br />
utilizando como ayuda la forma normal <strong>de</strong> Greibach<br />
G 2<br />
=<br />
Forma normal <strong>de</strong> . Greibach/ LL(1)<br />
Ejemplo 2<br />
1. El lenguaje no contiene la palabra vacía, no hay que hacer nada<br />
2. No hay reglas recursivas a izquierdas, no hay que hacer nada<br />
3. Se establece, entre los no terminales, el or<strong>de</strong>n (parcial)<br />
G 2<br />
=<br />
• De las reglas anteriores se pue<strong>de</strong> <strong>de</strong>ducir los dos siguientes ór<strong>de</strong>nes<br />
• De A→Ba se <strong>de</strong>duce A
Forma normal <strong>de</strong> . Greibach / LL(1)<br />
4. Se clasifica las reglas en tres grupos<br />
Ejemplo 2: opción 1 B
Forma normal <strong>de</strong> . Greibach / LL(1)<br />
Ejemplo 2: opción 1 B
Forma normal <strong>de</strong> . Greibach / LL(1)<br />
Ejemplo 2: opción 2 A
Forma normal <strong>de</strong> . Greibach / LL(1)<br />
Ejemplo 2: opción 2 A
8. (cont.)<br />
Forma normal <strong>de</strong> Greibach / LL(1)<br />
Ejemplo 2: opción 2 A
LL(1)<br />
Conversión <strong>de</strong>s<strong>de</strong> forma normal <strong>de</strong> Greibach a LL(1)<br />
• El nuevo no terminal tendrá tantas partes <strong>de</strong>rechas como diferentes “partes<br />
no comunes” haya (en este caso K→V|W).<br />
G 2<br />
=<br />
LL(1)<br />
Conversión <strong>de</strong>s<strong>de</strong> forma normal <strong>de</strong> Greibach a LL(1)<br />
• Hay que tener la precaución <strong>de</strong> <strong>de</strong>jar las reglas en “forma normal” a<strong>de</strong>cuada:<br />
• En este caso no es complicado ya que se pue<strong>de</strong> <strong>de</strong>rivar los primeros no<br />
terminales hasta llegar a un terminal<br />
• En este caso basta aplicar una vez las reglas <strong>de</strong> V (V→bX|cY) y <strong>de</strong> W<br />
(W→dZ|eT)...<br />
G 2<br />
=<br />
133<br />
134<br />
LL(1)<br />
Conversión <strong>de</strong>s<strong>de</strong> forma normal <strong>de</strong> Greibach a LL(1)<br />
• ... y eliminar los símbolos que, parece, que quedan inaccesibles (V y W)<br />
G 2<br />
=<br />
Análisis “top-down” selectivo<br />
Concepto<br />
• También se llama “sin vuelta atrás”, en oposición a la técnica <strong>de</strong>scrita al principio<br />
<strong>de</strong>l tema<br />
• También se llama “<strong>de</strong>scenso recursivo” por la técnica <strong>de</strong> paso automático <strong>de</strong> la<br />
gramática LL(1) al analizador<br />
• Intuitivamente, la razón <strong>de</strong> su eficiencia resi<strong>de</strong> en que las partes <strong>de</strong>rechas <strong>de</strong><br />
cada no terminal pue<strong>de</strong>n consi<strong>de</strong>rarse “in<strong>de</strong>xadas” por el siguiente terminal<br />
• De hecho (consúltese la bibliografía) con LL(1) se pue<strong>de</strong> construir una tabla <strong>de</strong><br />
doble entrada (no terminales / terminales ) en la que, cada celda, está ocupada<br />
solamente por una regla que es la única opción que se pue<strong>de</strong> aplicar cuando en<br />
el “árbol <strong>sintáctico</strong>” corresponda tratar el no terminal y en el recorrido <strong>de</strong>l<br />
programa toque tratar el terminal.<br />
135<br />
136
Análisis “top-down” selectivo<br />
Paso automático <strong>de</strong> la gramática LL(1) al analizador<br />
• Según el proceso <strong>de</strong>scrito, cuando lleguemos a LL(1) tendremos estos dos tipos<br />
<strong>de</strong> reglas:<br />
• Reglas con opción λ:<br />
U→xX 1<br />
X 2<br />
...X n<br />
|yY 1<br />
Y 2<br />
...Y m<br />
|...|zZ 1<br />
...Z p<br />
|λ<br />
• Reglas sin opción λ:<br />
Análisis “top-down” selectivo<br />
Paso automático <strong>de</strong> la gramática LL(1) al analizador: reglas con λ<br />
• Se generará la siguiente función C<br />
int U(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case x;<br />
i++;<br />
i=X1(ca<strong>de</strong>na, i);<br />
i=X2(ca<strong>de</strong>na, i);<br />
···<br />
i=Xn(ca<strong>de</strong>na, i);<br />
break;<br />
case y:<br />
i++;<br />
i=Y1(ca<strong>de</strong>na, i);<br />
i=Y2(ca<strong>de</strong>na, i);<br />
···<br />
i=Ym(ca<strong>de</strong>na, i);<br />
break;<br />
case z:<br />
i++;<br />
i=Z1(ca<strong>de</strong>na, i);<br />
i=Z2(ca<strong>de</strong>na, i);<br />
···<br />
i=Zp(ca<strong>de</strong>na, i);<br />
break;<br />
}<br />
return i;<br />
}<br />
U→xX 1<br />
X 2<br />
...X n<br />
|yY 1<br />
Y 2<br />
...Y m<br />
|...|zZ 1<br />
...Z p<br />
138<br />
···<br />
137<br />
Análisis “top-down” selectivo<br />
Paso automático <strong>de</strong> la gramática LL(1) al analizador: reglas sin λ<br />
• Se generará la siguiente función C<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• Se parte <strong>de</strong> la siguiente gramática in<strong>de</strong>pendiente <strong>de</strong>l contexto<br />
int U(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case x;<br />
i++;<br />
i=X1(ca<strong>de</strong>na, i);<br />
i=X2(ca<strong>de</strong>na, i);<br />
···<br />
i=Xn(ca<strong>de</strong>na, i);<br />
break;<br />
case y:<br />
i++;<br />
i=Y1(ca<strong>de</strong>na, i);<br />
i=Y2(ca<strong>de</strong>na, i);<br />
···<br />
i=Ym(ca<strong>de</strong>na, i);<br />
break;<br />
···<br />
case z:<br />
i++;<br />
i=Z1(ca<strong>de</strong>na, i);<br />
i=Z2(ca<strong>de</strong>na, i);<br />
···<br />
i=Zp(ca<strong>de</strong>na, i);<br />
break;<br />
/* El fin <strong>de</strong> ca<strong>de</strong>na va a<br />
<strong>de</strong>fault */<br />
<strong>de</strong>fault:<br />
return –n;<br />
/* El error <strong>de</strong>be ser distinto<br />
para cada regla */<br />
}<br />
return i;<br />
}<br />
G 3<br />
=<br />
139<br />
140
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• El alumno pue<strong>de</strong> comprobar que se obtiene la siguiente expresión en forma<br />
normal <strong>de</strong> Greibach<br />
• Y la siguiente expresión LL(1)<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
G 3<br />
=<br />
G 3<br />
=<br />
141<br />
142<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• Y se pue<strong>de</strong> escribir el siguiente analizador siguiendo el esquema <strong>de</strong>scrito<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• Y se pue<strong>de</strong> escribir el siguiente analizador siguiendo el esquema <strong>de</strong>scrito<br />
int E(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’i’:<br />
i++;<br />
i=V(ca<strong>de</strong>na, i);<br />
break;<br />
case ‘(‘:<br />
i++;<br />
i=E(ca<strong>de</strong>na, i);<br />
i=C(ca<strong>de</strong>na, i);<br />
i=V(ca<strong>de</strong>na, i);<br />
break;<br />
<strong>de</strong>fault: return –1;/*no λ*/<br />
}<br />
return i;<br />
}<br />
int V(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’*’:<br />
case ’/’:<br />
i++;<br />
i=T(ca<strong>de</strong>na, i);<br />
i=X(ca<strong>de</strong>na, i);<br />
break;<br />
case ‘+‘:<br />
case ‘-‘:<br />
i++;<br />
i=E(ca<strong>de</strong>na, i);<br />
break; /* λ */<br />
}<br />
return i;<br />
}<br />
int X(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’+’:<br />
case ’-’:<br />
i++;<br />
i=E(ca<strong>de</strong>na, i);<br />
break; /* λ */<br />
}<br />
return i;<br />
}<br />
int T(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’i’:<br />
i++;<br />
i=U(ca<strong>de</strong>na, i);<br />
break;<br />
case ‘(‘:<br />
i++;<br />
i=E(ca<strong>de</strong>na, i);<br />
i=C(ca<strong>de</strong>na, i);<br />
i=U(ca<strong>de</strong>na, i);<br />
break;<br />
<strong>de</strong>fault: return –2;/*no λ*/<br />
}<br />
return i;<br />
}<br />
143<br />
144
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• Y se pue<strong>de</strong> escribir el siguiente analizador siguiendo el esquema <strong>de</strong>scrito<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
• Y se pue<strong>de</strong> escribir el siguiente analizador siguiendo el esquema <strong>de</strong>scrito<br />
int U(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’*’:<br />
case ’/’:<br />
i++;<br />
i=T(ca<strong>de</strong>na, i);<br />
break; /* λ */<br />
}<br />
return i;<br />
}<br />
int F(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’i’:<br />
i++;<br />
break;<br />
case ‘(‘:<br />
i++;<br />
i=E(ca<strong>de</strong>na, i);<br />
i=C(ca<strong>de</strong>na, i);<br />
break;<br />
<strong>de</strong>fault: return –3;/*no λ*/<br />
}<br />
return i;<br />
}<br />
int C(char * ca<strong>de</strong>na, int i)<br />
{<br />
if (i < 0) return i;<br />
/* Aquí propaga errores<br />
anteriores */<br />
switch (ca<strong>de</strong>na[i]) {<br />
case ’)’:<br />
i++;<br />
break;<br />
<strong>de</strong>fault: return –4;/*no λ*/<br />
}<br />
return i;<br />
}<br />
145<br />
146<br />
Análisis “top-down” selectivo<br />
Análisis “top-down” selectivo<br />
Ejemplo completo<br />
Ejemplo completo<br />
• La ca<strong>de</strong>na x se analiza con la llamada<br />
• El siguiente no reconoce la ca<strong>de</strong>na<br />
axioma( x, 0);<br />
• Si el retorno es la longitud <strong>de</strong> la ca<strong>de</strong>na, se ha reconocido, en otro caso (retorno<br />
negativo) el valor indica la regla que i<strong>de</strong>ntificó el error<br />
• Po<strong>de</strong>mos mostrar los siguientes ejemplos <strong>de</strong> ejecución:<br />
E(“i + i * i”, 0)<br />
0[1]: E( “I + I * I”, 0)<br />
1[1]: V( “I + I * I”, 1)<br />
2[1]: E( “I + I * I”, 2)<br />
3[1]: V( “I + I * I”, 3)<br />
4[1]: T( “I + I * I”, 4)<br />
5[1]: U( “I + I * I”, 5)<br />
5[1]: returned 5<br />
4[1]: returned 5<br />
4[1]: X( “I + I * I”, 5)<br />
4[1]: returned 5<br />
3[1]: returned 5<br />
2[1]: returned 5<br />
1[1]: returned 5<br />
0[1]: returned 5<br />
5<br />
147<br />
E(“i + i *”, 0)<br />
0[1]: E( “I + I *”, 0)<br />
1[1]: V( “I + I *”, 1)<br />
2[1]: E( “I + I *”, 2)<br />
3[1]: V( “I + I *”, 3)<br />
4[1]: T( “I + I *”, 4)<br />
4[1]: returned -2<br />
4[1]: X( “I + I *”, -2)<br />
4[1]: returned -2<br />
3[1]: returned -2<br />
2[1]: returned -2<br />
1[1]: returned -2<br />
0[1]: returned -2<br />
-2<br />
148
Análisis <strong>sintáctico</strong><br />
Bibliografía<br />
[Alf] “Teoría <strong>de</strong> Autómatas y lenguajes formales” M. Alfonseca y otros<br />
[Hop] “Introducción a la teoría <strong>de</strong> autómatas, lenguajes y computación” Hopcroft, J.;<br />
Motwani, R.; Ullman, J.<br />
[Aho] “Compiladores. Principios, técnicas y herramientas” A. V. Aho; R. Sefthi; J. D.<br />
Ullman<br />
149