Za předpokladu, že máme sestavenou (LL1) gramatiku a chceme pro daný vstup generovat i výstup, tak můžeme obohatit pravé strany gramatiky výstupními symboly. Tyto symboly mohou triviálně znamenat „vypiš symbol na výstup“ nebo volání nějaké metody.

Tento postup je ovšem pro překlad složitějších jazyku příliš slabý, protože nám pro překlad nezajistí všechny potřebné informace. Pokud chceme výraz a = 5 + 3 jazyka C jako int a = 5 + 3, tak překladač jako první narazí na proměnnou „a“, ale není schopen posoudit její typ (může to být double, integer nebo nějaká struktura). Z tohoto důvodu se pro složitější překlady používá atributovaná překladová gramatika.

Příklad:

Mějme terminály {číslo, -, *, (, )} a infixový zápis čísla. Chceme tento zápis převést do postfixové notace (postfixová notace nemá závorky, priority jsou určeny pořadím operátorů a operandů). Například (3 - 4) * 2 převedeme na 3 4 - 2 *.

Gramatika:

E => E – T | T
T => T * F | F
F => číslo | (E)

Levá rekurze značí levou asociativitu, protože se při rekurzivním zpracování výraz expanduje směrem doleva, a proto se při návratu z rekurze zpracovává zleva doprava (což je levá asociativita).

Z obdobného důvodu má v této gramatice „*“ vyšší prioritu než „-“ („*“ je vždy ve stromě rekurze níže a proto se vyhodnotí jako první).

Nyní do gramatiky doplníme výstupní symboly.

E => E – T -
E => T
T => T * F *
T => F
F => číslo číslo
F => (E)

Číslo se pošle na výstup v okamžiku, kdy je zpracováno gramatikou, operace v okamžiku, kdy jsou zpracovány oba její operandy.

Zpracování výrazu:

Gramatika není pro přehlednost převedena na LL1, ale to je pouze otázkou levé faktorizace (při konstrukci rozkladové tabulky se výstupní symboly nepočítají).

Výraz: (3 - 4) * 2

E => T => T * F * => F * F * => (E) * F * => (E – T -) * F * => (T – T -) * F * =>
(F – T -) * F * => (číslo číslo – T -) * F * => (číslo číslo – F -) * F * =>
(číslo číslo – číslo číslo -) * F * => (číslo číslo – číslo číslo -) * číslo číslo *

Pokud nyní přečteme výstupní symboly, tak vidíme, že nám vyšlo číslo číslo - číslo *, což odpovídá očekávanému výstupu (3 4 – 2 *).








Doporučujeme