Table des matières
Automate reconnaissant une expression
Présentation
Il est fréquent que l'on doive reconnaître dans un texte la présence d'expressions respectant un certain modèle. Le cas typique est la reconnaissance d'une adresse mail : On voudrait reconnaître quelque chose comme :
[des lettres, chiffres et points]@[au moins 3 lettres].[2 ou 3 lettres].
C'est le domaine des expressions régulières. L'expression régulière correspondant à ce qui est écrit au dessus serait :
[A-Za-z0-9.]+@[A-Za-z]{3,}.[A-Za-z]{2,3}
Notre but ici sera de produire un programme capable de reconnaître si une chaîne de caractère respecte une expression régulière très simple.
Exemple
soit l'expression "(aa*|b)c".
asignifie : exactement unaa*signifie : un nombre quelconque deaaa*signifie : unasuivi d'un nombre quelconque deabsignifie : exactement unbaa*|bsignifie : soit unasuivi d'un nombre quelconque dea, soit exactement unb"(aa*|b)c"signifie : (soit unasuivi d'un nombre quelconque dea, soit exactement unb) le tout suivi d'exactement unc.
Voici quelques exemples qui valident l'expression ou non :
"aaaaaaaaac"→ oui"aaaaaaaaa"→ non"c"→ non"ac"→ oui"bc"→ oui"aaabc"→ non"acc"→ non"bbc"→ non
Utilisation d'un graphe
Pour modéliser l'expression, on réalise un automate qui a la forme d'un graphe. Voici le graphe pour le cas précédent.
Règles de fonctionnement
Le graphe étant défini, on se demande si une certaine chaîne est valide. Par exemple "aac" est-elle valide (la réponse devrait être oui).
- Au démarrage, on active le nœud initial,
- on active tous les nœuds qui peuvent être atteints depuis une un nœud actif par des arêtes sans étiquette,
- s'il reste un caractère à lire dans la chaîne à tester, on le lit. soit
carse caractère.- On note tous le nœuds pouvant être atteints depuis un nœud actif, par une arête dont l'étiquette est
car. - On désactive tous les nœuds, puis on active tous ceux que l'on vient de noter.
- On retourne au point 2.
- sinon, c'est terminé. Si le nœud final est actif, alors la chaîne testée est valide.
- À n'importe quel moment, s'il n'y a plus aucun nœud actif, on peut s'arrêter, la chaîne n'est pas valide.
Exemple de mis en œuvre
Test de la chaîne "aac".
- A : activation nœud initial,
- B : activation des nœuds pouvant être atteints par des arêtes sans étiquette (gratuitement)
- C : lecture du premier
a, on note le(s) nœud(s) pouvant être atteint(s) par une arête étiquetéea, - D : désactivation de tout, activation des nœuds marqués,
- E : activation des nœuds pouvant être atteints gratuitement
- F : lecture du second
a, on note le(s) nœud(s) pouvant être atteint(s), - G : désactivation de tout, activation des nœuds marqués,
- H : activation des nœuds pouvant être atteints gratuitement
- I : lecture de
c, on note le(s) nœud(s) pouvant être atteint(s), - J : désactivation de tout, activation des nœuds marqués,
- On activera ensuite les nœuds pouvant être atteints gratuitement (ce qui ne changera rien) puis comme il n'y a plus de caractère à lire, on s'arrêtera là.
Le nœud final étant actif, on conclut que"aac"valide l'expression régulière dont le graphe est une représentation.
De l'expression régulière au graphe
On se demande ici comment on peut obtenir le graphe.
La méthode consiste à créer des graphes élémentaires puis à les assemble pour des expressions plus complexe.
Simple lettre
Alternative, OU
On a deux expressions "exp1" et exp2" représentée par les graphes G1 (en bleu) et G2 (en violet).
On souhaite obtenir le graphe représentant le choix exp1 OU exp2, que l'on notera "exp1|exp2".
J'ai marqué en pointillé les nœuds initiaux et finaux de G1 et G2 qui cessent de l'être une fois intégrés dans le graphe complet.
Étoile
On a une expression "exp" associée à son graphe g. On souhaite obtenir le graphe représentant la répétition indéterminée de "exp" ce que l'on notera "exp*".
Concaténation
On a deux expressions "exp1" et exp2" représentée par les graphes G1 (en bleu) et G2 (en violet).
On souhaite obtenir le graphe représentant la suite exp1 exp2 que l'on notera simplement "exp1exp2".
Pour vous entraîner, vous pouvez essayer d'appliquer ces règles pour retrouver le graphe de "(a*|b)c". Sachez cependant que l'application de ces règles de constructions peut conduire à ajouter des nœuds qui pourraient être supprimés. J'en ai supprimé pour alléger le graphe que j'ai donné en exemple. Vous n'obtiendrez donc pas exactement le même, mais ce sera tout comme.
Votre travail
- Définir une classe de graphe permettant de construire à la main le graphe désiré et d'exécuter les règles de fonctionnement décrites plus haut afin de tester si telle chaîne de caractère est validée par le graphe.
- Construire le graphe automatiquement à partir d'une expression régulière simple ne contenant que des symboles (par exemple des lettres), le symbole pour l'alternative
|et le symbole étoile*, en utilisant les règles de construction ci-dessus.







