2 Principes
2.1 TeX ou LATEX ?
Une première réponse est brutale, après tout nous écrivons plutôt en
LATEX. Néanmoins la question mérite d'être un peu approfondie, car
elle permet de mieux définir les objectifs d'un traducteur.
Rappelons que LATEX est en fait un ensemble de macros TeX.
LATEX est généralement préféré car il se charge de maints détails
de mise en page et de composition, ce qui doit permettre à l'auteur de
se concentrer sur l'écriture de son texte et non pas sur sa
composition.
De fait, le source TeX apparaît comme celui d'un langage
très influencé par
son implantation. Autrement dit, il faut comprendre comment fonctionne
TeX pour pouvoir s'en servir.
Une telle démarche est raisonnable pour l'auteur qui compose finement
son texte, elle est dissuasive pour l'auteur qui veut simplement
écrire.
LATEX propose un langage source qui met plus en avant les concepts
que leur réalisation.
Typiquement, pour comprendre, par exemple, un changement de style
des polices de caractères, on doit en TeX se référer à un « état
courant » du moteur interne, tandis que LATEX propose des concepts
de plus haut niveaux, comme une commande qui compose son argument
avec un attribut de police déterminé.
De même un des concepts centraux de TeX est la boite, qui de plus
peut être horizontale (un mot) ou verticale (un paragraphe), ce
concept provient du monde de l'imprimerie et intéresse finalement peu
l'auteur du document.
Une conséquence intéressante est qu'un document écrit en LATEX
ressemble beaucoup plus à un programme écrit dans un langage moderne
(donc réputé de haut-niveau), qu'un document écrit en TeX qui lui
ressemble à de l'assembleur.
On peut même penser qu'il est impossible d'écrire un traducteur
complet de TeX vers HTML, car HTML n'offre pas énormément de contrôle
sur l'aspect final du document, qui d'ailleurs dépend fortement du
dispositif utilisé pour le visualiser (cependant, un traducteur
commercial TeXpider [9] suit cette démarche, mais il y
a fort à parier que ce programme est bien plus complexe qu'HEVEA).
En résumé, traduire LATEX vers HTML est possible et raisonnable,
parce que ces deux langages sont tous deux des langages qui spécifient
une certaine structure du document, plus qu'ils ne décrivent
complètement quel sera l'aspect du produit final.
En outre, le langage LATEX est relativement uniforme, toutes les
constructions ayant sensiblement la même syntaxe,
ce qui facilite grandement sa compréhension par un programme.
Classiquement, un traducteur d'un langage vers un autre
possède une phase initiale
d'analyse syntaxique qui, à partir du source construit un arbre de
syntaxe abstraite.
Cet arbre est en fait le support de la sémantique du langage, qui très
souvent procède par assemblage récursif de sous-eléments.
La traduction finale se fait ensuite par un parcours de cet arbre
ou d'un arbre transformé.
Les compilateurs rapides et peu optimisants font l'économie de la
construction de l'arbre de syntaxe et génèrent directement leur
produit dans la phase d'analyse syntaxique.
Dans notre cas, c'est cette démarche qui est adoptée, tant pour des
raisons d'efficacité que parce que, comme on va le voir, les langages
LATEX et HTML ont des structures syntaxiques proches.
En outre il n'est pas immédiat de définir complètement LATEX sous
forme d'une grammaire BNF, un préalable indispensable si l'on veut
effectivement construire un arbre de syntaxe abstraite d'un document
LATEX.
Ici, on se contente d'admettre que les documents ont des structures
comparables dans les deux langages, sans expliciter exactement ce
qu'est cette structure.
2.2 Structuration
Donc, il est frappant de constater que les documents LATEX et
HTML ont nombre de structures communes. Les environnements LATEX
(ouverts par ``\begin{
env}
'' et refermés par
``\end{
env}
'' correspondent aux éléments de niveau
bloc HTML (« block-level elements », ouverts par la balise
``<
bloc>
'' et
refermés par la balise ``</
bloc>
'').
Les documents complets sont structurés selon le même modèle de sections et
sous-sections (les « sectional units » de LATEX, introduites par les
commandes ``\section{
...}
'',
``\subsection{
...}
'', etc et les « headers
elements » ``<H1>
...</H1>
'',
``<H2>
...</H2>
'', etc. de HTML).
Le principe général de la traduction est donc celui d'une traduction
lexicale : reconnaître les entités lexicales et les traduire une à une
la structuration du document restant inchangée.
Par entité lexicale, j'entends ici un groupe de caractères
significatif et de taille réduite.
Par exemple:
\begin{quote}
\begin{flushright}
Ceci est une citation de deux lignes,\\
avec fer \begin{em}à droite\end{em}.
\end{flushright}
\end{quote}
Se formate comme suit:
Une traduction simple et logique en HTML est:
<BLOCKQUOTE><DIV ALIGN=right>
Ceci est une citation de deux lignes,<BR>
avec fer <EM>à droite</EM>.
</DIV>
</BLOCKQUOTE>
On a donc traduit \begin{quote}
en <BLOCKQUOTE>
,
la construction \begin{flushright}
en <DIV ALIGN=right>
,
\\
en
<BR>
, etc.
L'imbrication des environnement et des éléments est la même dans les deux
langages.
De même la traduction d'une liste est particulièrement directe.
En LATEX, on a:
\begin{itemize}
\item Premier item.
\item Deuxième item.
\end{itemize}
En HTML, il vient:
<UL>
<LI>Premier item.
<LI>Deuxième item.
</UL>
Évidemment, les structures des documents LATEX et HTML ne sont
pas identiques en tout point.
Par exemple,
l'effet des déclarations de changement de style LATEX
court de leur occurrence à la fin de
l'environnement ou du groupe courant, tandis que les
éléments de niveau texte HTML (« text-level
elements ») ont
une structure bien parenthésée, leur effet courant entre une balise
d'ouverture et une balise
de fermeture.
Ainsi, le texte « normal, en italique normal »
est obtenu à partir du source LATEX suivant :
normal, {\itshape en italique} normal
Une traduction possible en HTML est :
normal, <I>en italique</I> normal
En outre,
la définition de HTML [8] interdit la présence d'éléments
de niveau bloc à l'intérieur des éléments de niveau texte.
Nous verrons à la section 3, comment
HEVEA garantit le bon parenthésage de toutes les balises
d'ouverture et de fermeture, ainsi que le respect de cette contrainte.
Pour traiter cette différence de structure entre les deux langages,
ainsi que d'autres comme les commandes définies par l'utilisateur,
HEVEA s'écarte de la pure traduction lexicale pour
revenir à un modèle plus proche de TeX, où les diverses commandes
sont interprétées comme des ordres de modification de l'état courant
du traducteur.
2.3 Organisation d'HEVEA
Figure 1 :
Les dépendances entre modules d'H
EV
EA
La traduction d'HEVEA se divise en deux sous-tâches, d'une part
reconnaître du source LATEX que l'on supposera correct, et d'autre
part produire du HTML correct. Le programme HEVEA s'articule
donc en deux sous-unités, d'une part un analyseur lexical
principal et d'autre part un gestionnaire de sortie.
L'interaction entre les deux sous-unités est simple : l'analyseur
réalise des appels aux fonctions du gestionnaire de sortie.
L'analyseur se garde bien d'échouer sur une entrée incorrecte,
lorsque l'incorrection n'est pas trop grave (par exemple, une commande
inconnue).
En effet, ces erreurs peuvent résulter d'une insuffisance d'HEVEA
et elle ne présagent pas d'une traduction inacceptable. Néanmoins, un
avertissement est donné à l'utilisateur, afin de lui permettre de
contrôler visuellement le résultat.
En revanche le gestionnaire de sortie échoue lorqu'il a
pu détecter qu'il est en train d'émettre du HTML incorrect.
HEVEA lit des documents composés de plusieurs fichiers sources, car
il interprète correctement la construction \input
de LATEX,
mais sa sortie est un fichier HTML unique.
Le résultat d'HEVEA peut ensuite être segmenté en
plusieurs fichiers par un autre programme HACHA, qui est inclus dans
la distribution d'HEVEA.
HEVEA s'efforce de réaliser toutes les constructions LATEX
décrites dans le « Blue Book » [4], à
l'exception de certains packages.
L'analyseur lexical principal est compilé par ocamllex, le générateur
d'analyseurs lexicaux inclus dans la distribution d'Objective
Caml [5], il est réalisé par le module Scan.
Le gestionnaire de sortie est réalisé directement en
Objective Caml par le module Html.
HEVEA comprend de nombreux autres modules,
Le total du source d'HEVEA et de HACHA s'élevant à un peu
moins de 7000 lignes de code. Enfin le développement d'HEVEA, à
partir du prototype htmlgen [6] de X. Leroy
et la rédaction de
la documentation [7] m'ont pris de l'ordre
de quatre ou cinq mois à mi-temps.
Les dépendances entre les modules sont données à la figure 1,
on notera l'analyseur principal Scan et le
gestionnaire de sortie Html et leur dépendance.
HEVEA comprend d'autres analyseurs lexicaux, ce sont les
modules :
-
Auxx
- Lecture des fichier auxiliaires .aux
produits par
LATEX. Les informations lues permettent à Scan
d'introduire dans sa sortie les étiquettes des références croisées et
des citations bibliographiques.
- Save
- Lecture des argument des commandes (voir
section 5).
- Entry
- Lecture du fichier d'index .idx.
Cette lecture est optionnelle, elle s'impose lorsque l'utilisateur
modifie ce fichier après sa production par LATEX.
Trois modules réalisent la gestion des entrées et des sorties :
-
Mylib
- Localisation du répertoire de la librairie
d'HEVEA et gestion du chemin de recherche des fichiers.
- Myfiles
- Localisation et ouverture des fichiers.
- Out
- Gestion de toutes les sorties.
Le module Out présente une abstraction d'un flot de sortie.
Ce flot peut être un fichier ou un tampon mémoire. Tous les analyseurs
lexicaux produisent et rendent leur résultat par des appels aux
fonctions de ce module.
Les autres modules réalisent certaines des fonctionnalités d'HEVEA :
-
Macros
- Gestion de l'environnement de commandes LATEX.
- Index
- Production du ou des index.
- Foot
- Gestion des notes de bas de page.
- Symb
- Définition des symboles mathématiques.
- Image
- Production d'un fichier LATEX qui regroupe
les sous-parties du source traduit à transformer en images.
Le document final contient ensuite des liens vers les images en lieu
du source transformé.
Cette procédure est toujours demandée explicitement par l'utilisateur.