Cours LAC
Cours LAC
Cours LAC
BIBLIOGRAPHIE
Les références bibliographiques suivantes sont celles des publications originelles des résultats
fondamentaux qui ont été mentionnés dans le cours :
1. Chomsky, N., On certain formal properties of grammars, Information and Control, 1 (1959),
pages 91-112
2. Chomsky, N., Three models for the description of language, IRE Transactions on Information
Theory, 2 (1956), pages 113-124
3. Greibach, S., A New Normal-Form Theorem for Context-Free Phrase Structure Grammars,
Journal of the ACM (JACM), Volume 12 Issue 1 (1965)
4. Kleene, S. , Representation of Events in Nerve Nets and Finite Automata in Automata Studies
(1956) eds. C. Shannon and J. McCarthy.
INTRODUCTION
Le but est de construire une grammaire qui permette de produire cette phrase.
Il faut tout d’abord préciser les « ingrédients » nécessaires : ce sera l’alphabet des symboles
ou lexique. Dans notre cas, nous pouvons prendre comme alphabet l’ensemble
Σ = {LE, VIEUX, PETIT, CHAT, RAT, ATTRAPE}
( il contient ici six symboles).
Noter que le terme « alphabet » n’a pas ici le sens habituel A, B, C,…. : en fait, l’alphabet
contient les « briques de base » avec lesquelles on peut former… tout ce qu’on veut pouvoir
former ! Dans un langage de programmation par exemple, les mots réservés, balises, etc…
comme program, real, <head>, </head>, … sont dans l’alphabet de symboles.
Voyons maintenant comment ces symboles sont assemblés. Dans la structure de la phrase,
on peut distinguer :
• un groupe sujet
• un verbe
• un groupe complément d’objet (CO)
Les groupes sujet et CO sont eux-mêmes des groupes nominaux : un groupe nominal est
formé d'un article suivi d'un nom, lui-même précédé ou suivi d'adjectifs.
Voici un exemple de (petite) grammaire pouvant produire notre phrase ; elle a onze règles
de grammaire (on dit aussi de production, ou de réécriture) :
- Les variables sont les « ingrédients » qui peuvent encore être remplacés par d’autres
(<phrase>, <article>, <groupe CO>, etc…).
- Les règles 1 à 5 sont des règles syntaxiques (la première règle concerne toujours l’axiome).
Les règles 6 à 11 sont des règles complètement terminales (ou : lexicales).
- Le langage engendré par la grammaire est l'ensemble de toutes les phrases que l'on peut
produire à partir de l’axiome en utilisant des règles de grammaire, une phrase étant une chaîne
de symboles.
On peut associer à chaque phrase ainsi produite un arbre de dérivation où figurent les
variables auxquelles on a appliqué des règles de grammaire.
Nous avons ajouté aux nœuds de cet arbre de dérivation, pour faciliter la compréhension,
les numéros des règles qui ont été appliquées aux variables.
<phrase>
1
1. Définitions.
L’alphabet des symboles est un ensemble fini. On le notera en général Σ dans la suite du
cours.
Exemples. LE LE CHAT est une chaîne de longueur 3 sur l’alphabet de l’exemple 1. Les
expressions arithmétiques (correctes ou non !) sont des chaînes sur l'alphabet de l’exemple 2.
La chaîne vide, notée λ , ne contient aucun symbole ; sa longueur est nulle. On verra qu'elle
est particulièrement utile !
On peut concaténer des chaînes de symboles, c’est-à-dire les « coller » les unes derrière
les autres, de la même façon que plusieurs textes peuvent être assemblés les uns derrière les
autres pour former un nouveau texte. Si u et v sont deux chaînes de symboles, leur
concaténation sera notée u.v ou plus simplement uv .
Exemples. Sur l’alphabet Σ = {a, b, c, d}, les ensembles suivants sont des langages :
• L1 = {ac, abbc}
• l’ensemble L2 de toutes les chaînes qui commencent par a.
• L’ensemble L3 de toutes les chaînes de longueur paire.
Notation. Afin de faciliter la lecture, nous adopterons en général une notation a, b, c, … pour
des symboles de Σ et u, v, w, x, … pour des chaînes de symboles.
2. Opérations sur les langages.
Un alphabet de symboles Σ étant fixé, voyons les opérations que nous appliquerons aux
langages sur Σ .
• Concaténation de langages.
Comme nous savons concaténer des chaînes de symboles, nous pourrons également
concaténer deux langages, c'est-à-dire collecter dans un nouvel ensemble, noté L1.L2 , toutes
les chaînes que l'on peut obtenir en concaténant une chaîne de L1 avec une chaîne de L2 .
Par récursivité, nous pourrons concaténer aussi un nombre fini de langages.
Exemple. Sur l’alphabet Σ ={0, l, 2, ....,9}, le langage {l, 2, ...., 9}.Σ* U {0} est le langage
de tous les nombres entiers naturels, écrits en base 10 et sans 0 inutiles à gauche.
« Par récursivité » veut dire qu’on applique un nombre fini de fois de telles opérations, à
partir des langages " de base ".
Exemple. Sur Σ = {a, b, c}, le langage L des chaînes commençant par a est régulier,
puisqu'on peut en donner une expression régulière en l’écrivant sous la forme
L = {a}.({a}U{b}U{c})*
Notation. Par abus de notation, on peut omettre les accolades pour alléger l’écriture. Le point
de concaténation n'est pas toujours écrit non plus, si cette omission peut se faire sans
ambiguïté :
L = a (a U b U c)*
Remarque. Attention ! dans la définition, l’intersection ne figure pas comme une opération
autorisée. En fait, on peut démontrer (mais c’est difficile…) que l’intersection de deux
langages réguliers est encore un langage régulier :
Proposition 1.
1) Tout langage fini est régulier.
2) Si L est un langage régulier, alors L* est régulier.
3) Si L 1 et L 2 sont des langages réguliers, alors les langages L1UL2 et L 1.L2 sont
aussi réguliers.
Proposition 2.
Si L1 et L2 sont des langages réguliers, alors L1 L2 est régulier.
Le problème : un langage L étant fixé, comment savoir si une chaîne w donnée appartient
à L?
Une solution possible : décrire une grammaire adéquate engendrant L , grammaire qui
pourrait permettre
En pratique, les variables seront répertoriées sous la forme d’une liste (elles seront donc
ordonnées), mais la première de ces variables est toujours l’axiome. Les règles de production
seront elles aussi ordonnées, en respectant l’ordre des variables auxquelles elles s’appliquent.
La première règle concerne donc toujours l'axiome. L’ordre ainsi choisi aura une incidence
sur le déroulement des algorithmes qui s’appliqueront aux grammaires.
Notations.
Dans la suite du cours, afin de rendre le texte plus lisible, les variables d’une grammaire
seront en général désignées par des lettres majuscules S, A, B, C, …
Pour les symboles terminaux, nous aurons les minuscules a, b, c, … sauf cas particuliers.
Les notations x, y, u, v, … désigneront souvent des chaînes de (Σ U V)*, formées de
symboles terminaux et/ou de variables.
Les « grammaires » seront toujours des grammaires algébriques.
Définition. Une chaîne w dérive d'une chaîne v si, à partir de v , on peut arriver à w par un
nombre fini d’applications de règles de grammaire :
v =>.... => w , ce qu’on notera également v => w
Définition. Le langage engendré par une grammaire G est l’ensemble de toutes les chaînes
terminales (autrement dit, dans Σ*) qui dérivent de l’axiome S . Il est noté L(G) .
S => abSA => abS => ababSA => ababSAa => ababAa => ababa ∈ Σ*
1 4 1 3 2 4
Pour chaque dérivation, on a mis en gras (l’occurrence de) la variable qui a été réécrite et
on a indiqué sous la flèche le n° de la règle appliquée.
Exemple 2. Le langage engendré par la grammaire du PASCAL est l’ensemble de tous les
programmes qui sont correctement écrits en code source PASCAL.
On peut tracer un arbre de dérivation associé à toute suite de dérivations. Chaque nœud
représente un exemplaire d’une variable réécrite, avec le numéro de la règle de grammaire
appliquée.
a b S A
a b S A λ
λ Α a
En lisant les symboles qui figurent aux extrémités des branches, de gauche à droite, on
obtient la chaîne ababa
Remarque 1. Des suites de dérivations différentes peuvent être associées à un même arbre de
dérivation. En effet, il apparaît clairement sur cet exemple que l’ordre de certaines des
dérivations peut être échangé sans que l’arbre en soit modifié.
Définition. Une dérivation à gauche est une dérivation qui s'applique à la première variable
rencontrée dans la chaîne (c'est la variable qui est le plus "à gauche" possible).
Théorème 1. Soit w une chaîne de L(G) . A toute suite de dérivations S => w correspond
une unique suite de dérivations à gauche ayant le même arbre de dérivation.
Cette façon de parcourir un arbre s'appelle "en profondeur d'abord" : on descend toujours
autant que possible, en commençant à gauche ; on ne remonte que le minimum nécessaire
pour pouvoir redescendre sur une branche située plus à droite. Un parcours "en largeur
d'abord" se fait, lui, en allant d'abord de gauche à droite, ensuite de haut en bas.
Remarque 2. Des suites de dérivations différentes peuvent produire la même chaîne de L(G)
, tout en étant associées à des arbres de dérivation différents.
4. Grammaires régulières.
Définition. Une grammaire algébrique est dite régulière si toutes ses règles sont de l'un des
types suivants :
• A aB
• A a où A, B ∈ V et a ∈ Σ
• A λ
Il en découle que les chaînes qui dérivent de l’axiome contiennent au plus une variable, et
cette variable est nécessairement en fin de chaîne (en « suffixe »). Plus précisément, ces
chaînes sont de l’une des formes suivantes :
Les arbres de dérivation associés aux suites de dérivation ont l’aspect d’un « peigne »
(symboles et variables sont indiqués à titre d'exemple sur la figure suivante) :
S
a
A
b B
a B
a , ou λ
Le théorème suivant met en relation les langages réguliers (que nous avons vus au chapitre
précédent) et les grammaires régulières. Il sera difficile à prouver : plus précisément, la
démarche suivie sera surtout très longue (mais très belle aussi).
Théorème 2. Tout langage régulier peut être engendré par une grammaire régulière.
Réciproquement, si G une grammaire régulière, alors L(G) est un langage régulier.
Exercice 3. G : S abSA | λ
A Aa | λ
n'est pas une grammaire régulière. Mais…
1) Prouver que L(G) = {λ}U (ab)+.a* .
Vérifier aussi que L(G) est différent de (ab)*.a*
Le langage L(G) est donc un langage régulier. D'après le théorème 2 précédent, il doit
exister une grammaire régulière qui l’engendre.
2) Trouver une grammaire régulière G1 telle que L(G1) = L(G).
On a vu (cf. la définition) que des règles du type A a peuvent figurer dans une grammaire
régulière. De telles règles peuvent être éliminées, à condition d'introduire une nouvelle
variable dans la grammaire : il suffit en effet de remplacer la règle A a par le groupe des
deux règles suivantes
A a.A1 (où A1 désigne ici la nouvelle variable
introduite) A1 λ
Cette opération est un exemple simple de transformation d'une grammaire en une autre
grammaire qui lui est équivalente : le langage engendré reste inchangé.
Nous avons ainsi établi la proposition suivante.
Proposition. Toute grammaire régulière est équivalente à une grammaire régulière dont les
règles sont du type A aB ou A λ
Exemple. La grammaire G : S bA | b | λ
A aA | aS | a
est équivalente à G’ : S bA | bZ | λ
A aA | aS | aZ
Exercice 4. Décrire le langage engendré par ces grammaires, à l’aide d’une propriété
caractérisant ses chaînes.
Dans la suite du cours, sauf mention du contraire, nous ne considérerons plus que des
dérivations à gauche : en lisant une chaîne de gauche à droite, c’est toujours la première
variable rencontrée qui est réécrite. Nous avons vu en effet (cf. théorème 1) que toute chaîne
w de L(G) peut être obtenue à partir de l’axiome par une suite de dérivations à gauche.
Définition. Une grammaire G est dite ambiguë s’il existe dans L(G) une chaîne w que
l’on peut obtenir par deux suites différentes de dérivations à gauche.
Remarque. L’ambiguïté est une propriété qui se rapporte à une grammaire, et non à un
langage.
Il n'est pas difficile de trouver un exemple de langage engendré par une grammaire non
ambiguë et par une (autre) grammaire qui, elle, est ambiguë : il suffit de partir d'une (petite)
grammaire G dont on est certain qu'elle est non ambiguë, puis de la modifier en "doublant"
une variable :
G : S aA G' : S aA | aB
A λ A λ
B λ
Exemple. L’exercice 2 (cf. §3.) permet en fait de prouver que la grammaire G considérée
est ambiguë.
Définition. Une grammaire G étant donnée, on peut lui associer un graphe orienté (il s’agit
d’un graphe infini, en général) :
• les sommets de ce graphe sont toutes les chaînes que l’on obtient à partir de l’axiome
par des dérivations à gauche
• les flèches issues d’un sommet donné sont les règles de grammaire applicables à la
première variable de la chaîne correspondant à ce sommet.
Exemple. Soit G : S aS | aA | λ
A Ab | a | b
Le graphe orienté de cette grammaire commence ainsi (il est infini, en fait) :
aS aA λ
3 3
aS aA
Sur cette partie du graphe orienté, l’ambiguïté de G est déjà mise en évidence puisque on
y voit deux chemins différents qui mènent de S à la chaîne aa , chaîne qui est terminale et
appartient donc au langage engendré.
De manière générale :
• Dans le graphe orienté de la grammaire, un arbre de dérivation (cf. §3.) est représenté
par un chemin partant de l’axiome et aboutissant à un élément de L(G) . En effet, un
arbre de dérivation correspond à une (unique) suite de dérivations à gauche, cf. théorème
1.
• La grammaire est ambiguë si et seulement si son graphe orienté contient des chemins
différents issus de l’axiome et aboutissant à une même chaîne de L(G).
Le problème : un langage L étant donné, comment savoir s’il peut être engendré par une
grammaire régulière ?
Une réponse : le lemme de l’Etoile donne une condition que les chaînes de L doivent
nécessairement satisfaire s’il y a une telle grammaire.
Cette condition nécessaire sera ensuite exploitée pour prouver que, pour certains langages,
il n’existe pas de grammaire régulière : il suffira de produire des chaînes servant de « contre-
exemple », c’est-à-dire des exemples de chaînes du langage qui ne vérifient pas la condition
énoncée par le lemme de l’Etoile.
Rappelons que pour une grammaire G régulière, les règles sont de l'une des formes
suivantes :
• A aB où
a ∈ Σ et B ∈ V
• A a où a ∈ Σ
•A λ
et si w est un élément du langage engendré L(G) , il y a un arbre de dérivation de la forme
particulière suivante :
a
A
b B
a B
a , ou λ
où w est la chaîne formée par les symboles figurant aux extrémités des branches (symboles
et variables sont indiqués à titre d'exemple).
Faisons une remarque évidente, mais décisive pour la suite : si la longueur de la chaîne w
est strictement supérieure au nombre de variables de la grammaire G , alors il y a une variable
(au moins) qui figure deux fois dans l’arbre de dérivation.
A
a1
a2 B
a3 C
a4 A
a5
a6
Dans cette situation, nous pouvons construire de nouvelles chaînes qui devront
certainement, elles aussi, appartenir au langage L(G), pour la bonne raison qu’elles sont
produites en se servant uniquement de règles qui ont été utilisées pour produire w , donc des
règles qui sont dans la grammaire G . La procédure est la suivante : jusqu’à la deuxième
occurrence de la variable répétée, on applique les mêmes règles que celles qui ont servi pour
produire w ; à ce moment-là, on réutilise la règle qui avait déjà été appliquée lors de la
première occurrence, et celles qui ont suivi.
Sur notre exemple, au lieu d’appliquer A a5C , on réutilise la règle A a2B et celles qui
suivent. Nous obtenons ainsi une nouvelle chaîne w’ = a1a2a3a4a2a3a4a5a6 qui appartient
également à L(G).
a1 A
a2 B
a3 C
a4 A
a2 B
La partie de l’arbre entourée en pointillés
a été dupliquée a3 C
a4 A
a5
C
a6
Bien entendu, la duplication de ce tronçon de l’arbre de dérivation peut être
recommencée autant de fois que l’on veut : la chaîne a1 a2 a3 a4 a2 a3 a4 a2 a3 a4 a5 a6 et, plus
généralement, toutes les chaînes qui sont de la forme a1(a2a3a4)i.a5a6 appartiennent
nécessairement au langage L(G) .
En outre, il est évident que si K désigne le nombre de variables dans la grammaire, la
répétition d’une variable se produira déjà parmi les K+1 premiers noeuds de l’arbre (la racine
S est comptée comme le premier noeud).
Rappelons le théorème 2 (que nous prouverons dans le chapitre sur les automates) : pour
tout langage régulier L , il existe une grammaire régulière G telle que L = L(G) . De cette
grammaire dont on ignore à peu près tout, nous savons au moins qu’elle a un nombre fini de
variables. Nous ignorons quel est ce nombre, mais nous pouvons maintenant appliquer la
proposition précédente aux chaînes du langage régulier considéré.
Voici donc la version définitive du « critère de régularité » qui découle des considérations
et de la proposition précédentes :
Soit L un langage régulier. Il existe une constante K telle que toute chaîne w de L
dont la longueur est strictement supérieure à K peut s’écrire sous la forme w = u.x.v
où : x est une chaîne non vide,
la longueur de u.x est inférieure ou égale à K , la chaîne
u.xi.v appartient au langage L pour tout entier i .
Mais alors la chaîne uxxv = aK+p.bK , et cette chaîne n’est pas dans le langage. Le lemme
de l’Etoile est contredit.
On en conclut que L n’est pas un langage régulier.
Définition. Un palindrome sur un alphabet Σ donné est une chaîne de symboles de Σ qui
peut être lue indifféremment de gauche à droite ou de droite à gauche.
Quelques exemples de palindromes, sur Σ = {a, b} : aabaa, abba, abababa, aaaa.
Exercice. Prouver que le langage des palindromes sur Σ = {a, b} n’est pas un langage régulier.
Note. Il existe une version « perfectionnée » de Lemme de l’Etoile pour les langages engendrés par des
grammaires algébriques.
Nous verrons de manière détaillée l’analyse syntaxique descendante. Celle-ci peut se faire
selon deux types de parcours :
• en largeur d’abord
• en profondeur d’abord
Définition. Le préfixe terminal d’une chaîne u ∈ (ΣUV)* est la sous-chaîne des symboles
terminaux qui précédent la première variable figurant dans u .
Remarque. Lorsqu’on procède à une dérivation, le préfixe terminal se trouve soit inchangé
soit prolongé.
Cette remarque simple est à la base du test qui se fera lors de l’analyse syntaxique : si le
préfixe terminal d’une chaîne u ∈ (ΣUV)* n’est pas identique au début de la chaîne analysée
w , il est impossible que w dérive de u .
Le test : tester une chaîne u consiste à comparer son préfixe terminal avec le début de la
chaîne analysée w .
Noter qu’en informatique, la donnée d’une chaîne de symboles est toujours suivie d’un
signe de fin de chaîne : espace, guillemet, ou tout autre caractère spécifique servant à signifier
la fin. Dans le cas où u est complètement terminale (autrement dit dans Σ*), on arrive au
signe de fin de chaîne (puisqu’on n’a pas trouvé de variable), et on teste donc l’égalité des
chaînes : u = w oui ou non.
Remarque. Par une dérivation à gauche, en appliquant une règle de grammaire qui
commence par un symbole terminal, on est certain que le préfixe terminal sera allongé ; le test
sera donc plus efficace. Mieux : la complexité de l’analyse syntaxique sera contrôlée si toutes
les règles commencent par un symbole terminal. C’est pourquoi une étape préliminaire
consiste à transformer dans ce but la grammaire donnée. Nous verrons comment procéder à
ce type de transformation dans un chapitre ultérieur.
L'algorithme d’analyse.
• Les règles de G sont ordonnées (c'est-à-dire numérotées, mises dans une liste).
• Le test sur les chaînes : comparer leur préfixe terminal au début de la chaîne w à analyser.
• Une file sera créée, afin de mettre en attente les chaînes :
- qui dérivent de l'axiome,
- qui contiennent encore au moins une variable
- et qui restent susceptibles d'aboutir à w par dérivation (cf. le test).
Rappelons le principe d’une file : " le premier entré est le premier sorti ".
S
1 3
2
bS Sa a
1 2 3
1 3
2
1 2 3
Exercice. Pour cette analyse syntaxique, suivre sur l’arbre l’ordre dans lequel les chaînes ont
été examinées par l’algorithme ; préciser le contenu de la file Q .
Quelles sont les chaînes qui restent encore dans la file, au moment où l’analyse s'arrête ?
L'algorithme d’analyse.
2. Tester la chaîne q .
A bA | b | λ 4|5|6
S
1 2
aS aA
1 2 3 4
abbA
4 5 6
Au moment où cette analyse s’arrête (elle s’arrête parce qu'on a trouvé w ), le contenu de
la pile P est :
On retrouve donc dans la pile un chemin joignant S à w , c'est-à-dire toute une suite de
dérivations à gauche :
S => aA => abA => abbA => w
Remarque. L'analyse syntaxique peut être longue, ou même inopérante, selon la forme des
règles de grammaire. Les règles qui commencent par une variable, et particulièrement celles
qui sont de la forme A Au (où u est une chaîne quelconque), dites directement récursives
à gauche, peuvent empêcher l'analyse syntaxique d'aboutir. Mais nous verrons ultérieurement
des algorithmes qui permettent de transformer la grammaire en une grammaire équivalente
pour laquelle toutes les règles (non vides) commencent par un symbole terminal.
Une règle A u donne des dérivations de la forme pAq => puq . Il faut donc pouvoir
reconnaître la séquence u dans une chaîne, afin de pouvoir la remplacer par la variable A .
Pour cela, on pratique le test de la manière suivante.
Une chaîne w ∈∑* étant donnée, on découpe w en deux chaînes concaténées w = y.z .
Ce découpage est initialisé avec y = λ et z = w , puis il progressera vers la droite : on
allongera y et raccourcira z d'un symbole à la fois. A chaque fois, les règles de grammaire
sont successivement comparées à la fin de la chaîne y .
Noter qu'on obtient ainsi une suite de dérivations à droite, qu'il suffit d’ailleurs d'avoir
gardées en mémoire dans une pile pour reconstituer une dérivation (à droite) S => w .
AUTOMATES
1. Définitions.
Une transition (i, a, j ) se représente par une flèche de i à j , munie d'une étiquette a :
a
j i
Un automate se représente donc à l'aide d'un graphe orienté, sur lequel il faut toutefois
indiquer les états particuliers que sont les entrées et les sorties. Les états initiaux sont indiqués
par une double flèche entrante ; pour les états finaux, une double flèche sortante.
Exemple. 4
b
1 a 2 a 3 a
b
Pour simplifier les dessins, on convient de représenter deux transitions entre les mêmes états
(i,a,j) et (i,b,j) par une seule flèche, munie des deux étiquettes. Il faut donc comprendre " a
ou b ", en lisant l’étiquette suivante :
a, b
i j
Définition. Le langage reconnu par un automate A est l'ensemble de toutes les chaînes
reconnues. Il est noté L(A ) .
Exercice.
1) Parmi les chaînes aabaa, aabab, baba, ab, abaaaa , déterminer lesquelles sont reconnues
par l'automate A représenté au §1. 2) Déterminer le langage L(A) reconnu.
L’intérêt d’un ADC est qu’en lisant une chaîne (quelconque) w de Σ* , il lui correspond
un parcours bien défini à partir de l’état initial, et la progression dans l’automate ne se trouve
jamais bloquée : la chaîne peut toujours être lue jusqu’au bout. La chaîne w est reconnue si
et seulement si on aboutit à l’un des états « de sortie », c’est-àdire à un état final.
a {1,2,3}
1
Bien entendu, cette construction doit se faire « de proche en proche », à partir des états
initiaux, qui sont les premiers états qu’il faut regrouper pour obtenir une entrée unique. C’est
donc une construction récursive, et algorithmique.
A
Soit = ( Σ , E, Eo, F, δ ) l’automate initial donné.
Le nouvel automate, déterministe, sera noté A’ = (Σ , E’, {s’o}, F’, δ') . Les états de ce
nouvel automate sont des groupes d’états de l’ancien automate, c’est-à-dire des
sousensembles de l’ensemble E . L’état initial s’o est unique.
L’algorithme.
A
- initialiser : s’o = Eo ( s’o est l’ensemble de tous les états initiaux de . C’est l’état initial
A’
de )
a b
1 a 2
a
b
b 3
Réponse :
a b
{1} [1,2,3} {2,3}
a b
Preuve du théorème 4.
L’opération est élémentaire : si l’AD n’est pas déjà complet,
• lui rajouter un nouvel état (« état poubelle »)
• rajouter les transitions d’étiquettes manquantes en les dirigeant toutes vers cet état
poubelle P ; ne pas oublier les transitions de P lui-même vers P .
a b
S 1 2
c
b
3
c
2) La correspondance se fait :
- entre les variables de la grammaire G et les états de l’automate A - entre
les règle de grammaire et les transitions de l’automate
a
A B
A
l’axiome S de la grammaire : l’(unique) état initial de l’automate
les variables : les états
les règles : les transitions, ou les sorties :
A aB :
A λ :
Exemple. G: S aA
A bA | λ a
S A
Corollaire. Les langages reconnus par les automates sont les langages engendrés par les
grammaires régulières.
Il s’agit d’une légère généralisation de la notion d’automate. Son intérêt est technique : elle
nous permet de faire les « bricolages » à partir d’automates dont nous aurons besoin par la
suite (jonction, réunion,…).
Remarque. Si des transitions d’étiquette vide sont permises, la deuxième condition n’est plus
du tout contraignante ! s’il y a plusieurs états initiaux, il suffit de banaliser ces états et de
rajouter un nouvel état, qui devient l’unique état initial, avec des transitions d’étiquette vide
adéquates :
devient λ 1
3
1 S
3 λ 2
2
L’unicité de l’état initial est une condition indispensable si l’on veut progresser vers la
construction d’une grammaire. Du point de vue des grammaires, d’ailleurs, une transition
d’étiquette vide corespond très exactement à une règle d’ « enchaînement de variables » (les
états A et B du λ−automate correspondent à des variables A et B de la grammaire) :
λ
A B : A B
Les grammaires naturellement associées aux λ−automates ne sont donc pas les grammaires
régulières : on autorise, de plus, des règles du type « enchaînement de variables » .
Néanmoins :
Théorème 7. Tout λ−automate peut être transformé en un automate, avec un état initial
unique et non récursif.
L’état initial est dit non récursif si on n’y passe qu’une seule fois (à l’entrée dans
l’automate) ; autrement dit, il n’y a pas de cheminement qui y revient en boucle fermée.
Preuve du théorème 7.
λ 1
S’ S
3
2
1
S 3
2
2) il faut maintenant supprimer les transitions d’étiquette vide, ce qui ne peut se faire qu’en
ajoutant de nouvelles transitions afin de compenser ces suppressions (le langage reconnu doit
rester inchangé). Pour cela, il faut :
- repérer tous les chemins qui sont constitués d’une succession de transitions d’étiquette
vide, suivie d’une transition d’étiquette non vide.
- remplacer chacun de ces chemins par une nouvelle transition « court-circuitant » la suite
des transitions d’étiquette vide ; elle est bien sûr étiquetée avec le même symbole que la
dernière transition du chemin.
Exemple :
A
λ B
λ C
a
D
Nous avons ici deux chemins du type voulu qui sont issus de l’état A (l’un aboutit à D,
l’autre aboutit à C après avoir suivi la transition d’étiquette b ) ; nous avons aussi deux
chemins analogues issus de l’état B .
Nous obtenons les transitions suivantes :
a
a
B C a D
A
b
b b
- Attention à ne pas oublier les sorties : si des transitions d’étiquettes vides aboutissent à un
état final, elles ne peuvent être supprimées que si leur état de départ devient un état final.
A
λ B
λ C devient A B C
Soit L un langage régulier. D’après le théorème 8, il est reconnu par un λ−automate, qui
peut être transformé en un automate (et même un ADC) à un seul état initial, non récursif,
d’après le théorème 7 ; à cet automate correspond une grammaire régulière (dont l’axiome
sera d’ailleurs non récursif), d’après le théorème 6.
Nous avons ainsi obtenu une preuve du théorème 2 , que nous rappelons ici :
Théorème 2 (p.12). Tout langage régulier est engendré par une grammaire régulière.
Ce qui précède nous permet aussi de prouver la Proposition 2 , déjà énoncée p.7 :
Preuve du théorème 8.
1
• langage {λ} :
a
1 2
• les langages de la forme {a} :
λ A1
S
λ A2
λ
A1 A2
λ
A
λ
λ
Exercice. Expliquer pourquoi, dans cette dernière construction (pour l’étoile de Kleene), il
faut éviter de partir d’un λ−automate dont l’état initial est récursif.
Note. Ce chapitre, plus technique que les précédents, est un complément à la présentation des algorithmes
d’analyse syntaxiques. Il est indépendant du chapitre précédent qui, traitant des automates est lié essentiellement
aux grammaires régulières.
Le problème : on a vu que l'analyse syntaxique peut être longue, et même inopérante, selon
la forme des règles de grammaire. Les règles qui commencent par une variable, et
particulièrement celles de la forme A Au (où u est une chaîne quelconque), dites
directement récursives à gauche, peuvent empêcher l'analyse syntaxique d'aboutir.
La transformation consiste en une suite d’opérations successives, qui seront décrites à l’aide
d’algorithmes et donc programmables. Résumons-en les étapes consécutives :
1. suppression de la récursivité de l’axiome
2. suppression des règles vides
3. suppression des enchaînements de variables
4. suppression des variables et symboles inutiles
5. mise sous forme normale de Chomsky
6. élimination de la récursivité directe à gauche
7. mise sous forme normale de Greibach
Le but est d’éviter un retour à l’axiome au cours des dérivations, autrement dit d’éviter les
dérivations de la forme S => uSv . Pour cela, l’axiome ne doit pas figurer dans les règles de
grammaire (à droite de la flèche, bien entendu).
Si la variable axiome S est récursive, c’est-à-dire s’il existe une règle de la forme
A uSv :
• rajouter une nouvelle variable, disons S’ , qui sera dorénavant l’axiome (la variable S
est de ce fait banalisée)
• rajouter (en tête de liste) la règle de grammaire S’ S
G’ : S’ S (l’axiome est S’ )
S aS | A (S est une variable banale) A
b | λ
2.1. Construction de l’ensemble NUL des variables dont dérive la chaîne vide.
Exemple. G: S T
T aT
| AA
A b | bATA |
On commence par construire, pour chaque variable, l’ensemble des variables qu’on atteint
par des règles d’enchaînement.
Par définition, CHAIN(A) = { B : variable telle qu’il existe une dérivation A => B }
1. initialiser CHAIN(A) = { A }
2. répéter s’il y a une règle B C avec B ∈ CHAIN(A) telle que C soit une variable
non encore dans CHAIN(A), faire
CHAIN(A) = CHAIN(A) U { C }
tant que l’ensemble CHAIN(A) n’est pas stationnaire (c’est-à-dire jusqu’à ce qu’un passage
en revue complet de toutes les règles laisse l’ensemble inchangé).
1. Pour chaque variable A , pour chaque variable B ∈ CHAIN(A) pour chaque règle
B w telle que w ne soit pas une variable, rajouter la règle A w
2. Supprimer toutes les règles d’enchaînement de variables.
Exemple. G: S T |
T aT |
AA | A
A b
4.1. Construction de l’ensemble des variables dont dérivent des chaînes terminales
Elle est simplissime : on ne garde que les variables collectées dans TERM, ainsi que les
règles qui les concernent.
L’étape TERM est supposée faite ; on peut donc obtenir une chaîne terminale à partir de
chaque variable restante de la grammaire. On définit l’ensemble
ATTEINT = { A : variable telle qu’il existe une dérivation S => uAv }
1. initialiser ATTEINT = { S }
2. répéter pour chaque une règle A u avec A ∈ ATTEINT, pour chaque variable B
figurant dans u faire ATTEINT = ATTEINT U { B }
tant que l’ensemble ATTEINT n’est pas stationnaire.
Comme auparavant, on ne garde que les variables collectées dans ATTEINT, et les règles
qui les concernent.
De ce fait, des symboles terminaux peuvent éventuellement être supprimés : c’est le cas pour
ceux qui ne figuraient que dans des règles concernant des variables supprimées.
Définition. Une grammaire G est sous forme normale de Chomsky si toutes ses règles sont
de l'un des types suivants :
• A BC où B, C ∈ V−{S} • A
a où a ∈ ∑
• S où S est
l’axiome (cette règle est utilisée lorsque est
dans le langage).
Théorème 9. Toute grammaire algébrique est équivalente à une grammaire sous forme
normale de Chomsky.
Preuve du théorème 9.
Faire, si nécessaire, les transformations précédentes 1, 2, 3 et 4. Il reste à modifier les règles
non conformes A w où w ∈(∑ U V)+.
Comme les règles d’enchaînements de variables ont déjà été supprimées, la chaîne w est
de longueur supérieure ou égale à deux. Tout d’abord, on introduit des nouvelles variables de
manière à pouvoir remplacer w par une chaîne de même longueur mais sans symboles
terminaux. Ensuite, les règles de longueur strictement supérieure à deux pourront être
remplacées par des règles plus courtes grâce à des variables supplémentaires introduites dans
ce but.
Exemple.
∑
Soit la règle A aBAdC où a, d ∈ et A, B, C ∈ V.
1) On introduit des variables nouvelles pour chacun des symboles terminaux figurant dans la
chaîne. La règle précédente est ainsi remplacée par le groupe de règles
A
A’
D’
A’BAD’C
a d
Définition. Une grammaire G est sous forme normale de Greibach si toutes ses règles sont
de l'un des types suivants :
• A a où a∈∑
A’ B A D’ C
• A a A1 A2 …An où a ∈ ∑ et A1 , A2
, …, An ∈ V−{S}
• S où S est l’axiome (cette règle est utilisée lorsque est dans le langage).
L’intérêt de cette forme de grammaire est évident : le préfixe terminal des chaînes est
rallongé à chaque utilisation d’une règle de grammaire.
Théorème 10. Toute grammaire algébrique est équivalente à une grammaire sous forme
normale de Greibach.
Définition. Une règle directement récursive à gauche est une règle de la forme A Au où
u∈(∑ U V)+.
Nous avons vu que ce type de règle est particulièrement gênant pour l’analyse syntaxique,
et nous allons décrire une technique permettant de remplacer la récursivité directe à gauche
par de la récursivité directe à droite, qui ne présente aucun désavantage particulier.
Considérons l’ensemble des règles pour une variable A donnée. S’il y a une (ou plusieurs)
règles directement récursives à gauche, il y a aussi d’autres règles qui ne le sont pas, puisque
A n’a pas été éliminée lors de la transformation 4 (suppression des variables inutiles). Une de
ces autres règles est nécessairement utilisée à la suite d’une séquence d’applications de règles
On vérifie que la variable auxiliaire sert à produire toutes les chaînes de la forme un , et
celles-ci sont ensuite concaténées à u ou à v . Elle est directement récursive à droite.
Ce petit exemple peut facilement se généraliser au cas où il y a un nombre quelconque de
règles :
A Au1 | Au2 | … | Aup | v1 | v2 | … | vq avec p règles directement récursives à
gauche, et q règles qui ne le sont pas. On obtient les nouvelles règles
A v1Z | … | vqZ | v1 | v2 | … | vq
Z u1Z | … | upZ | u1 | … | up
Exemple. Voici un autre exemple, concret, sous forme normale de Chomsky, avec deux règles
directement récursives à gauche : A AB | AC | a | BA
Les chaînes dérivées de A en appliquant uniquement les règles directement récursives à
gauche sont A.{B, C}+. Il faut ensuite appliquer avec la troisième ou la quatrième règle, ce
qui nous donne a.{B, C}+ et BA.{B, C}+. On peut donc remplacer les règles pour A par
le groupe de règles
A aZ | BAZ | a | BA
Z BZ | CZ | B | C ( Z désigne la nouvelle variable introduite)
On peut remarquer à cette occasion que ces nouvelles règles ne sont plus sous forme de
Chomsky : nous obtenons des chaînes de variables avec éventuellement un symbole terminal
en préfixe ; de plus, des règles d’enchaînements de variables sont ainsi réapparues, mais
uniquement pour la variable auxiliaire qui a été introduite.
Commençons par choisir un ordre sur les variables, l’axiome étant la première variable.
Définition. Une grammaire dont les variables sont ordonnées est de la forme presque
Greibach si les règles sont de l’un des types suivants :
• S
• A a.u où a ∈∑ et u ∈V*
Notre but est d’arriver à cette forme, à partir d’une forme de Chomsky.
Pour achever la preuve du théorème 10, il suffit de partir d’une grammaire sous la forme
presque Greibach. Seules les règles qui commencent par une variable doivent encore être
modifiées. Leur réécriture avec les règles concernant cette variable en préfixe ne peut
qu’augmenter le n° de la variable en préfixe, ou bien donner un symbole terminal en préfixe.
Comme il n’y a qu’un nombre fini de variables et de règles, la transformation est achevée
après un nombre fini de telles réécritures..
------------------