Sémantická analýza

Sémantická analýza je výraz z oblasti informatiky.

Sémantická analýza postupně prochází symboly či skupiny symbolů získané ze syntaktické analýzy a přiřazuje jim význam. Pokud například skupina symbolů představuje použití konkrétní proměnné, pak analyzátor zjišťuje zda je proměnná už deklarována (pokud je to požadováno, nevyžaduje například programovací jazyk Perl či PHP) a zda je správně použita vzhledem k jejímu datovému typu. Dále například u operací kontroluje zda jsou operandy správného typu, případně provede potřebnou konverzi datového typu. Pro všechny typy operátorů jsou stanoveny předpisy pro jejich operandy. Například pro některé jazyky platí, že pokud sčítáme řetězec a číslo, pak dojde k sémantické chybě. Pokud je to možné pak sémantický analyzátor je schopný implicitního přetypování, když operandy jsou různého datového typu. Implicitní přetypování se provádí na základě stanovených priorit jednotlivých typů. Pokud je tedy jeden operand typu s větší prioritou pak se automaticky druhý přetypuje na typ prvního operandu. U modernějších programovacích jazyků, kde je umožněné přetěžování funkcí, musí překladač správně určit, která funkce je volána a zda je volána správně, tedy zda předáváme správný počet a typ parametrů.

Tabulka symbolů

Související informace naleznete také v článku Tabulka symbolů.

Při sémantické analýze se používá tabulka symbolů, která obsahuje veškeré objekty, které jsou při analýze zaznamenány. Jedná se například o proměnné, konstanty, funkce, procedury, atd. Jsou zde uloženy informace o datovém typu objektu, jeho velikosti, názvu, adrese, zda už objekt byl deklarován a zda už byl použit. Tabulka symbolů je používána nejenom ke kontrole objektů v sémantické analýze, ale i ve všech ostatních částech překladače. Například generátor cílového kódu ji prochází při statické či dynamické alokaci paměti. Jednotlivé záznamy jsou do tabulky většinou přidávány lexikálním analyzátorem. V této fázi překladu ale ještě nemáme všechny potřebné informace, a tak jsou záznamy doplňovány dalšími částmi překladače.

Implementace tabulky symbolů

Kvůli častému přístupu sémantického analyzátoru do tabulky (například z důvodu kontroly, zda je proměnná již deklarována, …) je hlavním kritériem při implementaci tabulky symbolů rychlost vyhledávání. Tabulka je tedy většinou realizována pomocí dynamického seznamu řádků, stromových či hašovacích struktur. Při implementaci je také dalším důležitým kritériem typ překládaného jazyka.

Jazyk s blokovou strukturou

Pro jazyky bez blokové struktury (např. Basic) je tabulka symbolů implementována pomocí polí, seznamů, stromových struktur, kdežto u jazyků s blokovou strukturou je implementace mnohem složitější. U těchto jazyků (např. C, Pascal) se totiž rozlišují lokální a globální objekty, kde u lokálních je omezena jejich přístupnost. Například deklarujeme-li proměnnou uvnitř funkce, pak s touto proměnnou nemůžeme pracovat vně tohoto bloku. Pro každý blok je vyhrazena jedna tabulka, která je realizována pomocí zmíněných struktur. Ty mohou být zřetězeny do datové struktury zásobník, kde každá tabulka vnořeného bloku obsahuje odkaz na tabulku pro nadřazený blok. Například při vyhledávání záznamu o deklaraci proměnné se potom postupně prochází všechny bloky od nejvíce vnořeného až po blok k němuž neexistuje nadřazený, dokud se nenarazí na „nejbližší“ deklaraci. Na vrcholu zásobníku se vždy nachází tabulka bloku, který se zrovna prohledává. Pokud v bloku deklarace není nalezena, pak se tabulka odstraní ze zásobníku a na vrcholu získáme tabulku představující nadřazený blok.

Příklad (zapsaný v Pascalu)

program blok1;
var globalni: integer;

procedure blok2;

    function blok3: integer;
    var lokalni1: integer;
        begin
            
        end;

    function blok4: integer;
    var lokalni2: integer;
        begin
            
        end;

    begin
	
    end;

begin
    
end.

Budou tedy existovat vyhledávací vazby mezi tabulkami:

  • bloku3, bloku2 a bloku1
  • bloku4, bloku2 a bloku1
  • bloku2 a bloku1

Při použití proměnné globálni v bloku3, by se nejprve prohledala tabulka příslušející tomuto bloku, následně bloku2 a nakonec by deklarace byla nalezena v tabulce bloku1. Tudíž by použití bylo správné. Naopak pokud by byla použita proměnná lokalni1 v bloku4, pak by došlo k sémantické chybě.

Intermediální kód

Intermediální kód je výstupní kód sémantické analýzy. Jde o mezikód, který je dále zpracováván – interpretován, optimalizován nebo přeložen do cílového kódu. Má různé varianty s ohledem na další použití tohoto kódu.

Grafová reprezentace

Výrazy lze zapsat do formy sémantického stromu, který lze průchodem postorder vyhodnotit. Vyhodnocují se tedy nejprve podstromy, kde uzly obsahují operandy a teprve potom kořenový uzel představující operaci. Sémantický strom se snadno přímo interpretuje, ale hůře se přepisuje do strojového kódu, a proto je tento mezikód vhodnější pro interpretační překladač.

Zásobníkový kód

Je založen na postfixovém zápisu výrazu. V této notaci se operátory nacházejí až za svými operandy. Jeho hlavní výhodou je, že takovýto zápis výrazu nevyžaduje závorky a při zpracování výrazu si vystačíme s jedním zásobníkem. Zásobníkový kód lze optimalizovat a snadno se přepisuje do strojového kódu. Na základě těchto vlastností je tento mezikód vhodný jak pro kompilační, tak i pro interpretační překladač.

Tříadresový kód

Příkaz v tříadresovém kódu má tvar:

  • základní – je tvořen operátorem, dvěma argumenty a výsledkem
  • zhuštěný – obsahuje operátor a dva argumenty

Tříadresový kód je možné dobře optimalizovat, snadno se přepisuje do strojového kódu a složitěji se přímo interpretuje. Z toho vyplývá, že tato forma intermediálního kódu je vhodnější pro kompilační překladač.

Související články

Externí odkazy