cursus.

Cours 2 · Langages réguliersLeçon 3 sur 4

Expressions régulières

5 h de lecture9 sections Version PDF

À la fin de cette leçon, vous saurez

Syntaxe et sémantique ; théorème de Kleene, expressions régulières ↔ automates finis ; construction de Thompson et élimination d'états.

Vous connaissez déjà les expressions régulières sans le savoir : c'est la syntaxe \d{2}/\d{2} qui valide une date dans un formulaire, [a-z]+@[a-z]+\.[a-z]+ qui filtre une adresse de courriel, le motif tapé dans la recherche d'un éditeur de texte. Ce chapitre montre ce qu'elles sont vraiment — une troisième façon de décrire un langage régulier, purement textuelle — et révèle le résultat qui unifie tout le bloc II : le théorème de Kleene, qui affirme qu'expressions régulières et automates finis décrivent exactement les mêmes langages.

Trois descriptions, un seul monde. C'est l'un des plus beaux résultats du cours, et le plus utile en pratique.

Syntaxe : trois opérations et rien d'autre

Une expression régulière sur un alphabet Σ\Sigma se construit inductivement (chapitre 2), à partir de briques élémentaires et de trois opérations. Les briques :

  • \emptyset dénote le langage vide ;
  • ε\varepsilon dénote le langage {ε}\{\varepsilon\} ;
  • une lettre aΣa \in \Sigma dénote {a}\{a\}.

Les opérations, appliquées à des expressions déjà construites :

ÉcritureNomPriorité
EFE \mid Funion (alternative)la plus faible
EFE \cdot F ou EFEFconcaténationintermédiaire
EE^*étoile de Kleenela plus forte

La priorité se lit comme en arithmétique : l'étoile est le « puissance », la concaténation le « produit », l'union la « somme ». Ainsi abcab^* \mid c se lit (a(b))c\big(a(b^*)\big) \mid c, et les parenthèses servent à forcer un autre regroupement, comme dans (ab)(a \mid b)^*.

Ce sont exactement les trois opérations sur les langages du chapitre 1. Une expression régulière n'est rien d'autre qu'une notation compacte pour les combiner — pas un mécanisme nouveau.

Sémantique : le langage dénoté

À chaque expression EE correspond un langage L(E)L(E), défini en suivant sa construction :

L(a)={a},L(EF)=L(E)L(F),L(EF)=L(E)L(F),L(E)=L(E).L(a) = \{a\}, \quad L(E \mid F) = L(E) \cup L(F), \quad L(E \cdot F) = L(E) \cdot L(F), \quad L(E^*) = L(E)^*.

Lisons quelques exemples sur Σ={a,b}\Sigma = \{a, b\} — cette lecture est le savoir-faire du chapitre :

  • abab dénote {ab}\{ab\} — un seul mot ;
  • aba \mid b dénote {a,b}\{a, b\} — « aa ou bb » ;
  • aa^* dénote {ε,a,aa,aaa,}\{\varepsilon, a, aa, aaa, \dots\} — noter que ε\varepsilon en fait partie ;
  • (ab)(a \mid b)^* dénote tous les mots sur {a,b}\{a, b\}, c'est-à-dire Σ\Sigma^* ;
  • (ab)ab(a \mid b)^* ab dénote « tous les mots qui se terminent par abab » — le langage même des chapitres 3 et 4, décrit ici en cinq symboles.

Ce dernier exemple mérite qu'on s'y arrête : ce que l'AFD du chapitre 3 exprimait par trois états et six transitions tient en une courte expression. C'est la force de la notation — mais rappelez-vous qu'elle décrit exactement le même langage, ni plus ni moins.

Deux pièges classiques, tous deux liés au chapitre 1 :

  • L'étoile inclut toujours le mot vide. L(E)L(E^*) contient ε\varepsilon même si εL(E)\varepsilon \notin L(E) — la concaténation de « zéro copie ». Oublier ce cas fausse la moitié des exercices.
  • \emptyset et ε\varepsilon ne sont pas la même chose. ={ε}\emptyset^* = \{\varepsilon\}, tandis que \emptyset tout court dénote le langage vide. C'est la distinction du chapitre 1, qui revient à l'identique.
Quiz · vérifiez votre compréhension Sans réponse

Que dénote l'expression régulière (a|b)*a sur Σ = {a, b} ?

Le théorème de Kleene

Voici le résultat qui referme le bloc et justifie tout ce qui précède :

Théorème de Kleene. Un langage est décrit par une expression régulière si et seulement si il est reconnu par un automate fini.

Les trois descriptions — AFD, AFN, expression régulière — sont donc équivalentes : elles définissent une seule et même classe, les langages réguliers. C'est pourquoi on peut passer librement de l'une à l'autre selon ce qui est commode : écrire une expression régulière (concis), la transformer en automate pour l'exécuter efficacement (rapide), raisonner sur l'automate pour prouver une propriété.

La preuve se fait dans les deux sens, et chaque sens est une construction algorithmique — pas seulement une existence. C'est ce qui la rend utile : elle donne les recettes qu'emploient les outils réels.

D'une expression à un automate : Thompson

Le sens « expression → automate » emploie la construction de Thompson. Elle procède inductivement, exactement selon la structure de l'expression, en assemblant de petits AFN avec des ε-transitions (chapitre 4) — dont c'est ici l'usage principal :

  • une lettre aa : deux états reliés par une flèche aa ;
  • une union EFE \mid F : un nouvel état initial pointe par ε\varepsilon vers les automates de EE et de FF (les deux branches de l'alternative) ;
  • une concaténation EFE \cdot F : la sortie de l'automate de EE est branchée par ε\varepsilon sur l'entrée de celui de FF ;
  • une étoile EE^* : on ajoute des ε-transitions pour pouvoir répéter l'automate de EE ou le sauter (le cas « zéro copie »).

Le résultat est un AFN avec ε-transitions, qu'on rend déterministe par la construction du chapitre 4 si l'on veut l'exécuter. C'est très exactement la chaîne qu'un moteur d'expressions régulières parcourt en interne.

D'un automate à une expression : élimination d'états

Le sens inverse, « automate → expression », emploie l'élimination d'états. On retire les états un par un ; à chaque retrait, on reporte l'information perdue sur les transitions restantes, en les étiquetant non plus par des lettres mais par des expressions régulières. À la fin, il ne reste qu'une transition de l'entrée à la sortie, étiquetée par l'expression régulière cherchée.

Vous n'avez pas à mémoriser les détails de ces deux constructions en L2 ; vous devez retenir qu'elles existent, qu'elles sont effectives (on peut les programmer), et qu'ensemble elles prouvent le théorème de Kleene par double construction.

Quiz · vérifiez votre compréhension Sans réponse

Un ingénieur écrit une expression régulière pour valider un format de saisie, puis a besoin de la vérifier des millions de fois par seconde sur un flux. Que permet le théorème de Kleene dans ce contexte ?

À vous

L'exercice donne aux expressions régulières leur sens en code. Vous implémentez la sémantique — chaque opérateur (union, concaténation, étoile) est l'opération correspondante sur les langages du chapitre 1 — puis vous calculez le langage de (ab)ab(a \mid b)^* ab et vérifiez quels mots il contient.

L'étoile vous forcera à traiter le cas « zéro copie » : oublier le mot vide initial rend l'opération fausse. Et vous devrez borner par une longueur, parce que le langage est infini — une petite expression décrit un langage sans fin, tout comme un automate avec ses boucles. C'est là, concrètement, le théorème de Kleene.

Exercice · JavaScript · à vous de jouer

Implémentez la sémantique d'une expression régulière : chaque opérateur (union, concaténation, étoile) est une opération sur les langages du chapitre 1. Calculez le langage de (a|b)*ab et vérifiez quels mots il contient — l'étoile vous rappellera le piège du « zéro copie ».

En attente
// Une expression régulière décrit un LANGAGE. Ici on la représente par un
// arbre, et on calcule le langage qu'elle dénote — jusqu'à une longueur max,
// car l'étoile produit un ensemble infini.
//
// Opérateurs (rappel chapitre 1) :
//   lettre  -> { "a" }              vide -> {}          epsilon -> { "" }
//   union(E,F)  = L(E) ∪ L(F)
//   concat(E,F) = L(E) · L(F)   (tous les u·v, u∈L(E), v∈L(F))
//   etoile(E)   = L(E)*         (zéro, un ou plusieurs mots de L(E))

// Constructeurs d'arbre :
const lettre = (c) => ({ type: "lettre", c });
const epsilon = { type: "epsilon" };
const vide = { type: "vide" };
const union  = (g, d) => ({ type: "union", g, d });
const concat = (g, d) => ({ type: "concat", g, d });
const etoile = (e) => ({ type: "etoile", e });

// ── À VOUS : la sémantique ──────────────────────────────────────────────────
// langage(expr, max) rend l'ENSEMBLE (Set) des mots de longueur <= max décrits
// par expr.
function langage(expr, max) {
  switch (expr.type) {
    case "vide":    return new Set();          // aucun mot
    case "epsilon": return new Set([""]);      // le seul mot vide
    case "lettre":  return new Set([expr.c]);  // un seul mot d'une lettre
    case "union": {
      // à compléter : réunir les deux langages
      return new Set();
    }
    case "concat": {
      // à compléter : tous les u+v (u du gauche, v du droit), longueur <= max
      return new Set();
    }
    case "etoile": {
      // à compléter : ε, puis L, puis L·L, ... tant que la longueur <= max
      return new Set();
    }
  }
}

// ── L'expression (a|b)*ab  :  « se termine par ab » ─────────────────────────
const expr = concat(etoile(union(lettre("a"), lettre("b"))), concat(lettre("a"), lettre("b")));

const mots = [...langage(expr, 3)].sort((x, y) => x.length - y.length || x.localeCompare(y));
console.log("(a|b)*ab, mots de longueur <= 3 :");
console.log("  [" + mots.join(", ") + "]");
console.log("  ab present ?", mots.includes("ab"));   // attendu true
console.log("  aab present ?", mots.includes("aab")); // attendu true
console.log("  ba present ?", mots.includes("ba"));   // attendu false

Console de sortie
Le résultat s'affiche dans la console

Ce que la suite en fait

Le bloc II tient debout : trois descriptions équivalentes des langages réguliers, reliées par des constructions effectives. Une question reste ouverte, et c'est la plus importante — tous les langages sont-ils réguliers ?

Le chapitre 6 y répond, et la réponse est non. Il donne d'abord l'outil pour ranger un automate (la minimisation), recense ce que la classe régulière sait faire (les propriétés de clôture), puis l'outil qui prouve qu'un langage échappe aux automates : le lemme de pompage, second point qui coince de l'année, avec son exemple canonique anbna^n b^n — celui-là même que l'exercice du chapitre 1 avait déjà mis de côté.

À retenir

Flashcards · 1 / 4Toucher pour retourner

Exercices d'entraînement

Exercice 1 · cherchez avant de lire la correction

Écrire des expressions régulières

Sur Σ={a,b}\Sigma = \{a, b\}, donner une expression régulière pour chacun de ces langages :

  1. les mots contenant au moins un a ;
  2. les mots de longueur paire ;
  3. les mots ne contenant pas le facteur aa.
Exercice 2 · cherchez avant de lire la correction

Décrire un langage

Décrire en français le langage dénoté par chacune de ces expressions, sur Σ={a,b}\Sigma = \{a, b\} :

  1. aba^* b^* ;
  2. (ab)(ab)^* ;
  3. (ab)aa(ab)(a \mid b)^* \, aa \, (a \mid b)^*.
Exercice 3 · cherchez avant de lire la correction

Du théorème de Kleene

Donner une expression régulière décrivant le langage reconnu par l'AFD « mots se terminant par a » (croisé au chapitre 3). Que garantit le théorème de Kleene à propos d'une telle conversion ?

Fin de la leçon

Vous avez parcouru les 9 sections.

Marquez-la terminée pour faire avancer votre parcours, ou revenez sur un point avant de passer à la suite.