Parser Bottom UP
Giuseppe Morelli
Parser Bottom UP
• Un parser Bottom Up lavora costruendo il
corrispondente albero di parsing per una data
stringa di input partendo dalle foglie (bottom) e
risalendo via visa verso la radice (top).
• Nel seguito verranno trattati parser bottom up
noti come Shift-Reduce parser.
• Sono in grado di costruire grammatiche
chiamate LR.
• La costruzione di parser LR è alquanto
complessa;
• Esistono tuttavia generatori automatici di parser
in grado di costruire parser LR efficienti
Riduzioni
• Il parsing Bottom Up può essere pensato come
il processo di “riduzione” di un data stringa w al
simbolo iniziale della grammatica.
• Ad ogni passo della riduzione uno specifica
sottostringa che coincide con il corpo di una
produzione è sostituita da il simbolo non
terminale della testa della produzione stessa.
• Durante il parsing è fattore chiave riuscire a
determinare quando effetturare una riduzione e
quale produzione applicare affinchè il parsing
possa proseguire
• Ritornando all’esempio:
• La sequenza di riduzioni applicate può essere
codificata attraverso:
NOTA:
Dopo le prime due riduzioni (F->id; T->F) si potrebbe Ridurre T
attraverso E->T oppure id (di destra) attraverso F -> id
• Per definizione una riduzione è il passo inverso
della procedura di derivazione (attraverso la
quale un non terminale era sostituito dal corpo
di una produzione, durante la generazione di
una stringa).
• Lo scopo del parsing bottom-up è costruire un
darivazione al contrario (in senso inverso).
• Derivazione
• Riduzione
Esempio
• Si consideri la grammatica
S -> aABe
A -> Abc |b
B -> d
E l’input: abbcde
• Riduzione:
abbcde (A->b A->Abc B->d S->aABe)
abbcde, aAbcde, aAde, aABe, S
• Derivazione
S => aABe => aAde => aAbcde => abbcde
• Per ottenere una riduzione al simbolo iniziale
attraverso l’inversa di una derivazione è
necessario essere in grado di riconoscere gli
handles(maniglie) delle varie forme
proposizionali.
• Un handle è una sottostringa che coincide con
il corpo di una produzione e la cui riduzione
rappresenta un passo lungo il processo di
derivazione destra inverso
• Esempio precedente i simboli sottolineati sono
handles
…
• Data una forma proposizionale destra γ un
handle per γ è una produzione A -> β ed una
posizione in γ corrispondente ad una occorrenza
di β tale che rimpiazzando β con A si ottiene
ancora una forma sentenziale destra che
precede immediatamente γ in una derivazione
destra per γ.
o equivalentemente
• Se S => αAw => αβw allora la produzione
A->β nella posizione seguente ad α è un handle
di αβw.
NOTE
• Alla destra dell’handle la stringa w è fatta solo
di simboli terminali
• Se una grammatica è non ambigua ogni forma
sentenziale destra avrà solo un handle (ovvero
le derivazioni destre sono univocamente
determinte)
• Sebbene formalmente un handle è una
produzione spesso ci si riferirà solo al suo body
Esempi
• .
• Si consideri la stringa id+id*id e la grammatica:
E -> E+E | E*E | (E) | id
– id+id*id => E + id * id => E+E*id => E+E*E => E+E
=> E
– id+id*id =>E+id*id =>E+E *id => E*id => E*E => E
• L’inversa di una derivazione destra può essere
ottenuta attraverso un procediemento di
“potatura” degli handle (handle pruning).
• Si parte dalla stringa di terminali w da ridurre;
se w è una frase della grammatica(sentence:
derivazione ovvero forma sentenziale con soli
terminali) allora sia w =γn dove γn è n-esima
forma sentenziale destra di una derivazione destra
• Per ricostruire la derivazione nell’ordine inverso:
localizzare l’handle βn in γn e rimpiazzare βn con la
testa della produzione An -> βn per ottenere la
forma sentenziale γn-1. Si continua trovando βn-1 in
γn-1 …. fino ad arrivare al simbolo iniziale.
• La sequenza delle produzioni utilizzate (in ordine
inverso) rappresenta la derivazione destra per la
stringa di input
Shift- Reduce parser
• Per una corretta potatura dell’albero si devono
affrontare e risolvere due problemi:
1. Bisogna essere in grado di localizzare la
sottostringa da ridurre
2. Bisogna determinare quale produzione
utilizzare nella riduzione
• Tali problemi possono essere affrontati
utilizzando:
– Uno stack per contenere i simboli della grammatica
ovvero un prefisso della forma sentenziale destra
fino ad un handle
– Un buffer di input per contenere la porzione di input
di cui ancora si deve fare il parsing.
• Convenzionalmente il $ indica sia il top dello
stack sia la destra della stringa di input
• Inizialmente stack vuoto e stringa w si indicherà
con:
• Durante il processo di analisi della stringa di
input da sinistra a destra, il parser muoverà 0 o
più simboli nello stack fino a quando non sarà in
grado di ridurre una stringa della grammatica
(corpo della produzione) con il top dello stack
(sostituisce top con non terminale testa della
produzione). La fine senza errori è determinata
dalla presenza del simbolo iniziale nello stack,
con buffer di input vuoto.
Operazioni di un parser Shift Reduce.
• Shift: sposta il successivo simbolo di input nello
stack
• Reduce: riduzione dell’handle sullo stack (top)
mediante una opportuna produzione.
Sostituzione dell’handle con un non terminale
• Accept: Segnalazione che il parsing si è
concluso con successo
• Error: Segnalare errore di sintatti e richiamare
una opportuna procedure di recovery.
Esempio
E
E
E
E
STACK
INPUT
$
$ id
$E
$ E + id
$E+E
$ E + E  id
$E+EE
$E+E
$E
id + id  id $
+ id  id $
+ id  id $
id $
id $
$
$
$
$
->
->
->
->
E+E
E*E
(E)
id
AZIONE
SHIFT
REDUCE E  id
SHIFT, SHIFT
REDUCE E  id
SHIFT, SHIFT (perché NON REDUCE E  E + E)
REDUCE E  id
“ E E  E
“ E E + E
ACCEPT
Conflitti
• Un parser shift-reduce può raggiungere una
configurazione in cui, pur conoscendo lo stack
nella sua interezza ed i simboli di input da
trattare , non sa decidere se:
– Effettaure una operazione di SHIFT o di
REDUCE (conflitto Shift/Reduce)
– Scegliere fra più riduzioni possibili quale
effettuare (conflitto Reduce/Reduce)
Esempio
• Quando il parser è nella seguente configurazione:
• Non è possibile determinare se nello stack c’è un
handle oppure no quindi se fare un o shift o una
riduzione
Esempio
• Quando il parser è nella seguente configurazione:
• Non sappiamo decidere quale riduzione fare tra (5)
e (7)
• Se invece di id per array e procedure il lexer
restituisce risp. id e procid per i costrutti
Scarica

Parser BOTTOM UP