Hlavní navigace

TeX pro každého - TeX jako jazyk

Stanislav Brabec 21. 10. 2002

Čím jiným bychom měli začít popis TeXového systému, nežli samotným TeXem. A protože čtenářům Roota není většinou programování cizí, začneme poněkud neobvykle – podíváme se na TeX jako na programovací jazyk.

TEXový začátečník si často vůbec neuvědomuje, že TEX je nejenom sázecí systém, ale i programovací ja­zyk.

Patří do kategorie makrojazyků a jedná se o velmi silný makrojazyk. Holý TEX tak, jak ho nabízí initex při svém startu, v sobě obsahuje interpretr makrojazyka a pak něco přes tři sta základních příkazů, zvaných primitiva. Primitiva jsou základní typografické příkazy, nástroje pro práci s vlastním makrojazykem a řídící příkazy.

To, co si nyní probereme, je tedy chování samotného TEXu, nikoliv jeho nadstaveb. Místy však pro jednoduchost výkladu předpokládám, že bylo provedeno i základní nastavení, použité v těchto nadstavbách.

Práce TEXu

Základní filozofií TEXu je výrazné oddělení části zpracovávající makra a části provádějící sazbu. Obrazně lze říci, že TEX nejdříve vstupní text „přežvýká“ (provede analýzu souboru a expanduje makra) a poté „spolkne“ (předá k typografickému zpracování).

Makrojazyk TEXu

Podobně jako u ostatních makrojazyků i činnost TEXu spočívá v postupném procházení souboru, zpracovávání definic maker a expanzi maker. TEX prochází soubor znak po znaku a interpretuje jejich význam.

Makra

Makra jsou základní programovací strukturou TEXu.

Ve standardním nastavení TEXu začínají makra znakem \ a jejich názvy končí před prvním nepísmenným znakem (názvy maker však obsahují vždy alespoň jeden znak). Zvláštní význam dále mají závorky { a } – ohraničují oblast platnosti lokálních definic, definici a argumenty makra, znak# – označuje číslo argumentu, % pro započetí komentáře a & – znak pro tabulátor. Existují ještě další speciální znaky (NUL a EOL) a znaky, které mají význam pro matematický režim, o němž se zmíníme později.

Expanze maker

Pokud TEX narazí na sekvenci začínající \, předpokládá, že jde o makro a snaží se jej expandovat, a to až do konečné podoby primitiv. Pokud se jedná o řídící primitivum, interpretuje jej.

Jedno primitivum slouží k definování maker – \def a další pro vzájemné přiřazování –\let. Do souboru test.tex si napíšeme:

% definice makra se dvěma parametry
\def\test#1#2{===#1***#2===}

% ukázka lokální a globální platnosti
% definice
\def\makro{bbbb}
{\def\makro{aaaa}
  \global\let\glmakro\makro
% a použití
  1) \makro
}
2) \makro\ 3) \glmakro

% prvním argument: "p"
% druhým argument: "a"
\test parametr

% prvním argument: "para"
% druhým argument: "metr"
\test {para}{metr}

\end

Pozorní čtenáři si ještě mohli všimnout dvou primitiv \  (lomítko a mezera – vysadí mezeru) a\end (ukončí práci).

Příkazem tex test si test zpracujeme a poté třeba pomocí xdvi test zobrazíme.

Uvidíme stránku s texty:

1) aaaa 2) bbbb 3) aaaa
===pa===rametr
===para
metr===

K čemu se taková expanze dá použít? Podívejme se do souboru plain.tex na jednu z nejjednodušších definic – vysazení úzké mezery:

\def\thinspace{\kern .16667em }

Složitější TEXová makra se mohou bez problémů expandovat i na tisíce primitiv.

Ve většině maker si vystačíme s takto jednoduchým schematem expanze, ale TEX má prostředky na ovlivnění pořadí expanze.

Je třeba také vědět, že existují režimy TEXu, kdy expanze probíhá trochu jinak (zápis do souboru).

Pro bystřejší čtenáře poznamenávám, že na obsahu makra vytvořeném pomocí \let se pozdější změny původního makra neprojeví, zatímco při expanzi makra se v ní obsažená makra expandují a vyhodnocují až při použití. Existuje však primitivum \edef, které provede nejdříve expanzi a teprve na výsledku expanze provede definici.

Mezery, řádkování a základní práce s textem

Ve standardně nastaveném TEXu se libovolný počet mezer srazí vždy na jedinou.

Znak konce řádku se převádí na mezeru. Dva znaky konce řádku za sebou vygenerují primitivum \par, které slouží pro přechod na nový odstavec.

Jinými slovy – text se píše s běžným řádkováním textových souborů a prázdný řádek znamená nový odstavec.

Mezery na začátku a konci odstavce se ignorují. Pro odstavcové zarážky a východové řádky se použije sázecí předpis, definovaný typografickými primitivy.

Objekty a programové konstrukce

TEX disponuje několika typy registrů – jsou to čítače (count), dimenze (dimen), výplňky(glue), registry symbolů (toks), registry boxů (box – grafických objektů). Každých z těchto registrů je k dispozici 256.

Existují primitiva, která umí sčítat (a odčítat), násobit a dělit čítače, dimenze a výplňky. Tím aritmetické schopnosti TEXu končí.

Podobně jednoduchá je i nabídka několika druhů větvení typu \ifporovnání výraz \else výraz \fi (porovnání různých typů objektů). TEX tedy neobsahuje žádné příkazy na smyčky. Přesto si s nimi poradí, jak ukazuje definice makra \loop:

\def\loop#1\repeat{\def\body{#1}\iterate}
\def\iterate{\body \let\next\iterate
  \else\let\next\relax\fi \next}

Kategorie znaků

Důležitou vlastností TEXu jsou kategorie znaků. Při spuštění TEXu má každý znak přidělenu svou kategorii, které určuje jeho chování.

TEX je jazyk variabilní, a proto existuje primitivum, které umožní tuto kategorii změnit – je jím \catcode (jeho parametrem je číslo, proto ve výpisu níže najdete před měněným znakem ještě `). Tím je možné změnit naprostou většinu předdefinovaných vlastností znaků (ve skutečnosti spíš nadefinování – výše uvedené základní nastavení provádí z větší části až základní soubor plain.tex, nikoliv TEX samotný).

Ukážeme si to na jednoduchém příkladu příkladu. Konstrukce {\bf text} je nadefinovaná k vyznačení tučného textu a {\it text} k vyznačení kurzívy. Po následující změně bude možné používat <b>text</b> a <i>text</i>.

% změníme kategorii znaku < na uvození makra
\catcode`\<=0

% Nadefinujeme makra <b resp. <i
% (jinak též \b resp. \i),
% ktera jsou povinně následována znakem >,
% jako začátek skupiny a změnu písma.
\def<b>{\begingroup\bf}
\def<i>{\begingroup\it}

% Nadefinujeme makro </ (jinak též \/ -
% což však zastíní jedno primitivum)
% jako makro s jedním argumentem,
% povinně následovaným znakem >.
% Makro argument zahodí a zavře skupinu
% (tedy ukončí platnost změny písma).
\def</#1>{\endgroup}

O poznání složitější a bezkonfliktní makra dokáží tímto způsobem přímo zpracovávat dokonce i XML a XSLT soubory!

Nyní už si můžeme prozradit, jak funguje vlastní analýza textu a hledání maker. Pokud po znaku „uvození makra“ následuje „písmeno“ (znak s kategorií písmeno), budou se načítat i následující „písmena“, dokud se nenarazí na první „nepísmeno“. Pokud je tento znak„mezera“, spolkne se (toto opatření je užitečné, aby nám v sazbě nevznikaly nechtěné mezery). Takto načtená sekvence písmen pak vytvoří tzv. symbol (token), tedy jméno makra.

Příklady: \line, \bf

Ukázka na spolknuté mezery:

Mějme \def\texta{pes} \def\textb{spí}

\texta \textb dá tentýž špatný výsledek jako \texta\textb – pesspí. Napravíme to pomocí \texta\ \textb nebo \texta\space\textb.

Pokud po znaku „uvození makra“ následuje „nepísmeno“, bude se jednat o makro s jednoznakovým názvem. V tomto případě se již případná následující „mezera“ nespolkne.

Příklady: \!, \%

Zvláštní kategorií je „aktivní znak“ – tvoří název makra sám o sobě. Objeví-li se tento znak kdekoliv v textu, vyvolá makro, které je pod jeho jménem definováno.

V případě definic maker se použije kategorie znaku, platná v době definice.

Jako příklad mimořádně divokého použití změn kategorie znaků jsem připravil ukázku nejkratší implementace Gaussova algoritmu pro výpočet data velikonoc. Vlastní kód i s výpisem výsledku se vejde do 326 bajtů! Ale nelekněte se, takhle se v TEXu běžně nepracuje.

V jediném článku (ba ani v celém seriálu) není možné postihnout všechny aspekty makrojazyka TEXu. Mým cílem proto bylo pouhé seznámení s jeho základními rysy. Příště se podíváme na jeho typografické schopnosti.

Našli jste v článku chybu?

25. 11. 2002 12:12

Stanislav Brabec (neregistrovaný)

\def\loop#1\repeat{\def\body{#1}\iterate}

\def\iterate{\body \let\next\iterate

\else\let\next\relax\fi \next}

Příklad použití:

\newcount\cnt

\loop\ifnum\cnt<10 a\advance\cnt by1\fi

(vypíše deset a)

Tedy if se nachází mimo makro. TeX skutečně nemá konstrukci na cykly. Toto makro funguje tak, že:

- nadefinuje tělo cyklu jako makro \body

- pokud není splněna podmínka opuštění cyklu, expanduje se \next v makru \iterate opět na \iterate

- pokud je splněna, expanduje…



















22. 11. 2002 13:04

Vojtech Hala (neregistrovaný)

Ja jsem sice v zivote v TeXu neprogramoval, ale ten priklad s definici makra \loop se mi nejak nelibi. Nejvic asi proto, ze tam je \else a \fi, ale neni tam \if, takze to v me hlave neproslo syntaktickou analyzou. ;-) Krome toho jsem nepochopil, co dela \repeat, kdyz je nad tim napsano, ze TeX nema zadnou konstrukci na cykly. Za vysvetleni dekuji.

PS. Serial je jinak sqelej, diky za nej! :)



Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Lupa.cz: Není sleva jako sleva. Jak obchodům nenaletět?

Není sleva jako sleva. Jak obchodům nenaletět?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Podnikatel.cz: EET zvládneme, budou horší zákony

EET zvládneme, budou horší zákony

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky