Preprocessor

Preprocesor alebo predkompilátor je v informatike program, ktorý spracováva svoje vstupné dáta, aby vytvoril výstup, ktorý sa používa ako vstup pre iný program. Výstup je považovaný za predspracovanú formu vstupných údajov, ktoré často používajú niektoré následné programy, ako sú kompilátory. Množstvo a druh vykonaného spracovania závisí od povahy preprocesora; niektoré preprocesory sú schopné vykonávať iba relatívne jednoduché textové substitúcie a rozšírenia makier, zatiaľ čo iné majú silu plnohodnotných programovacích jazykov.
Bežným príkladom z počítačového programovania je spracovanie vykonané na zdrojovom kóde pred ďalším krokom kompilácie. V niektorých počítačových jazykoch (napr. C a PL/I) existuje fáza prekladu známa ako predspracovanie ("preprocessing"). Môže tiež zahŕňať spracovanie makier, zahrnutie súborov a jazykové prípony.
Lexikálne preprocesory.
Lexikálne preprocesory sú najnižšou úrovňou preprocesorov, pretože vyžadujú iba lexikálnu analýzu, to znamená, že pracujú so zdrojovým textom pred akoukoľvek analýzou vykonávaním jednoduchého nahradenia tokenizovaných sekvencií znakov za iné tokenizované sekvencie znakov podľa užívateľom definovaných pravidiel. Zvyčajne vykonávajú substitúciu makra, textové zahrnutie iných súborov a podmienenú kompiláciu alebo zahrnutie.
C preprocesor.
Najbežnejším príkladom je C preprocesor, ktorý používa riadky začínajúce znakom '#' ako direktívy. Pretože nevie nič o základnom jazyku, jeho použitie bolo kritizované a mnohé z jeho funkcií sú priamo zabudované do iných jazykov. Napríklad makrá nahradené agresívnym vložením a šablónami, vrátane importov v čase kompilácie (to si vyžaduje zachovanie typových informácií v kóde objektu, čo znemožňuje spätné prispôsobenie tejto funkcie do jazyka); podmienená kompilácia sa v niektorých jazykoch efektívne vykonáva pomocou codice_1 a eliminácie mŕtveho kódu. Kľúčovým bodom na zapamätanie je však to, že všetky príkazy preprocesora by mali začínať na novom riadku.
Iné lexikálne preprocesory.
Medzi ďalšie lexikálne preprocesory patrí univerzálny m4, ktorý sa najčastejšie používa v systémoch zostavovania medzi platformami, ako je autoconf, a GEMA, makroprocesor s otvoreným zdrojovým kódom, ktorý pracuje so vzormi kontextu.
Syntaktické preprocesory.
Syntaktické preprocesory boli zavedené s rodinou jazykov Lisp. Ich úlohou je transformovať syntaktické stromy podľa niekoľkých pravidiel definovaných používateľom. Pre niektoré programovacie jazyky sú pravidlá napísané v rovnakom jazyku ako program. To je prípad Lisp a OCaml. Niektoré iné jazyky sa pri definovaní transformácií spoliehajú na úplne externý jazyk, ako napríklad preprocesor XSLT pre XML alebo jeho staticky typovaný náprotivok CDuce.
Syntaktické preprocesory sa zvyčajne používajú na prispôsobenie syntaxe jazyka, rozšírenie jazyka pridaním nových primitív alebo vloženie doménovo špecifického programovacieho jazyka (DSL) do jazyka na všeobecné použitie.
Prispôsobenie syntaxe.
Dobrým príkladom prispôsobenia syntaxe je existencia dvoch rôznych syntaxov v programovacom jazyku Objective Caml. Programy môžu byť napísané ľahostajne pomocou „normálnej syntaxe“ alebo „revidovanej syntaxe“ a môžu byť na požiadanie pekne vytlačené s ktoroukoľvek syntaxou.
Podobne množstvo programov napísaných v OCaml prispôsobuje syntax jazyka pridaním nových operátorov.
Rozšírenie jazyka.
Najlepšie príklady rozšírenia jazyka prostredníctvom makier možno nájsť v rodine jazykov Lisp. Zatiaľ čo jazyky sú samy osebe jednoduchými dynamicky typovanými funkčnými jadrami, štandardné distribúcie Scheme alebo Common Lisp umožňujú imperatívne alebo objektovo orientované programovanie, ako aj statické písanie. Takmer všetky tieto funkcie sú implementované syntaktickým predspracovaním, aj keď je potrebné poznamenať, že fázu kompilácie „rozširovania makra“ má na starosti kompilátor v Lispe. Toto možno stále považovať za formu predspracovania, pretože prebieha pred ďalšími fázami kompilácie.
Špecializácia na jazyk.
Jednou z neobvyklých vlastností rodiny jazykov Lisp je možnosť použitia makier na vytvorenie interného DSL. Vo veľkom projekte založenom na jazyku Lisp môže byť modul zvyčajne napísaný v rôznych minijazykoch, jeden môže používať dialekt jazyka Lisp založený na SQL, ďalší je napísaný v dialekte špecializovanom na grafické používateľské rozhranie alebo peknú tlač atď. Štandardná knižnica Common Lisp obsahuje príklad tejto úrovne syntaktickej abstrakcie vo forme makra LOOP, ktoré implementuje minijazyk podobný Algolu na opis komplexnej iterácie, pričom stále umožňuje použitie štandardných operátorov Lisp.
Preprocesor/jazyk MetaOCaml poskytuje podobné funkcie pre externé DSL. Tento preprocesor preberá popis sémantiky jazyka (tj tlmočníka) a kombináciou interpretácie v čase kompilácie a generovania kódu premení túto definíciu na kompilátor do programovacieho jazyka OCaml – az tohto jazyka buď do bajtkódu alebo do natívny kód.
Predprocesor na všeobecné použitie.
Väčšina preprocesorov je špecifická pre konkrétnu úlohu spracovania údajov (napr. kompilácia jazyka C). Preprocesor môže byť propagovaný ako "všeobecný", čo znamená, že nie je zameraný na konkrétne použitie alebo programovací jazyk a je určený na použitie pre širokú škálu úloh spracovania textu.
M4 je pravdepodobne najznámejším príkladom takéhoto preprocesora na všeobecné použitie, hoci preprocesor C sa niekedy používa v úlohe, ktorá nie je špecifická pre C.
Príklady:
GPP je všeobecný lexikálny preprocesor, ktorý sa podobá cpp. Okrem iného ho možno použiť na predbežné spracovanie markdown súborov.