Obligement - L'Amiga au maximum

Mardi 23 avril 2024 - 17:55  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

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

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des 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,
ALL


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


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


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 standard.

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]