• No se han encontrado resultados

Análisis Sintáctico Descendente

N/A
N/A
Protected

Academic year: 2021

Share "Análisis Sintáctico Descendente"

Copied!
26
0
0

Texto completo

(1)

Análisis Sintáctico Descendente

CI4721 – Lenguajes de Programación II

Ernesto Hernández-Novich <emhn@usb.ve>

Universidad “Simón Bolívar”

(2)

PDA Descendente con lookahead

Reconocedor descendente determinístico

Sea G = (N,Σ,P,S) una CFG cualquiera. Entonces el PDA extendido

LLk(G) = ({q0,q1},Σ,N∪Σ, δ,q0,{q1})

con δ definida según

δ(q0, λ, λ, λ) ={(q1,S)}

δ(q1,a,a,a) ={(q1, λ)},a∈Σ

δ(q1, λ,u,A) ={AαPuLAk(Aα) : (q1, α)},AN

es un reconocedor descendente y determinístico para G.

u∈Σ+ corresponde al lookahead.

Si G esLL(k) la conjunción asegura que habrá exactamente una

transición por cada combinación de no-terminal y lookahead.

(3)

Reconocedor basado en tablas

¿Cómo convertirlo en un programa?

Convirtiendo transiciones en datos

En nuestro PDA determinístico con lookahead. . .

El estado inicial solamente se usa para empilarS. El estado final solamente tiene transiciones a sí mismo.

En cada transición solamente varían ellookaheady el símbolo a remover del tope de la pila.

Las expansiones están implícitas en las transiciones.

Podemos diseñar un algoritmo muy compacto alrededor de

Una entrada con su marcador final #k.

Unbufferde tamañok para ellookahead.

Una pila que comienza conteniendoS sobre un centinela #.

Una tabla cuyas entradas indiquen la producción a expandir para cada combinación delookaheady tope de pila.

El algoritmo es independiente de la gramática solamente necesita la tabla.

(4)

Reconocedor basado en tablas

¿Cómo convertirlo en un programa?

Convirtiendo transiciones en datos

En nuestro PDA determinístico con lookahead. . .

El estado inicial solamente se usa para empilarS. El estado final solamente tiene transiciones a sí mismo.

En cada transición solamente varían ellookaheady el símbolo a remover del tope de la pila.

Las expansiones están implícitas en las transiciones.

Podemos diseñar un algoritmo muy compacto alrededor de

Una entrada con su marcador final #k.

Unbufferde tamañok para ellookahead.

Una pila que comienza conteniendoS sobre un centinela #.

Una tabla cuyas entradas indiquen la producción a expandir para cada combinación delookaheady tope de pila.

El algoritmo es independiente de la gramática solamente necesita la tabla.

(5)

Reconocedor basado en tablas

Reconocedor

LL(k

)

por Tabla

Inicialización

input: w ∈Σ con #k marcadores y la TablaM asociada a la gramática {Empilar el centinela y el símbolo inicial}

push(#)

push(S)

{Preparar elklookahead}

a← los primerosk símbolos dew

{Determinar el tope de la pila sin consumirlo}

(6)

Reconocedor basado en tablas

Reconocedor

LL(k

)

por Tabla

Procesamiento

whileX 6= #do

if X =trunc1(a) then

pop() y consumir siguiente dew al final dea

else if X ∈Σ then

error por terminal inesperado en la entrada

else if M[X,a] vacío then

error por no poder expandir el no terminal

else if M[X,a] =XY1Y2. . .Yn then print XY1Y2. . .Yn pop() push(YnYn−1. . .Y2Y1) end if Xtop() end while

output: SiwL(G), la derivación más izquierda, sino error

(7)

Reconocedor basado en tablas

El secreto está en la tabla

Características

Una fila por cada AN.

Una columna por cadalookaheadposible.

k

X

i=0

|Σ|i = 1− |Σ|k+1

1− |Σ|

(no se les olvide la columna para #k)

En cada posición se almacena

La producción a expandir – para ahorrar espacio, típicamente es un identificador numérico o apuntador a la representación de la regla. Un indicador de error sintáctico.

(8)

Reconocedor basado en tablas

El secreto está en la tabla

Características

Una fila por cada AN.

Una columna por cadalookaheadposible.

k

X

i=0

|Σ|i = 1− |Σ|k+1

1− |Σ|

(no se les olvide la columna para #k)

En cada posición se almacena

La producción a expandir – para ahorrar espacio, típicamente es un identificador numérico o apuntador a la representación de la regla. Un indicador de error sintáctico.

Los requerimientos de espacio son prohibitivos para k >1

(9)

Reconocedor basado en tablas

El secreto está en la tabla

Características

Una fila por cada AN.

Una columna por cadalookaheadposible.

k

X

i=0

|Σ|i = 1− |Σ|k+1

1− |Σ|

(no se les olvide la columna para #k)

En cada posición se almacena

La producción a expandir – para ahorrar espacio, típicamente es un identificador numérico o apuntador a la representación de la regla. Un indicador de error sintáctico.

(10)

Reconocedor basado en tablas

El secreto está en la tabla

Construcción

input: G = (N,Σ,P,S) y ∀AN,FIRSTk(A) y FOLLOWk(A) for allAαP do

for allaFIRSTk(α) do M[A,a]←Aα

end for

if λFIRSTk(α) then

for all bFOLLOWk(A) do M[A,b]←Aα

end for end if end for

Las posiciones que queden vacías corresponden a errores de sintaxis.

(11)

Reconocedor basado en tablas

Reconocer (mini) JSON

La gramática

Gramática inicial para una versión reducida de JSON

J → {L} Ls:V LL,s:V A→[X] XV XV,L Vs Vn VJ VA La gramática no esLL:

Símbolo inicial J recursivo

indirectamente a través

de Lpor más de una vía.

Recursión izquierda enL.

(12)

Reconocedor basado en tablas

Reconocer (mini) JSON

La gramática transformada – 30 % más reglas

SJ# J→ {L} Ls:VR R,L Rλ A→[X] XVY Y,X Yλ Vs Vn VJ VA FIRST FOLLOW S { # J { # , } ] L s } R λ , } A [ , } ] X s n { [ ] Y λ , ] V s n { [ , } ]

Verifiquen que la gramática es

fuertemente LL(1)

(13)

Reconocedor basado en tablas

Reconocer (mini) JSON

La tabla s n , : [ ] { } # S SJ# J J → {L} L Ls:VR R R,L Rλ A A→[X] X XVY XVY XVY XVY Y Y,X Yλ V Vs Vn VJ VA 72 celdas – 77 %vacío

¿Por qué: es irrelevante?

(14)

Reconocedor basado en tablas

Recuperación de Errores

. . . porque el mundo no es perfecto

El reconocedor predictivo es capaz de detectar dos errores:

Terminal al tope de la pila diferente del siguiente terminal de entrada. La combinación de no terminal al tope de la pila y ellookaheadno

tiene regla de expansión asociada.

Abortar el reconocimiento es inaceptable

El programa “está mal” – el proceso de síntesis no ocurrirá, pero el análisis debería continuar tanto como se pueda.

Cada error debe ser amplio y detallado

Ubicación – línea y columna, contexto de ser posible.

Condición – “esperabaX pero recibíY

Encontrar otros defectos ayudará al programador.

Existen dos técnicas de recuperación aplicables

Técnica del Pánico (Panic Mode).

Técnica del Engaño (Phrase Level Recovery).

(15)

Reconocedor basado en tablas

Recuperación de Errores

. . . porque el mundo no es perfecto

El reconocedor predictivo es capaz de detectar dos errores:

Terminal al tope de la pila diferente del siguiente terminal de entrada. La combinación de no terminal al tope de la pila y ellookaheadno

tiene regla de expansión asociada.

Abortar el reconocimiento es inaceptable

El programa “está mal” – el proceso de síntesis no ocurrirá, pero el análisis debería continuar tanto como se pueda.

Cada error debe ser amplio y detallado

Ubicación – línea y columna, contexto de ser posible.

Condición – “esperabaX pero recibíY

Encontrar otros defectos ayudará al programador.

Existen dos técnicas de recuperación aplicables

Técnica del Pánico (Panic Mode).

(16)

Reconocedor basado en tablas

Técnica del Pánico

Panic Mode, a.k.a. Discard all the tokens!

Descartartokenshasta encontrar alguno que permita resincronizar.

Conjuntos de sincronización construidos con heurísticas:

ResincronizarAusandoFOLLOW(A) – “se terminó elAincompleto”. FIRST de construcciones de “alto nivel” para resincronizar

construcciones de “bajo nivel” – depende de la gramática.

En algunos casos, agregarFIRST(A) para resincronizarAhace posible continuar reconociendo cuando aparezca – depende de la gramática. Ante un error expandiendoA, si existeAλentonces usarlo – esto

difiere el error para más adelante.

Si el terminal al tope de la pila no coincide con el de la entrada, eliminarlo como si lo hubieras visto – “faltaba un ; y lo agregué”.

La posición de la tabla apunta al conjunto de resincronización.

(17)

Reconocedor basado en tablas

Técnica del Engaño

(Phrase Level Recovery, a.k.a. Let me type for you)

Aplicada para recuperarse de los errores de expansión.

La posición de la tabla apunta a una subrutinade manejo del error.

Cada rutina es específica para la recuperación particular – altamente

dependiente del lenguaje.

Las rutinas “completan” lo que falta para continuar

Agregan, quitan o cambian símbolos en la entrada. Sacan cosas de la pila – Muy peligroso.

Anuncian lo que hicieron para “corregir” el problema.

Solamente aplicable a lenguajes (o sub-lenguajes)

Se conocen los errores más frecuentes.

Es fácil alcanzar formas sentenciales válidas con edición mínima.

(18)

Reconocedor basado en tablas

Técnica del Engaño

(Phrase Level Recovery, a.k.a. Let me type for you)

Aplicada para recuperarse de los errores de expansión.

La posición de la tabla apunta a una subrutinade manejo del error.

Cada rutina es específica para la recuperación particular – altamente

dependiente del lenguaje.

Las rutinas “completan” lo que falta para continuar

Agregan, quitan o cambian símbolos en la entrada. Sacan cosas de la pila – Muy peligroso.

Anuncian lo que hicieron para “corregir” el problema.

Solamente aplicable a lenguajes (o sub-lenguajes)

Se conocen los errores más frecuentes.

Es fácil alcanzar formas sentenciales válidas con edición mínima.

No la llamead hoc, llámelaad hack.

(19)

Reconocedor Recursivo Descendiente

¿Cómo convertirlo en un programa?

Convirtiendo transiciones en llamadas a funciones

En nuestro PDA determinístico con lookahead. . .

La pila se usa para almacenar formas sentenciales.

Tan pronto se expande una forma sentencial, se intenta consumir tantos terminales como se pueda antes de volver a expandir. Las expansiones están implícitas en las transiciones.

Podemos diseñar un algoritmo muy compacto alrededor de

Una subrutina por cada no-terminal – la ejecución comienza porS(). Cada procedimiento modela la secuencia de expansiones y consumo de

entrada para las reglasAα.

El algoritmo es dependiente de la gramática simulando la pila del PDA con la pila de ejecución.

(20)

Reconocedor Recursivo Descendiente

¿Cómo convertirlo en un programa?

Convirtiendo transiciones en llamadas a funciones

En nuestro PDA determinístico con lookahead. . .

La pila se usa para almacenar formas sentenciales.

Tan pronto se expande una forma sentencial, se intenta consumir tantos terminales como se pueda antes de volver a expandir. Las expansiones están implícitas en las transiciones.

Podemos diseñar un algoritmo muy compacto alrededor de

Una subrutina por cada no-terminal – la ejecución comienza porS(). Cada procedimiento modela la secuencia de expansiones y consumo de

entrada para las reglasAα.

El algoritmo es dependiente de la gramática simulando la pila del PDA con la pila de ejecución.

(21)

Reconocedor Recursivo Descendiente

Un procedimiento típico

void A () { Escoger algunaAX1X2. . .Xn fori = 1 ton do if Xi es un no-terminalthen call Xi ()

else if Xi = el símbolo actual de entradathen avanzar al siguiente símbolo de entrada

else

reportar error de sintaxis

end if end for

}

Si la selección no es determinística, requierebacktracking.

Para incluirbacktracking el ciclo debe cambiarse por un avance

(22)

Reconocedor Recursivo Descendiente

Reconocer (mini) JSON

Uno de los procedimientos triviales

Reconocer Les trivial

Una sola regla – Ls:VR

LookaheadsegúnFIRST1(Ls:VR)

v o i d L () { t r y _ r u l e ( 2 ) ; m a t c h ( ’ L ’ , ’ s ’); m a t c h ( ’ L ’ , ’: ’); V (); R (); }

try_rulepermite recordar los pasos de derivación.

match verifica ellookaheadesperado o aborta con error.

(23)

Reconocedor Recursivo Descendiente

Reconocer (mini) JSON

Uno de los procedimientos interesantes

Reconocer Res sólo un poco más complicado

Dos reglasR,L yRλ

Lookaheads FIRST1(R,L) y FOLLOW1(R), respectivamente.

v o i d R () { s w i t c h ( l o o k a h e a d ) { c a s e ’ , ’: t r y _ r u l e ( 3 ) ; m a t c h ( ’ R ’ , ’ , ’); L (); c a s e ’} ’: t r y _ r u l e ( 4 ) ; r e t u r n ; d e f a u l t : e r r o r ( ’ R ’ , l o o k a h e a d ); } }

Necesario verificar el lookaheadantes de decidir cuál regla usar.

(24)

Consideraciones

Consideraciones

El reconocedor por tabla solamente tiene sentido práctico para

gramáticasLL(1) – para el resto es muy costoso.

Las gramáticas generales transformadas a LL(k) suelen ser más

complejas tanto en número como en forma de las reglas.

¿Cómo optimizaría una tablaLL(k) para reducir la ocupación de

espacio al mínimo posible?

Aplique la técnica de recuperación de errores Modo de Pánico a la

tabla para (mini) JSON. ¿Son útiles todas las heurísticas?

Si el lenguaje es suficientemente simple y LL(1), un recursivo

descendiente es más barato – incluso si una de las subgramáticas es

LL(k)>1, ¿por qué?

¿Cómo extender el reconocedor para construir el árbol de derivación?

(25)

Consideraciones

En la práctica

Muchos lenguajes de programación proveen librerías que asisten en la

construcción de Reconocedores Recursivos Descendentes con o sin

backtracking.

Perl ofreceParse::RecDescent. Haskell ofreceParsec.

Java dispone de JavaCC y ANTLR. C++ dispone de Spirit Parser Generator. . . . siempre se puede escribir a mano.

Si el lenguaje a reconocer es simple, es más práctico usar esta técnica

Lenguaje de un archivo de configuración – INI, JSON, . . . Lenguaje de comandos interactivos.

(26)

Referencias Bibliográficas

Bibliografía

[Aho]

Sección 4.4

WikiPedia – Recursive Descent Parser

JSON: The Fat-Free alternative to XML

Referencias

Documento similar

Habiendo organizado un movimiento revolucionario en Valencia a principios de 1929 y persistido en las reuniones conspirativo-constitucionalistas desde entonces —cierto que a aquellas

The 'On-boarding of users to Substance, Product, Organisation and Referentials (SPOR) data services' document must be considered the reference guidance, as this document includes the

In medicinal products containing more than one manufactured item (e.g., contraceptive having different strengths and fixed dose combination as part of the same medicinal

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

Package Item (Container) Type : Vial (100000073563) Quantity Operator: equal to (100000000049) Package Item (Container) Quantity : 1 Material : Glass type I (200000003204)

De hecho, este sometimiento periódico al voto, esta decisión periódica de los electores sobre la gestión ha sido uno de los componentes teóricos más interesantes de la