1 / 56

Implementazione di Linguaggi 2 PARTE 4

Implementazione di Linguaggi 2 PARTE 4. Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley. PARSER LR. Algoritmo di Parsing LR. Il parser usa uno stack su cui impila stringhe della forma:

bianca
Download Presentation

Implementazione di Linguaggi 2 PARTE 4

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementazione di Linguaggi 2PARTE 4 Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley

  2. PARSER LR

  3. Algoritmo di Parsing LR Il parser usa uno stack su cui impila stringhe della forma: s0X1s1X2s2…Xmsm consm sul top dove XiN mentre si rappresenta uno stato del parser. Il parser e’ di tipo shift-reduce e il suo comportamento e’ deciso dall’input corrente ai e dall top dello stack sm. Le tavole del parser sono formate da due funzioni dette action function f e goto function g. Il parser consulta [sm,ai] che puo’ valere: • shift • reduce by A • accept • error

  4. Algoritmo di Parsing LR La funzione goto g mappa stati e simboli grammaticali in stati g: SVS ed e’ la funzione di transizione di un DFA che accetta prefissi accessibili (PrAc) della grammatica G. Un PrAc di una grammatica G e’ un prefisso di una forma sentenziale canonica destra (FSCD) che puo’ comparire sul top dello stack. Piu’ formalmente un PrAc di G e’ una stringa  tale che: S*rmAwrmw e PREF() (*) Una maniglia/chiave (handle) di una FSCD di G e’ una coppia formata da una produzione e una posizione nella FSCD. Nell’ esempio (*) (A,) o (A,n) dove n=|+1|. Lo handle esprime che la stringa

  5. Algoritmo di Parsing LR Canonico  alla posizione specificata dallo handle puo’ essere sostituita da A per ottenere la FSCD precedente in una derivazione canonica destra. Il DFA ha come stato iniziale quello impilato dal parser all’inizio. Una configurazione del parser e’ una coppia formata da: • il contenuto dello stack • l’input non ancora letto (s0X1s1X2s3…Xmsm,ajaj+1…an) La mossa corrente del parser e’ determinata da aj, da sm e dal valore di f[sm,aj] (action[sm,aj]) come segue:

  6. Algoritmo di Parsing LR Canonico • Se f[sm,aj]=shift allora il parser esegue uno shift e passa alla configurazione (s0X1s1X2s3…Xmsmajs,aj+1…an) dove s=g[sm,aj]. • se f[sm,aj]=reduce A allora il parser esegue una azione reduce passando alla configurazione (s0X1s1X2s3…Xm-rsm-rAs,ajaj+1…an) dove s=g[sm-r,A] ed r=||. Cioe’ il parser spila 2r simboli dallo stack fino ad esporre sul top sm-r; quindi impila A seguito da s=g[sm-r,A]. • Se f[sm,aj]=accept allora il parser termina l’analisi con successo. • Se f[sm,aj]=error allora attiva una routine di errore.

  7. Struttura delle tavole di Parsing LR Si consideri l’esempio (1) EE+T, (2) ET,(3) TT*F (4) TF, (5) F(E), (6) Fid. La prima slide mostra le tavole canoniche. Il loro difetto e’ di avere la tavola f sparsa e spreca-spazio. Per questo la slide successiva sposta la parte delle azioni goto sui terminali nella tavola f. Ad esempio se f[s,a]=shift e g[s,a]=n allora f[s,a] diviene action[s,a]=shift n, mentre la funzione g(a) scompare restando solo g(A). Di conseguenza il parser va ridescritto come segue (le nuove funzioni f e g vengono chiamate action e goto):

  8. Algoritmo di Parsing LR libro • Se action[sm,aj]=shift s allora il parser esegue uno shift e passa alla configurazione (s0X1s1X2s3…Xmsmajs,aj+1…an) • se action[sm,aj]=reduce A allora il parser esegue una azione reduce passando alla configurazione (s0X1s1X2s3…Xm-rsm-rAs,ajaj+1…an), s=goto[sm-r,A] e r=||. Cioe’ il parser spila 2r simboli dallo stack fino ad esporre sul top sm-r; quindi impila A seguito da s=goto[sm-r,A]. • Se action[sm,aj]=accept allora il parser termina l’analisi con successo. • Se action[sm,aj]=error allora attiva una routine di errore.

  9. Algoritmo di Parsing LR Driver Routine PROC ParserLR; DO/* s TOS state, a next input and ip pointer to it */ IF action[s,a]=shift s’ THEN push a; push s’; ip++ ELSIF action[s,a]=reduce A THEN pop 2|| symbols; /* s’ becomes TOS */ push A; push goto[s’,A]; out “A” ELSIF action[s,a]=accept THEN RETURN ELSE Error() FI OD END.

  10. Esempio di Parsing LR Step stack input action output 1 0 id*id+id$ shift 2 0id5 *id+id$ reduce Fid Fid 3 0F3 *id+id$ reduce TF TF 4 0T2 *id+id$ shift 5 0T2*7 id+id$ shift 6 0T2*7id5 +id$ reduce Fid Fid 7 0T2*7F10 +id$ reduce TT*F TT*F 8 0T2 +id$ reduce ET ET 9 0E1 +id$ shift 10 0E1+6 id$ shift 11 0E1+6id5 $ reduce Fid Fid

  11. Esempio di Parsing LR cont. Step stack input action output 12 0E1+6F3 $ reduce TF TF 13 0E1 +6E9 $ reduce EE+T EE+T 14 0E1 $ accept Da un punto di vista pratico sono state usate le grammatiche LR(0) ed LR(1) ed alcune sottoclassi di queste uktime: SLR(1) e LALR(1) benche’ le potenzialita’ dei processori di oggi permetta di prendere in considerazione le LR(1) ed anche le LR(k) con k>1 senza grossi problemi.

  12. Tavole di Parsing Canoniche Stato id + * ( ) $ E T F id + * ( ) $ 0 s s 1 3 5 2 4 s 1 A 6 2 s 2 2 7 2 3 4 4 4 4 4 s s 8 2 3 5 4 5 6 6 6 6 6 s s 9 3 5 4 s 7 s 10 5 4 8 s s 6 11 9 1 s 1 1 7 10 3 3 3 3 11 5 5 5 5

  13. Tavole di Parsing del Libro Stato id + * ( ) $ E T F 0 s5 s4 1 3 2 1 A s6 2 s7 2 2 2 3 4 4 4 4 4 s5 s4 8 2 3 5 6 6 6 6 6 s5 s4 9 3 s4 7 s5 10 8 s6 s11 9 1 s7 1 1 10 3 3 3 3 11 5 5 5 5

  14. Costruzione dell Tavole di Parsing LR Per questo vedremo in dettaglio le tavole LR(0), SLR(1) ed LR(1) trattando le LALR(1) marginalmente solo come meccanismo di semplificazione delle tavole LR. Item LR(0). Un item LR(0) e’ una produzione con un dot che ne marca una posizione nella parte destra. La produzione AXYZ origina quattro item: A.XYZ AX.YZ AXY.Z AXYZ.; Mentre A genera il solo item A. . L’idea centrale alla base del metodo consiste nel costruire dalla grammatica un automa finito che riconosca i PrAc della grammatica G. Alla base dei metodi piu’ semplici (SLR LALR) vi e’ la Collezione Canonica di Stati LR(0) (CCS0).

  15. Tavole LR(0): funzione closure Definizione. Data G=(N,T,P,S) definiamo grammatica estesa G’=(NS’,T,PS’S,S’) dove S’N e’ un nuovo simbolo iniziale. Scopo: determinare esattamente la terminazione del parser. Definizione. Chiusura di un insieme di item I. • Inizialmente Closure(I)=I. • Se A.BClosure(I) e B alllora aggiungere B.a closure(I). Il significato intuitivo di Closure e’ il seguente: se A.BClosure(I) allora durante il parsing e’ possibile che si analizzi una sottostringa derivata da B. Se inoltre B allora e’ anche possibile analizzare una sottostringa derivabile da .

  16. Tavole LR(0): chiusura Esempio di chiusura. Data la grammatica estesa G’ (0)E’E; (1)EE+T; (2)ET; (3)TT*F; (4)TF; (5)F(E); (6)Fid. Calcolo della chiusura di un insieme di item I. • Se inizialmente I={E’  .E} • Allora Closure(I)={E’.E, E.E+T, E.T, T.T*F, T.F, F.(E), F.id}.

  17. Tavole LR(0): routine di chiusura FUNC Closure(I: ItemSet); VAR J:ItemSet; BEGIN J:=I; DO FOR each itemA.BJ & each B DO J:=J{B.} OD UNTIL J unchanged; RETURN J END.

  18. Tavole LR(0): kernel item e item validi Definizione: Un kernel item e’: • S’.S • Un item con il dot chenon precede la parte destra della produzione Definizione Valid item. Un item A1.2e’ valido per per un PrAc 1 se esiste una derivazione S’rm*Awrm*12w Sapere che un item A1.2e’ valido per un PrAc 1 permette di decidere tra un’azione shift e reduce quando 1 e’ al top dello stack. In particolare se 2 allora lo handle non si trova ancora sullo stack e l’azione e’ shift. Se invece 2= allora A1e’ lo handle e l’azione sara’ reduce. E’ chiaro che due item validi diversi possono suggerire due azioni contrastant per lo stesso PrAc.

  19. Tavole LR(0): funzione closure Definizione. Data G=(N,T,P,S) definiamo grammatica estesa G’=(NS’,T,PS’S,S’) dove S’N e’ un nuovo simbolo iniziale. Scopo: determinare esattamente la terminazione del parser. Definizione. Chiusura di un insieme di item I. • Inizialmente Closure(I)=I. • Se A.BClosure(I) e B alllora aggiungere B.a closure(I). Il significato intuitivo di Closure e’ il seguente: se A.BClosure(I) allora durante il parsing e’ possibile che si analizzi una sottostringa derivata da B. Se inoltre B allora e’ anche possibile analizzare una sottostringa derivabile da .

  20. Tavole LR(0): funzione closure Definizione. Data G=(N,T,P,S) definiamo grammatica estesa G’=(NS’,T,PS’S,S’) dove S’N e’ un nuovo simbolo iniziale. Scopo: determinare esattamente la terminazione del parser. Definizione. Chiusura di un insieme di item I. • Inizialmente Closure(I)=I. • Se A.BClosure(I) e B alllora aggiungere B.a closure(I). Il significato intuitivo di Closure e’ il seguente: se A.BClosure(I) allora durante il parsing e’ possibile che si analizzi una sottostringa derivata da B. Se inoltre B allora e’ anche possibile analizzare una sottostringa derivabile da .

  21. Tavole LR(0): funzione goto Definizione. Funzione goto(I,X) definita su insiemi di item esimboli grammaticali: goto(I,X)=Closure({ AX.| A.XI} Intuitivamente se I e’ l’insieme degli item validi per un PrAc  allora goto(I,X) e’ l’insieme degli item validi per il PrAc X. Esempio: goto({E’E.,EE.+T},+)=Closure({EE+.T})= {EE+.T, T.T*F, T.F, F.(E), F.id}

  22. Tavole LR(0): funzione goto cont. Per ogni G la funzione goto definisce un DFA che riconosce PrAc di G. Il DFA e’ costruibile tramite un NFA che usa gli insiemi di item come stati e transizioni da A.X a AX. etichettate X e da A.B a B. etichettate . Ne segue che Closure(I) coincide con la -closure di un insiemi di stati di un NFA come visto a suo tempo. La funzione goto(I,X) realizza la transizione da da I tramite l’input X nel DFA ottenuto dal NFA tramite la costruzione basata sui sottoinsiemi di stati gia’ vista.

  23. Insiemi di item canonici LR(0) Algoritmo: Costruzione della Collezione Canonica degli item LR(0) per una grammatica (augmented) G’. PROC Items(G’); BEGIN C=Closure({s’.s}); DO FOR (I) IC & (X) XV: goto(I,X) DO C:=C goto(I,X) UNTIL C unchanged END;

  24. Insiemi di item canonici LR(0) di G’ G’: (0)E’E;(1)EE+T;(2)ET;(3)TT*F;(4)TF; (5)F(E); (6)Fid. I0: E’.E I3: TF. T.F I11: F(E). E .E+T I4: F(.E) F.(E) goto(I0,E)=I1 E .T E.E+T F.id goto(I0,T)=I2 T .T*F E.T I7: TT*.F goto(I0,F)=I3 T .F T.T*F F.(E) goto(I0,()=I4 F .(E) T.F F.id goto(I0,id)=I5 F.id F.(E) I8: F(E.) goto(I1,+)=I6 I1: E’ E. F.id E E.+T goto(I2,*)=I7 E E.+T I5: Fid. I9: EE+T. goto(I4,+)=I8 I2: E T. I6: EE+.T TT.*F goto(I4,T)=I2 T T.*F T.T*F I10: TT*F. goto(I4,F)=I3

  25. Insiemi di item canonici LR(0) di G’ G’: (0)E’E;(1)EE+T;(2)ET;(3)TT*F;(4)TF; (5)F(E); (6)Fid. I0: E’.E I3: TF. T.F I11: F(E). E .E+T I4: F(.E) F.(E) goto(I4,()=I4 E .T E.E+T F.id goto(I4,id)=I5 T .T*F E.T I7: TT*.F goto(I6,T)=I9 T .F T.T*F F.(E) goto(I6,F)=I3 F .(E) T.F F.id goto(I6,()=I4 F.id F.(E) I8: F(E.) goto(I6,id)=I5 I1: E’ E. F.id E E.+T goto(I7,F)=I10 E E.+T I5: Fid. I9: EE+T. goto(I7,()=I4 I2: E T. I6: EE+.T TT.*F goto(I7,id)=I5 T T.*F T.T*F I10: TT*F. goto(I8,))=I11

  26. Insiemi di item canonici LR(0) di G’ G’: (0)E’E;(1)EE+T;(2)ET;(3)TT*F;(4)TF; (5)F(E); (6)Fid. I0: E’.E I3: TF. T.F I11: F(E). E .E+T I4: F(.E) F.(E) goto(I8,+)=I46 E .T E.E+T F.id goto(I9,*)=I7 T .T*F E.T I7: TT*.F T .F T.T*F F.(E) F .(E) T.F F.id F.id F.(E) I8: F(E.) I1: E’ E. F.id E E.+T E E.+T I5: Fid. I9: EE+T. I2: E T. I6: EE+.T TT.*F T T.*F T.T*F I10: TT*F.

  27. Diagrammi LR(0) esempio

  28. Tavole di parsing SLR(1) Si costruisce a partire dalla collezione C di insiemi di item LR(0) di G’ calcolando action e goto come segue: • Costruire C={I0,I1,…In} Collezione di insiemi di item LR(0) di G’ • La tavola (stato) i deriva da Ii con azioni: • A.aIi & goto(I,a)=Ij  action[i,a]=“shift j” • A.Ii  aFOLlOW(A) &AS’ action[i,a]=“reduce A” • S’SIi  action[I,$]=“accept” Se le regole precedenti generano azioni in conflitto allora G’ non e’ SLR(1).

  29. Tavole di parsing SLR(1) • AN goto[Ii,A]=Ij goto(i,A)=j • Ogni entry non definita in 1. 2. 3. e’ posta a error • Lo stato iniziale del parser e’ costruito da I0={S’.S,…} Una grammatica che possieda una tavola di parsing SLR(1) e’ detta SLR(1). Ogni grammatica SLR(1) e’ non ambigua. Esistono grammatiche non ambigue che non sono SLR(1), Es: SL=R SR L*R Lid RL

  30. Tavole di Parsing Stato id + * ( ) $ E T F id + * ( ) $ 0 s s 1 3 2 s 1 A 2 s 2 2 2 3 4 4 4 4 4 s s 8 2 3 5 6 6 6 6 6 s s 9 3 s 7 s 10 8 s s 9 1 s 1 1 10 3 3 3 3 11 5 5 5 5

  31. Item LR(1) Un item LR(1) e’ una coppia [A.,a] con aT{$} e A. Il secondo componente di un item e’ chiamato stringa di lookahead. Essa non si usa quando β≠. Se invece β=la stringa di lookahead a specifica una riduzione A solo quando il token in input è a. Definizione. Un item LR(1) [A.,a] è valido per un PrAc  a se esiste una derivazione canonica destra S’rm*Awrm*w, con = e w=aw’ o w= & a=$. In relazione alle grammatiche SLR(1) va notato che l’ insieme di stringhe di lookahead a che formano gli item LR(1) [A.,a]validi per un prefisso  verifica FOLLOW(A) ma in generale FOLLOW(a)

  32. Tavole LR(1): funzione closure Definizione. Chiusura di un insieme di item I per una G’ estesa: • Inizialmente Closure(I)=I. • Se [A.B,a]Closure(I) e B alllora aggiungere [B.,b]a closure(I) per ogni bFIRST(a) Il significato intuitivo di Closure e’ il seguente: se A.BClosure(I) allora durante il parsing e’ possibile che si analizzi una sottostringa derivata da B. Se inoltre B allora e’ anche possibile analizzare una sottostringa derivabile da  per tutti gli input b tali che bFIRST(a)

  33. Tavole LR(1): routine di chiusura FUNC Closure(I: ItemSet); VAR J:ItemSet; BEGIN J:=I; DO FOR each item [A.B,a]J & each B & each bFIRST(a) DO J:=J{[B.,b]} OD UNTIL J unchanged; RETURN J END.

  34. Tavole LR(1): funzione goto Definizione. Funzione goto(I,X) definita su insiemi di item esimboli grammaticali: goto(I,X)=Closure({ [AX.,a]| [A.X,a]I} Ancora se I e’ l’insieme degli item validi per un PrAc  allora goto(I,X) e’ l’insieme degli item validi per il PrAc X.

  35. Insiemi di item canonici LR(1) Algoritmo: Costruzione della Collezione Canonica degli item LR(1) per una grammatica (augmented) G’. PROC Items(G’); BEGIN C=Closure({[s’.s,$]}); DO FOR each IC & each XV such that goto(I,X) DO C:=C goto(I,X) /* INCL(C,goto(I,X)) */ UNTIL C unchanged END;

  36. Insiemi di item canonici LR(1) di G2’ G2’: (0)S’S;(1)SCC;(2)CcC;(3)Cd; I0: [S’.S,$] I3: [Cc.C,c] [C.d,$] goto(I2,d)=I7 [S.CC,$] [Cc.C,d] I7: [Cd.,$] goto(I3,C)=I8 [C.cC,c] [C.cC,c] I8: [CcC.,c] goto(I3,c)=I8 [C.cC,d] [C.cC,d] [CcC.,d] goto(I3,d)=I4 [C.d,c] [C.d,c] I9: [Cc.,$] goto(I6,C)=I9 [C.d,d] [C.d,d] goto(I0,S)=I1 goto(I6,c)=I6 I1: [S’S.,$] I4: [Cd.,c] goto(I0,C)=I2 goto(I6,d)=I7 I2: [SC.C,$] [Cd.,d] goto(I0,c)=I3 [C.cC,$] I5: [SCC.,$] goto(I0,d)=I4 [C .d,$] I6: [Cc.C,$] goto(I2,C)=I5 [C.cC,$] goto(I2,c)=I6

  37. Insiemi di Item LR(1): diagramma

  38. Costruzione delle Tavole LR(1) Input: una grammatica estesa G’. Output: tavole canoniche LR(1) di G’. • Costruire C={I0,I1,...,In} CCII LR(1) • La tavola i deriva da Ii con action seguente: • se [A.a,b]Iie goto(Ii,a)=Ijallora action[i,a]=shift j • se [A.,a]Iie A≠S allora action[i,a]=reduce A • se [S’S,$]Iiallora action[i,$]= accept • Se goto(Ii,A)=Ij allora goto[i,$]=j • Porre tutte le entry non definite in 1),2) e 3) a error • Lo stato iniziale del parser è quello contenente [S’.S,$] Se le tavole non presentano conflitti shift-reduce o reduce-reduce allora la grammatica G è LR(1).

  39. Tavole di Parsing LR(1) esempio Stato c d $ S C 0 s3 s4 1 2 G2’: (0)S’S;(1)SCC;(2)CcC;(3)Cd; 1 A s6 s7 5 2 s4 s3 8 3 4 r3 r3 5 r1 s6 s7 9 6 7 r3 8 r2 r2 r2 9

  40. Tavole di Parsing LR(1) esempio Stato c d $ S C 0 s3 s4 1 2 G2’: (0)S’S;(1)SCC;(2)CcC;(3)Cd; 1 A goto (I0,c)=I3 goto(I0,d)=I4 goto(I0,S)=I1 goto(I0,C)=I2 goto(I2,c)=I6 goto(I2,d)=I7 goto(I2,C)=I5 goto(I3,c)=I3 goto(I3,d)=I4 goto(I3,C)=I8 goto(I6,c)=I6 goto(I6,d)=I7 goto(I6,C)=I9 s6 s7 5 2 s4 s3 8 3 4 r3 r3 5 r1 s6 s7 9 6 7 r3 8 r2 r2 r2 9

  41. Costruzione delle Tavole LALR(1) Definiamo core(I)={[A.] | [A.,u]I} Poichè il core di goto(I,X) dipende dal core di I, ne segue che goto(HIi)= Hgoto(Ii). Quindi i goto di stati immersi sono a loro volta tra loro immergibili. Le tavole ottenute in questo modo, come ottimizzazione della collezione di stati canonici LR(1) sono tuttavia anche ottenibili a partire dalla collezione canonica di stati LR(0). Questo ne fa un algoritmo molto efficiente.

  42. Costruzione delle Tavole LALR(1) Se nella collezione canonica di insiemi di item LR(1) di G2’ uniamo gli stati I4 e I7 in un nuovo stato I47 con 3 item [Cd.,c/d/$] allora il parser ha azione reduce_Cd su ogni input, anche su quelli su cui l’originale dichiara error (es. ccd cdcdc) . La primo token in input errato. L’ottimizzazione consiste nell’ immergere gli stati con lo stesso core, cioè stati che differiscono solo per il token di lookahead (idem per I3-I6 e I8-I9).

  43. Corrispondenti Item LALR(1)

  44. Corrispondenti Item LALR(1)

  45. Corrispondenti Item LR(0)

  46. Insieme LALR(1) e LR(0)

  47. Corrispondenti Item LALR(1)

  48. Grammatiche LL ed LR Teorema (decidibilita’): date due grammatiche LL(k), G1 e G2, il problema L(G1)=L(G2) e’ decidibile. La seguente grammatica: SA|B, AaAb|0, BaBbb|1 e’ LR(0) ma non LL(k) per ogni k0. Teorema. Ogni grammatica LL(k) e’ anche LR(k), k0. Definizione. Um linguaggio CFG e’ deterministico se esite un DPDA (Det, PushDown Automaton) che lo accetta.

  49. Linguaggi LL ed LR Definizione. Un linguaggio L tale che nessuna wL e’ della forma w=xy con xL e’ detto avere la proprieta’ del prefisso (prefix-free). Teorema. L linguaggio deterministico: GLR(1): L=L(G). Se inoltre L e’ prefix-free allora: GLR(0): L=L(G). Altrimenti detto LT* CFG deterministico e TGLR(0): L=L(G).

  50. Linguaggi LL ed LR cont. Teorema. Dato un linguaggio L per cui esiste una grammatica G, LL(k) e priva di -produzioni, tale che L=L(G) e k>1, allora esiste una grammatica G’, LL(k-1) tale che L=L(G’). Teorema. Per ogni k 0 la classe dei linguaggi LL(k) e’ propriamente inclusa in quella dei linguaggi LL(k+1).

More Related