X = {a, b} - BigBozoid

publicité
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Langages formels
Projet de cours
Idées en vrac à organiser :
Minimisation d’un automate
Algo de reconnaissance : automate à pile.
Exos : mots du Grand Dyck ; palindromes ; etc…union de tel et tel ;
intersection pas toujours algébrique. Grammaires régulières pour les
expressions rationnelles déjà vues. Passer du dessin d'un automate à sa
spécification abstraite et vice versa.
M.M. Département Informatique
Décembre 2000
1
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Plan
1.
2.
3.
4.
5.
Langages
Systèmes de réécriture
Langages rationnels
Langages reconnaissables
Langages algébriques
Introduction
La notion de langage formel est à distinguer (entre autres) de celle de
langage de programmation, même s’il existe des liens entre un
langage formel et un langage de programmation : les mots d’un
langage formel seront étudiés indépendamment de toute sémantique.
On se préoccupe seulement de questions syntaxiques.
On peut rattacher la théorie d’abord aux travaux du mathématicien
américain Stephen Cole Kleene dont les préoccupations étaient
avant tout orientées vers les fondements des mathématiques (à
rapprocher de Gödel, Turing, Church) ; à l’occasion de certains de ses
travaux, il est amené au milieu des années 50 (1956) à définir une
classse de langages formels, les langages dits réguliers ou langages
de Kleene, ou encore langages rationnels.
Quelques années plus tard, le linguiste américain Noam Chomsky
(qui avait fait aussi des études de mathématiques et de philosophie),
s’interroge sur les mécanismes qui permettent la production du
langage (quelques règles apprises en très peu d’années  nb. infini de
phrases syntaxiquement correctes) et sa reconnaissance (un enfant se
rend très vite compte si une phrase qu’il entend est ou non une phrase
de sa langue, i.e. syntaxiquement correcte) ; à partir de ces réflexions,
il travaille sur la (très vieille) notion de grammaire, apportant des
définitions nouvelles, très précises, qui lui permettent de proposer des
théorèmes et une classification : parmi les grammaires, les
grammaires algébriques.
Mais si la théorie provient de divers horizons, son succès vient de sa
grande fécondité dans plusieurs domaines essentiels de l’informatique,
au premier rang desquels la compilation.
M.M. Département Informatique
Décembre 2000
2
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
1. Langages
1.1. Définitions et notations
Définition 1 : on appelle alphabet un ensemble fini non vide. Les
éléments d’un alphabet sont appelés lettres.
Remarque : la notion d’ensemble donne un contenu précis (définition,
propriétés, opérations possibles, etc…) aux notions communes
d’alphabet et de lettre. Mais le fait de nommer alphabet un ensemble
fini quelconque ne le munit évidemment d’aucune structure
particulière, et ne le distingue en rien du même ensemble que l’on
n’aurait pas ainsi baptisé.
Exemples :
X1 = { 2, 4, 8, 16, 24, 48}
X2 = {a, b, c, d, e, f}
X3 = {‘0‘, ‘1‘,‘2‘,‘3‘}
Sont des alphabets.
Définition 2 : soit n un entier naturel ; un mot f de longueur n sur un
alphabet X est une application de {1, 2, … n} dans X.
La longueur n du mot f se note |f|.
Exemples : f = (16, 16, 4, 2) et g = (4, 8, 48, 2, 4, 24) sont des mots
sur X1. On a |f| = 4 et |g| = 6
De même u = (a,a,a,d,a,f,a,d,a) est un mot sur X2.
L’application de  dans X est appelée le mot vide ; ce mot, de
longueur nulle, est noté  ou 1X.
Notation : lorsqu’il n’y a pas d’ambiguïté, on note un mot f sous la
forme
f(1) f(2) f(3) … f(n) plutôt que (f(1), f(2), … f(n))
Exemples : abba est un mot sur X2.
Mais 248 n’est pas un mot sur X1 : (2, 4, 8) ? (2, 48) ? (24, 8) ?
M.M. Département Informatique
Décembre 2000
3
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Par ailleurs, la notation d’un mot par juxtaposition des lettres conduit
à ne pas distinguer le mot f de longueur 1 et la lettre f(1) : sauf en de
rares cas, il est inutile d’alourdir les explications en distinguant
systématiquement le mot a de la lettre a !
Notation : le nombre d’occurrences de la lettre x dans le mot f se note
|f|x.
Cette notion est suffisamment claire ; notons cependant que
formellement, le nombre d’occurrences de x dans f est le cardinal de
l’image réciproque de {x} : Card f-1 {x}
Notation : l’ensemble de tous les mots sur un alphabet X est noté X*.
Remarque : cet ensemble est infini.
Exercice : montrer que X* est dénombrable.
Réponse : on peut le faire en s’inspirant de la méthode de Gödel pour
les listes : X est fini, on peut donc numéroter ses éléments ; par
exemple X = {a, b, c}  n(a) = 1, n(b) = 2, n(c)=3
Ensuite, un mot f sur X étant donné, on considère les |f| premiers
nombres premiers, que l’on note p(1) (=2) , p(2), etc…
On forme alors le nombre  (f) =
f
 p(i)
n(f(i))
i1
Exemple : f = acbaacb
(f) = 21x32x53x71x111x133x172
= 110002142250
Par l’unicité de la décomposition en facteurs premiers,
(f) = (f’)  f = f’ et est injective ; les mots de X* ne sont pas plus
nombreux que les entiers naturels. Cqfd.
Exercice : quel mot de X* a pour numéro 415800
415800 = 23x33x52x71x111
M.M. Département Informatique
Décembre 2000
4
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
donc c c b a a
Même question avec numéro 30 ? c’est a a a
Et numéro 15 ? aucun : 3 x 5 et il n’y a pas eu 2.
Définition 3 : On définit sur X* une loi de composition interne notée .
ou <vide>, appelée produit de concaténation :
X* x X*  X*
(f, g)
 fg, avec
fg (i) = f(i) i  {1, 2, … |f|}
fg (i) = g(i-|f|) i  {|f|+1, … |f|+|g|}
Exemple :
Avec l’alphabet X2 ci-dessus prenons
u = ac, v = dc
u v = acdc
Propriétés du produit de concaténation :
Il est clair que cette loi est associative :
u (v w) = (u v) w
D’autre part elle admet le mot vide pour élément neutre :
 x  X*, x = x = x
Ces propriétés sont très intuitives : il suffit de considérer des suites de
lettres. Mais il est possible de les vérifier de façon plus formelle à
partir des définitions : ce peut être un excellent exercice…
Remarque très importante : les deux propriétés ci-dessus font de
l’ensemble X* muni du produit de concaténation un monoïde. On
désigne souvent X* par l’expression « le monoïde libre ».
Dans cette expression, l’adjectif libre signifie que les éléments de X
ne sont liés entre eux par aucune relation.
On remarque enfin que le produit de concaténation n’est pas en
général commutatif.
u = ac, v = dc
u. v = acdc  v. u = dcac
M.M. Département Informatique
Décembre 2000
5
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Remarques : (1) on dit souvent plus simplement concaténation, parfois
même produit lorsqu’aucune confusion n’est à craindre. Les
remarques suivantes sont à rapprocher du caractère multiplicatif de
cette loi.
(2) on note souvent exponentiellement une séquence d’occurrences
consécutives d’une même lettre :
a3b2a4
plutôt que aaabbaaaa
(clairement a0 = = b 0 etc …)
Enfin, on parle de facteur : les mots u, v et w sont facteurs du mot
f = uvw .
Exercice : donnez tous les facteurs du mot aababa
Réponse : , a, b, aa, ab, ba, aab, aba, bab, aaba, abab, baba, aabab,
ababa, aababa.
Définition 4 : pour tout mot f sur un alphabet X, on appelle image
~
miroir de f le mot noté f et tel que : i  {1,2 … |f|}, f (i) = f(|f|i+1)
~
Exemple si f = aaabba alors f = abbaaa
~
Définition 5 : Un langage (formel) est une partie de
X*
Exemples :
X = {a, b}
L1  X* = { f  X* / |f|a = |f|b}
L2 = {ubu / u  X*} mots symétriques autour d’un b
L3 = 
L4 = {}
Exercice : donner des exemples de mots de chacun de ces langages.
M.M. Département Informatique
Décembre 2000
6
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
1.2. Opérations sur les langages
On retrouve très naturellement les opérations ensemblistes classiques
(justifiées par la définition d’un langage comme un ensemble de mots,
plus précisément une partie de X*) :
, , C L1 L2 (noté L1 \ L2 ou L1 - L2). Le complémentaire de L par
rapport à X* est noté L
On a aussi L1 L2 : concaténation de deux langages, opération induite
par la concaténation des mots :
L1 L2 = {f  X* / (u,v)  L1 x L2 /f = uv}
De la même façon, ~L = {~f/ f  L}
Une opération très importante est appelée l’étoile d’une partie :
Définition 6 : A toute partie A d’un langage L on associe
A* = {} A  AA  AAA…
A
n
Soit encore
n0
Remarque : en identifiant les éléments de X et les mots de longueur 1
sur X, l’ensemble des mots sur X est bien X*.
Enfin, on note A+ l’étoile propre d’une partie A :
A+ = A.A* = A*.A
Exercice : soit X = {a, b}, L1, L2, L3 comme ci-dessus.
Expliciter L1.L2, L1.L3, L4.L1, L1*, L2*, L3*, L4*, L1  L2, L1 
L3, L1  L4, L1  L2, etc…
On remarque ici ~L1 = L1, ~L2 = L2, ~L3 = L3, ~L4 = L4. Est-ce
toujours le cas ?
Non ! L = {anbn / n  N} alors ~L = { bn an / n  N}
L  ~L = {}
On étudiera en TD certaines propriétés des opérations sur les
langages.
M.M. Département Informatique
Décembre 2000
7
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
2. Systèmes de réécriture.
Avant d’aller plus loin, il peut être intéressant de faire quelques
2.1. Rappels et compléments sur les relations :
Notation :
Soit R une relation sur un ensemble E
Pour tout couple (x,y) de E², et pour tout entier k > 0, on note
x Rk y  x R o R k-1 y
et x R 0 y  x = y
Autrement dit x Rk y signifie x R o R o R . . (k fois). . o R y
Définition 7.a :
Soit R une relation sur un ensemble E.
On appelle clôture transitive de R et on note R + la
relation définie sur E par
(x,y)  E², x R + y   k  N* / x R k y
DIAPO 32
Propriété :
Pour toute relation R, R + est la relation transitive dont le graphe est
le plus petit incluant celui de R.
1) G R  G R+
2)  T transitive sur E, G R  G T  G R +  G T
Cette propriété découle directement de la construction : on se contente
de « rajouter » au graphe de R les couples qui manquaient pour
assurer la transitivité.
Exemple :
A = { 1, 2, 3}
GR = {(1,1), (1,2),(2,1), (2,2), (2,3)}
GR+ = {(1,1),(1,2) (1, 3), (2,1), (2,2), (2,3)}
M.M. Département Informatique
Décembre 2000
8
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Définition 7.b : si R est une relation sur un ensemble E, on appelle
clôture transitive et réflexive R la relation notée R* et définie
comme suit :
 (x,y)  E², x R*y  x R+ y  x = y
On a donc G R* = G R+   A
2.2. Définition d’un système de réécriture
Définition 7.c : on appelle système semi-thuéien une partie finie de
X* x X*.
Définition 7 : à tout système semi-thuéien T on associe une relation
de réécriture sur X*, notée  ; pour tous mots f, g de X*, on dit que
T
le mot f se réécrit en le mot g selon T et on note f  g ssi  u, v, x, y
T
 X* tq. f = u x v  g = u y v  (x, y)  T
Langage engendré (définition 7bis) : à toute partie A de X*, à tout
système T (sur X*) on associe le langage
L(A, T) = {f  X* /  a  A tq a *T f}
Autrement dit, le langage L(A,T) est l’ensemble des mots f en lesquels
se réécrivent les éléments de A selon*T, fermeture réflexive et
transitive de la relation de réécriture  associée au système T
T
Exemple : X = {a, b}, A = {ab, ba}
T = {(ab, aabb), (ba, bba)}
L(A,T) = {anbn /n>0}  {bna/ n>0}
Exercice : X = {a, b, c}, A = {abc}, T = {(ab, ba), (ac, ca), (bc, cb)}
Les mots suivants sont-ils éléments de L(A,T) ? si oui, expliciter *T,
c’est à dire écrire les différentes étapes de la réécriture (en utilisant
seulement  .
T
cba, bac, cbabac
Comme on peut intuitivement le deviner, un système de réécriture est
un moyen très pratique pour « produire » des mots, en revanche, il
M.M. Département Informatique
Décembre 2000
9
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
n’est pas très facile à utiliser pour valider l’appartenance d’un mot à
un langage. Plus précisément, soit X un alphabet, A une partie de X*,
T une relation de réécriture sur X*, et u un mot de X*, on appelle
problème du mot la question de savoir si u  L(A,T). Nous
admettrons le résultat suivant (très technique) :
Proposition 1 : le problème du mot est indécidable.
Ceci signifie exactement qu’il ne peut exister d’algorithme (se
terminant toujours en un temps fini) permettant de résoudre le
problème du mot. Attention, il ne s’agit pas d’une absence historique
(« on n’a pas encore trouvé d’algorithme… ») mais d’une
impossibilité théorique (liée à l’indécidabilité du problème de l’arrêt
d’un algorithme, lui-même prouvé par Alan Turing selon une méthode
qui imite l’argument diagonal de Cantor). Ceci est très « fâcheux » :
pour simplifier la question, comment le compilateur g++ va-t-il
pouvoir décider si le programme que vous lui soumettez est un mot du
langage formel que constitue l’ensemble des programmes C++ ?
« Heureusement », si le problème du mot est indécidable en général, il
existe des systèmes possédant des propriétés particulières qui
permettent de décider. Ce sont évidemment ces cas particuliers qui
vont retenir maintenant notre attention.
3. Langages rationnels
Définition 8.a : l’expression d’un langage L sur X selon une
décomposition finie d’unions, produits et étoiles de parties finies
de X* s’appelle une expression rationnelle de L.
Définition 8 : un langage L sur X est dit rationnel ssi il possède une
expression rationnelle.
Remarque 1 : il résulte des définitions qu’un langage rationnel est un
langage formé à partir des lettres de X (en fait mots de longueur 1)
au moyen d’un nombre fini d’applications des opérations d’union,
produit, et étoile.
Remarque 2 : on dit aussi expression régulière, d’où langage régulier
(on verra plus loin un prolongement) et parfois langage de Kleene.
M.M. Département Informatique
Décembre 2000
10
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Exemple : X = {a, b}
L = {a}*  {b}* {abab,a}
est une expression rationnelle de L qui est donc un langage rationnel.
On simplifie l’écriture en identifiant un langage composé d’un seul
mot et ce mot lui-même ; de plus, on note + pour l’union :
L = a* + b*(abab+a)
Exercice : donnez tous les mots de L de longueur < 7
Autre exemple :
X = {0, 1}
L = 0 + 1.X*
Exercices :
1. Expliciter L (écriture binaire des entiers naturels).
2. Montrer que l’ensemble des identificateurs du langage C forme un
langage rationnel ; rappel : un identificateur C commence par un
caractère alphabétique, suivi d’une séquence éventuellement vide de
caractères alphanumériques ; les lettres majuscules et minuscules sont
distinguées ; _ est considéré comme alphabétique.
Réponse : X = {A .. Z}  {a .. z}  {0 .. 9}  {_}
IdentC = (X – {0..9})+ . X*
Ou encore (plus joli) :
L = {A, B, .. Z, a, b, .. z}
C = {0, 1, ..9}
IdentC = (L + _).(L + C + _ )*
IdentC est rationnel puisqu’il s’exprime selon etc…
On note Rat(X*) l’ensemble des parties rationnelles de X*.
Remarque : il résulte des définitions que tout langage fini est
rationnel.
On va se servir d’une nouvelle notion :
Définition : soit E un ensemble muni d’une loi de composition interne
© . On dit qu’une partie A de E est fermée par © ssi
 (x, y)  A² , x © y  A.
M.M. Département Informatique
Décembre 2000
11
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Exemples : N  R est fermé par addition, produit, pas par division ni
soustraction.
Autrement dit, © est une l.c.i. dans A.
Propriétés de Rat(X*) :
La famille des langages rationnels est fermée par , produit et * : ceci
résulte des définitions.
Définition 9 : on dit qu’un mot u  X* possède un facteur itérant
dans L  X* si u = f g h, avec |g| > 0 (g n’est pas le mot vide), et fg*h
 L. Ce facteur itérant est noté (f, g, h).
Lemme 1(dit lemme de l’étoile, en anglais pumping lemma) :
Si un langage L sur un alphabet X est rationnel, alors il existe un
entier naturel non nul N tel que tout mot de L de longueur au moins
égale à N possède un facteur itérant dans L.
 u  L, |u|  N   f,g,h  X*, |g| > 0  u = fgh  fg*h  L
Preuve : si L est fini, il ne peut admettre de facteur itérant. En
revanche, il contient des mots de longueur maximale M. Ainsi
N = M+1 et le lemme est vérifié puisque l’antécédent de l’implication
est toujours faux.
si L est infini, il s’exprime en une décomposition finie d’unions,
produits et étoiles de parties finies de X*.
Notons L1, L2, … Ln ces parties.
Il est clair que L1.L2. … .Ln est une partie finie dont les mots les plus
longs ont pour longueur M1 + M2 …+ Mn.
De même Li + Lj ( Li  Lj) est une partie finie dont les mots les plus
longs ont pour longueur max{Mi, Mj}.
En revanche, Li* est clairement une partie infinie.
On ne perd donc rien en généralité à considérer une expression
simplifiée de tout langage rationnel non fini L = La.Lb*.Lc
Si un mot u de L a une longueur supérieure à Ma + Mc, c’est qu’il
comporte au-moins un facteur qui est un mot de Lb ; on a donc
u = abc, |b| > 0 puisque |u| > Ma+Mc, et ab*c  L par définition de L.
Exercice : montrer que L = {anbn/ n N} n’est pas rationnel.
Il suffit d’utiliser la contraposée du lemme de l’étoile : aucun mot de
L n’admet de facteur itérant dans L.
M.M. Département Informatique
Décembre 2000
12
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
On raisonne par l’absurde
Montrer que le langage suivant est rationnel :
Lk = {anbm/n,m N  n  m (mod k)}
Réponse : Lk = (ak)*(bk)* + (ak)*a(bk)*b + (ak)*a2 (bk)*b2…+ (ak)*ak1 k
(b )*bk-1
NB : attention, le lemme de l'étoile ici ne sert à rien (  mais pas )
4. Langages reconnaissables.
4.1. Automate fini
définition 10 : un automate fini A est la donnée < X, E, I, F,  > où :
X est un alphabet appelé ici alphabet d’entrée.
E est un ensemble fini dont les éléments sont appelés les états de A
I  E est l’ensemble des états initiaux
F  E est l’ensemble des états d’acceptation (ou états terminaux)
  E x (X  ) x E est l’ensemble des transitions de l’automate.
On représente souvent un automate par un graphe valué (au sens où
chaque arc est étiqueté par une valeur, ici une lettre de X ou ) :
< (X  ), E,  > où E représente l’ensemble des sommets du graphe,
(X  ) celui des étiquettes et  l’ensemble des arcs.
On représentera par exemple (ei, a, ej)   par le schéma suivant :
a
ei
ej
Un symbolisme de type flèche entrante (resp. sortante) suffira à
distinguer les états initiaux (resp. terminaux)
e0
M.M. Département Informatique
Décembre 2000
ef
13
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Exemple 1 :
a
b
0
1
a
On parlera d’automate fini non déterministe (AFN) parce que
1) la lecture d’une même lettre peut conduire d’un état donné à
plusieurs états différents (« au choix »). Plus précisément, on peut
avoir
(e,x,e’)   (e,x,e’’)    e’  e’’
2) il peut exister une transition d’un état e vers un état e’ sans
qu’aucune lettre ait été lue : on parle d’- transition.
3) il peut exister plusieurs états initiaux
Sur l’exemple ci-dessus, (0,a,0) et (0, a, 1) sont des éléments de .
Voici un autre exemple d’automate non déterministe :
Exemple 2 :
a
e2
b
b
e0
e1

b
e3
a
c
e4
Définition 10bis : un mot u  X* est reconnu (on dit aussi accepté)
par l’automate A ssi il existe une suite de |u| éléments de  de la
forme :
(ei0,u1,ei1),(ei1,u2,ei2), … (ei|u|-1, u|u|, ei|u|), avec ei0  I et ei|u|  F et
u=u1u2..u|u|….
Intuitivement, on peut passer dans le graphe d’un sommet initial à un
sommet terminal en « lisant » le mots sur les arcs traversés.
L’automate ci-dessus (exemple 1) reconnaît les mots :
M.M. Département Informatique
Décembre 2000
14
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
abbb, aaabb, aaaaaa, a
Donnez-en d’autres.
Définition 10ter : l’ensemble des mots reconnus par l’automate fini A
s’appelle le langage reconnu par A et se note généralement L(A).
Sur l’exemple : mots commençant par un nombre non nul de a
éventuellement suivis par des b.
{f  {a,b}*/  m N*, n  N / f = ambn}
Donnez une expression rationnelle
L’ensemble des langages reconnus par AFN est noté ND(X*)
Théorème 1 (Kleene[1]) : Rat(X*) = ND(X*)
On admettra ce résultat dont la preuve est un peu technique ; on peut
cependant remarquer :
a

a
ab

a
b
a+b 
a
b
a
a*
de même (ab)*

a
b
Définition 11 : un automate fini <X,E,I,F,> est déterministe si :
I est un singleton.
 est le graphe d’une relation fonctionnelle de E x X vers E
Remarque : dans ce cas, il est courant de spécifier l’automate par
<X,E, e0, F, > (au lieu de {e0})
M.M. Département Informatique
Décembre 2000
15
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
L’ensemble des langages reconnus est noté Rec(X*) ; ils sont appelés
langages reconnaissables.
Exemple
a
a
0
1
b
b
2
Langage reconnu ?
Le même que pour l’exemple précédent.
Méthode générale pour passer d’un automate à une expression
rationnelle : on résout un système d’équations
L0 = aL1
L1 = aL1 + bL2 + 
L2 = bL2 + 
Pour résoudre ce système, on va utiliser la propriété suivante dite
lemme d’Arden :
Pour tous A, B, C  P(X*), l’équation A = BA + C admet pour
solution A = B*.C
Preuve : de la définition de l’étoile, il découle que
B*C = B*B.C + C = B.B*.C + C.
Donc, si on substitue B*C à A, l’équation devient une proposition
vraie.
Donc ici L2 = b* (lemme)
L1 = a*b* (substitution + lemme)
L0 = a.a*b* = a+b*
Théorème 2 (Kleene[2]) : ND(X*) = Rec(X*)
Preuve : l’inclusion Rec(X*)  ND (X*) résulte des définitions.
M.M. Département Informatique
Décembre 2000
16
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
L’inclusion réciproque est prouvée par l’existence d’un algorithme de
déterminisation qui à tout AFN fait correspondre un AFD
reconnaissant le même langage. L’algorithme consiste à reprendre
l’AFN A’, à supprimer les -transitions pour obtenir A", et à
remplacer l’ensemble E" des états par P(E") ; l’ensemble I" des états
initiaux de A" devient alors l’unique état initial I de A ; enfin, on
remplace " par  :
 Q  E", (Q, x) = {e"  E" /  e  Q /. (e,x,e") "}
La suppression des -transitions se fait ainsi :
pour chaque état e :
 calculer son -fermeture, i.e. l'ensemble des états que l'on peut
atteindre à partir de lui en ne suivant que des -transitions. On a
e -fermeture(e).
 (e,x,e")  "   r  -fermeture(e) / (r, x, e")  '
 Enfin un état e appartient à F" ssi son -fermeture contient un
élément de F'.
A faire en TD : déterminiser un AFN.
On voit sur les diapos 1) AFD reconnaissant le même langage que
précédemment ; 2) AFN  suppression des -transitions
Exercice :
Montrer que les langages suivants parties de {a,b}* sont rationnels :
Lp = {f /|f|a 0 (mod 2)}
Lpi = {f / |f|a  0  |f|b  1 (mod 2)}
Lkp = {f /  k  N / |f|a = kp} p donné
Lk = {f / |f|a  |f|b (mod k)}
Il suffit de montrer qu’ils sont reconnaissables (Kleene) et donc
d’exhiber pour chacun des langages un automate fini qui le
reconnaisse (on pourrait ensuite calculer l'expression rationnelle à
partir de l'automate) :
Lp :
b
a
b
0
1
a
M.M. Département Informatique
Décembre 2000
17
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Lpi
a
p,p
i,p
a
b
b
b
b
a
p,i
i,i
a
etc…
Corollaire (Kleene) : la famille RAT(X*) est fermée par  et
différence.
La preuve repose sur la construction d’automates finis reconnaissant
L1L2 et L1 – L2 (L1, L2  RAT(X*) donc à REC(X*)).
L’intersection est facile à construire si l’on considère des automates
non déterministes.
Pour L1-L2 c’est l’automate construit à partir de A(L1), A(L2), et
donc A(X*-L2), enfin A(L1  (X*-L2))
Définition 12 : un automate fini déterministe <X,E, e0, F, > est dit
complet si  est le graphe d’une application.
En pratique on parle souvent de la fonction de transition de
l’automate.
Il est très facile et très commode de compléter un AFD A non
complet : il suffit de rajouter un état e qui n’est pas un état
d’acceptation, et pour tout état ei, s’il existe une lettre x telle que pour
tout état ej (ei, x, ej)  , on rajoute une transition (ei,x,e).
En particulier, x  X, ( e, x) = e
Un état e pour lequel , ( e, x) = e pour tout x (comme e ) est appelé
un état puits.
On peut le voir comme l’état correspondant à une situation d’erreur.
Exemple :
M.M. Département Informatique
Décembre 2000
18
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17

b
a
a
a
b
b
Le théorème suivant permet de prouver qu’un langage est
reconnaissable, ou de vérifier qu’il ne l’est pas (utile lorsque le lemme
de l’étoile ne permet pas de conclure) :
Définitions 13 : (a) soit L  X*, w  X*, w-1L = {v  X*/ wv  L}
(un langage, appelé résiduel de L par rapport à w)
(b) R(L) = {w-1L : w  X*} (un ensemble de langages)
Théorème 3 (Nérode – Myhill)
L  Rec(X*)  R(L) est fini
Preuve :
 
L = L(A), A déterministe complet. Donc, w  X*, il existe un unique
état e(w) tq e0  wA e(w)
Et w-1L = {v / e(w)  vA e’, e’ F} e’ acceptation
Donc Card(R(L))  |A| (nb. états de A)
 
Soit R(L) = {L0, L1, … Ln}
Comme L =  -1L, L  R(L), L0=L
On construit A = < X, {e0, e1…en}, , {e0}, F}
avec F = {ei /   Li, i  {0,1, … n}}
 (ei, x) = ej tq Lj = x-1 Li
On vérifie par induction sur |w| que
e0 wA ei  w-1L = Li
Donc L = L(A)
M.M. Département Informatique
Décembre 2000
19
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Langages rationnels et algorithmes de reconnaissance et de
traitement
Les langages rationnels se prêtent donc à une reconnaissance
« automatique », d’où leur intérêt en informatique. Cet intérêt se
manisfeste particulièrement dans le cas des automates déterministes,
qui se traduisent directement par des algorithmes :
M.M. Département Informatique
Décembre 2000
20
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Algorithme de reconnaissance simulant un automate :
On indique ici seulement le principe
fonction reconnu(f : chaîne de caractères) : booléen
var TableTransitions : tableau[N][M] d’états
e : état
début
e  e0
tant que il reste des lettres à lire
faire début
lire (lettre)
e  TableTransitions[e][lettre]
fin
retourner (e est un état d’acceptation)
fin
Exercice : préciser les structures de données et écrire une fonction
C++ implémentant cet algorithme dans le cas où l’alphabet est {a, b}
et langage Lp = {f /|f|a 0 (mod 2)}
Par exemple :
// automate reconnaissant le langage formé
// sur {a,b} par les mots ayant un nombre pair de a
#include <iostream.h>
#include <string>
typedef int etat ;
const int NB_ETATS = 2;
const int NB_LETTRES = 2;
// les états :
const etat e0 = 0;
const etat e1 = 1;
// la fonction de transition :
const etat delta[NB_ETATS][NB_LETTRES] = {{e1,e0}, {e0,e1}};
bool correct(string f){
etat e=e0;
int i=0; // pour parcourir le mot
char lettre; // pour lire les lettres de f
while((lettre = f[i])!='\0'){
M.M. Département Informatique
Décembre 2000
21
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
if(lettre != 'a' && lettre != 'b')return false;
e=delta[e][lettre-'a'];
i++;
}
return (e==e0);
}
int main(int argc, char** argv){
if(correct(argv[1]))
cout << "OK\n";
else
cout << "NON\n";
return 0;
}
Mais dans le cas non déterministe, deux possibilités :
1. Déterminisation de l’automate (ce qui est une opération
automatisable !)
2. méthode des essais / erreurs, (algorithme appelé backtracking ou
encore rétro-parcours)
Automates finis avec sortie :
On peut donner plusieurs définitions. En voici une assez simple :
Définition 14 : un automate fini avec sortie A est un triplet <A’, S, >
où A’ est l’automate fini (que pour simplifier on considèrera
déterministe) <X,E,e0,F,>, S un alphabet dit alphabet de sortie, et 
une application de E x X dans S*.
Remarques : XS est quelconque (pas nécessairement vide, etc…).
On peut voir  comme un traducteur : si je suis dans l’état e, et que je
lis la lettre x, alors je produis la sortie s (i.e.  (e,x)=s) et je passe dans
l’état e’(i.e. (e,x)=e’).
Exemples :
A partir d’un mot de {a, b}*, on veut produire un mot de (a + ba)*, ce
qui modélise la suppression des blancs multiples dans un texte (a
représente un signe typographique quelconque, et b un blanc) :
M.M. Département Informatique
Décembre 2000
22
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
b/
a/a
b/b
0
1
a/a
Codage / décodage
Définition 15 : soient X, Y des alphabets ; un homomorphisme
injectif de X* dans Y* est appelé un codage.
L’injectivité garantit que deux mots distincts de X* ne seront pas
codés identiquement dans Y*
Le problème du décodage consiste à trouver h-1({w}), w  Y*.
Remarque : puisque h est injective, h-1 est fonctionnelle, et h-1({w})
est soit l’ensemble vide, soit un singleton.
Définition 16 : un langage L  X* est dit préfixe ssi  f  L, u,v 
X*,
f = uv  u  L
Exemple sur X = {a,b}
L1 = {a, aab, ab, abba} n’est pas préfixe
L2 = {a, bba, bab, baab} est préfixe.
Nous admettrons le résultat suivant, fort intéressant :
Proposition 2 : soit h : X*  Y* un homomorphisme de monoïdes tel
que {h(u) / |u| = 1} est un langage préfixe, alors h est injectif et h -1 est
définissable par un automate avec sortie.
Exemple :
h: a
b
c
d




M.M. Département Informatique
Décembre 2000
01
0011
1
0001
23
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
1/b
1/
0/
1/c
0/
0/
1/a
1/d
Application : compression de fichier
Un fichier est une suite de mots binaires, par exemples d’octets (huit
chiffres binaires). On peut classer les octets selon leur fréquence et
coder les plus fréquents par les mots les plus courts : le plus fréquent =
1, ensuite 01, etc…
Exemple : « ceci est un exemple » est codé en ASCII par 19 octets.
Fréquence : e (5), spc (3), c (2), le reste : 1
Donc par exemple :) e 1 ; spc 01 ; c : 001 ; i : 0001 ; s : 00001 ; t :
000001 ; u : 0000001 ; n : 00000001 ; x : 000000001 ; m :
0000000001 ; p :00000000001 ; l : 00000000000
La phrase devient :
001 1 001 0001 01 1 00001 000001 01 0000001 00000001 01 1
000000001 1 0000000001 00000000001 0000000000 1
On vérifie aisément qu’elle est décodable sans ambiguïté, et elle
occupe un peu moins de 11 octets (au lieu de 19).
Conclusion sur les langages réguliers
Plusieurs utilisations évidentes en informatique :
 Comme on vient de le voir, compression des textes (gzip,
winzip, etc…)
 La commande Unix grep recherche dans un fichier les
occurrences de chaînes définies par expression rationnelle.
Par exemple
grep a.*e.*i.*o.*u.* toto
affiche toutes les lignes du fichier toto contenant les voyelles
M.M. Département Informatique
Décembre 2000
24
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
dans l’ordre croissant au milieu de n’importe quels autres
caractères (pour cette commande le point signifie n’importe quel
caractère, la concaténation est notée par juxtaposition sans
espace, l’étoile est l’étoile, et bien d’autres aspects encore…)
 Plus couramment, une commande comme rm accepte des
arguments de type f*a*.o (pour f.X*.a.X*.o) ce qui signifie
suppression des fichiers dont le nom commence par f, comporte
un a, et se termine par la chaîne .o ; la syntaxe est ici légèrement
différente (moins puissante en fait mais adaptée au but !) que
pour grep.
 Enfin, il faut évoquer la phase d’analyse lexicale dans la
compilation, i.e. les identificateurs, les opérateurs, etc… sont ils
bien formés ? Par ex. 3ab25 = 6 est refusé par g++, de même
a #=5. Nous reviendrons sur cette question ultérieurement.
Mais un morceau de programme C++ comme
as_long_as (x = w ; or + if = 2) ;
Complètement incohérent ne peut pas être détecté au niveau lexical.
Les « mots »  vocabulaire C++ (parenthèses, +, = , identificateurs),
mais la structure de l’énoncé, la « grammaire » n’est pas respectée.
D’où l’intérêt d’un outil plus puissant que les automates et les
langages de Kleene.
Langages algébriques
Une grammaire algébrique permet de définir un langage. On utilise
notamment les grammaires algébriques pour définir la syntaxe d’un
langage de programmation.
Définition 17 : une grammaire algébrique est la donnée de < X, V, P,
S > où :
X est un alphabet dit terminal
V (comme variables) est un alphabet dit non terminal, tel que
XV=
P, appelé ensemble des productions, est une partie finie de
Vx(XV)*, c’est-à-dire un système semi-thueien.
S est une lettre distinguée de V, appelée axiome.
M.M. Département Informatique
Décembre 2000
25
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Notation :
Les non terminaux sont généralement notés en minuscules et les NT
en majuscules.
(A, m)  P sera noté A  m
De même si (A,m), (A,n), (A,tB) sont des règles de la grammaire
considérée, on notera A  m + n + tB
Enfin, on néglige souvent de préciser l’axiome (on ne le fait
éventuellement qu’après coup), notamment lorque V est un singleton.
Exemple :
G1 = < X1, V1, P1, A>
X1 = {a,b}, V1 = {A}, P1 = {A  aAb + }
Définition 17bis : soit G = < X, V, P, A> une grammaire algébrique.
On appelle langage engendré par G l’ensemble
L(G) = {f  X* / A *P f}
Par exemple, il est facile de deviner que L(G1) (ci-dessus)
= {anbn /n  0}
Remarque : les grammaires algébriques sont aussi appelées non
contextuelles (context free) : w1 A w2 * w1 w’ w2 ; la production
ne modifie pas le contexte.
Définition 17ter : un langage est algébrique ssi il existe une
grammaire algébrique qui l’engendre.
Ainsi {anbn /n  0} est algébrique.
On note ALG(X*) la famille des langages algébriques.
Définition 18 : pour tous u, v  (X  V)*, on appelle dérivation de u
en v toute suite (u0, u1, …uk) tq u0=u, uk=v et i<k, ui  ui+1
Une telle dérivation est notée u0  u1  u2 …  uk .
L’entier k s’appelle l’ordre (ou la longueur) de la dérivation, et on
note u k v
Exemple : X = {a, b}, V = {A}, P = {A  aAbA + }
Dérivation n° 1 :
M.M. Département Informatique
Décembre 2000
26
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
A  aAbA  aAbaAbA  aaAbAbaAbA  aabAbaAbA 
aabbaAbA  aabbaAb  aabbab
Dérivation n°2 :
A  aAbA  aaAbAbA  aaAbbA  aabbA  aabbaAbA 
aabbabA  aabbab
On voit que deux dérivations distinctes peuvent engendrer le même
mot. Mais on définit sur les dérivations une relation d’équivalence, et
il existe un moyen simple de vérifier que deux dérivations sont
équivalentes ; pour cela, il faut introduire la notion d’arbre :
Définition 19.1 : si R est une relation sur un ensemble E, et si x, y
sont des éléments de E, on appelle R-chemin de x à y une suite
x = x0,x1,x2 ... xn-1,xn = y telle que
(x,x1),(x1,x2) ... (xn-2,xn-1),(xn-1, y) sont éléments de GR
Définition 19.2 : un arbre A sur un ensemble E est une relation sur E
possédant les propriétés suivantes :
(a) il existe un élément r de E tel que pour tout xr il existe un et
un seul A-chemin de r à x
(b) (r,r) n’est pas élément de A+
R est appelé racine de l’arbre ; on montre facilement que
r est unique, et que
A est acyclique (i.e. A+ est antiréflexive). De même
x  E, (x,r)  GA. et aussi
 x, y, z éléments de E, x A z  y A z  x = y.
On appelle feuille de l’arbre A un élément
x  E tq  y E/ yAx  z  E,
xAz
Enfin, il est souvent utile de considérer des arbres ordonnés.
Définition 19.3 : on dit qu’un arbre est ordonné ssi x E, l’ensemble
{y  E / xAy} est un ensemble totalement ordonné.
M.M. Département Informatique
Décembre 2000
27
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
L’utilité de cette notion est telle que souvent on dira par abus de
langage arbre à la place de arbre ordonné.
Cette utilité se comprend intuitivement lorsqu’on représente
graphiquement un arbre ; si l’arbre n’est pas ordonné, alors
a
a
=
b
c
c
b
Ce qui peut être gênant, par exemple si on remplace a par l’opérateur
de division, et que b et c représentent des réels !
Définition 19.4 : dans le cas d’un arbre ordonné, le mot formé par la
suite des feuilles parcourue de gauche à droite s’appelle frontière de
l’arbre.
Revenons aux dérivations ; à chaque dérivation, on peut associer un
arbre (ordonné) de dérivation
A
a
A
A b
a

b
A
A
A
a


b
A

On s’aperçoit que D1 et D2 donnent le même arbre. La seule
différence est en fait l’ordre dans lequel on a appliqué les règles. On
ferait apparaître cette différence sur les arbres en numérotant les
nœuds dans l’ordre de leur création. Mais la différence ne se répercute
pas sur le mot engendré, qui se lit en parcourant les feuilles de gauche
à droite. Lorsque deux dérivations produisent le même arbre, on dit
qu’elles sont équivalentes.
Il peut cependant se faire qu’un même mot soit engendré par deux
dérivations non équivalentes au sens ci-dessus :
M.M. Département Informatique
Décembre 2000
28
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Exemple :
Dans l’exemple suivant, le ou (union) est noté | car + fait partie des
symboles terminaux. Cette notation est courante de toute façon.
E  E + E | E x E | ( E ) | - E | id
Cette grammaire engendre les expressions arithmétiques, avec id
représentant un identificateur, qui peut lui-même être reconnu par un
automate fini. Par exemple :
E *id x (id+id)
Ou encore E *id x id+id
Considérons des dérivations pour cette dernière expression :
D1 : E  E x E  id x E  id x E + E  id x id + E  id x id + id
D2 : E  E + E  E + id  E x E + id  id x E + id  id x id + id
Construisons les arbres A1 et A2 correspondant :

A1
A2
E
E
E
x
E
id
E
+
id
E
E
E
id
id
x
+
E
E
id
Ces deux arbres ont même frontière, mais ils sont différents ; les deux
dérivations ne sont donc pas équivalentes. Ici par exemple, A1
pourraît s’interpréter comme id x (id + id), et A2 id x id + id.
Plus formellement :
Définition 19 : une grammaire algébrique G = < X,V,P,A> est dite
ambiguë s’il existe un mot f de (X V)* qui est la frontière de deux
arbres de dérivation distincts et de même racine.
Remarque : c’est la grammaire qui est ambiguë, non en général le
langage engendré.
Définition 19.bis : un langage algébrique est dit ambigu si toute
grammaire qui l’engendre est ambiguë.
M.M. Département Informatique
Décembre 2000
29
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
La preuve du fait qu’un langage est ambigu est très technique (il faut
prouver que toutes les grammaires le sont…). Voici néanmoins un
exemple de langage algébrique ambigu :
La = {anbnc*/ n > 0}  {a*bpcp / p>0}
Au contraire, le langage des expressions arithmétiques n’est pas
ambigu.
Exercice : trouver une grammaire non ambiguë qui engendre les
expressions arithmétiques.
Réponse :
EE+T|T
TTxF|F
F  (E) | id
Le résultat suivant est très important : il est utile lorsque l’on veut
prouver que telle grammaire engendre tel langage :
Lemme 3 : Soit une grammaire algébrique G = < X, V, P, A> ;
n
 u1,u2, v  (XV)*, n  N, u1u2  v ssi :
n1
n2
 n1,n2  N, v1,v2  (XV)* tq n1+n2=n  u1  v1  u2  v2
La preuve se fait par récurrence sur n :
i. Si n = 0 , c’est trivial
La preuve du pas récurrent utilise le pas n = 1 qu’il faut donc prouver :
ii. Par définition de ,  M  V, u’, u’’  (X  V)* tq u1u2 =
u’Mu’’, v = u’mu’’ et (M,m)  P.
Il faut alors distinguer deux cas :
1. |u’|  |u1| : alors  t  (X  V)* tq u’ = u1t  u2 = tMu’’.
On pose alors v1 = u1 et v2 = tmu’’ et le lemme est vérifié
puisqu’on a bien u1 0 v1 et u2 (= tMu’’) 1 v2 (= tmu’’)
2. |u’| < |u1|, de la même façon u1 = u’Mt et u’’=tu2
iii. Supposons donc le lemme vérifié pour n < k
u1u2 k v  u1u2 k-1 w  v
M.M. Département Informatique
Décembre 2000
30
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Donc (HR) w = w1w2 et u1 k1 w1, u2  k2 w2 et k1+k2 = k-1
D’après l’étape ii, w1w2  v donc w1 e1 v1 et w2  e2 v2, avec
v1v2 = v et e1+e2 = 1.
Par conséquent u1 k1+e1 v1 et u2  k2+e2 v2 et k1+e1+k2+e2 = k
QED
Application : prouver que la grammaire ci-dessus
(X = {a, b}, V = {A}, P = {A  aAbA + })
engendre les mots de parenthèses, autrement dit que
L(G) = P = {f {a,b}* tq |f|a = |f|b   u, v  X*, uv = f  |u|a  |u|b}
i.e. toujours ouvrir les parenthèses avant de les fermer.
Remarque utile : un mot  P ssi soit il est vide, soit il est de la forme
afbg, avec f, g  P (les parenthèses ne peuvent pas se « croiser »).
1. P  L(G)
récurrence sur la longueur des mots
longueur nulle   P et   L(G)
HR : |f| < n et f  P  f  L(G)
Soit g  P, |g| = n alors g = a u b v ; u et v  P et de longueur < n donc
u, vL(G). Donc A *u et A *v. Il existe donc une dérivation
AaAbA*aubA*aubv = g, ainsi g  L(G).
Il reste à montrer que L(G)  P, ce qui se fait par récurrence sur la
longueur des dérivations.
Ordre 1 : A  f  f =  et   P
HR : A k f  f  P
Soit A k+1 f, alors A  u k f
et u = aAbA k f.
Le lemme ci-dessus nous permet alors d’écrire :
f = af1bf2 avec A k1 f1 et Ak2 f2 et k1+k2=k
Par hypothèse de récurrence, f1 et f2  P, et donc af1bf2 = f  P
La proposition suivante est très utile pour construire une grammaire à
partir de grammaires plus simples :
Proposition 3 : ALG(X*) est fermée par , . et *
Preuve :
M.M. Département Informatique
Décembre 2000
31
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
 : si L1 et L2  ALG(X*) alors L1=L(G1) et L2=L(G2).
Notons G1= < X, V1,P1, A1>, G2 = <X,V2,P2,A2>
On peut supposer sans perte de généralité V1  V2 = . Si ce n’est
pas le cas, on renomme les éléments de V2 par exemple.
Posons
V = V1V2{A} , avec A  V1V2
P = P1P2{(A,A1), (A,A2)}
G = <X,V,P,A>
Il est clair que L(G) = L1L2
Remarque : si L1 et L2 ne sont pas disjoints, G est ambiguë
. (produit) : même construction, sauf P = P1P2({A, A1.A2)}
* : ici, on part de G = <X, V, P, A > engendrant L ; on contruit G’
engendrant L* de la façon suivante :
V’ = V  {A’} ; P’ = P  { (A’, AA’), (A’, )}
En effet, par définition de *,   L* ; or   L(G’).
Si w  L* (w   ), alors w = w1w2 … wn avec wi  L, et donc on a la
dérivation suivante :
A’ AA’ * w1A’  w1AA’ * w1w2A’ … w1w2 … wn-1A’ 
w1w2 … wn-1AA’* w1w2…w n-1wnA’  w1w2 … wn-1 wn
Donc L*  L(G’)
Réciproquement, si A’ se dérive directement en un mot de L(G’),
alors ce mot est  ; sinon, A’ se réécrit AA’ et A se dérive en un mot
de L puisque c’est l’axiome de G. Par induction sur la longueur de la
dérivation, il vient donc que L(G’)  L*
Grammaires régulières :
Définition 20 : une grammaire algébrique G = < X, V, P,A> est dite
régulière ssi pour tout élément (U, m) de P on a m  (XV  X  )
Exercice : quelles sont les grammaires régulières, X = {a,b}
G1 : A  aAb + 
G2 : A  aB ; B  baBb + 
G3 : A  aA + bB +  ; B  bB + a
Seule G3.
M.M. Département Informatique
Décembre 2000
32
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Proposition 4 : Si G est une grammaire régulière, alors L(G) est
rationnel.
Preuve : il suffit d’identifier chaque non terminal à un état d’un
automate ; chaque règle, de la forme U1  xU2 peut s’interpréter
comme un élément de  : (U1, x, U2).
Grammaire en forme de Backus-Naur (BNF)
Le mot forme ne doit pas ici faire illusion : il s’agit uniquement d’une
notation ; commode et surtout très usuelle, cette notation permet de
spécifier une grammaire ; reprenons l’exemple de la grammaire E,T,F,
soit G = <X,V,P,A>,
P = {(E,E+T),(E,T),(T,T*F),(T,F),(F,(E)), (F,id)}
On la décrira en notation BNF :
<expression> ::= <expression> + <expression>
|
<terme>
<terme> ::= <terme> * <facteur>
|
<facteur>
<facteur> ::= ( <expression> )
| <identificateur>
le symbole ::= signifie « se dérive directement en »
le symbole | (ou) permet de regrouper les règles issues d’un même non
terminal.
Les non terminaux sont notés entre chevrons ; ils sont souvent
désignés par des symboles assez explicites (expression, ou expr plutôt
que E).
Les terminaux sont notés tels quels.
Compléments sur l’analyse lexicale :
On rappelle qu’en informatique la compilation est la traduction d’un
texte (dit texte source) en un autre texte (dit texte objet). Cette
opération, en particulier dans le cas des langages de programmation,
permet de passer d’un programme écrit en langage symbolique proche
de l’homme (C++, Pascal, etc…) à un programme équivalent mais
« proche » de la machine (et donc exécutable après l’édition des
liens). La compilation peut donc se décompose très schématiquement
M.M. Département Informatique
Décembre 2000
33
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
en deux grandes étapes, l’analyse du code source, et la production de
code objet ; l’analyse, elle, comporte, toujours très schématiquement,
deux phases qui sont, dans l’ordre chronologique : analyse lexicale,
analyse syntaxique. L’analyse lexicale consiste à découper le texte en
lexèmes, et pour chaque lexème reconnu à produire une unité lexicale
(ou token). Par exemple soit le morceau de programme C++ suivant :
moyenne = somme / nbElements ;
l’analyse lexicale permet de découper ce texte en 6 lexèmes :
moyenne / = / somme / / / nbElements / ;
et de produire la chaîne lexicale (suite de tokens) suivante (ou quelque
chose d’équivalent) :
id affect id oparithm id terminstr
L’analyse syntaxique pourra alors reconnaître dans cette chaîne une
instruction valide.
L’analyse lexicale telle que l’on vient de la décrire peut être réalisée
par un automate avec sortie : chaque fois qu’un lexème est reconnu,
le token correspondant est produit :
NB : en plus, l’analyse lexicale s’efforce de ne pas perdre la trace des
symboles ! (ils sont recopiés dans la table des symboles qui sera
utilisée ultérieurement). En effet, de même qu’on peut associer des
sorties à un automate, on peut plus généralement lui associer des
actions (une sortie étant une action de la forme écrire(x))
Mais comme nous l’avons vu, le fait de lui ajouter des sorties ne
transforme pas essentiellement un automate et le besoin apparaît d’un
outil plus puissant pour mener à bien la phase suivante : l’analyse
syntaxique repose sur la notion de grammaire algébrique, et de même
qu’à une expression rationnelle on peut associer un automate fini
(théorème de Kleene), de même à toute grammaire algébrique on va
associer un automate à pile.
Automate à pile
Introduction. Rappelons-nous qu’un automate sait reconnaître a*b*,
mais pas anbn. On dit familièrement qu’un automate ne sait pas
compter : il lui manque une mémoire, c’est ce que va lui fournir une
pile qu’on va lui associer.
M.M. Département Informatique
Décembre 2000
34
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
La notion de pile est familière aux informaticiens ; on peut utiliser le
cadre de la théorie des langages pour fournir une définition précise de
ce qu’est une pile :
Définition : soit un mot p sur un alphabet Y ; on dit que p est une pile
si on autorise sur ce mot les seules manipulations suivantes :
pilevide : Y*  {vrai, faux}
p
 pilevide(p) = (p = 
En particulier, on ne dispose pas de |p|

valeursommet: Y+  Y
p
valeursommet(p) = p(1)
p(1) est appelé le sommet de pile.
On interdit de faire référence à p(i) i  1

empiler : Y x Y*  Y*
(y,p)
empiler(y, p) = y.p
La concaténation est donc limitée à un mot d’une lettre concaténé à
gauche de p.
Remarque : cette limitation n’est qu’apparente ; en effet soit Y = {y,z}
et soit p  Y* ; alors empiler(y, empiler(z, empiler (z, p))) = yzzp =
up, u=yzz.
dépiler: Y+  Y*
p
dépiler(p) = p’ / |p’| = |p|-1  p’(i) = p(i+1)
dépilement : p(1), le sommet de pile, est supprimé.
1 i < |p|
Informellement, une pile est la donnée d’un alphabet, et de règles de
construction des mots sur cet alphabet.
Il existe plusieurs façons de définir un automate à pile. De façon
intuitive, un automate (comme ceux que nous avons déjà rencontrés)
lit une lettre, et selon son état e et la lettre lue, il passe dans un état e’ ;
comme son nom l’indique un automate à pile est un automate mais qui
peut « décider » son état suivant en consultant, en plus ou à la place de
M.M. Département Informatique
Décembre 2000
35
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
la lettre lue, le sommet de pile ; de même, en plus de la transition
d’état, il peut effectuer des manipulations de sa pile.
Définition 21 : on appelle automate à pile la donnée
< X, Y, E,e0, F,  > où :
X est un alphabet, dit alphabet d’entrée
Y est un alphabet dit alphabet de pile
E,e0, F sont l’ensemble des états, l’état initial, et l’ensemble des états
terminaux
 est une partie finie de X  {} x E x Y  { x E x Y* appelée
ensemble des règles de l’automate à pile
Remarque : les règles de l’automate à pile intègrent les primitives de
manipulation de la pile (applications pilevide , valeursommet, empiler,
dépiler ). Ainsi, soit (x, e, y, e’, h)   ; y est le symbole de sommet
de pile, ou le mot vide si la pile est vide, h est le mot éventuellement
vide qui va remplacer y en sommet de pile.
Définition 21bis : une configuration de l’automate à pile est un
élément de X* x E x Y* : un mot restant à lire, l’état courant, la pile.
Pour compléter la définition d’un automate à pile, il faut préciser une
configuration initiale, et une ou plusieurs configurations
d’acceptation. On simplifiera en disant qu’initialement la pile est vide
(configuration initiale = (f,e0, )), et l’acceptation se fait par pile vide
et état d’acceptation (configuration d’acceptation = (, ef,), où ef 
F). Il existe d’autres possibilités, et on démontre qu’elles sont
équivalentes à celle-ci (très technique).
Un automate à pile va nous permettre de reconnaître les langages
algébriques :
anbn : tant qu’on lit des a, les empiler ; tant qu’on lit des b, dépiler ; le
mot est reconnu si on a une pile vide à la fin (pas avant !).
plus précisément :
X = {a, b} ; Y = {a} ; E = { e0 , e1, e }, F = {e1}.
={
(a, e0, ,e0, a), // config init = (f, e0, )
(a, e0, a ,e0, aa) , // empilement des a
M.M. Département Informatique
Décembre 2000
36
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
(b, e0, a, e1, ) , // premier b, on change d’état, on veut dépiler tous les a
(b, e1, a, e1, ), // on dépile les a
// config accept = (, e1, 
}
Exercice : faire tourner l’automate sur aaabbb, puis sur aba.
Nous allons préciser un peu ce qui se passe :
Définition 21ter : on dit qu’il existe une transition entre c = (xf, e,
yp) et c’=(f, e’, hp) ssi (x, e, y, e’, h)   .
Remarque : x peut être le mot vide. On parle alors d’-transition.
Définition 21quater : un mot f  X* est reconnu par l’automate à
pile A ssi il existe une suite de transitions c1  c’1, c2  c’2 ….cm 
c’m telle que  i, (0<i<m), c’i = ci+1
c1 = (f, e0, ) et c’m = (, ef, ) (ef  F)
On parlera de même de langage reconnu pour l’ensemble des mots
reconnus.
Enfin, on admettra la proposition suivante :
Proposition 5 : un langage est algébrique ssi il est reconnu par un
automate à pile.
Prenons un nouvel exemple :
X = Y = {a,b} ; E = {e0, e1}, F = { e1 }
Configuration initiale (f, e0, )
Acceptation (, e1, )
Pour faciliter les explications, on numérote les règles (éléments de )
={
// première phase : on empile tout ce qui se présente
(a, e0, , e0, a) (1)
(b, e0, , e0, b) (2)
(a, e0, a, e0, aa) (3)
(a, e0, b, e0, ab) (4)
(b, e0, a, e0, ba) (5)
M.M. Département Informatique
Décembre 2000
37
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
(b, e0, b, e0, bb) (6)
// on change de politique :
(, e0, a, e1, a) (7)
(, e0, b, e1, b) (8)
(, e0,  , e1, ) (9)
(a, e0 , a, e1 ,a) (10)
(b, e0 , b, e1 ,b) (11)
// phase 2 : on tente de reconnaître ~u, on dépile si le sommet = la
lettre lue
(a, e1, a, e1, ) (12)
(b, e1, b, e1, ) (13)
}
Faisons tourner l’automate sur le mot ab :
(ab, e0, )  (1) (b, e0, a)  (4) (e0, ba) : échec
il serait fastidieux (mais possible : nombre fini de règles et de lettres)
de vérifier que l’on ne peut réussir
prenons maintenant le mot abaaba
On vérifie qu’en appliquant successivement les règles 1, 5, 4, 7, 12,
13, 12 l’automate reconnaît le mot proposé.
Essayer avec le mot aba
Néanmoins, on aura remarqué une difficulté : comment prévoir le bon
moment pour passer dans l’état e1 ? réponse : au hasard ! Cet
automate n’est pas déterministe. Sa mise en œuvre effective
(algorithme) suppose le backtracking. On essaie jusqu’à trouver un
calcul valide ou avoir épuisé sans succès toutes les possibilités.
M.M. Département Informatique
Décembre 2000
38
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Schéma de l'algorithme de backtracking :
fonction reconnaître(f : mot, e : état, p : pile) : booléen
var accepté : booléen ;
début
Si f = p =   e  F
// on a lu le mot, la pile est vide, l'état est d'acceptation
Alors accepté  vrai
Sinon début
accepté  faux
Tant Que ((il existe une règle non essayée)
et (accepté = faux))
// on suppose f = xf', p = yp', et règle = (x, e, y, e', h)
faire accepté  reconnaître(f', e', hp')
retourner accepté
fin
Or ici on n’a hélas pas la possibilité de déterminiser tout automate à
pile, comme c’était le cas pour les automates. En fait, il existe des
langages algébriques non déterministes (les palindromes,
ou anbp / 0  n p<2n ou encore { anbn} { anb2n.}). On s’intéressera
de préférence aux langages déterministes, c’est à dire ceux qui
peuvent être reconnus par automate à pile déterministe :
Définition 22 : un automate à pile est dit déterministe ssi quelle que
soit la configuration, une règle au plus est applicable.
Exemple : on a vu anbn.
Prenons les mots de parenthèses : tant qu’on n’a pas fini de lire le mot,
quand on lit un a on l’empile, un b on dépile ; la pile doit être vide à la
fin (pas avant).
Plus précisément : X = {a, b} ; Y = {b} ; E = {e0}
Conf. Init = (f, e0 ,  ) , accept = (, e0 ,  )
 = { (a, e0 ,  , e0 , a), (a, e0 , a, e0 , aa), (b, e0 , a , e0 ,  )}
Enfin, de même que les langages rationnels débouchent sur l'analyse
lexicale, de même les langages algébriques autorisent la mise en
œuvre de techniques puissantes (algorithmes) d'analyse syntaxique.
On évoquera l'analyse descendante LL et l'analyse ascendante LR. On
se contentera cependant d'un aperçu schématique, car ces notions
peuvent facilement conduire à des considérations fort techniques.
M.M. Département Informatique
Décembre 2000
39
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Grammaires LL(1)
LL signifie Left to right scanning Leftmost derivation. Le 1 signifie 1
seul symbole d'entrée. Les grammaires LL(1) autorisent une analyse
descendante (en quelque sorte on part de la racine et on construit
l'arbre de dérivation) en par la seule connaissance d'un seul symbole
d'entrée, et du non terminal à dériver.
Exemple de grammaire LL(1):
(1) E  T E'
(2) E'  + T E' | 
(3) T  F T'
(4) T'  * F T' | 
(5) F  ( E ) | id
Soit l'expression (id + id) * id ; au départ, on cherche à dériver E.
Pile
Mot
Dérivation
E
id*id+id
TE'
id*id+id
E  TE'
FT'E'
id*id+id
T  FT'
idT'E'
id*id+id
F  id
T'E'
*id+id
*FT'E'
*id+id
T'  *FT'
FT'E'
id+id
idT'E'
id+id
F  id
T'E'
+id
E'
+id
T'  
+TE'
+id
E'  +TE'
TE'
id
FT'E'
id
T  FT'
idT'E'
id
F  id
T'E'

E'
T'  

E'  


On voit que c'est toujours le non terminal le plus à gauche qui est
dérivé, de même la chaîne est parcourue de gauche à droite.
M.M. Département Informatique
Décembre 2000
40
I.U.T. Bordeaux I
Cours de mathématiques 1° année : Théorie des langages
version du 16/04/17
Grammaires LR
Left to right scanning Rightmost derivation.
Ces grammaires permettent une analyse ascendante : on part des
feuilles pour construire l'arbre de dérivation en dérivant à chaque fois
le non terminal le plus à droite. Très utilisé par les constructeurs
automatiques d'analyseurs syntaxiques (Yacc , yet another compiler of
compilers). Mais assez technique à mettre en œuvre.
M.M. Département Informatique
Décembre 2000
41
I.U.T. Bordeaux I
Téléchargement