...

Analizzatori sintattici a discesa ricorsiva

by user

on
Category: Documents
56

views

Report

Comments

Transcript

Analizzatori sintattici a discesa ricorsiva
Analizzatori sintattici a discesa ricorsiva
E’ uno schema di analizzatore che sfrutta la descrizione grammaticale in EBNF adatto a grammatiche
LL(1). Si basa sulla scrittura di procedure ricorsive ricavate direttamente dalle regole grammaticali.
IDEA
Ogni produzione viene interpretata come una procedura in cui la parte sinistra rappresenta il
nome e la parte destra la definizione (corpo) della procedura. Lo stack risulta implementato
implicitamente dal meccanismo di implementazione delle chiamate ricorsive.
Data una generica regola
X ! x1 | x2 | ...... | xn !
si distinguono due possibili strutture della procedura a seconda di quale delle due condizioni si verifichi
1. X# + " Cioé la variabile non genera "
2. X #+ "
Cioé la variabile genera "
Inoltre, si deve supporre l’esistenza di una routine che rende disponibile i caratteri che via via vengono
scanditi. Questa routine in genere è associata ad un analizzatore lessicale.
Analizzatori lessicali
Un analizzatore lessicale ha il compito di esaminare carattere per carattere la stringa in ingresso e
produrre una forma standard degli item di volta in volta individuati.
Tipicamente gli analizzatori lessicali vengono implementati con automi a stati finiti.
Esempio:
procedure somma (var S:integer);
!var i:integer;
! begin
!
S:=0;
!
for i:=1 to 10 do S:= S + i * 500;
end;
procedure somma ( var S : integer ) ; var i : integer ; begin
!
S := 0 ; for i := 1 to 10 do S := S + i * 500 ; end ;
In pratica l’analizzatore lessicale ha il compito di categorizzare le varie stringhe selezionate in
modo che ciascuna stringa rappresenti un unico item.
Ad esempio: alfa + pigreco * gamma
è come dire
i +i*i
Al momento dell’analisi sintattica interessa la struttura di una espressione e quindi la tipologia
degli operandi indicati.
Analizzatori sintattici a discesa ricorsiva
1. X # + "
! procedure X;
!
begin
!!
if cc in FIRST(x1) then {codice di x1 }
!!
else if cc in FIRST(x2) then {codice di x2 }
$ !
$ $
!!
!!
!
!
......
$
else if cc in FIRST(xn) then {codice di xn }
else ERRORE
end;
2. X #+ "
procedure X;
!
begin!
if cc in FIRST(x1) then {codice di x1 }
!!
else if cc in FIRST(x2) then {codice di x2 }
!!
! !
!!
!
......
else if cc in FIRST(xn) then {codice di xn }
else if not [ cc in FOLLOW(X)] then ERRORE
end;
- cc = carattere corrente
- per l’ipotesi
FIRST(xi)% FIRST(xj) = &
viene attivata una sola
parte destra
Esempio
Grammatica
E ! T E’ ! !
E’ ! + T E’ | "
T ! F T’
T’ ! *F T’ | "
F ! (E) | i
E ! T E’
!!
$
!
tabella codici di errore
1. omissione di operando
2. omissione di operatore
3. simbolo inatteso
4. carattere ‘) ‘omesso
5. simboli restanti
procedure E!
! if cc in FIRST (TE’)
! then T; E’!
!
! else ERRORE (1);
T ! F T’
procedure T
! if cc in FIRST (FT’)
! then F; T’ !
! else ERRORE (1);
E’ ! + T E’ | "
procedure E’
! if cc in FIRST (+TE’)
!
then NEXT (cc); T; E’
!
else if not [cc in FOLLOW(E’)] then ERRORE (2);
!
Esempio cont.
T’ ! *F T’ | "
F ! (E)
F! i
procedure T’
! if cc in FIRST (*FT’)
! then NEXT (cc); F; T’
!
! else if not [cc in FOLLOW(T’)] then ERRORE (3);
procedure F
! if cc in FIRST ((E))
! then NEXT (cc); E
!
if cc = ‘)’
!
then NEXT (cc)
else ERRORE (4)
else if cc in FIRST (i)
!
then NEXT (cc)
else ERRORE (1);
{main}
!!
!!
!
NEXT (cc);
E;
if cc <> $ then ERRORE (3)
Costruzione della tabella di guida
I due insiemi FIRST e FOLLOW possono essere impiegati per costruire una tabella avente nelle righe i
simboli non terminali e nelle colonne i simboli terminali che consente di guidare deterministicamente il
riconoscitore, così definita:
Per ogni regola X " x | x | ....| x si considerano gli insiemi FIRST di ciascun x e l’insieme FOLLOW(X).
1 2
n
i
• Per ogni terminale t # FIRST (xi ) si pone TAB [ X, t] = xi.
•
Se xj $*! si pone TAB [X,t] = ! per ogni terminale t # FOLLOW (X).
Con riferimento alla grammatica vista in precedenza:
FIRST
E
-
(
E’
+ -
T
(
T’
i
*
F
(
E
TE’
)
)
+
TAB[E, -] = -TE’
E " TE’
TAB[E, ( ] = TE’, TAB[E, i] = TE’
TAB [E’, $] = !, TAB[ E’, )] = !
E’ " !
- +
-
*
-TE’
(
)
$
e!
!
!
!
TE’
-TE’
FT’
FT’
!
i
E " -TE’
$ ) - + *
+TE’
T’
F
)
$
$ )
+
E’
T
$
$
i
i
FOLLOW
i
!
*FT’
(E)
Tabella di guida
Struttura del parser
Pila
Stringa
E$
-i+i*i$
-TE’$
TE’$
-i+i*i$
FT’E’$
i T’E’$
T’E’$
-i+i*i$
E’$
+TE’$
TE’$
-i+i*i$
FT’E’$
i T’E’$
T’E’$
-i+i*i$
* FT’E’$
FT’E’$
-i+i*i$
i T’E’$
T’E’$
-i+i*i$
E’$
$
Elemento indirizzato
TAB[E, -] = - TE’
TAB[T, i] = FT’
TAB[ F, i] = i
tabella di guida
i
E
TAB[T’,* ] = *FT’
TAB[F, i] = i
TAB[T’, $] = !
TAB[E’, $] = !
-
*
-TE’
+TE’
)
$
-TE’
!" !"
FT’
!"
i
(
TE’
FT’
T’
F
TAB[T, i] = FT’
TAB[F, i] = i
TE’
E’
T
TAB[T’, +] = !
TAB[E, +] = +TE‘
+
!"
*FT’
!" ! "
(E)
1. Se il simbolo al top della pila è un
terminale esso deve coincidere col
carattere in lettura. Tale carattere viene
rimosso dalla pila e si avanza il
puntatore di un carattere.
2. Se il simbolo al top della pila è un non
terminale esso viene espanso con una
parte destra individuata dalla tabella
e rimosso dalla pila.
Albero sintattico
E
-
E’
T
F
T’ +
i
!
T
E’
F
T’
!
i
#
F
T’
i
!
Macchina di Turing
Nastro di Input
.......... !
!
!
a
b
b
a
b
!
!
!
testina
st
sr
Unità
di
Controllo
qi
Q
qj
P
S/D/F
!
...........
Definizione Formale
Una macchina di Turing deterministica è una sestupla < !, ", Q, q0, Z, # >
$
! - Alfabeto esterno o dei simboli di nastro
" - Simbolo speciale che indica cella vuota
"%!
Nastro di Input
.......... !
!
a
!
b
b
!
a
b
!
!
!
testina
Q - Un insieme finito e non vuoto di stati
st
s
r
q0 - stato iniziale
!
Unità
di
Controllo
q0 % Q
# - Funzione (parziale) di transizione definita come:
!
!
Q
qj
!Z - Insieme di stati finali (halting states)
!
qi
# : (Q - Z) x ( ! & {" }) ' Q x ( ! & {" }) x {S, D, F}
avendo indicato con S uno spostamento a Sinistra della Testina, con D uno
spostamento a Destra e con F nessuno spostamento
P
S/D/F
...........
Configurazione di una MT
Una configurazione di una MT rappresenta la più piccola porzione di nastro contenente tutti i
simboli non ! includente la cella cui è posizionata la testina ad eccezione di qualche simbolo !
che si trova “immerso” in una stringa.
qi
!
abbreviata con
!
a
b
b
!
b
a
a qi b b ! b a
formalmente una configurazione è una stringa x q y in cui:
x " # (#$ !)*${%},
q " Q,
y " (#$ !)*#${!}
la condizione x = % equivale a dire che alla sinistra di q non vi è alcun simbolo ovvero
compaiono solo simboli !, mentre se y =!, sulla cella dove è puntata la testina ed alla
destra della testina compaiono simboli !.
Configurazioni notevoli
Configurazione iniziale
E’ caratterizzata dalla stringa
!
!
!!
x = !, q = q ,
0
x q y con
y " #+$ { % }
Configurazione finale
E’ caratterizzata dalla stringa x q y con
!!
x " # (#$ %)*${!},
q " Z,
y " (#$ %)*#${%}
Per come è definita la matrice di transizione &, una macchina che si trovi in una
configurazione finale non può effettuare ulteriori passi di computazione.
Ciclo di macchina o transizione
E’ il meccanismo di base per il passaggio da una configurazione i-esima ad una
configurazione i+1-esima. Ad ogni ciclo viene cambiato il simbolo contenuto nella cella
esaminata con un altro simbolo (eventualmente lo stesso), il simbolo di stato
(eventualmente lo stesso) e lo spostamento della testina a Sinistra (S) Destra (D)
oppure nessun movimento (F).
Ci |! Ci+1
Più formalmente:
1. Ci = x q a y
e se "(q,a) = (q’, a’, D) allora Ci+1 = x a’ q’ y
2. Ci = x q a
e se "(q,a) = (q’, a’, D) allora Ci+1 = x a’ q’ #
3. Ci = x a q b y
e se "(q,b) = (q’, b’, S) allora Ci+1 = x q’ a b’ y
4. Ci = q b y
e se "(q,b) = (q’, b’, S)
5. Ci = x q a y e se "(q,a) = (q’,a’, F)
allora Ci+1 = q’ # b’ y
allora
Ci+1 = x q’ a’ y
Computazione
Una successione di transizioni stabilisce una computazione o calcolo
C0 |!
C1 .......... |! Cn
Vedremo nel prosieguo come una computazione può essere infinita o arrestarsi in una
configurazione finale.
Fly UP