Preprocesor: Porovnání verzí

Smazaný obsah Přidaný obsah
m +kat
Doplnění textu převážně z anglické verze
Řádek 1:
'''Preprocesor''' je [[počítačový program]], který zpracovává svá vstupní data tak, aby výstup mohl dále zpracovávat jiný program. Častým příkladem, kdy se používá preprocesor, je zpracovánípředzpracování [[zdrojový kód|zdrojového kódu]] před dalším krokem, kterým je [[Překladač|kompilace]]. TétoDruh a míra předzpracování závisí primárně na požadavcích kompilátoru. Většina preprocesorů je relativně jednoduchá, zvládá nahrazování textu a jednoduchá [[makro|makra]]. Malé procento preprocesorů disponuje silnými prostředky na zpracování programovacího jazyka. V takových případech není zpravidla fázinutné sepoužívat říkásložité ''preprocessing''kompilátory.
 
==Lexikální preprocesory==
Lexikální preprocesory jsou nejnižším stupněm preprocesorů. Pro svoji činnost využívají pouze [[lexikální analýza|lexikální analýzu]], tzn. že, pracují se zdrojovým kódem pouze jako s textem. Ve vstupním textu provádějí úpravy typu: najít a nahradit, použít makro, připojit externí soubor, atd.
 
===Preprocesing v jazyce C/C++===
Nejznámějším a hojně využívaným preprocesorem je [[Preprocesor jazyka C|preprocesor jazyka C/C++]]. Tento preprocesor funguje na výše zmíněném principu.
 
====Připojení externích souborů====
Preprocesoru v jazyce C/C++ se nejčastěji používá pro připojení hlavičkových souborů.
<source lang="c">#include "..."</source>
nebo
<source lang="c">#include <...></source>
Rozdíl mezi těmito příkazy je pouze v umístění, kde bude preprocesor zadaný soubor hledat. "..." značí lokalní hlavičkový soubor v projektu. <...> znamená soubor umístěný v některém společném úložišti hlavičkových souborů pro všechny projekty.
Na ukázku, připojení souborů <code><[[math.h]]></code> a <code><[[stdio.h]]></code> ze standardní C/C++ knihovny umožňuje využívat matematické a I/O operace.
 
Avšak takovýto lexikální preprocesor není schopný ohlídat vícenásobné připojení jednoho hlavičkového souboru nebo dokonce cyklické připojování hlavičkových souborů. Mimo jiné je takovýto přístup pomalý, neboť je nutné před každou kompilací připojovat hlavičkové soubory, ikdyž se v nich nic nezměnilo.
 
Od roku 1970, bylo vymyšleno mnoho alternativ hlavičkových souborů používaných v jazyce C/C++. Tyto alternativy jsou mnohdy efektivnější, rychlejší a použití je přehlednější. Vybrané implementace zdílených souborů: [[Java (programming language)|Java]] a [[Common Lisp]] používají balíčky, [[Pascal (programming language)|Pascal]] má unity, [[Modula]], [[OCaml]], [[Haskell (programming language)|Haskell]] a [[Python (programming language)|Python]] mají moduly a C# podobně jako Java využívá importy balíčků.
 
====Makra====
Makra jsou primárně používána v jazyce C. Umožňují vkládat drobné části kódu na mnoho míst, čímž se šetří velikost zdrojového kódu a přehlednost. V makrech je možné používat i zástupné znaky (něco jako parametry funkcí). Makra jsou zpracovávána preprocesorem, proto je tento kód kompilovám vícekrát, ikdyž je zapsán pouze jednou. Makra nemají vliv na rychlost překladu.
 
Na ukázku:
<source lang="c">#define max(a,b) a > b ? a : b</source>
definuje makro <tt>max</tt> se dvěma parametry <tt>a</tt> a <tt>b</tt>. Takovéto makro může být "voláno" jako funkce (stejnou syntaxí).
Využití maker je v C/C++ velmi významné hlavně při debugingu, kdy je možné rychle předefinovat makro a měnit tak kód na mnoha místech zaroveň.
 
To, že se makra nechovají stejně jako funkce si ukážeme na následujícím příkladu, kde <tt>f</tt> a <tt>g</tt> jsou dvě funkce vracející integer. Zavolání <source lang="c">z = max(f(), g());</source>
nevyčíslí <tt>f()</tt>jednou a <tt>g()</tt> taky jednou jak by se dalo čekat i funkce, nýbrž jedna z fukcí <tt>f</tt> nebo <tt>g</tt> bude vyčíslena dvakrát (v závislosti na tom, která vrací větší číslo). Toto chování může mít za následek katastrofální chování v případě, že záleží na počtu volání <tt>f</tt> nebo <tt>g</tt>.
 
Většina moderních programovacích jazyků již nevyužívá tyto možnosti maker, právě z těchto nejednoznačných důvodů a snadného zaměnění za funkce. Z toho důvodu existují v dnešních jazycích pouze funkce nebo metody.
 
====Podmíněná kompilace====
Preprocesor jazyka C/C++ podporuje podmíněnou kompilaci. To umožňuje mít více verzí stejného kódu, který se například liší ve výpisu logovacích informací a podobně. Takto je možné do jednoho zdrojového kódu napsat program kompilovatelný na více platforem, či různé jazykové mutace, ...
 
Nejčastěji se používá následující konstrukce:
<source lang="c">
#ifndef FOO_H
#define FOO_H
...(header file code)...
#endif
</source>
Programátor tím zabraňuje mnohonásobnému připojení hlavičkového souboru. Tímto problémem sme se zabývali výše.
 
Podmínky preprocesuru je možné využít v kompexnějších případech jako je tento:
<source lang="c">
#ifdef DEBUG
...
#else
...
#endif
</source>
nebo
<source lang="c">
#if DEBUG
...
#else
...
#endif
</source>
 
Naneštěstí většina moderních programovacích jazyků odstraňuje tuto schopnost a uchyluje se k tradičnímu použití <code>if...then...else...</code>. To má ale za následek pomalejší běh programu, neboť tato podmínka musí být vyhodnocena za běhu programu a nikoliv pouze při kompilaci.
 
==Syntaktické preprocesory==
Syntaktické preprocesory byly poprvé představeny v jazyce [[Lisp programming language|Lisp]]. Jejich úkolem je převést syntaktické strom na sérii uživatelem definovaných přepisovacích pravidel. V několika jazycích jsou pravidla napsána ve stejném jazyce jako program (compile-time reflection), případ právě jazyka [[Lisp programming language|Lisp]] a [[OCaml]]. Ostatní jazyky mají tyto pravidla definovaná v jiných jazycích jako například [[XSLT]] preprocesor pro [[XML]] nebo statické [[CD]].
 
Syntaktické preprocesory jsou typicky použity ke custimizaci jazyka, doplnění nových primitiv, atd. Takto je možné dosáhnout všeobecně použitelného jazyka.
 
===Přizpůsobení syntaxe===
Dobrý příklad se nachází na adrese http://caml.inria.fr/pub/docs/manual-camlp4/manual007.html. Program může být zapsán dvěma různými syntaxemy při zachování stejné funkčnosti a záleží hlavně na subjektivním posouzení programátora.
 
Velký počet programů napsaných v [[OCaml]] přispůsobuje syntaxi doplněním nových operátorů. Definici vlastních operátorů podporuje i jazyk C++.
 
<!--
===Extending a language===
The best examples of language extension through macros are found in the [[Lisp programming language|Lisp]] family of languages. While the languages, by themselves, are simple dynamically-typed functional cores, the standard distributions of [[Scheme (programming language)|Scheme]] or [[Common Lisp]] permit imperative or object-oriented programming, as well as static typing. Almost all of these features are implemented by syntactic preprocessing, although it bears noting that the "macro expansion" phase of compilation is handled by the compiler in Lisp. This can still be considered a form of preprocessing, since it takes place before other phases of compilation.
 
Similarly, statically-checked, type-safe [[regular expressions]] or [[code generation]] may be added to the syntax and semantics of [[OCaml]] through macros, as well as micro-threads (also known as [[coroutines]] or [[fiber (computer science)|fibers]]), [[Monads in functional programming|monads]] or transparent XML manipulation.
 
===Specializing a language===
One of the unusual features of the [[Lisp programming language|Lisp]] family of languages is the possibility of using macros to create an internal
[[Domain-specific programming language|Domain-Specific Programming Language]]. Typically, in a large [[Lisp programming language|Lisp]]-based project, a module may be written in a variety of such minilanguages, one perhaps using a [[SQL]]-based dialect of [[Lisp programming language|Lisp]], another written in a dialect specialized for GUIs or pretty-printing, etc. [[Common Lisp]]'s standard library contains an example of this level of syntactic abstraction in the form of the LOOP macro, which implements an Algol-like minilanguage to describe complex iteration, while still enabling the use of standard Lisp operators.
 
The [[MetaOCaml]] preprocessor/language provides similar features for external [[Domain-specific programming language|Domain-Specific Programming Languages]]. This preprocessor takes the description of the semantics of a language (i.e. an interpreter) and, by combining compile-time interpretation and code generation, turns that definition into a compiler to the [[OCaml]] programming language -- and from that language, either to bytecode or to native code.`
 
==General purpose preprocessor==
Most preprocessors are specific to a particular data processing task (e.g., [[compilers|compiling]] the [[C (programming language)|C]] language). A preprocessor may be promoted as being ''general purpose'', meaning that it is not aimed at a specific usage or programming language, and is intended to be used for a wide variety of text processing tasks.
-->
 
===Externí zdroje===
* [http://lispm.dyndns.org/news?ID=NEWS-2005-07-08-1 DSL Design in Lisp]
* [http://www.paulgraham.com/progbot.html Programming from the bottom up]
* The [http://www.nothingisreal.com/gpp/gpp.html Generic PreProcessor]
* Gema, the [http://gema.sourceforge.net General Purpose Macro Processor]
* The [[PIKT]] [http://pikt.org/pikt/ref/ref.4.piktc.html piktc] [http://pikt.org/pikt/ref/ref.3.html text, script, and configuration file preprocessor]
 
== Související články ==
*[[Preprocesor jazyka C]]
 
{{Pahýl - počítače}}
 
[[Kategorie:Programování]]