22a - Příklad na vytváření LL tabulky
Máme zadefinovánu gramatiku s epsilon pravidly:
1. S → XCd
2. X → AB
3. A → aAB
4. A → ε
5. B → bB
6. B → ε
7. C → cCd
8. C → ε
Empty
Nejprve spočítáme množiny Empty.
Pro jakýkoli terminál je množina Empty ∅, jelikož je ničím v nula krocích nahradit.
Dále řešíme, zda jdou v nula krocích odmazat neterminály
A, B, C jdou odmazat - pravidla 4, 6, 8
dále nás zajímá pravidlo 2, jelikož, X jde nahradit neterminály A a B a ty jdou nahradit ε ⇒ X jde odmazat
S nejde smazat, jelikož tam vždy zůstane terminál d
| Empty |
S | ∅ |
X | {ε} |
A | {ε} |
B | {ε} |
C | {ε} |
First
Pak vyřešíme množinu First
Pro jakýkoli terminál je množina First množina obsahující daný terminál ⇒ v nula krocích nemůžeme z terminálu nagenerovat nic jiného než samotný terminál
Dále řešíme neterminály
v počátku nastavíme First každého neterminálu na prázdnou množinu
prázdnou množinu plníme prvními neterminály, které můžou nastat po rozgenerování (! zde je třeba dát pozor, pokud je první rozgenerovaný prvek další neterminál - je třeba řešit First tohoto neterminálu a zároveň musíme kouknout na množinu Empty, jestli náhodou nejde odmazat - v takovém případě, bychom koukali ještě na další prvek za tímto neterminálem)
je dobré procházet gramatiku odspodu
First(C) je {c}, pravidlo 7 … terminál c nejde odmazat, tzn. takto nechávám
First(B) je {b}, pravdilo 5
First(A) je {a}, pravidlo 3
First(X) obsahuje First(A) - tzn {a}, pravidlo 2 a jelikož A jde odmazat (Empty(A) = {ε}), First(X) obsahuje zároveň First(B) - tzn {b} - tedy výsledek je sjednocení {a,b}
First(S) - je intuitivní, obsahuje First(X), jelikož X jde smazat, tak přidáme First(C) a jelikož toto také můžeme odmazat a dojdeme k terminálu d, který přidáme do First(S) a končíme
| First |
S | {a,b,c,d} |
X | {a,b} |
A | {a} |
B | {b} |
C | {c} |
Follow
Nakonec vyřešíme Follow
Nejprve to celé zainicializujeme tím, že dáme do Follow(S) {$} a ostatní Follow budou prázdné množiny
Dále se budeme koukat na pravé strany pravidel a řešit, co může následovat po daném terminálu
začněme pěkně z vrchu od pravidla 1, kde pravá strana je XCd
po neterminálu C může následovat pouze d - d, přidáme do Follow(C)
po neterminálu X následuje neterminál C - First(C) přidáme do Follow(X) a jelikož C můžeme odmazat, přidáme tam ještě Follow(C) - tzn. do Follow(X) přidáme First(C) ∪ Follow(C) = {c,d}
dále se posuneme na pravidlo 2 a jeho pravou stranu AB
B končí rozgenerovávání neterminálu X - to znamená, že po B následuje to samé, co po X - tzn. do Follow(B) přidáme Follow(X)
dále vidíme, že po A následuje B tzn. do Follow(A) přidáme First(B) a jelikož B jde odmazat, přidáme zároveň Follow(B)
a takto intuitivně pokračujeme až k poslednímu pravidlu (pravidla, kde na pravé straně máme terminály a epsilony nás nezajímají)
| Follow |
S | {$} |
X | {c,d} |
A | {b,c,d} |
B | {c,d} |
C | {d} |
Sestavení tabulky
Predict
Když už máme spočítány tři množiny First, Follow a Empty, budeme chtít sestavit samotnou tabulku. Nejprve si budeme muset sestavit množinu Predict ⇒ nepočítá se pro neterminály, ale pro celá pravidla
V každém případě do Predict(levá strana) dáme First(pravá strana)
Pokud pravá strana jde odmazat, přidáme do Predict(levá strana) ještě Follow(levá strana)
1. S → XCd … {a,b,c,d} //First(XCd)
2. X → AB … {a,b,c,d} //First(AB) ∪ Follow(X)
3. A → aAB … {a} //First(aAb)
4. A → ε … {b,c,d} //First(ε) ∪ Follow(A)
5. B → bB … {b} //First(bB)
6. B → ε … {c,d} //First(ε) ∪ Follow(B)
7. C → cCd … {c} //First(C)
8. C → ε … {d} //First(ε) ∪ Follow(C)
Tabulka
Samotné sestavení tabulky
| a | b | c | d | $ |
S | 1 | 1 | 1 | 1 | |
X | 2 | 2 | 2 | 2 | |
A | 3 | 4 | 4 | 4 | |
B | | 5 | 6 | 6 | |
C | | | 7 | 8 | |
V každém políčko musí být maximálně jedno pravidlo, jinak tabulka pravidel není deterministická a těžko ji naimplementujeme. Číslo nám totiž říká, které pravidlo se uplatní. Pokud ovšem načteme terminál a nejde na něj uplatnit žádné pravidlo, znamená to, že program je syntakticky špatně.
Čerpal jsem ze streamu IFJ-2008-12-11 Romana Lukáše
Diskuze
Chyba u sestaveni tabulky u mnoziny Predict, 6. pravidlo - vysledek ma byt mnozina {c,d}, protoze Follow(B) je {c,d}.
jj, překlep, upraveno … jinak tabulka už je pak dobře
Podle mě follow(B) = {b, c, d}. U 3. pravidla je B poslední symbol a proto se do follow(B) přidají prvky z follow(A).
Tiež si myslím.