500 likes | 696 Views
Deterministick á SA zhora nadol. Gramatiky a jazyky LL(k) a ich analýza. Gramatiky LL(k). Umožňujú deterministickú SA Umožňuje deterministickú SA zhora nadol – robí sa teda ľavá derivácia
E N D
Deterministická SA zhora nadol Gramatiky a jazyky LL(k) a ich analýza
Gramatiky LL(k) • Umožňujú deterministickú SA • Umožňuje deterministickú SA zhora nadol – robí sa teda ľavá derivácia • Cena za determinizmus je vyjadrená potrebou poznať ďalších k symbolov zo vstupu za práve vyšetrovaným symbolom • Na základe tohoto – tzv. vopred prezretého reťazca pozostávajúceho z najviac k nasledujúcich symbolov dokáže rozšriešiť problém výberu zodpovedajúcej alternatívy pravej strany pravidla
Funkcia FIRST • Umožňuje určiť množinu reťazcov danej dľžky, ktoré možno generovať z VF, ktorá je jej argumentom • Nech G = (N, T, P, S) je BKG, k je celé kladné číslo, (N T )*. Potom pre G je FIRSTk ( ) = { w / w T*, |w| k a *w, alebo |w| = k a *wx pre nejaké x} Funckia FIRSTk ( ) dáva teda množinu všetkých terminálnych reťazcov, ktoré možno derivovať z a ich dĺžka je menšia ako k, alebo tvoria prefix dĺžky k VF, ktorú možno derivovať z .
Gramatika LL(k) df BKG G = (N, T, P, S) je LL(k) ak pre každé dve ľavé derivácie tvaru S *wA w *wx S *wA w *wy Pre ktoré akFIRSTk (x ) = FIRSTk (y ) tak =
Poznámky k definícii • Definícia hovorí, že ak je „ďalších k symbolov“ rovnakých, musí existovať iba jedna laternatíva pravej strany pravidla pre A. • Budeme hovoriť, že BKG je LL, ak je LL(k) pre nejaké k • Budeme hovoriť, že jazyk je LL ak ho možno špecifikovať gramatikou LL(k) pre nejaké k
Od derivácií k pravidlám G • Uvedená definícia LL gramatiky je príliš všeobecná na praktické využitie – je nereálne vyšetrovať všetky ľavé derivácie • Snahou je určiť vlastnosti LL gramatiky z jej pravidiel • Dopracujeme sa k tomu postupne
Vlastnosť LL a ľavé VF • BKG G = (N, T, P, S) je LL(k) ak pre každé dve rôzne pravidlá z P A a A a všetky ľavé VF wA platí FIRSTk ( ) FIRSTk ( ) =
Od jednoduchých gramatík • BKG G = (N, T, P, S) bez e-pravidiel nazývame jednoducháLL(1) ak pre každý neterminál A sa všetky jeho alternatívy začínajú rôznymi terminálnymi symbolmi • BKG G = (N, T, P, S) bez e-pravidiel je LL(1) ak pre všetky neterminály z N a zodpovedajúce pravidlo z P A 1| 2| ... | n Platí FIRST1(i) FIRST1(j) = pre i j
Ošetrenie e-pravidiel • Nech G = (N, T, P, S) je BKG, k je celé kladné číslo, (N T )*. Potom pre G je FOLLOWk ( ) = { w / S *, w FIRSTk( ) }
Rozšírenie FIRST a FOLLOW • Funkcie FIRST a FOLLOW možno rozšíriť na množiny takto • Nech G = (N, T, P, S) je BKG a M (N T)*. Potom • FIRSTk(M) = {w / w FIRSTk( ), pre nejaké M } • FOLLOWk(M) = {w / w FOLLOWk( ), pre nejaké M }
LL(1) G • BKG G = (N, T, P, S) je LL(1) práve vtedy, ak pre každé dve pravidlá z P • A a A pričom platí, že FIRST1 ( FOLLOW1(A)) FIRST1 ( FOLLOW1(A)) = Silná LL(k) gramatika – uvedená vlastnosť platí pre ľubovolné celé k.
Podmienky pre LL(1) BKG G = (N, T, P, S) je LL(1) práve vtedy, ak pre všetky neterminály A a zodpovedajúce pravidlá A 1| 2| ... | n platí: • Ak i *w, w T+, j *u, u T+, tak FIRST1(i) FIRST1(j) = pre 1 i, jn, i j. Podmienka FIRST-FIRST • Ak i *e,t.j. e FIRST1(i) pre niektoré i, potom FIRST1(j) FOLLOW1(A) = pre 1 j n, i j Podmienka FIRST-FOLLOW
Niektoré vlastnosti LL gramatík • Zľava rekurzívna G nie je LL(k) pre žiadne k • Ak G1 a G2 sú LL(k), potom je rozhodnuteľné, či sú ekvivaletné, teda či L(G1) = L(G2)
Transformácia LL(k) gramatík • Motív transformácie je hľadanie ekvivalentnej LL(k) gramatiky s čo najmenším k – zvyčajne k = 1. • Postup – cez odstraňovanie negatívnych vlastností • Gramatiky programovacích jazykov to zvyčajne umožňujú. • Najčastejšie sa používajú dve transformácie - odstránenie ľavej rekurzie - faktorizácia Tieto transformácie zvyčajne postačujú
Odstránenie ľavej rekurzie • Gramatika je rekurzívna – zľava / sprava, ak obsahuje aspoň jeden neterminál rekurzívny – zľava /sprava • Neterminál A z G je rekurzívny, ak existuje derivácia A + A pre nejaké , (N T )*,pričom , nemôžu byť súčasne prázdne. Ak je prázdne , A je zľava rekurzívny, ak , tak sprava. • Samozrejme, že hľadáme ekvivaletnú gramatiku • Odstránenie ľavej rekurzie je známe z úpravy gramatiky na Greibachovej normálny tvar
Pravidlá transformácie Nech G = (N, T, P, S) je BKG, v ktorej A A1| A2| ... | An| 1| 2| ... | m sú všetky pravidlá v P s neterminálom A na ľavej strane a žiadne i pre i= 1, 2, ..., m nezačínaneterminálom A. Potom gramatika G’ = (N {A ’}, T, P’, S) , v ktorej uvedené pravidlá nahradíme pravidlami A 1| 2| ... | m | 1A’| 2A’| ... | m A’ A’ 1| 2| ... | n| 1A’| 2A’| ... | nA’ je s G ekvivalentná, teda L(G’) = L(G)
Poznámky k transformácii • Uvedená transformácia odstraňuje ľavú rekurziu • Uvedená transformácia neodstraňuje rekurziu – ak G obsahuje rekurziu, tak zodpovedajúci jazyk je nekonečný a rekurzia je jediný spôsob jeho špecifikácie • Rekurziu nemožno zamieňať s cyklom (A +A)
Príklad Majme gramatiku G: G = ({E, T, F}, {+, *, a, (, ) }, P, E) P: E E + T|T T T * F|F F ( E )| a Ľahko vidieť, že G je zľava rekurzívna E E + T , T T * F Urobíme transformáciu.
Príklad – transformácia G E E + T|T T T * F|F F ( E )| a E E + T|T E T|T E’ E’ + T| +T E’ T T * F|F T F|F T’ T’ * F|* F T’ F ( E )| a F ( E )| a
Poznámky k transformácii • Gramatika s tranformovanými pravidlami nie je zľava rekurzívna • Je LL(k) ? • Je LL(1) ? • Že nie je LL(1) vidieť už na prvý pohľad, lebo má pravidlá, ktoré začínajú rovnakým terminálom • Vidíme, že viaceré pravidlá majú spoločný prefix. Jeho odstránenie umožňuje faktorizácia
Faktorizácia Nech G = (N, T, P, S) je BKG, v ktorej PA= { A 1| 2| ... | n } je podmnožina A – pravidiel, ktorých pravá strana má spoločný prefix , e. Potom gramatika G’ = (N {A ’}, T, P’, S) , kde P’ = P - PA{ A A’, A’ 1| 2| ... | n } a A’ je neterminálny symbol je s G ekvivalentná, L(G’) = L(G)
Poznámky • Interpretáciu faktorizácie si ľahko možno zapamätať, ak s pravidlom urobíme jednoduchú matematickú operáciu „vyňatia pred zátvorku“ • A 1| 2| ... | n • A (1| 2| ... | n) • A A’ • A’ 1| 2| ... | n
Príklad • Vrátime sa ku gramatike v ktorej odstránili ľavú rekurziu. Zoberme iba pravidlá E T|T E’ E T E’’ E’’ E’| e E’ + T| +T E’ E’ +T E’’’ E’’’ E’| e
Príklad Cont T F|F T’ T F T’’ T’’ T’ | e T’ * F|* F T’ T’ * F T’’’ T’’’ T’ | e F ( E )| a F ( E )| a
Poznámky • Gramatiku po fakturizácii možno zjednodušiť, keďže viaceré pravidlá majú rovnakú pravú stranu (sú rovnako definoané) • Možno to urobiť jednoduchou substitúciou • Okrem uvedených dvoch transformácií sú aj ďalšie, ale tými sa zaoberať nebudeme. Pre programovacie jazyky vystačíme s uvedenými pravidlami
Príklad – zednodušenie pravidiel • Gramatika: • E T E’ • E’ + T E’ • E’ e • T F T’ • T’ * F T’ • T’ e • F ( E ) • F a
Syntaktická analýza pre LL gramatiky • Ide o SA zhora nadol – hovoríme tiež o vetnom rozbore (zhora nadol) • Modelom je ZA – ale deterministický • Keďže stav ZA (je iba 1) nemal vplyv na rozhodovaní „čo robiť“, ZA automat, ako model, sa reprezentuje formou procedúry – algoritmu a hovoríme o algoritme rozboru • Vzhľadom na podmienenosť determinizmu znalosťou ďalších k symbolov zo vstupu, algortimus sa nazýva k-prediktívny algoritmus rozboru A
Reprezentácia algoritmu rozboru • Reprezentácia vychádza zo ZA a používa: • Vopred prezretý reťazec u • vstupný a výstupný reťazec • Zásobník Z : N T { } - je začiatočný symbol • Riadiacu tabuľku M – reprezentuje zo ZA • Konfiguráciu algoritmu – na opis činnosti
Riadiaca tabuľka M: Z x T*k {( , i), vylúčenie, prijatie, chyba} Kde (N T )* i je číslo pravidla s pravou stranou vylúčenie znamená – vylúčenie vrchu zásobníka prijatie znamená úspešné ukončenie analýzy chyba znamená neúspečné ukončenie analýzy
Konfigurácia • Pod konfiguráciou prediktívneho algoritmu rozboru sa rozumie trojica ( x, X, ) Kde x je doteraz nespracovanáčasť vstupu, X je obsah zásobníka – X je vrchný symbol zasobníka je doterajší výstup – postupnosť pravidiel (čísel) použitých v ľavej derivácii doteraz spracovanej časti vstupu
Činnosť • Opisuje sa pomocou relácie prechodu • Používa vopred prezretý reťazec u • ( x, X, )( x, , i ) ak M(X,u)= (, i) • ( ax, a, )( x, , ) ak M(X,u)= vylúčenie • (e, , ) konfigurácia prijatia M(,e) = prijatie • (x, X, ) chybová konfigurácia ak M(X, u) = chyba
Stupeň relácie prechodu, uzávery • Stupeň a uzávery relácie prechodu sú definované rovnako ako pri ZA • Začiatočná konfigurácia: (w, S, e) • Koncová konfigurácia: (e, , ) • Rozpoznanie: (w, S, e) * (e, , ) - potom je ľavým rozborom • Zápis: A(w) =
Syntaktická analýza pre LL(1) G – konštrukcia Vstup: LL(1) gramatika G = (N, T, P, S) s očíslovanými pravidlami Výstup: tabuľka rozboru M • Ak A P s číslom i, potom M(A, a) = ( , i) pre všetky a e, ktoré sú z FIRST1( ). Ak e FIRST1( ), tak M(A, b) =( ,i) pre všetky b FOLLOW1(A) • M(x, x) = vylúčenie pre všetky x T • M(,e) = prijatie • M(X, x) = chyba vo všetkých ostatných prípadoch X N T { }, x N {e}
Príklad • Vrátime sa zase ku gramatike, ktorú sme transformovali na LL(1) • E T E’ • E’ + T E’ • E’ e • T F T’ • T’ * F T’ • T’ e • F ( E ) • F a
Zdôvodnenie • E: FIRST1(T E’) = {}. T E’ FT’E’ (E)T’E’ teda “(“ je v {} aT’E’ teda aj “a” je v {} FIRST1(T E’) = {(, a} preto M(E, () = (TE’, 1) M(E, a) = (TE’, 1)
Zdôvodnenie Cont E’: máme 2 pravidlá: E’ + T E’ FIRST1(+T E’) = {+} E’ e FIRST1(e) = {e} musíme preto vyčísliť FOLLOW1(E’) E TE’ teda tam patrí „e“ (prvý symbol za E’) E T E’ FT’E’ (E)T’E’ (TE’)T’E’ teda tam patrí aj “)”(znova prvý symbol za E’) FOLLOW1(E’) = {e, )} Analogicky zvyšok.
Výpočet hodnoty funkcie FIRST • Aj teraz budeme hľadať konštruktívny výpočet na základe pravidiel gramatiky • Najprv si zavedieme funkciu „sčítania“ reťazcov ⊕k • Využijeme obmedzenie dĺžky výsledného reťazca na dĺžku k. Preto aj operátor bude mať index udávajúci dĺžku výsledného reťazca
Operácia ⊕ • Nech T je množina terminálnych symbolov a L1 T*, L2 T* . Potom nad L1aL2operáciu ⊕k definujeme nasledujúcim spôsobom: L1 ⊕kL2 = {w / w = xy ak | xy | k inak w pozostáva z prvých k symbolov reťazca xy, pre nejaké x L1ay L2}
Vzťah funkcie FIRST a operácie ⊕k Ak G = (N, T, P, S) je BKG a , (N T)* Potom FIRSTk( ) = FIRSTk() ⊕kFIRSTk() Poznámka: Práve uvedenú vlastnoť funkcie FIRST a operácie ⊕k využívame na výpočet hodnoty funkcie FIRST
Výpočet hodnoty funkcie FIRST Vstup:BKG G = (N, T, P, S) a reťazec , pričom ho budeme písať v tvare X1X2 ...Xn Výstup: FIRSTk() Postup: Predpoklad FIRSTk() = FIRSTk(X1) ⊕kFIRSTk(X2) ⊕k ...⊕k FIRSTk(Xn) Dôsledok: ak Xi T {e} tak FIRSTk(Xi) = {Xi} V ďalšom skrátime zápis FIRSTk iba na F
Postup výpočtu • Fi(a) = {a} pre všetky a T, i 0 • F0(A) = {x / x T*k a v P existuje pravidlo A x pre ktoré je | x | = k , alebo | x | k a = e} • Predpokladajme, že F0, F1, ... , Fi-1 je spočítané pre všetky A N. Potom Fi(A) = Fi-1(A) {x / A Y1Y2 … Yn P a x Fi-1(Y1)⊕k Fi-1(Y2)⊕k … ⊕kFi-1(Yn) } • Pretože Fi-1(A) Fi(A) T*k pre všetky A a i, musíme v konečnom dôsledku prísť k takému i, že Fi-1(A) = Fi(A) pre veštky A N. Potom FIRSTk(A) = Fi(A)
Príklad • Zoberme znova gramatiku, ktorú sme transformovali na LL(1) E T E’ E’ + T E’| e T F T’ T’ * F T’| e F ( E )| a
Postup pre i= 0 i= 0:F0(E) = F0(E’) = { +, e } F0(T) = F0(T’) = { *, e } F0(F) = { (, a }
Postup pre i= 1 i= 1:F1(E) = F0(E)F0(T)⊕1 F0(E’) = F1(E’) = {+, e } F0(+) ⊕1 F0(T) ⊕1 F0(E’) F0(e) = { +, e } F1(T) =F0(T)F0(F)⊕1 F0(T’) = { (, a } F1(T’) =F0(T’)F0(*)⊕1 F0(F)⊕1 F0(T’) F0(e) = { *, e } F1(F) =F0(F)F0(()⊕1 F0(E) ⊕1 F0()) F0(a) = { (, a }
Postup pre i= 2 i= 2:F2(E) = F1(E)F1(T)⊕1 F1(E’) = { (, a } F2(E’) = {+, e } F1(+) ⊕1 F1(T) ⊕1 F1(E’) F1(e) = { +, e } F2(T) =F1(T)F1(F)⊕1 F1(T’) = { (, a } F2(T’) =F1(T’)F1(*)⊕1 F1(F)⊕1 F1(T’) F1(e) = { *, e } F2(F) =F1(F)F1(()⊕1 F1(E) ⊕1 F1()) F1(a) = { (, a }
Postup pre i= 3 F3(X) =F2(X) preto FIRST1(E) = { (, a } FIRST1(E’) = { +, e } FIRST1(T) = { (, a } FIRST1(T’) = { *, e } FIRST1(F) = { (, a }