Linguaggi Formali e Compilazione: Parsing

  • Published on
    12-Aug-2015

  • View
    3.108

  • Download
    2

Transcript

  1. 1. LFCParsing dilinguaggi liberiIntroduzioneParsing top-downParsing bottom-upLinguaggi formali e compilazione Corso di Laurea in InformaticaA.A. 2008/2009
  2. 2. LFC Linguaggi formali e compilazioneParsing dilinguaggi liberiIntroduzioneParsing top-downParsing bottom-up Parsing di linguaggi liberiIntroduzioneParsing top-downParsing bottom-up
  3. 3. LFC Linguaggi formali e compilazioneParsing dilinguaggi liberiIntroduzioneParsing top-downParsing bottom-up Parsing di linguaggi liberiIntroduzioneParsing top-downParsing bottom-up
  4. 4. LFC Parsing di linguaggi liberi Ogni linguaggio libero pu essere riconosciuto in Parsing di linguaggi liberi tempo proporzionale al cubo della lunghezza della Introduzionestringa in input. Parsing top-down Parsing bottom-up Lalgoritmo che stabilisce questo limite di complessit, basato su una classica applicazione della programmazione dinamica, tuttavia inutilizzabile in applicazioni reali. Gli algoritmi di parsing utilizzati nella pratica sono generalmente classicati base alla strategia utilizzata per la costruzione (anche solo ideale) del parse-tree, top-down o bottom-up. Allinterno di queste due categorie generali, gli algoritmi si differenziano in base a scelte strategiche pi dettagliate. Tali algoritmi non possono analizzare tutti i linguaggi context-free.
  5. 5. LFC Tipi di parserParsing dilinguaggi liberiIntroduzioneParsing top-down In concreto, i tipi di parser pi diffusi includono: Parsing bottom-up parser a discesa ricorsiva (top-down), parser di tipo LR (bottom-up), parser a precedenza di operatori (bottom-up). Nel parsing top-down si cerca una derivazione canonica per la stringa/programma in input partendo dallassioma iniziale. La costruzione top-down dellalbero di derivazione corrisponde in modo naturale al riconoscimento di un blocco/procedura/espressione in termini delle parti costituenti.
  6. 6. LFC Tipi di parser (continua)Parsing dilinguaggi liberiIntroduzioneParsing top-downNel parsing bottom-up si cerca una derivazione Parsing bottom-up canonica per la stringa/programma in input partendo dalla stringa stessa e applicando riduzioni successive. Una riduzione non nientaltro che lapplicazione in senso contrario di una produzione della grammatica. La costruzione bottom-up dellalbero di derivazione corrisponde in modo naturale al riconoscimento di singole porzioni di un programma e alla loro composizione in parti pi complesse.
  7. 7. LFC Non determinismo Parsing di linguaggi liberi Introduzione In entrambi i tipi di parser (top-down o bottom-up) Parsing top-down Parsing bottom-up possibile (anche se non desiderabile) che la scelta della produzione da utilizzare, in una delle due direzioni, non sia determinabile con certezza. Se la scelta di una produzione errata il riconoscimento fallisce. In tal caso, prima di dichiarare che la stringa sintatticamente errata, necessario operare un backtracking sullinput, ritornando al punto di scelta. Per i parser a discesa ricorsiva (e implementati mediante ricorsione) ci pu essere sufcientemente agevole, anche se computazionalmente pesante.
  8. 8. LFC Linguaggi formali e compilazioneParsing dilinguaggi liberiIntroduzioneParsing top-downParsing bottom-up Parsing di linguaggi liberiIntroduzioneParsing top-downParsing bottom-up
  9. 9. LFC Parsing a discesa ricorsiva (recursive descent) Parsing di linguaggi liberi Introduzione Parsing top-down Parsing bottom-upUn parser a discesa ricorsiva (d.r.) pu essere realizzato come collezione di procedure (mutuamente) ricorsive, una per ogni simbolo non terminale della grammatica. Siano A 1 . . . k le produzioni relative al ii nonterminale A, e sia i = X1 . . . Xni , i = 1, . . . , k. La procedura relativa al simbolo A illustrata nel seguente algoritmo, in cui (per semplicit di notazione) evitiamo i doppi indici e supponiamo che il simbolo corrente di input sia contenuto nella variabile globale x.
  10. 10. LFCParsing dilinguaggi liberiIntroduzioneParsing top-down Algorithm 1 Procedura per il nonterminale AParsing bottom-up 1: Scegli opportunamente una produzione A X1 X2 . . . Xk (Xj V)2: for j = 1, . . . , k doif Xj N then3:Xj ()4:else if Xj = x then5:x read()6:else7:error()8:
  11. 11. LFC Backtracking La scelta della produzione da applicare (riga 1Parsing di linguaggi liberi dellalgoritmo 1) pu essere meno critica se, nel caso IntroduzioneParsing top-downdi fallimento, viene effettuato backtracking sullinput. Parsing bottom-upLalgoritmo deve essere modicato in modo tale da dichiarare fallimento solo quando tutte le produzioni per il nonterminale A sono state provate senza successo. Deve per essere disposto un meccanismo per riposizionare il puntatore di input su quello che era il simbolo corrente al momento della chiamata della procedura. Ne consegue che: o il parser bufferizza linput ricevuto dallo scanner, oppure questultimo che deve essere opportunamente programmato per la ripetizione di certe sequenze di token.
  12. 12. LFC Scelta della produzione Fortunatamente, in molti casi concreti il backtracking Parsing di linguaggi liberi non necessario perch la scelta della produzioneIntroduzione Parsing top-down pu essere fatta con lookahead limitato (cio Parsing bottom-up guardando pochi token a partire dalla posizione corrente di input). Consideriamo la semplice grammatica: A aA | bBB | bBPer entrambi i non terminali, la scelta della produzione da usare pu essere fatta guardando il prossimo simbolo x in input. Per A: se x = a, usa la produzione A aA; se x = b, usa la produzione A bB. Per B. se x = $ (end of input), usa la produzione B ; se x = b, usa la produzione B bB;
  13. 13. LFC Grammatiche inadatte al parsing a discesa ricorsivaParsing di Alcune produzioni sono inadatte al r.d. parsing. linguaggi liberi IntroduzioneProduzioni con ricorsioni a sinistra, che possono Parsing top-downParsing bottom-upcausare cicli inniti, come nella grammatica E +T | T E T F | F T id | (E )F Produzioni con pressi comuni (come il noto caso del dangling else), che rendono non limitabile a priori la quantit di lookahead. Un altro esempio (articiale) A aB | aCB aB | bC aC | c Come sappiamo, esistono opportune trasformazioni per risolvere questi problemi.
  14. 14. LFC FIRST e FOLLOWData una grammatica G, limplementazione di parserParsing dia d.r. per G utilizza (secondo le teorie pi accettate) linguaggi liberiIntroduzionedue funzioni, dette FIRST e FOLLOW , cheParsing top-downParsing bottom-updeterminano la scelta della produzione da utilizzare.Data G = (N , T , P, S) e data una stringa (N T ) , si denisce FIRST () linsieme deisimboli terminali con cui pu iniziare una frasederivabile da , pi eventualmente se :FIRST () = {x T | x, T } {} , se .Per ogni nonterminale A N si denisceFOLLOW (A) linsieme dei terminali che si possonotrovare immediatamente alla destra di A in unaqualche forma di frase. In altri termini,x FOLLOW (A) se S Ax, con e opportuni.
  15. 15. LFC Calcolo di FIRST () Parsing di linguaggi liberi Introduzione Deniamo innanzitutto come si calcola FIRST () nel Parsing top-down Parsing bottom-up caso in cui sia un singolo simbolo della grammatica, cio = X con X N T . Se X un terminale, si pone naturalmente FIRST (X ) = {X }; se X un nonterminale poniamo innanzitutto FIRST (X ) = {}. Se esiste la produzione X X1 . . . Xn , e risulta FIRST (Xj ), j = 1, . . . , k 1, poniamo FIRST (X ) = FIRST (X ) {x} per ogni simbolo x FIRST (Xk ). Inne, se esiste la produzione X oppure FIRST (Xj ), j = 1, . . . , k , poniamo FIRST (X ) = FIRST (X ) {}.
  16. 16. LFC EsempiSi consideri nuovamente la grammaticaParsing dilinguaggi liberi (E ) E | id E EIntroduzioneParsing top-downParsing bottom-up E + E E | E E | Per questa grammatica risultaFIRST (E) = {( , id} FIRST (E ) = {+, , } Si consideri ora la grammatica per an bm ckA aA | BC | B bB | C cC | Per questa grammatica risultaFIRST (C) = {c, } FIRST (B) = {b, } FIRST (A) = {a, b, c, }
  17. 17. LFC EsempioParsing dilinguaggi liberiIntroduzioneParsing top-down Si riconsideri la grammatica per le espressioni che Parsing bottom-upforza la precedenza di operatori: E +T | T E T F | FT id | (E )F Per questa grammatica risultaFIRST (F ) = {( , id}; FIRST (T ) = FIRST (F ); FIRST (E) = FIRST (T ).
  18. 18. LFC Calcolo di FIRST () (continua)Parsing dilinguaggi liberiIntroduzioneIl calcolo di FIRST (), dove = X1 . . . Xn unaParsing top-down Parsing bottom-upgenerica stringa di terminali e nonterminali, pu ora essere svolto nel modo seguente a FIRST () se e solo se, per qualche indice k 1, . . . n 1, risulta a Xk e Xj , j = 1, . . . , k 1 (si suppone sempre FIRST (X0)). Se inoltre FIRST (Xj ), j = 1, . . . , n, allora FIRST (). Ad esempio, nel caso della seconda grammatica del lucido precedente risulta: FIRST (aA) = {a} e FIRST (BC) = {b, c, }.
  19. 19. LFC Calcolo di FOLLOW (A) Parsing di linguaggi liberi IntroduzioneIl calcolo di FOLLOW (A), per un generico non Parsing top-down Parsing bottom-upterminale A, pu essere svolto in questo modo. Se A = S, si inserisce il simbolo speciale $ (marcatore di ne input) in FOLLOW (A). Se esiste la produzione B A, tutti i terminali in FIRST () si inseriscono in FOLLOW (A); inoltre, se FIRST (), tutti i terminali che stanno in FOLLOW (B) si inseriscono in FOLLOW (A) . Analogamente, se esiste la produzione B A, tutti i terminali che stanno in FOLLOW (B) si inseriscono in FOLLOW (A) .
  20. 20. LFC EsempioParsing diConsideriamo la solita grammaticalinguaggi liberiIntroduzioneParsing top-down (E ) E | id E EParsing bottom-up +E E | E E | E Possiamo subito stabilire che FOLLOW (E ) include ilsimbolo $ e il simbolo ); inoltre contiene i simboli inFIRST (E ) (eccetto ) e cio + e .FOLLOW (E ) include FOLLOW (E ), a causa (adesempio) della produzione E idE .La produzione E +EE , unitamente a E ,stabilisce che vale anche il contrario, e cio cheFOLLOW (E ) include FOLLOW (E ).Mettendo tutto insieme si ottieneFOLLOW (E ) = FOLLOW (E ) = {$, ) , +, }.
  21. 21. LFC EsempioParsing dilinguaggi liberiIntroduzioneParsing top-downParsing bottom-up Per la grammatica A aA | BC | B bB | C cC | risulta FOLLOW (A) = FOLLOW (C) = {$} eFOLLOW (B) = {c, $}.
  22. 22. LFC Esempio Parsing di linguaggi liberi Introduzione Parsing top-down Parsing bottom-upPer la grammatica con precedenza di operatori: E +T | T E T F | F T id | (E )F risulta:FOLLOW (E) = {$, +, )}; FOLLOW (T ) = FOLLOW (E) {}; FOLLOW (F ) = FOLLOW (T ).
  23. 23. LFC Grammatiche LL(1) Per opportune classi di grammatiche libere Parsing di possibile realizzare parser a d.r. che non richiedono linguaggi liberi Introduzionebacktracking (tali parser sono anche detti predittivi). Parsing top-down Parsing bottom-up Una tale classe di grammatiche la LL(1), dove le due L stanno per left-to-right e leftmost derivation. In altri termini, il parsing avviene leggendo linput unidirezionalmente, da sinistra a destra, e costruendo una derivazione canonica sinistra della stringa. Il parametro 1 indica che richiesto un solo simbolo di lookahead. La classe LL(1) in grado di esprimere molte fra le caratteristiche della sintassi dei linguaggi di programmazione. Nessuna grammatica ricorsiva a sinistra o con produzioni aventi previssi comuni pu per essere LL(1) (come pure nessuna grammatica ambigua).
  24. 24. LFC Grammatiche LL(1) (continua) Parsing di linguaggi liberi Come possiamo stabilire se una grammatica Introduzione Parsing top-downLL(1)?Parsing bottom-upConsideriamo la procedura per un generico nonterminale A. Se esistono due produzioni A e A , allora certamente non deve accadere cheFIRST () FIRST () = {} ,perch in tal caso un solo carattere di lookahead non basterebbe per decidere correttamente la produzione da usare. Tuttavia ci potrebbe non essere sufciente.
  25. 25. LFC Grammatiche LL(1) (continua) Parsing di linguaggi liberi Supponiamo (ad esempio) che . Potremmo Introduzione Parsing top-downtrovarci nella seguente situazione: Parsing bottom-upS Ax, T , x T , V dove, se il prossimo carattere di input fosse proprio x, potrebbe essere corretto usare la produzione A . Tuttavia, se x fosse anche in FIRST () potrebbe essere corretto pure usare la produzione A . Deve quindi risultare implica FOLLOW (A) FIRST () = {} e, analogamente, implica FOLLOW (A) FIRST () = {}
  26. 26. LFC EsempioSi consideri la grammatica Parsing di linguaggi liberi A BEIntroduzione Parsing top-downB C|D Parsing bottom-upC | ccD | dd c|dE Poich risulta FIRST (C) FIRST (D) = {}, lagrammatica non LL(1).Infatti, supponiamo che la stringa in input inizi con c.Dopo la riscrittura dellassioma il parser verrebbe atrovarsi con la forma di frase BE e il carattere c ininput.A questo punto potrebbe essere corretto derivaretanto CE (se linput fosse, ad esempio, ccd) quantoDE (se linput fosse c).
  27. 27. LFC EsempioSi modichi la precedente grammatica nel modoParsing diseguentelinguaggi liberiIntroduzioneParsing top-downParsing bottom-upA BEB C|DC | ccD dd c|dE (cancellando cio la produzione D ).Poich risulta FIRST (D) FOLLOW (B) = {d}, lagrammatica non LL(1).Il problema si verica con input che inizia con d,perch potrebbe essere corretto (dopo la derivazioneiniziale) derivare tanto CE (se linput fosse d) quantoDE (se linput fosse, ad esempio ddc).
  28. 28. LFC Costruzione della tabella di parsingParsing di Per una grammatica LL(1) possibile costruire linguaggi liberi Introduzione (utilizzando le funzioni FIRST e FOLLOW ) unaParsing top-downParsing bottom-up tabella, detta tabella di parsing, che, per ogni nonterminale A e ogni terminale x, prescrive il comportamento del parser. Indicheremo con MG la tabella di parsing relativa alla grammatica G (o semplicemente con M, se la grammatica evidente). La generica entry MG [A, x] della tabella pu contenere una produzione A di G, oppure essere vuota, ad indicare che si vericato un errore. Disponendo di MG , la prima riga dellalgoritmo 1 viene sostituita da un lookup a MG [A, x].
  29. 29. LFC Costruzione della tabella di parsing (continua)Parsing dilinguaggi liberiIntroduzioneParsing top-down Lalgoritmo di costruzione della parsing table molto Parsing bottom-up semplice ed formato da un ciclo principale nel quale si prendono in considerazione tutte le produzioni. Per ogni produzione A : per ogni simbolo x in FIRST () si pone M[A, x ] = A ; se FIRST (), per ogni simbolo y in FOLLOW (A) si pone M[A, y ] = A . Tutte le altre entry della tabella vengono lasciate vuote (ad indicare loccorrenza di un errore). Se la grammatica LL(1), nessuna entry della tabella viene riempita con pi di una produzione.
  30. 30. LFC EsempioConsideriamo ancora la grammatica con precedenzaParsing didi operatori: linguaggi liberiIntroduzione E +T | T EParsing top-downParsing bottom-up T F | F T id | (E ) FTale grammatica (pur non ambigua) non LL(1)perch (p.e.), entrambe le produzioni E E + T eE T verrebbero poste nella entry M[E , id].Elimi...

Recommended

View more >