Lukáš Turek
Napište program, který naformátuje zadaný zdrojový kód v jazyce Pascal.
Základem programu je vyhledávací stroj (konečný automat) sloužící k hledání klíčových slov a operátorů. Je implementován stromem: v každém uzlu je pole 256 pointerů (1 pointer odpovídá jednomu znaku), tzv. přechodová funkce. Přechodová funkce je buď definována (ukazuje na další uzel stromu) nebo je nedefinována (pointer je nil). Tento strom se po spuštění programu vytvoří ze souboru keywords.txt, obsahujícího klíčová slova a jejich formát. Formát je hodnota typu longint, jejíž jednotlivé bity určují formátovací příznaky. Jejich popis a vztahy mezi nimi jsou v komentářích ke zdrojovému kódu.
Hledání ve stromě: začneme v kořeni, pokud je přechodová funkce pro znak slova definována, přejdeme na další uzel stromu a postup opakujeme pro další písmeno. Je-li nedefinována, vrátíme formát uložený v posledním navštíveném uzlu.
Konstrukce stromu: dokud je přechodová funkce definována, postupujeme jako u vyhledávání. Potom začneme vytvářet nové uzly pro zbývající písmena slova. Do posledního vytvořeného uzlu uložíme formát slova.
Formátování lze rozdělit do tří částí:
Nejjednodušší, poměrně jednoduchá pravidla. Problém způsobuje snad jen operátor ^ (někdy je před identifikátorem a někdy za ním).
Nejsložitější (tělo cyklu může být 1 příkaz nebo blok, přiřazení else správnému if). Použil jsem zásobník, do kterého se odsazení ukládá. Při zvýšení odsazení se do zásobníku vloží značka. Značka označuje skutečné odsazení a má dva typy: normální (IND_ONELINE) a speciální (IND_2PARTS). Ta se používá u příkazu if, ke kterému může příslušet else. Na konci řádku se ze zásobníku vyhodí všechny hodnoty do poslední zarážky.
Zarážkou je:
Spolu s přidáváním a odstraňováním ze zásobníku se upravuje i proměnná indent určující aktuální odsazení.
Vedle toho existuje zvláštní odsazení (special_indent) pro var, type, const apod., aby byly identifikátory deklarovaných proměnnných, typů a konstant pěkně pod sebou.
Prázdné řádky pro zlepšení čitelnosti textu se vkládají podle souboru pravidel: před a za blok, mezi procedury apod.
Detailní popis je v komentářích ke zdrojovému kódu.
Poznámka: program zcela ignoruje původní formát, vytváří jej znovu. Jedinou vyjímkou jsou komentáře: rozlišuje, zda je komentář umístěn na konci řádky nebo na samostatné řádce.
Vstup je načítán ze souboru, jehož jméno je zadáno jako 1. parametr na příkazové řádce. Program kontroluje, zda soubor existuje a lze jej číst. Vstupem programu je libovolný syntakticky správný zdroják v jazyce Pascal. Pokud nebude vstup syntakticky správně, program se nezhroutí, pouze bude výsledné naformátování nedefinované (a pravděpodobně horší, než původní).
Výstup se zapíše do souboru, jehož jméno je zadáno jako 2. parametr na příkazové řádce. Program kontroluje, zda lze do souboru zapisovat. Pokud nedojde k žádné chybě, nevypisuje program na konzoli nic. V případě chyby (nelze číst vstupní soubor, nelze zapisovat výstupní soubor, chybí parametr) vypíše odpovídající hlášení. Je-li program zavolán bez parametrů, vypíše požadovanou syntaxi.
K programu přikládám testovací soubor Test.pas, který jsem používal k ladění programu. Druhým testovacím souborem je samotný zdrojový kód programu :-)
Formátování komentářů: např. komentáře před procedurou nejsou umístěný správně. Problém je, že k umístění komentáře je nutno znát formátování následujícího slova. Musel by se tedy načíst do řetězce, ale může být delší, než maximum 255 znaků. Program by také mohl rozdělovat komentáře přesahující konec obrazovky.
Program nedělí dlouhé řádky ani nedává několik krátkých příkazů na jeden řádek
Původně jsem uvažoval, že výstup bude v nějakém rich-text formátu, např. HTML, vše je na to připraveno. Snad v příští verzi :-)
Předpokládal jsem, že bude program výrazně jednodušší. Ale Pascal mě nepříjemně překvapil, neustále jsem musel přidávat další pravidla, vyjímky z nich, vyjímky z vyjímek: dvojznačná klíčová slova (of, var), operátor "^", operátor ":", …