Obligement - L'Amiga au maximum

Mardi 25 juillet 2017 - 22:41  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - Flex, des filtres à tout faire
(Article écrit par Rodrigo Reyes et extrait d'Amiga News - avril 1997)


Comment fabriquer des outils de conversion texte MS-DOS->Amiga et HTML->texte ?

Lex est un outil des plus utilisés dès qu'il s'agit de traiter rapidement de gros volumes de texte. Des plus utilisés, mais pas par tout le monde, puisqu'il n'est finalement pas aussi connu qu'il mériterait de l'être.

Cet article traitera donc de Flex, qui est sa variante GNU (disponible gratuitement), et de ce qu'il est possible d'en faire, même pour des débutants en programmation. Pour l'utiliser, il est nécessaire de posséder un compilateur C quelconque (GCC par exemple, qui est également sous licence GNU), même si les connaissances requises en programmation sont élémentaires.

Flex, donc, se présente comme un compilateur qui prend un programme Lex, et le transforme en programme C. Il suffit ensuite de compiler ce dernier pour obtenir un exécutable.

Commençons par un petit exemple pratique. Vous êtes seul sur une île déserte, avec votre Amiga, Flex, un compilateur C, et un gros texte au format MS-DOS. Vos petits yeux sensibles ne pouvant tolérer le très mauvais spectacle d'un texte peu lisible, il vous faut de suite le reformater. Très pénible à faire à la main, un petit programme Lex peut vous faire ça très rapidement.

Un programme Lex se décompose en trois parties, chacune séparée par le double signe "%%". La première partie concerne les déclarations, définitions, et autres gracieusetés. La seconde est le programme Lex en lui-même, qui n'est rien d'autre qu'une liste de règles. La troisième partie sera rajoutée telle qu'elle au source C généré, et vous permet d'insérer vos propres routines.

En gros, vous devriez avoir pour chaque programme Lex :

DECLARATIONS
%%
PROGRAMME LEX
%%
FONCTIONS DIVERSES

Dans la partie "déclarations", vous pouvez mettre des définitions, qui vous serviront plus tard dans les règles. Par exemple :

CR x0D
LF x0A

...définit CR et LF, qui sont respectivement les caractères de valeurs hexadécimales OD et OA. Il est également possible d'assigner des expressions rationnelles à un mot-clé. Par exemple, la séquence [a-z] signifie littéralement "n'importe quelle lettre comprise entre "a" et "z"". Mais Flex différencie minuscule et majuscule. Aussi, pour préciser "n'importe quelle lettre, majuscule ou minuscule", il faudra taper : [a-zA-Z]. Vous aurez noté que le métacaractère "-" indique que la séquence va de la lettre qui le précède à la lettre qui le suit. De plus, toutes les lettres placées entre [] seront acceptées à l'emplacement donné.

Pour "n'importe quelle lettre, majuscule ou minuscule, ou n'importe quel chiffre, ou n'importe quel caractère accentué" : [a-zA-Z0-9êéèâàîïôûù].

Il est également possible de définir le même genre de chose, mais en négatif [^(séquence)]. Ainsi [^a-z] signifiera "n'importe quel caractère sauf les lettres de "a" à "z"".

Pour en revenir aux définitions, elles pourront être utilisées dans les règles entourées de crochets. Pour le premier exemple, il faudra les nommer par {CR} et {LF}.

Pour obtenir un fichier qui modifie les retours à la ligne du PC en retour à la ligne de l'Amiga, il suffit de transformer toutes les séquences CR-LF en LF. C'est ce que fait le programme Flex suivant :

CR (x0D)
LF (x0A) 

%%

{CR}{LF} {printf("); }

%%

int main()
{ 
   yylex();
   return 0;
}
int yywrap()
{
   return 0;
}

Les fonctions qui se trouvent dans la troisième partie sont les fonctions C. main() est la fonction principale du programme, c'est lui qui va appeler la fonction yylex(), qui est chargée de faire tourner les règles. yywrap() par contre n'est pas encore utile pour nous, mais est réclamée par la fonctions yylex().

Si vous utilisez le compilateur GCC, vous pouvez vous affranchir de la troisième partie et éliminer les fonctions main() et yywrap(), à condition de compiler le programme avec la bibliothèque fl (les deux fonctions s'y trouvent déjà).

Donc, avec GCC, tapez :

flex dos2ami.l (Flex produit alors le fichier lex.yy.c)
gcc lex.yy.c -o dos2ami

...ou si vous préférez éliminer main() et yywrap(), qui sont déjà intégrés dans la bibliothèque fl :

gcc lex.yy.c -lfl -o dos2ami

Si vous utilisez n'importe quel autre compilateur :

flex dos2ami.l
lex.yy.c -o dos2ami

En remplaçant CC par sc si vous utilisez le SAS-C, par exemple. Vous pouvez alors lancer le programme à partir d'un CLI, avec une commande du genre "dos2ami <fichier_msdos >fichier amiga". Vous devez mettre un < devant le fichier d'entrée, et un > devant le fichier de sortie, car flex utilise par défaut les entrées-sorties standards.

Revenons maintenant à la structure des règles proprement dites, et voyons ce qu'elles font dans notre petit programme, ou plutôt, examinons notre seule et unique règle.

{CR}{LF} {printf("); }

Très simplement, lorsque le scanner tombe sur le caractère CR suivi par le caractère LF, il exécute la commande C qui se trouve entre crochets. En l'occurrence, il se contente d'afficher un retour à la ligne standard sur Amiga (caractère spécial "").

Tout ce qui n'est pas reconnu par les règles du programme Flex est systématiquement renvoyé tel quel dans la sortie standard. Ainsi, tous les autres caractères, les CR/LF solitaires ou dans un ordre différent, ne seront pas modifiés.

Mais pour l'instant, notre programme se contente de transformer (efficacement, certes) les retours à la ligne. Une amélioration notable serait de transformer également les caractères accentués. Pour ce faire, rajoutons aux règles du programme :

x85 {printf("à"); }
x83 {printf("à"); }
x82 {printf("é"); }
x88 {printf("ê"); }
x8a {printf("è"); }
x93 {printf("ô"); }
x8c {printf("i"); }
x97 {printf("ù"); }
x96 {printf("ü"); }

Et nous avons déjà un convertisseur bien plus performant, puisqu'il permet aussi de remplacer les voyelles accentuées du PC par leurs équivalentes Amiga.

Mettons que vous désiriez également supprimer tous les espaces inutiles du texte original, afin d'avoir un texte joli et compact. Il faut alors définir une règle qui signifierait "remplace toutes les séquences de plusieurs espaces par un seul espace".

Pour désigner le "plusieurs", nous disposons de deux opérateurs : "?" et "+". Faites suivre le caractère (ou une expression rationnelle entre crochets) par "*" et la signification en sera "0 ou plusieurs occurrences du caractère" (les spécialistes auront reconnu l'étoile de Kleene). Faites le suivre par "+", et la signification sera "une ou plusieurs occurrences du caractères". De plus, pour désigner un espace, nous sommes obligés de le mettre entre guillemets, pour que Flex puisse le repérer. Soit finalement la règle suivante :

""+ {printf(" "); }

...qui remplace toutes les séquences de un ou plusieurs espaces par un seul. Si maintenant nous voulons aller encore plus loin, et remplacer toutes les séquences de plusieurs espaces ou de plusieurs tabulations par un seul espace, il suffit de préciser :

[\t]+ {printf (" "); }

Vous remarquerez que l'espace n'est pas placé entre guillemets dans les crochets, car il y est automatiquement reconnu comme un caractère de l'expression.

Arrivé à ce stade de l'article, vous aurez déjà pu remarquer que Flex permet très facilement de faire des filtres de conversion pour du texte. Certes, un convertisseur de texte PC->Amiga n'a rien de grandiose en soi, mais ce n'est ici qu'un exemple très simple. Flex permet d'utiliser beaucoup d'autres opérateurs pour gérer ses expressions rationnelles, et une lecture de la documentation vous en donnera une liste exhaustive. Après tout, il ne s'agit ici que de présenter un outil fort pratique.

Néanmoins, ne nous arrêtons pas là, et voyons s'il est possible de faire des choses plus intéressantes à peu de frais. Comme ce genre de chose est très à la mode en ce moment, faisons notre propre convertisseur HTML->texte. Ce genre de programme se fait facilement sous (F)Lex, comme vous allez le voir. Je vous propose donc le petit programme suivant :

Flex

Dans la première partie, vous pouvez voir quelque chose que je n'avais pas encore introduit, les définitions entre %{ et %}. Cela signifie tout simplement que ce qui se trouve entre les crochets est une séquence de déclaration C qui n'est pas interprétée par Flex, et qui se retrouvera inchangée dans le source C généré. Cela permet de mettre des variables globales, des prototypes, bref toutes ces bonnes choses du C. En l'occurrence, nous définissons et initialisons une variable numérique "ligne" qui tiendra le décompte de la longueur de la ligne.

Ensuite, l'option case-insensitive indique à Flex qu'il doit générer un scanner qui ne tienne pas compte des différences majuscule/minuscule. L'option 8 bits indique qu'il doit également pouvoir travailler sur les caractères supérieurs à 127, car c'est là que se trouvent les lettres accentuées. Il existe d'autres options, mais seules ces deux-là nous sont utiles ici.

Les déclarations Flex qui suivent, définissent ALL, qui est n'importe quel caractère sauf ">", MOT, qui consiste en tout ce qui peut constituer un mot, et ESPACE, tout ce qui peut être un espace.

Dans la seconde partie, les règles de la transformation en texte sont données. Tout d'abord, il faut bien voir que les espaces et les retours à la ligne ne sont pas toujours pertinents en HTML. Aussi, notre programme doit pouvoir les interpréter correctement. C'est pourquoi nous gérerons nous-mêmes le formatage du texte. Ainsi, un "", qui est le caractère "retour à la ligne" est transformé en espace, un "<BR>" est transformé en retour à la ligne, de même que le "<P>". un "<HR>" donne un trait horizontal (soumis ici à la dure réalité de l'ASCII). un "<LI>" qui est dédié aux énumérations diverses est transformé en "1", qui est censé transmettre au lecteur le sentiment profond que ce qui suit est une énumération. Il ne vous sera pas difficile, j'imagine, de trouver une représentation ASCII plus pertinente. Les espaces multiples sont transformés en un seul espace dans le fichier texte.

Chaque mot est ensuite traité séparément. Il s'agit de voir s'il tient dans la ligne. Si c'est le cas, nous l'imprimons sans rien changer, sinon il faut d'abord revenir à la ligne. C'est là qu'intervient la variable "ligne", qui tient le décompte du nombre de caractères déjà posés sur la ligne courante. La variable yytext, qui est fournie par Flex, est primordiale ici, puisqu'elle contient toujours le texte qui correspond à la règle. Elle n'est pas toujours utilisée dans nos règles, mais elle est toujours accessible. Grâce à elle, nous pouvons déterminer la longueur du texte, avec la fonction strlen().

La dernière règle, quant à elle, "oublie" purement et simplement tout ce qui peut avoir la forme d'une commande HTML, et que nous ne traitons pas dans les règles précédentes. C'est pourquoi aucune action n'est effectuée entre crochets.

Comme pour l'exemple précédent, compilez alors le programme par un "flex -i htmlconv.i", puis "gcc lex.yy.c -lfl -o htmlconv" et vous possédez un nouveau convertisseur HTML (rajoutez tout de même main() et yywrap() si vous utilisez un autre compilateur que GCC). Le programme donné est évidemment très simpliste, pour des raisons évidentes de compacité, mais rien n'est plus simple que d'augmenter le nombre de commandes reconnues et correctement transformées, de gérer les indentations imbriquées, de mettre des couleurs ANSI, etc.

Nous avons donc pu voir que Flex est un générateur de scanner très performant, qui permet au débutant de faire de petits programmes de conversion très efficaces, et qui fournit au programmeur averti un analyseur lexical apte à beaucoup de choses (analyse d'un fichier de configuration, "tokenisation" d'un langage, etc.). C'est finalement beaucoup de temps de développement épargné. Flex, GCC et plein de bonnes choses sont disponibles sur le CD ADE et Aminet.


[Retour en haut] / [Retour aux articles]