Pojmy z jazyků, gramatik a automatů
Některé důležité pojmy ze státnicových otázek z EaI - předmět PJP (snad nikomu nebude vadit, že jsem to sem dal :), pokud by to vadilo, tak to smáznu )
Abecedy a jazyky
abeceda = konečná množina symbolů
řetězec (řetěz, slovo) nad abecedou T:
operace zřetězení
xy je řetězec, který vznikne připojením řetězce y za řetězec x
je asociativní, není komutativní
ε je jednotkový prvek
|x| je délka řetězce x (počet symbolů)
formální jazyk L je libovolná podmnožina množiny všech řetězců nad abecedou T: L ⊂ T*
operace nad formálními jazyky:
obvyklé množinové operace
součin (zřetězení) jazyků L1 · L2 = {xy: x ∈ L1, y ∈ L2}
n-tá mocnina Ln = L · Ln-1, L0 = {ε}, L1 = L
iterace L* = ∪Ln pro n = 0 .. ∞
pozitivní iterace L+ = ∪Ln pro n = 1 .. ∞
Gramatiky
přímá derivace
x ⇒ y (x přímo derivuje y), jestliže x = αAβ, y = αχβ, A ∈ N, α, β, χ ∈ (N ∪ T)* a v P existuje pravidlo A → χ
k-tá mocnina relace ⇒ se označuje ⇒k
tranzitivní uzávěr relace ⇒ se označuje ⇒+
reflexivně tranzitivní uzávěr relace ⇒ se označuje ⇒*
derivací řetězce β z řetězce α délky k v gramatice G = (N, T, P, S) se nazývá posloupnost řetězců α0, α1, …, αk takových, že α = α0, αi-1 ⇒ αi pro 1 ≤ i ≤ k a αk = β
větnou formou v gramatice G = (N, T, P, S) se nazývá řetězec α, pro který platí S ⇒* α, α ∈ (N ∪ T)*. Větná forma neobsahující neterminální symboly se nazývá věta generovaná gramatikou G
jazyk generovaný gramatikou G je množina všech vět generovaných gramatikou G a označuje se L(G)
gramatiky G1 a G2 jsou ekvivalentní, když generují stejný jazyk: L(G1) = L(G2)
Derivační stromy
derivační strom v gramatice G = (N, T, P, S) má tyto vlastnosti:
uzly derivačního stromu jsou ohodnoceny terminálními a neterminálními symboly
kořen stromu je ohodnocem počátečním symbolem gramatiky
jestliže má uzel alespoň jednoho následníka, pak je ohodnocen neterminálním symbolem
jestliže n1, n2, …, nk jsou bezprostřední následnovníci uzlu n, který je ohodnocen symbolem A, a tyto uzly jsou ohodnoceny symboly A1, A2, …, Ak, pak A → A1A2…Ak je pravidlo v P
listy derivačního stromu tvoří zleva doprava větnou formu nebo větu v gramatice G
gramatika G je jednoznačná, pokud pro každou větu existuje právě jeden derivační strom
věta w se nazývá víceznačná, jestliže pro ni existují alespoň dva různé derivační stromy
gramatika G je víceznačná, když generuje alespoň jednu víceznačnou větu
napr. věta: a+a+a (pro tuto větu lze vyvořit 2 derivační stromy → tato gramatika je víceznačná) soubor: derivacnistrom.jpg
Konečný automat
(deterministický) Konečný automat (DKA, DFA) je pětice A = (Q, T, δ, q0, F), kde
Q je konečná neprázdná množina stavů,
T je vstupní abeceda,
δ je přechodová funkce, která pro každou dvojici (stav, vstupní symbol) určuje následující stav,
q0 z Q je počátečním stavem,
F částí Q je množinou koncových stavů.
Vztah mezi nimi
Regulární gramatika generuje věty regulárního jazyka, konečný automat tyto věty přijímá (rozpoznává) - je formálním modelem procedury, jejímž vstupem je posloupnost symbolů a výstupem je odpověď, zda je vstup větou daného jazyka.
Pozn:
Jazyk přijímaný DFA je množina všech slov, která po přečtení uvedou DFA z počátečního do nějakého koncového stavu. POZOR: Konečný automat skončí činnost po přečtení posledního vstupního symbolu a přijme tehdy, pokud se v tomto okamžiku nachází v koncovém stavu. Představa, že DFA skončí čtení po dosažení koncového stavu je NESPRÁVNÁ. Konečné automaty jsou schopné rozpoznat regulární jazyky.
Lexikální analyzátor je aplikací konečného automatu. Používá se jako první blok překladače, který čte vstupní text (program) a přemění jej na tok lexikálních elementů (tokens). Při tom vynechává nevýznamné mezery, konce řádků a komentáře. Jeho výstupem není boolská hodnota přijato/nepřijato, ale (většinou) hodnota typu integer nebo enum, která udává jaký lexikální element byl načten. Přikladem lexikálního elementu je číslo, identifikátor, if, =, := a pod. Základní rozdíly mezi konečným automatem (KA) a lexikálním analyzátorem (LA) jsou:
KA přečte celý zadaný vstupní řetězec a na jeho konci rozhodne (svým stavem), zda řetězec patří do daného jazyku. LA přečte pouze část řetězce (tj. LA je volán pro zadaný řetězec opakovaně nějakou vyšší vrstvou překladače) a vrací jaký jeden načtený lexikální element nalezl, případně chybu, pokud nenalezl (nerozpoznal) žádný.
KA končí poté, co přečte celý svůj vstup. LA naproti tomu skončí čtení vstupu, pokud již nemůže provést žádný další přechod. Pokud byl LA v okamžiku, kdy již nemohl provést následující přechod v koncovém stavu, vrací „nalezen lexikalni element xxx“ (kde xxx zaleží na tom, ve kterém z koncových stavů se LA nacházel), pokud v koncovém stavu nebyl, vrací chybu (nerozpoznaný žádný lexikální element, obvykle se to projeví chybou překladače „syntax error“ nebo „unrecognized statement“).
LA přeskakuje komentáře a nevýznamné mezery.
LA může provádět sémantické akce, počítat hodnoty atributů. Příkladem je lexikální element cislo, který míva atribut hodnota.
LA může být spojen s preprocesorem, rozpoznávat bloky podmíněného překladu (#ifdef … #endif ) a expandovat makra.
Podobně jako KA, i LA můžeme realizovat pomocí tabulky přechodů nebo řídící struktury.
Vytvoření konečného automatu z regulární gramatiky
vstup = pravá regulární gramatika G = (N, T, P, S)
výstup = nedeterministický konečný automat M = (Q, T, δ, q0, F), pro který platí L(M) = L(G)
množina stavů Q = N ∪ {K}, K ∉ N
vstupní abeceda automatu M je rovna množině terminálních symbolů T gramatiky G
zobrazení δ sestrojíme takto:
je-li v P pravidlo A → aB, pak δ(A, a) obsahuje B
je-li v P pravidlo A → a, pak δ(A, a) obsahuje K
q0 = S
jestliže je v P pravidlo S → ε, pak F = {S, K}, jinak F = {K}
Převod nedeterministického konečného automatu na deterministický
vstup = nedeterministický konečný automat M = (Q, T, δ, q0, F)
výstup = ekvivalentní deterministický konečný automat M' = (Q', T, δ', q0', F')
definujeme Q' =
q0, stav {q0} považujeme za neoznačený
jestliže v Q' jsou již všechny stavy označeny, pokračujeme krokem 4
vybereme z Q' neoznačený stav q' a provedeme tyto operace:
definujeme přechodovou funkci δ'(q', a) pro všechna a ∈ T takto: δ'(q', a) = ∪δ(p, a) pro každý stav p ∈ q'
přidáme do Q' každý stav δ'(q', a), který v ní ještě není, a stav q' označíme
pokračujeme krokem 2
počáteční stav q0' je {q0}
množina koncových stavů F' je tvořena všemi stavy q', které obsahují alespoň jeden koncový stav q ∈ F
Nahoru