14/11/2010
201011142003 lex yacc
lex et yacc, mes nouveaux copains
Depuis quelques temps (mais il remonte à quand mon dernier billet ?) je bosse à mes heures perdues sur un projet qui roxe. Ce projet utilise un fichier de configuration dont la syntaxe ressemble à ceci:# comment set key value
Rien de spécial. Là où ça se corse (comme on dit à Bastia), c'est quand, plutôt que de faire son parser avec ses petites mimines toutes crades et maladroites, on décide d'utiliser les bon outils. A ma droite lex, à ma gauche yacc. Mes deux nouveaux copains.
On ne peut pas dire qu'on croule sous la documentation, et je me suis largement inspiré de http://ds9a.nl/lex-yacc/cvs/lex-yacc-howto.html. Je me fends d'un billet, modeste contribution à ces outils qu'on utilise tous les jours sans le savoir.
On commence par définir notre fichier de configuration:# set debug on|off set debug on # set userset user nobody # set chroot /path/to/chroot set chroot /tmp/chroot
Ne pas hésiter à bien commenter son fichier de conf', ça mange pas de pain. Petite analyse:
* set: debut d'une commande * debug user chroot: commande * on|off: valeur booleenne * nobody: un utilisateur du systeme * /tmp/chroot: un repertoire
Mes nouveaux copains se partagent le boulot: un s'occupe de la syntaxe (token.l) pendant que l'autre s'occupe de la grammaire (parse.y). Pour ne pas transformer ce billet en série de listings indigestes, les tgz des différentes étapes sont disponibles ici.
dsx@itanium>tar xzvf step1.tgz x Makefile x conf.conf x main.c x parse.y x token.l dsx@itanium>make && make check set debug '1' set chroot '/tmp/chroot' set user 'nobody'
Etape n°2: contrôler les valeurs saisies. Un chroot nobody ou un user /tmp/ risque d'être du plus mauvais effet, je rajoute deux fonctions dans parse.y :
dsx@itanium>make clean && make && make check && make fail set debug '1' set chroot '/tmp/chroot' set user 'nobody' set debug '1' parse_conf: '/if/this/file/exists/you/are/crazy': directory not exists *** Error code 1 Stop in /tmp/for_rm.
Etape n°3: c'est bien joli ces printf, mais une structure correctement remplie ça serait mieux.
dsx@itanium>make clean && make && make check
Dump config
debug: '1'
chroot: '/tmp/chroot'
user: 'nobody'
Notre fichier de conf est un peu tristounet, on va rajouter un truc qui poutre:
set debug on
set user nobody
set chroot /tmp/chroot
color {
blue
white
red
}
Etape n°4: autant le dire tout de suite, sys/queue.h ça aide. Beaucoup. Vraiment.
dsx@itanium>make clean && make && make check
Dump config
debug: '1'
chroot: '/tmp/chroot'
user: 'nobody'
couleurs
'blue'
'white'
'red'
Pour les syntaxes un peu plus compliquées, ne pas hésiter à jouer des regexp et des fonctions d'affectation dans token.l .
![Validate my Atom 1.0 feed [Valid Atom 1.0]](/valid-atom.png)
![Validate my RSS feed [Valid RSS]](/valid-rss-rogers.png)