====== Tahák IFJ ======
===== Gramatika =====
N, T, P, S
*N -- neterminály
*T -- terminály
*P -- pravidla
*S -- počáteční symbol
===== Nedeterministický konečný automat =====
Q, T, δ, s, F
*Q -- stavy
*T -- vstupy
*δ -- přechody
*s -- počáteční stav
*F -- koncové stavy
===== Zásobníkový automat =====
Q, T, Z, δ, q, Z0, F
*Q -- stavy
*T -- vstupy
*Z -- zásobníková abeceda
*δ -- přechody
*q -- počáteční stav
*Z0 -- počáteční zásobníkový symbol
*F -- koncové stavy
Přechod: zásobník stav vstup -> zásobník stav (vstup lze vynechat)
U rozšířeného zásobníkového automatu nemusíme číst ze zásobníku a můžeme zpracovávat více symbolů ze zásobníku zároveň.
==== Konfigurace zásobníkového automatu ====
q, w, z
*q -- stav
*w -- vstup
*z -- zásobník
===== Konstrukce LL tabulky =====
==== Empty ====
Když se daný neterminál (nebo celá posloupnost neterminálů) dá rozložit na ε, bude množina //Empty(N) = {ε}//, jinak ∅.
==== First ====
Obsahuje všechny terminály které se mohou v neterminálu (posloupnosti) vygenerovat jako první (úplně vlevo). Pokud se může ze začátku generovat i ε, je potřeba řešit i následující neterminály.
==== Follow ====
Ukazuje jaké terminály mohou následovat po neterminálech.
-//Follow(S) = {\$}; Follow(neterminály) = ∅//
-Zpracovávej pravidla které mají na pravé straně aspoň jeden neterminál
-Pravidla rozkládej do tvarů: //A -> xBy// (//x// a //y// (//y// může být i ε) je posloupnost neterminálů i terminálů, //B// je neterminál)
-Pokud //y ≠ ε// tak //Follow(B) = First(y)//
-Pokud //Empty(y) = {ε}// tak //Follow(B) = Follow(A)//
-Krok 2 dělej tak dlouho, dokud v průchodu nedojde k žádné změně
Bacha! First a Empty se dělají pro posloupnosti!
==== Predict ====
Pro pravidlo číslo //n: A -> x//
//Predict(n) =//
*//First(x) ∪ Follow(A)// pokud //Empty(x) = {ε}//
*//First(x)// v ostatních případech
==== Tabulka ====
^ ^T^T^T^
^N| | | |
^N| | | |
^N| | | |
Buňky se vyplňují tak, že se zvolí řádek podle levé strany pravidla a do buněk se doplní číslo pravidla do těch sloupců, které jsou v množině Predict daného pravidla.
Pokud by do nějaké buňky mělo přijít více než jedno pravidlo, nastane zhroucení vesmíru a gramatika není LL.
==== Průchod tabulkou ====
-Na zásobník nacpi \$ a počáteční neterminál
-Prováděj cyklus dokud vstup ≠ zásobník ≠ \$
-Když je na vrcholu neterminál a existuje v LL tabulce pravidlo které by jej společně se vstupním terminálem zpracovalo, proveď toto pravidlo (starý neteminál zanikne) a na zásobník ho dej v opačném pořadí. Pokud není pravidlo, chyba.
-Když je na vrcholu terminál a na vstupu terminál, musejí být stejné, jinak chyba.
Levý rozbor je pak posloupnost čísel použitých pravidel od začátku.
===== Precedenční tabulka =====
^ ^vstup^vstup^vstup^
^zásobník| | | |
^zásobník| | | |
^zásobník| | | |
Symboly (terminály) budou zřejmě stejné, poslední je \$ (dno zásobníku, konec vstupu).
==== Operátory ====
*Pokud má operátor na zásobníku vyšší prioritu než na vstupu (* > +), doplň >
*Pokud má operátor na zásobníku nižší prioritu než na vstupu (+ < *), doplň <
*Pokud mají operátory stejnou prioritu a oba jsou levě asociativní (+-*/), doplň >
*Pokud mají operátory stejnou prioritu a oba jsou pravě asociativní (^), doplň <
==== Identifikátory ====
Jako proměnné
Když dáš vedle sebe symbol na zásobníku a symbol na vstupu (jeden ze symbolů je identifikátor), "vetší" bude indentifikátor.
Bacha na závorky (//identifikátor(// a //)identifikátor// nelze), a identifikátor/identifikátor (taktéž nelze)!
==== Závorky ====
*Celý sloupec i řádek s ( vyplň <
*Celý sloupec i řádek s ) vyplň >
*Do buňky () doplň =
*Smaž obsah buněk (\$ i( )( )i
==== \$ ====
Řeší se jen s operátory. Když dám vedle sebe symbol ze zásobníku a symbol ze vstupu (\$ a operátor), bude //\$ < operátor//.
Hint: Řádek s \$ obsahuje pouze < a prázdné buňky, sloupec s \$ obsahuje pouze > a prázdné buňky.
==== Průchod tabulkou ====
-Vlož na zásobník \$
-Prováděj úpravy, dokud nejvrchnější terminál zásobníku ≠ vstupní symbol ≠ \$
-Najdi v tabulce znaménko pro nejvrchnější terminál zásobníku a vstupní symbol
*=
-Šoupni vstupní symbol na zásobník
*<
-Za nejvrchnější terminál zásobníku (nemusí být vrchol) dej <
-Na vrchol zásobníku dej vstupní symbol
*>
-Najdi na zásobníku nevrchnější <
-Mezi < a vrcholem najdi pravou stranu nějakého pravidla
-Odstraň tuto část zásobníku včetně <
-Nahraď ji levou stranou pravidla
*Prázdné políčko
-Syntaktická chyba!
Pravý rozbor je pak posloupnost čísel použitých pravidel od začátku.
===== LR tabulka =====
^ ^ Akční část ^^^ Přechodová část ^^^
^ ^vstup^vstup^vstup^neterminál^neterminál^neterminál^
^stav| | | | | | |
^stav| | | | | | |
^stav| | | | | | |
Zásobník ukládá dvojice ////. V akční části jsou dvojice //s// nebo //r// a číslo stavu, také je v jedné buňce :-) značící úspěšný konec. V přechodové části jsou jen číslice stavů.
==== Analýza ====
-Vlož na zásobník //<\$, q0>// (//q0// je počáteční stav, většinou 0).
-Opakuj cyklus, dokud neskončí:
-Najdi v akční části buňku odpovídající aktuálnímu stavu a vstupnímu symbolu.
*s číslo
-Vlož na zásobník dvojici ////.
-Aktuální stav nastav na akční číslo.
*r číslo
-Najdi pravidlo //A -> X1X2...Xd// odpovídající akčnímu číslu
-Ověř, že vrchní symboly na zásobníku jsou ve tvaru //1, ?>2, ?>...d, ?>//, jinak syntaktická chyba!
-Zjisti stav před X1
-Nastav aktuální stav podle čísla na souřadnicích //[stav před X1, levá strana pravidla]// přechodové části tabulky.
-Odstraň ze zásobníku //1, ?>2, ?>...d, ?>//
-Vlož na zásobník ////
*:-)
-OK, hotovo
*Prázdná buňka
-Syntaktická chyba
Pravý rozbor: použitá pravidla u //r// buněk.