Analyse lexicale
La solution complète est
ici.
Un exemple d'analyseur
L'analyseur untag.mll se compile par
« ocamllex untag.mll ; ocamlc -o untag untag.ml
»
(ou par « make untag
» à l'aide de ce
Makefile),
en une commande qui prend un
nom de fichier HTML en argument en affiche le contenu du fichier
moins les balises et les commentaires.
Récupérez ces deux fichiers tout de suite, ainsi que ce document lui
même (menu File, entrée Save,en format source).
Compilez, puis essayez « ./untag index.html
».
HTML est effet structuré à l'aide d'éléments,
qui s'ouvrent par une balise d'ouverture et se ferment (parfois) par une balise
de fermeture.
Par exemple, on met un texte en italique à l'aide de l'élément
« I
» , soit <I>en italiques</I>
donne en
italiques.
Un autre exemple est celui des hyperliens introduits par l'élément
« A
», soit :
<A HREF="http://pauillac.inria.fr/~maranget/">chez moi</A>
qui donne
On remarquera que la référence distante (url) est
donnée comme la valeur de l'attribut « HREF
» de la balise
d'ouverture de l'élément « A
».
Enfin une image incluse dans le texte est codée par un élément
« IMG
» qui consiste en l'unique balise
« <IMG SRC=
...>
».
Par example :
<IMG ALT="Le tango.gif en SRC" SRC=tango.gif>
nous donne
Ici la référence distante (le fichier qui contient l'image) est la valeur de
l'attribut « SRC
».
L'analyseur untag est votre point de départ pour les
exercices de cette semaine.
On remarquera que les points suivants :
-
Une balise commence par «
<
» et se termine par
« >
». Les caractères « <
» et
« >
» ne peuvent pas apparaître autrement que pour démarrer et
terminer une balise.
(Lorque l'on veut afficher ces caractères, on utilise « <
» et
« >
»).
- Un commentaire commence par «
<!--
» et se termine par
« -->
», il peut contenir à peu près n'importe quoi, sauf un
commentaire.
- L'analyseur fournit un traitement des exceptions (fonction
prerr_error
)
qui permet de se positionner dans la zone du fichier d'entrée qui a
provoqué l'erreur.
Pour en profiter, il faut lancer untag
sous emacs (par
C-c C-c
)
dans un buffer en mode caml, on se positionnera alors sur les erreurs
par C-x`
.
1 Extraire toutes les balises d'un document
C'est une première étape, cela revient en quelque sorte à inverser
l'analyseur untag.
Il est vivement conseillé de commencer par copier untag.mll
dans un nouveau fichier tag.mll (par cp untag.mll
tag.mll). Dès lors vous pourrez vous servir
de la commande « make tag » pour fabriquer l'analyseur
tag (à condition bien entendu d'avoir récupéré le
Makefile).
Évidemment il faut d'abord modifier les règles d'analyse (et seulement
elles, veillez bien à garder tout le code du prélude (entre accolades
au début) et du postlude (entre accolades à la fin).
Rapelons que par « balise » on entend tout ce que est de la forme
<
...>
.
Normalement « ./tag index.html
» devrait produire
ce fichier :
001: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
002: <HTML>
003: <HEAD>
004: <TITLE>
...
320: <FONT SIZE=2>
321: <sup>
322: </sup>
323: </FONT>
324: </A>
325: </EM>
326: </BLOCKQUOTE>
327: </BODY>
328: </HTML>
(Les numéros de ligne sont là pour aider à comparer avec la
sortie de votre programme. On affiche un entier i comme ci-dessus
par Printf.printf "%03"
i.)
2 Extraire toutes les références distantes d'un document
Écrire l'analyseur url qui extrait toutes les références
distantes d'une page HTML.
Comme on l'a déjà vu, les références distantes sont
les valeurs des attributs
HREF
des balises <A
...>
et
les valeurs des attributs
SRC
des balise
<IMG
...>
,
C'est à dire que l'on cherge maintenant les arg dans des
constructions du genre:
<A ... href=arg ... >
<iMg ... SrC=arg ... >
On notera :
-
Les « mots-clés »
IMG
, HREF
etc. sont à reconnaître
indépendamment de la casse des lettres.
- Une balise peut avoir plusieurs attributs, séparés par des
(suites) d'espaces. Un espace pouvant être, un espace, un saut à la
ligne (
'\n
ou même une tabulation '\t'
...
- Les attributs qui nous intéressent sont de la forme
ATTR
=
arg, où
arg est normalement n'importe quoi (ou presque !) entre deux
doubles quotes « "
» ou deux simple quotes « '
».
Le presque veut dire que l'on ne peut pas mettre
des simples quotes dans un argument cité simples quotes, ni de
doubles quotes dans dans un argument cité entre doubles quotes.
Toutefois on peut ne pas citer les arguments,
lorsqu'ils ne sont pas « ambigus ». Ce qui n'est pas ambigu est défini
ainsi dans
un document de
référence idoine :
In certain cases, authors may specify the value of an attribute
without any quotation marks. The attribute
value may only contain letters (a-z and A-Z), digits (0-9), hyphens ``-''
(ASCII decimal 45), periods ``.'' (ASCII
decimal 46), underscores ``_''(ASCII decimal 95), and colons
``:''(ASCII decimal
58). We recommend using
quotation marks even when it is possible to eliminate them.
- La balise
<IMG ALT="Le tango.gif en SRC" SRC=tango.gif>
est piégeante. Il faudra penser à ne pas aller chercher les
SRC (ou les HREF) dans les arguments cités.
À vous donc d'écrire le lexer url.mll, vous pourrez le
compiler directement ou toujours avec le même
Makefile par
« make url
».
La démarche suggérée est de démarer de
tag.mll (en oubliant pas de le nommer url.mll).
Dans le source, notez cette fois la présence
d'une définition
de l'expression régulière reconaissant les blancs.
Il va falloir:
-
Identifier les balises
<A
...>
et
<IMG
...>
.
- Dans le premier cas, aller chercher un attribut
HREF
et dans le second un attribut SRC
.
- Récupérer un argument.
Cela donne assez naturellement quatre analyseurs mutuellement
récursifs.
Attention certains analyseurs devront renvoyer quelque chose,
typiquement le type du dernier analyseur sera
Lexing.lexbuf
->
string
, tandis que le
type du premier sera Lexing.lexbuf
->
unit
.
Pour le dernier analyseur, qui récupére les
arguments des attributs, inspirez vous du
traitement des chaînes dans le poly. Vous pouvez
aussi lire les explications de l'exemple de la calculette,
toujours dans le poly.
Vous aurez sans doute besoin de travailller un peu sur les chaînes,
voir le module String.
Une fois votre analyseur terminé, si vous l'appliquez, après
sa récupération, à ce document
lui-même par « ./url index.html
», vous devriez obtenir
ce fichier :
01: sol.html
02: sol/untag.mll
03: sol/Makefile
04: http://pauillac.inria.fr/~maranget/
05: tango.gif
06: sol/Makefile
07: balises.txt
08: sol.html#tag
09: http://www.w3.org/TR/html401/intro/sgmltut.html
10: sol/Makefile
11: ../../poly/lexical.html#chaine
12: ../../poly/lexical.html#lexcalc
13: http://caml.inria.fr/ocaml/htmlman/libref/String.html
14: urls.txt
15: sol.html#un
16: ftp://ftp.inria.fr/lang/caml-light/
17: //www.ics.uci.edu/pub/ietf/uri/rfc2396.txt
18: /
19: index.html
20: http://caml.inria.fr/ocaml/htmlman/libref/Str.html
21: ../../poly/lexical.html#libstr
22: sol.html#deux
23: http://pauillac.inria.fr/~maranget/hevea/index.html
(Les urls sont numérotées pour faciler la comparaison avec votre sortie
à vous).
3 Interpréter les références distantes
Une fois récupérées les réferences distantes, on remarque qu'elle ont
des aspects assez variables.
Dans l'url complète
http://pauillac.inria.fr/~maranget/
, on note un protocole
http
(qui pourrait être autre chose, par exemple, ftp
),
un nom de machine pauillac.inria.fr
et ensuite un chemin
d'accès /~maranget/
.
Rien que pour compliquer un peu, voici une url de protocole
ftp ftp://ftp.inria.fr/lang/caml-light/.
Protocole et nom de machine peuvent être omis, lorqu'ils sont les
mêmes que ceux du document (c'est une vue très simplifiée, voir le
document de
référence idoine, mais plus tard !).
Par exemple l'url minimale « /
» renvoie normalement à la
racine du serveur, tandis que « index.html
» renvoie
à ce document lui-même.
Il vous est demandé de completer l'analyseur url,
afin de destructurer les url.
Il est demandé cette fois d'utiliser
une expression régulière de la bibliothèque Str de Caml
(voir aussi éventuellement l'exemple du poly).
Cette bibliothèque n'est pas disponible par défaut, il faut l'ajouter
explicitement à l'édition de liens, donc on compile par les commandes
suivantes :
# ocamllex url.mll
# ocamlc -o url str.cma url.cmo
Le Makefile donné fait cela pour vous.
Ce document a été traduit de LATEX par
HEVEA.