Vous êtes sur la page 1sur 373

THEORIE DES LANGAGES ET

COMPILATION

Prof. : Souad AMJAD


Dépt. : Mathématiques et Informatique

Février 2009
OBJECTIF (1)

Ce cours vise à introduire les bases de


la théorie des langages (alphabet,
vocabulaire, expressions régulières,
grammaires et automates) et les
principales notions sur les
compilateurs.
OBJECTIF
(2)

Il permet d'appréhender un certain


nombre de techniques fondamentales :
• la présentation de bases pour des techniques
de compilation (analyseurs lexicaux) ;

• de nouvelles techniques de programmation


(notion de programmation dirigée par la
syntaxe) ;
• la compréhension et optimisation de nouveaux outils
proposant l'utilisation des expressions régulières ;

• le contrôle de validité ;
PLAN DU COURS

I. PRESENTATION GENERALE D’UN COMPILATEUR


II. GENERALITES SUR LES LANGAGES
III. LES LANGAGES RATIONNELS

IV. LES GRAMMAIRES DE CHOMSKY


V. LES AUTOMATES
VI. ANALYSES LEXICALE ET SYNTAXIQUE

VII. ANALYSE SEMANTIQUE


VIII.OPTIMISATION ET GENERATION DE CODE
Chapitre 1

Présentation générale sur les


compilateurs

1. Introduction
La compilation constitue la première
étape de la chaîne de production de
programmes.
Chapitre 1

2. Définition
La compilation permet la traduction
d’un programme dit programme
source écrit le plus souvent en
langage de haut niveau vers un
programme dit programme objet qui
est soit directement le langage
machine, soit le langage d’assemblage.
Chapitre 1

Programme Programme
source Compilateur cible

Exemple de langages sources :


Pascal, Fortran, C, Java …

Exemple de langages cibles :


un assembleur ou un code machine.
Chapitre 1

Les principes fondamentaux de


la compilation

1. Le compilateur doit conserver le sens


du programme compilé.

2. Le compilateur doit améliorer le code.


Chapitre 1

Les propriétés de la compilation

1. Code produit efficace (rapidité, mémoire).

2. Choix d’informations retournées en cas


d’erreurs.
3. Rapidité de la compilation.
Chapitre 1

La structure d’un compilateur


Un compilateur peut être subdivisé en
différentes phases :
1) L’analyse lexicale.
2) L’analyse syntaxique.
3) L’analyse sémantique.
4) La production du code objet.
5) L’optimisation du code.
6) Le traitement des erreurs.
Chapitre 1

La structure d’un compilateur

1. Analyse lexicale (reconnaissance des


mots du langage ie. appréhension du
vocabulaire). Elle lit la chaîne de
caractères d'entrée, caractère par
caractère, et la transforme en une suite
de mots ou unités lexicales ;
Chapitre 1

2. Analyse syntaxique (vérification de la


syntaxe ie. appréhension de la
grammaire). Elle vérifie si la suite d'unités
lexicales reconnues par l'analyseur lexical
est légale. L'analyse syntaxique dérive
d’une structure hiérarchique d'unités
lexicales qui peut être représentée par
des arbres abstraits :
Chapitre 1

a. Analyse syntaxique ascendante :


L’analyseur cherche, à partir de la phrase et à
l’aide des règles de la grammaire, à remonter à
l’élément initial (on monte des feuilles vers la
racine)

b. Analyse syntaxique descendante :


L’analyseur cherche, à partir de l’élément initial
et à l’aide des règles de la grammaire, à former
la phrase donnée (on descend de la racine vers
les feuilles)
Chapitre 1

3. Analyse sémantique (vérification de la


sémantique ie. appréhension du sens).
Elle contrôle si le programme source a un
sens. L'un des rôles importants de
l'analyse sémantique est, en particulier, le
contrôle de type : on vérifie si les
opérandes de chaque opérateur sont
conformes aux spécifications du langage
source (opérations arithmétiques entre
nombres entiers, ou réels...).
Chapitre 1

4. La production du code objet


Le but final d’un compilateur est la
production d’un programme objet.

5. L’optimisation du code
Le code produit par le compilateur doit
être performant (ie. rapide à l’exécution
et peut coûteux en place mémoire).
Chapitre 1

6. Le traitement des erreurs


Un compilateur doit détecter les erreurs
lexicales, syntaxiques ou sémantiques,
donner des diagnostics clairs et précis et
être capable de poursuivre l’analyse du
programme source.
Chapitre 1

Exemple
• lexicales, comme l'écriture erronée d'un
identificateur, d'un mot clé ou d'un opérateur ;

• syntaxiques, comme une expression


mathématique mal parenthésée;

• sémantiques, comme un opérateur appliqué


à un opérande incompatible ;

• logiques, comme un appel récursif infini ;


CHAPITRE 2

GENERALITES SUR LES


LANGAGES

DÉFINITIONS ET CONCEPTS DE BASE


Chapitre 2

1. Mots

Définition

Un symbole est une brique élémentaire, un


atome.

Si a Є A atome alors ∀ x, y Є A, a ≠ x+y.

Un alphabet A est un ensemble fini et non


vide de symboles.
Chapitre 2

Un mot m (ou chaîne) sur un alphabet A est


une suite finie m1m2 · · ·mn de lettres de A.
L’entier n est appelé la longueur du mot m,
notée |m|.

Le mot vide est le mot de longueur 0,


c'est-à-dire ne contenant aucun symbole. Il
est souvent noté ε.
Chapitre 2

Remarque

Les alphabets seront décrits comme des


ensembles de symboles (entre accolades),
composés de plusieurs caractères.

Les symboles représentés par des signes


de ponctuation seront entre quotes.
Chapitre 2

Exemple
A1 = {1}

A2 = {0, 1}

A3 = {., -, /}

A4 = {0, 1, 2, ..., 9}

A5 = {a, b, ..., z}
Chapitre 2

Exemple

A={a,b,c} : un alphabet.

abbc, aaaa, bc, ε sont des mots sur


l'alphabet A, respectivement de
longueur

4, 4, 2 et 0.
Chapitre 2

Remarque

Soit l'alphabet {a,b,c,h,ch,';',','}.

ch et c + h ≡ ch

sont théoriquement différents.

ch (|ch|=1)

c + h ≡ ch (|c + h|=2)
Chapitre 2

Notation
• a, b, c, d, e, f, 0, 1... désignent des symboles.
• t, u, v, x, y, z désignent des chaînes.
• La chaîne aaaa est aussi notée a4. Par
conséquent, a0=ε.
• Le symbole m(i) désigne le i-ème symbole de
la chaîne m.
Chapitre 2

Remarque

• L’opération particulière :
la concaténation.
x , y : chaînes ;
La concaténation de x et y : xy
Chapitre 2

Exemple
Si u = abaa et v = bab alors
uv = abaabab et vu = bababaa

N.B.
La concaténation n’est pas commutative.
Chapitre 2

• Cette opération est associative :


(xy)z=x(yz)=xyz .
• La chaîne vide ε est un élément
neutre pour la concaténation.
u ε = ε u = u.
Chapitre 2

Définition
Étant donné un alphabet A :

•A* : ensemble de tous les mots sur A.

•Dans A*, une opération dite produit


de concaténation ou simplement
concaténation est définit. Elle est
notée + ou plus souvent implicite
(simple juxtaposition des opérandes).
Chapitre 2

u et v deux mots de longueur p et q


La concaténation de u et v (dans cet
ordre) est le mot w de longueur p+q
défini par :
w(i)=u(i) si 1 ≤ i ≤ p

w(p+i)=v(i) si 1 ≤ i ≤ q.
Chapitre 2

Théorème de la Décomposition

Tout mot x (de longueur n=|x|) sur un


alphabet A se décompose de façon unique
en x1 + x2 + ... + xn , également noté

x1x2...xn , où i [1..n], xi A.
Chapitre 2

Démonstration
Comme les symboles de l'alphabet sont des
atomes, il n'est pas possible de diviser un mot
plus qu'au niveau de ces symboles. Si deux
divisions en symboles étaient possibles, cela
voudrait dire qu'un symbole peut être divisé et
donc il ne serait pas atomique.

Exemple: soit A = {a,b,c} un alphabet alors


abbcabbc = a + b + b + c + a + b + b + c.
Chapitre 2

Remarque

Une chaîne sur un alphabet A peut également


être définie récursivement par :
 la chaîne vide ε est une chaîne sur A;
 si x est une chaîne sur A et a A alors la
chaîne ax et xa sont des chaînes (mots) sur A
(Attention, dans le cas général, ax ≠ xa);
 aucun autre objet n'est une chaîne sur A.
Chapitre 2

Notation

An : ensemble des mots (ou chaînes) de


longueur n (pour n N) construits sur A

(An = {x1x2...xn | i, 1 ≤ i ≤ n, x i A})

Par conséquent:

toutes les chaînes y de l'ensemble A3 ont pour


longueur |y|=3
Notation
Chapitre 2

A+ : L'ensemble des chaînes de longueur finie et


non nulle définies sur A.

A+ = Un=1.. ∞ An = { x | ∀n ∈N, n ≥ 1 et x ∈An }


A* = A+ U {ε}

Par convention :
A0 = ε
A*=Un=0..∞ An
Chapitre 2

Exemple

A= {0,1} : alphabet

• A0={ε} ;

• A1 = A ={0, 1} ;

• A2 = {0,1}2 = {00, 01, 10, 11} ;


Chapitre 2

• A3 = {0,1}3 = {000, 001, 010, 011, 100, 101,


110, 111};

• A* = {0,1}* = {ε, 0,1, 00,01,10, 11,000,


001, 010, 011,..., 11111, ..., 1001101110...}

• A+ = {0,1}+ = {0,1, 00,01,10, 11,000, 001,


010, 011,..., 11111, ..., 1001101110...}.
Chapitre 2

Remarque

n m
Si c1 A et c2 A

alors

c1 + c2 An+m
Exercices
Chapitre 2

1) Donner la longueur des mots suivants


sur l'alphabet {a,b,c} :
 abccb
 abbcaa
 ε
 bbb

Solution :

5, 6, 0 quelque soit l’alphabet et 3.


Exercices
Chapitre 2

2) Donner la longueur des mots suivants


sur l'alphabet {a,b,ch,','} :
 a,bbaa
 achbbaa

Solution :

6,

6 car « ch » est un symbole de l’alphabet et


donc il compte pour un atome.
Chapitre 2

2. Relations entre mots

Définition

Si x et y sont deux chaînes quelconques sur A,


alors :
X est un préfixe de y (x Pref(y)) s'il existe z dans
A* tel que y = xz, autrement dit x Pref(y) si et
seulement si z A*, y = xz :
Chapitre 2

X est un suffixe de y (x Suff(y)) s'il existe z


dans A* / y = zx, autrement dit x Suff(y) si
et seulement si z A*, y = zx ;

X est une sous-chaîne (ou facteur) de y s'il


existe w et z dans A* tel que y = wxz,
autrement dit x Fact(y) si et seulement si
aw, z A*, y = wxz ;

Si x ≠ y (c'est-à-dire si z ≠ ε), alors le préfixe


ou le suffixe est dit propre.
Chapitre 2

Exemple

Soit la chaîne 001110 :

00 est un préfixe ;

10 est un suffixe ;

0111 est une sous-chaîne.


Chapitre 2

Remarque Générale

• x est un préfixe (facteur gauche)


de x+y+z ;

• z en est un suffixe (facteur droit) ;

• y en est une sous-chaîne ;


Chapitre 2

• x, comme y et z peuvent très bien


être vides ;

• ε est préfixe, suffixe et sous-chaîne


de toute chaîne;

• Pref(x) C Fact(x) et Suff(x) C Fact(x).


Chapitre 2

Définition
Une occurrence d'une chaîne x dans une
chaîne y est une apparition de x à un endroit
précis dans la chaîne y.
Exemple

A = {a,b} : alphabet

le mot y = ababababa comporte ? occurrences


de la sous-chaîne x = aba.
4
Chapitre 2

Relations d’ordre

Soit A* défini sur A = {x1,x2, ..., xn}, il est


possible de définir plusieurs relations
d'ordre:

Ordre préfixiel

•ordre partiel définit par : u < v si et


seulement si u est un préfixe propre de v ;
Chapitre 2

Ordre lexicographique

•ordre total défini par : u < v si et seulement si


u = wau2 et v = wbv2 tels que w A*, a < b
avec a et b A;

•u<v si et seulement si u=aw, v=bz et (a<b)


ou ((a=b) et (w<z)), a, b A et w,z A* avec
ε < t ∀ t A+. Tout ceci est valable si et
seulement si ∀ xi, xj A, xi ≤ xj si i ≤ j.
Chapitre 2

Ordre hiérarchique

•ordre total pour lequel les mots sont


classés en premier lieu par longueur, puis
pour les mots de même longueur, par ordre
lexicographique.
Chapitre 2

Exercice

Soit x=abbcc un mot sur l'alphabet


A={a,b,c} :
1) donner l'ensemble Pref(x)
2) donner l'ensemble Suff(x)
Chapitre 2

Solution
Chapitre 2

3. Langages et opérations
Définition
Un langage L sur un alphabet A est un
ensemble de chaînes (ou ensemble de mots)
sur A. L est un sous-ensemble de A*,
autrement dit L C A*.

l'ensemble des langages L sur A est l'ensemble


P(A*) des parties de A*, autrement dit : L C P(A*).
Chapitre 2

Exemple 1

Soit l'alphabet A = {0, 1}

L1 = {0, 00, 1, 01, 11, 10 } : langage sur A.

Pour tout entier naturel n, An est un langage


sur A.
Chapitre 2

L2 = { 0n1n | n ≥ 0},

L3 = {0n10m | n ≥ 0, m ≥ 1},

L4 = {1n | n ≥ 2}

L5 = {0i | i ≥ 0} = {0}* sont des langages


sur A.

Pour toute lettre a, an désigne le mot formé


de n symboles de a consécutifs,
Chapitre 2

Exemple 2

A= {a,b,c} : alphabet

• A*={ε, a, b, c, ab, ba, . . .} ;

• {ε, a, b, c} : tous les mots de longueur


strictement inférieure à 2 ;

• {ab, acb, aab, acab, aabb, . . .} : tous les


mots qui commencent par un a et finissent par
un b ;
Chapitre 2

• {ε, ab, aabb, aaabbb, . . .} : tous les mots


contenant n a suivis d’autant de b. Ce
langage est noté {anbn, n ≥ 0} ;

• {ε, abc, aabbcc, aaabbbccc, . . .} : tous les


mots contenant n occurrences de la lettre a,
suivies d’un nombre identique d’occurrences
de la lettre b, suivies d’autant de fois la lettre
c. Ce langage est noté {anbncn, n ≥ 0}.
Chapitre 2

Définition
Étant donné un alphabet A, parmi tous les
langages L de P(A*) :

langage neutre : langage dont le seul mot


est la chaîne vide , L = {ε}.

langage vide : langage qui ne contient


aucun mot, soit L = ∅.
∅ ≠ {ε}
Chapitre 2

langage fini : langage qui contient un


nombre fini de mots.

langage infini : langage non vide et non fini.

Un langage L est dit posséder la propriété


préfixe (resp. suffixe) si aucune chaîne de L
n'est préfixe propre (resp. suffixe propre)
d'une autre chaîne de L.
Chapitre 2

Exemple

L = {aib | i ≥ 0 }

= {b, ab, aab, aaab...}

est dit préfixe mais n'est pas suffixe.

L = {an | n N}

n'est ni préfixe ni suffixe.


Chapitre 2

Remarque
Comme les langages sont des ensembles,
des opérations ensemblistes classiques
peuvent être appliquées: union, intersection,
complémentation, ...

De plus, par extension de la concaténation


des mots aux langages, on peut définir
quelques autres opérateurs.
Chapitre 2

Définition

Soit A un alphabet. On définit sur les


langages de P(A*) les opérateurs
suivants : soient L et M deux langages
sur A,
Chapitre 2

Opérateurs ensemblistes classiques :

union : L U M = {x | x ∈ L ou x∈ M} ;

intersection : L ∩ M = {x | x∈ L et x∈ M};

différence (ou exclusion) :


L\M = L-M = {x | x ∈ L et x ∉ M};

complémentaire sur A* :
Comp(L)= A*\L = {x | x ∈ A* et x ∉ L};
Chapitre 2

Opérateurs induits par la concaténation


des mots :

produit des langages :


LM = L×M = {xy | x∈ L et y ∈ M};

fermeture de Kleene :
L* = Ui=0..∞ Li où L0 = {ε} et Ln = LLn-1 = Ln-1L

fermeture positive :
L+= Ui=1..∞ Li.
Chapitre 2

Remarque

le produit est parfois appelé "concaténation


de deux langages". Cette concaténation est
notée × (et le symbole × est souvent omis),
mais il s'agit bien de deux concaténations
différentes : l'une entre mots et l'autre entre
ensembles de mots.
Chapitre 2

Intuitivement, la concaténation de deux


langages est l'ensemble des mots obtenus
en concaténant un mot du premier langage
avec un mot du second.

Exemple

si L1={a,bc} et L2={de,f}
alors L1 × L2= L1L2 = {ade, af, bcde, bcf}.
Chapitre 2

Exemple

L = {A,B, … ,Z,a,b, … ,z} et C={0,1, … ,9}

LUC: Ensemble des lettres et des


chiffres;

LC: Ensemble des chaînes formées


d’une lettre suivi d’un chiffre;
Chapitre 2

L4 : Ensemble de chaînes de 4 lettres;

L* : Ensemble de toutes les chaînes de


lettres, y compris la chaîne vide
ε;
C+ : Ensemble de toutes les chaînes
formées d’au moins un chiffre;
Chapitre 2

Exercice
Soient les deux langages :
L = {u A∗ | |u| pair }
M = {u A∗ | |u| impair }.
• L + M = A*
• LM = M = ML
• MM = L \ {ε}
• LL = L
Chapitre 2

Propriété

•Le langage vide est absorbant pour la


concaténation des langages :

•∅L = ∅ = ∅L
•L+ = LL* = L*L

•L* = {ε} U L+

•∅* = {ε}
•{ε}* = {ε}
Chapitre 2

• Le langage neutre est élément neutre pour


la concaténation des langages :
{ε}L = L = L{ε}

• La concaténation des langages est


associative :
(L1L2)L3 = L1(L2L3)
 Exo :
Montrer que le produit de deux
langages préfix est un langage
préfixe

indication : L est un langage préfix si


qlqesoit y app L , y #x tel que y
napp pref(x)
Chapitre 3

LES LANGAGES RATIONNELS


1. Introduction

Parmi tous les langages constitués par les


parties de A* engendrés par un alphabet
A, une classe particulière est distinguée :
la classe Rat(A*) des langages rationnels
sur A.
Chapitre 3

L'intérêt de cette classe est qu'il existe


une méthode simple permettant de
décider pour chacun de ses langages si
un mot lui appartient ou non :

Automates Finis.
Chapitre 3

2. Langages rationnels

Définition

Soit A un alphabet. Les langages


rationnels sur A (appelés aussi
langages réguliers) sont les éléments de
la classe Rat(A*) définie inductivement de
la façon suivante : Rat(A*) est le plus
petit sous-ensemble de P(A*) tel que :
Chapitre 3

1. ∅ ∈ Rat(A*);

2. {ε}∈ Rat(A*);

3.∀ a∈ A, {a}∈ Rat(A*);

4. Si L1∈Rat(A*) et L 2

Rat(A*) alors L1UL2

Rat(A*);

5. Si L1 ∈ Rat(A*) et L2 ∈ Rat(A*) alors


L1×L2∈ Rat(A*);
6. Si L1 ∈ Rat(A*) alors L1* ∈ Rat(A*).
Chapitre 3

Exemple
A={a,b,c} : alphabet,

{a}* : (ensemble des mots qui ne sont


formés que de a) : langage de Rat(A*)

En effet : l’application des points 3, puis 6 de la


définition précédente ;

{a} U {b}∈ Rat(A*),

{b} × {a}∈ Rat(A*)...


Chapitre 3

{b} × ({a} U {b} U {c})* (ensemble des


mots sur A commençant par un b) :
langage de Rat(A*) ;

Ce langage est obtenu en appliquant


successivement les points 3 (3 fois), 4 (2
fois), 6 (1 fois) et 5 (1 fois).
Chapitre 3

Théorème des parties finies


Toute partie finie L de A* est dans
Rat(A*).

Démonstration

Comme toute partie finie peut être vue comme


la réunion de singletons, L peut être obtenu
par un certain nombre d'applications des points
1 à 5 et en utilisant le théorème de
décomposition unique d'un mot.
chapitre 3

Exercice

le langage L={0,1,00,11,000,111}
sur l'alphabet {0,1,2} est-il un
langage rationnel ?
chapitre 3

Solution

Il est construit par l'union de 6 langages


rationnels {0}, {1}, {00}, {11}, {000} et
{111}.

• les deux premiers sont des cas de base


pour la définition (point 3) ;
chapitre 3

• les 4 suivants correspondent aux produits de


langages rationnels (par exemple, {00} = {0}
× {0}) ;

• le produit de deux langages rationnels est un


langage rationnel ;

• l'union de deux langages rationnels est un


langage rationnel (point 4) ;

L est bien rationnel.


chapitre 3

Remarque
On peut construire à l'aide des opérateurs de la
définition précédente de nombreux langages
désignés par des expressions mathématiques.

Exemple
L={(({a}U{b})*×{a})*×({b}×{c})*}, ce qui,
en appliquant les définitions peut se simplifier
en L={({a,b}*×{a})*×{bc}*}.
chapitre 3

Remarque

Il existe pour les langages rationnels une


écriture simplifiée, plus compacte et
pratique : c'est ce qu'on appelle les
expressions rationnelles.

Chaque expression rationnelle décrit un


langage rationnel précis.
chapitre 3

Exercice

Soit l'alphabet A={0,1}, le langage


décrivant les symboles de la table ASCII
en binaire est-il un langage rationnel ?
chapitre 3

Solution

Le théorème des parties finies peut être utilisé.

Les symboles de la table d’ASCII sont


représentés sur un octet de (0 à 255) ;

Par conséquent, l’ensemble des mots est fini


(256!) ;

D’après le théorème, ce langage est rationnel.


chapitre 3

3. Expressions rationnelles

Définition

Les expressions rationnelles sur A


décrivent les langages rationnels. Elles
sont définies de la façon suivante :
chapitre 3

1. ∅ est une expression rationnelle qui


décrit le langage rationnel ∅ ;

2. ε est une expression rationnelle qui


décrit le langage rationnel {ε} ;

3.pour tout a de A, a est une expression


rationnelle qui décrit le langage
rationnel {a} ;
chapitre 3

4. Si l1 et l2 sont des expressions rationnelles


qui décrivent L1 et L2∈Rat(A*) alors :

a. (l1 | l2) et (l1 + l2) sont des


expressions rationnelles identiques
qui décrivent le langage rationnel
L1 U L 2 ∈Rat(A*),
chapitre 3

b. (l1l2) et (l1.l2) sont des expressions


rationnelles identiques qui décrivent le
langage rationnel L1 × L2∈ Rat(A*),

c. (l1)* est une expression rationnelle qui


décrit le langage rationnel (L1)*.
chapitre 3

Comme la réunion et la concaténation sont


associatives, les parenthèses inutiles sont
effacées. (u | v | w) remplacera ((u |v) | w)
ou (u | (v | w)).

Exemple:

L={(({a}U{b})*×{a})*×({b}×{c})*
}
= ((a|b)*a)*(bc)*
chapitre 3

N.B.

Il est sous-entendu qu'aucun des


symboles "|", "*", "ε", "(" et ")"
n'appartient à l'alphabet A. Sinon, il
faut soit les différencier en renommant
les symboles, soit les entourer de
guillemets.
chapitre 3

Théorème
chapitre 3

A : un alphabet
C = { |, *, ε, (, )} ; A∩C=∅ ;

Un élément w est une expression


rationnelle si et seulement si :

 w ∈ A* ;

 w est de la forme w1*, w1w2 ou w1 | w2


avec w1 et w2 des expressions rationnelles.
chapitre 3

une expression rationnelle désigne un


langage rationnel de la façon suivante :

 w ∈ A* désigne le langage dont le seul


mot est w (w peut être ε) ;

 soient w1 et w2 des expressions


rationnelles désignant les langages L(w1)
et L(w2) alors:
chapitre 3

w1w2 désigne le langage dont chaque mot


est obtenu en concaténant (juxtaposant)
un mot du langage désigné par w1 avec
un mot du langage désigné par w2 (dans
l'ordre) : L(w1) L(w2) ;
chapitre 3

w* désigne le langage dont chaque mot


est obtenu en concaténant un nombre
quelconque (éventuellement nul) de mots
du langage désigné par w : (L(w))*;

w1|w2 (parfois notée w1+w2) désigne la


réunion des langages
désignés par w1 et w2.
Les mots de w1|w2 sont
ceux qui appartiennent
chapitre 3

Notation

• w+ = w w* = w* w ;

• w? signifie 0 ou 1 instance de w. Donc w?


est une abréviation pour w | ε;

• la notation [a, b, c], où a, b et c sont des


symboles, abrège l'expression rationnelle a|b|
c. Une classe de caractères comme [a-z]
abrège l'expression rationnelle a | b | ... | z.
chapitre 3

• wn, pour un n ≥ 0 désigne la chaîne


composée de n occurrences du mot du
langage désigné par w.

Si n est quelconque :

wn (n ≥ 0) ≡ w* ;

wn (n > 0) ≡ w+.
chapitre 3

Exemple

01 désigne le langage {01} ;

0* désigne le langage {0}* ;

a|b désigne le langage : {a , b} ;

(a|b)(a|b) : aa|ab|ba|bb {aa, ab, ba, bb} ;

a* désigne le langage {ε, a, aa, aaa, …} ;


chapitre 3

Exemple

(a|b)* : L = {ε , a, aa , …, b, bb, …, ab,


aab, … , ba, bba, …., bbab, …} ;

a|a*b : L = {a, b, ab, aab, aaab, …} ;

(0|1)*011 : désigne le langage qui ne


comporte que des chaînes se
terminant par 011 ;
chapitre 3

[A-Z,a-z][A-Z,a-z,0-9]*

décrit la syntaxe des identificateurs en


Pascal : des mots commençant par une
lettre, majuscule ou minuscule ([A-Z,a-z])
et suivit d'une suite quelconque de
caractères parmi les lettres et les chiffres
([A-Z,a-z,0-9]*).
chapitre 3

Notation
wn : un langage rationnel quand n est un
entier fixé, par contre, ce n'est pas toujours
vrai dans le cas général, quand n est une
variable.
Exemple :

(ab)3 : désigne ababab qui est une expression


rationnelle ;
[a,b]2 : désigne (a|b)(a|b) ;
chapitre 3

Par contre, le langage désigné par anbn n'est


pas rationnel : il s'agit des mots commençant
par un certain nombre de a et suivis du
même nombre de b.

Ce langage ne peut pas être obtenu à partir


des parties finies d'un alphabet A par simple
application des opérations ×, U et *.

Ceci illustre bien le fait que tout langage sur A


n'est pas nécessairement rationnel.
chapitre 3

Définition

Une expression rationnelle est dite


standard si et seulement si les seuls
opérateurs utilisés sont les opérateurs
×, U et *.
chapitre 3

Remarque
Les expressions rationnelles décrivent des
langages, c'est-à-dire des ensembles de mots
sur un alphabet A donné (souvent
implicitement).

Il s'avère que deux expressions différentes


peuvent décrire un même langage.

a*a et aa* désignent toutes deux l'ensemble


des chaînes de n a consécutifs pour n>0.
chapitre 3

Définition

Deux expressions rationnelles w1 et w2


sont dites équivalentes (ou par abus de
langage "égales"), noté "w1≡w2" (ou
"w1=w2"), si elles décrivent le même
langage rationnel.
chapitre 3

Propriété
Soient u, v et w des expressions rationnelles :
Union

• u|v = v|u (commutativité)

• u|u = u (idempotence)

• u|∅ = u (∅ : élément neutre)

• u|(v|w) = (u|v)|w (associativité)


chapitre 3

La mise à l'étoile

• u** = u* (idempotence)

• ∅* = ε

La mise à l'étoile et l’union

• u* = u|u* (absorption)
chapitre 3

La concaténation

• uε = εu = u (ε : élément neutre à
gauche et à droite)

• u∅ = ∅u = ∅ (∅ : élément absorbant
à gauche et à droite)

• u(vw) = (uv)w (associativité)


chapitre 3

La concaténation et l’union

• (u|v)w = uw|vw (distributivité à droite


de la concaténation par rapport à
l'union)

• u(v|w) = uv|uw (distributivité à


gauche de la concaténation par rapport
à l'union)
chapitre 3

Remarque

uw ≠ wu (la concaténation n'est


pas commutative) !

sauf si u = w
chapitre 3

Définition

Un facteur itérant est une sous-chaîne


non vide pouvant être "étoilée". Autrement
dit, v est facteur itérant de m ∈L si :
m=uvw, |v| ≠ 0,∀ i, uviw∈ L (uv*w C L).

Exemple

Dans le mot "bbaab" du langage décrit par


bb(a2)*b, le facteur "aa" est un facteur itérant.
chapitre 3

Définition

Un mot primitif est un mot u tel que


u=vn si n=1, c'est-à-dire s'il n'est pas
puissance d'un autre mot que lui-même.
Exemple
{a,b} : alphabet ;
"abab" n'est pas primitif ;

"ab" est primitif.


chapitre 3

Exercice

Écrire les expressions rationnelles


décrivant les langages suivants :
 {ab}
 {anbam, n ≥ 0, m ≥ 0}
 {an, n ≥ 2}
chapitre 3

Solution

Les expressions rationnelles décrivant


ces langages sont :
 ab ;
 a*ba* ;
 aa+
chapitre 3

Exemple

• A* : tous les mots ;

• aA* : mots commençant par a ;

• A*a : mots finissant par a ;


chapitre 3

• (b + ab)*(a + ε)
mots n’ayant pas deux a consécutifs ;

• a* + b*
mots n’ayant que des a ou que des b ;

• (aa + b)*

mots avec des blocs de a de longueur paire ;


chapitre 3

4. Définitions rationnelles

Si A est un alphabet de symboles de base,


une définition rationnelle est une suite de
n définitions (n ∈
N) de la forme di → ri (pour
i ∈ n}), où chaque di est un nom
{1,...,
distinct, n'appartenant pas à (A U {|, *, ε,
(,)})*, et chaque ri une expression
rationnelle sur l'alphabet augmenté A U {d1,
..., di-1}.
chapitre 3

Exemple

Les identificateurs en Pascal sont définis


par :

 lettre → A | B | ... | Z | a | b | ... | z ;

 chiffre → 0 | 1 | ... | 9 ;

 id → lettre (lettre|chiffre)*.
chapitre 3

Remarque

 Chaque membre droit (ri) d'une règle


(di → ri) ne peut faire intervenir que
les nouveaux symboles définis
antérieurement (les dj tels que j<i) ;
chapitre 3

Exercice

Donner l'alphabet et les définitions


rationnelles permettant de décrire le
langage dont les mots sont les
nombres décimaux.
chapitre 3

Solution

L'alphabet : {0,1,2,3,4,5,6,7,8,9,’,’}

• PartieEntiere [1-9][0-9]*|[0-9]

• PartieDecimale [1-9][0-9]*|0

• NbreDecimale PartieEntiere,PartieDecimale
chapitre 3

5. Systèmes d'équations rationnelles

Les définitions rationnelles permettent de proposer


des expressions rationnelles plus lisibles.
Cependant, il est parfois nécessaire d'obtenir une
expression rationnelle ne comportant que des
symboles du vocabulaire. Il faut donc alors essayer
de trouver cette expression. La simple substitution
n'est pas toujours suffisante, surtout en cas de
récursivité.
chapitre 3

La solution consiste à passer par la résolution


d'un système d'équations rationnelles. La
transformation s'effectue en utilisant
directement les définitions rationnelles.
L'opérateur → devient =, l'opérateur | devient
+, parfois ε devient 1 et les identificateurs
deviennent des variables. La résolution du
système ainsi obtenu donne l'expression
rationnelle du langage.
chapitre 3

Définition

Les systèmes d'équations


rationnelles sont des ensembles
d'équations dont les coefficients
sont des expressions rationnelles.
chapitre 3

Exemple

Le système suivant est un système


d'équations rationnelles :

X=a1X+a2Y+a3

Y=b1X+b2Y+b3
ai, bi (i=1,2,3) : expressions rationnelles .
chapitre 3

Solution

X=(a1|a2b2*b1)*(a3|a2b2*b3)

Y=(b2|b1a1*a2)(b3|b1a1*a3)

Remarque
les solutions ne sont pas uniques, mais, en
général, on s'intéresse à la plus petite des
solutions .
chapitre 3

Définition
Un ensemble d'équations rationnelles
d'indéterminés D={X1, ..., Xn} est en forme
standard si Xi
∀ ∈
D, il y a une équation de
la forme :
Xi=ai0 + ai1X1 + ... + ainXn
avec aij des expressions rationnelles sur A
telles que A ∩ D = ∅.
chapitre 3

Remarque

il est possible d'avoir aij=∅ quand il n'y a


pas de terme correspondant à Xj dans
l'équation de Xi.
∅ joue le rôle de 0 ;
ε celui de 1 (l'équation pour Xi comporte
alors Xj sans coefficient à droite).
chapitre 3

Lemme d’Arden
Soient K et L deux langages sur A* (K ⊆ A*
et L ⊆ A*), ε ∉ K, alors :
1) K*L est l'unique solution de l'équation X =
KX + L.
2) LK* est l'unique solution de l'équation X =
XK + L.
Si ε ∈ K, alors A* est solution et K*L la plus
petite solution.
chapitre 3

De ce lemme, il est possible de démontrer un


certain nombre d'identités rationnelles très
utiles pour démontrer des équivalences
d'expressions rationnelles ou pour simplifier des
expressions.

En particulier, les identités suivantes :


(E+F)* = E*(FE*)* (e1)
(E+F)* = (E*F)*E* (e1')
(EF)* = 1+E(FE)*F (e2)
chapitre 3

Pour démontrer e1 par exemple, il suffit de


démontrer que

(a+b)* = a*(ba*)*.

(a+b)*, selon le lemme d'Arden, est l'unique


solution de l'équation X = (a+b)X+1.

Si (a+b)* = a*(ba*)* alors a*(ba*)* est aussi


solution de cette équation.
chapitre 3

(a+b)(a*(ba*)*)+1 = a+(ba*)* + ba*(ba*)*+1

= a+(ba*)* + (ba*)++1

= a+(ba*)* + (ba*)*

= (a+ + 1)(ba*)*

= a*(ba*)*

D’où : (E+F)* = E*(FE*)*


chapitre 3

Algorithme de résolution

Soit un système de n équations


rationnelles notées X1, ..., Xn. Cette
méthode se déroule en trois phases :
chapitre 3

1. Écrire, quand c'est possible, les équations du


système sous la forme :

Xi = xiXi + Yi

xi : expression rationnelle sur A ;

Yi : expression rationnelle de la forme

y0 + y1X1 + ... + yi-1Xi-1 +yi+1Xi+1 + ... + ynXn

avec yi des expressions rationnelles sur A.


chapitre 3

2. Pour toutes les équations Xi de X1 à Xn-1,


sachant que selon le lemme d'Arden,
l'unique solution pour Xi = xiXi+Yi est xi*Yi,
remplacer dans toutes les équations Xi+1...
Xn la variable Xi par xi*Yi.
3. Pour toutes les équations Xi de Xn à X1,
calculer la valeur de Xi en appliquant le
Lemme d'Arden et remplacer Xi par cette
valeur dans toutes les équations de Xi-1 à X1.
chapitre 3

Remarque
Il faut penser à simplifier continuellement vos
chapitre 3

Exemple
D = {X1, X2, X3}

A = {0,1}

le système S :

X1 = 0X2 + 1X1 + ε

X2 = 0X3 + 1X2

X3 = 0X1 + 1X3
chapitre 3

Étape 1

X1 = 1X1 + (0X2 + ε)

X2 = 1X2 + (0X3)

X3 = 1X3 + (0X1)
chapitre 3

Étape 2

X1 = 1*(0X2 + ε)

X2 = 1*0X3

X3 = 1X3 + (01*(01*0X3 + ε))


chapitre 3

Étape 3

X3 = (1+01*01*0)X3 + 01*

= (1+01*01*0)*01*
X2 = 1*(0X3)

= 1*0(1+01*01*0)*01*
X1 = 1*(0X2 + ε)

= 1*01*0(1+01*01*0)*01*+1*
chapitre 3

6. Lemme de l'étoile
Lemme de l’étoile (de la pompe)

Soit L un langage rationnel sur un alphabet


A. Alors il existe un entier naturel n tel que
pour tout mot z de L vérifiant |z|>n, il existe
u,v,w ∈ A* tels que z=uvw, v ≠ ε, |uv|≤n et
pour tout i ∈ N, uviw ∈ L.
chapitre 3

Attention

Ce lemme peut s’appliquer à des


langages qui ne sont pas rationnels. Mais
tout langage rationnel vérifie ce lemme.

Rat(A*) C Etoile(A*) C P(A*)


chapitre 3

Remarque 1
Ce théorème permet souvent de
démontrer par l'absurde qu'un
langage L n'est pas rationnel : il suffit
de montrer que, pour tout n de N, il
existe un mot z de L qui ne vérifie pas la
condition pour un i donné. Mais
attention, un mot peut ne pas fonctionner
parce que trop court !
chapitre 3

Généralement, il n'est pas nécessaire de


trouver le n. C'est vrai pour tout n'>n, il
n'est donc pas nécessaire de trouver le n
optimal. En effet, si le facteur itérant est
dans le n premières lettres alors il est
aussi dans les n' premières.
chapitre 3

Remarque 2
Par contre, montrer qu'un langage
vérifie le lemme de l'étoile ne prouve
pas qu'il est rationnel. Si le lemme de
l'étoile ne permet pas de prouver qu'un
langage est rationnel, une piste possible
est de faire une démonstration par
l'absurde en cherchant à démontrer qu'il
est rationnel.
chapitre 3

Exemple
Le langage{ambm|m ∈N} est il rationnel?

Hypothèses

Il existe un entier positif n z ∈


∈N, tel que ∀ L, |z| >

n, (H1) u,v,w, tels que z=uvw, (H2) v ≠ ε, (H3) |
uv| ≤ n, (H4) ∀i ∈N, uviw ∈{ambm|m ∈N}
chapitre 3

Le mot qui va poser problème :

Considérons le mot z=anbn (|z|=2n, donc


|z|>n). Soient u,v et w tels z=uvw (H1)
et vérifiant H2, H3 et H4 (z est plus long
que n et par hypothèse, u, v et w
existent).
chapitre 3

La contradiction :

Tout préfixe de z de longueur l ≤ n est


nécessairement composé uniquement de a.
Comme uv est un préfixe de z (H1 : z=uvw)
et |uv|<n (H3), ceci est vrai en particulier de
uv. Donc il existe k,p ∈N (p ≠ 0) tels que
u=ak, v=ap (H2 : v ≠ ε) et k+p ≤ n.
chapitre 3

On a z = uvw = akapw, avec w=an-(k+p)bn (car


z=anbn).
H4 s'écrit alors
∀ i∈N, ak(ap)ian-(k+p)bn ∈{ambm | m ∈N},
or ceci est faux :
ak(ap)ian-(k+p)bn = akap(ap)i-1an-(k+p)bn

= akapan-(k+p)(ap)i-1bn

= an(ap)i-1bn
chapitre 3

comme p ≠ 0, pour n'importe quel i > 1,


an(ap)i-1bn ∉ L.

Conclusion :

Donc l'hypothèse est fausse.

D’après le théorème de l'étoile, {ambm |


m ∈N} n'est pas un langage rationnel.
chapitre 3

Remarque
Ce lemme ne peut pas servir à démontrer
qu'un langage est rationnel : il existe en effet
des langages non rationnels qui le vérifient.

L = {ambpcp|m,p ∈N et m > p} : il suffit de


considérer n=2, car tout mot de L plus long
que 2 commence nécessairement par 2 a et
l'on peut itérer à volonté le deuxième a, par
exemple, sans sortir du langage L).
Chapitre 4

LES GRAMMAIRES
DE CHOMSKY
chapitre 4

1. Introduction
Un langage est défini par l'ensemble de ses
mots, de ses phrases correctes. Il est
impossible de donner la liste des phrases (ou
mots) correctes d'un langage parce qu'elle est
souvent infinie. Pour les langages rationnels
nous pouvons les dénoter par des expressions
rationnelles. Toutefois, tous les langages ne
sont pas rationnels et cette solution n'est donc
pas toujours possible.
chapitre 4

Pour atteindre d'autres classes de


langage, divers types de grammaires sont
utilisés.

Les grammaires peuvent être vues


comme des "algorithmes" d'une part pour
construire les mots du langage et d'autre part
pour vérifier la validité d'un mot par rapport à
un langage.
chapitre 4

2. Structures d’une grammaire

Une grammaire à structure de phrase G


permet de caractériser un langage
L(G), qui est un ensemble de phrases
(ou mots), appelé le langage engendré
par la grammaire. Une telle grammaire
ressemble à une définition rationnelle.
chapitre 4

1. VT : vocabulaire terminal dont chaque élément est


appelé symbole terminal. Ce vocabulaire correspond à
l'alphabet pour les langages rationnels et les symboles
terminaux aux symboles de l'alphabet. L(G) ⊆ VT*.
Dans ce cours, ne seront considérer que les
vocabulaires terminaux composés de symboles (lettres,
chiffres, caractères spéciaux comme '+', '-', ';'...). En
compilation, ce vocabulaire est un ensemble d'unités
lexicales (identificateurs réservés ou non, paramètres,
nom, opérateurs...).
chapitre 4

2.VN : vocabulaire non terminal dont chaque


élément est appelé symbole non terminal. Les
symboles non terminaux peuvent être vus comme
les nouveaux symboles des définitions rationnelles
(utilisés comme membres gauches des règles). Ils
ont toutefois un rôle un peu plus large. Ils
n'appartiennent pas au vocabulaire de base
(terminaux) et sont destinés à être éliminés,
remplacés pour former les mots du langage.
chapitre 4

3.Des règles permettant de déterminer


quelles séquences de VT* sont légales. Ces
règles ressemblent à celles des définitions
rationnelles mais sont plus souples et plus
générales.
chapitre 4

Définition

Une grammaire formelle, appelée aussi


grammaire de Chomsky, G est une
description de la forme des symboles et
des phrases d'un langage noté L(G). Elle
est définie par un quadruplet G = (VT, VN,
S, R) où :
chapitre 4

a) VT est un ensemble fini non vide : le

vocabulaire terminal ou alphabet; L(G) ⊆ VT* .

b) VN est un ensemble fini non vide : le


vocabulaire non terminal (on parle aussi de
variable ou de catégorie syntaxique) ;

VT ∩ V N = ∅ ;

V = VT U VN : le vocabulaire de la grammaire;
chapitre 4

c) S ∈ VN est un symbole non terminal


particulier appelé l'axiome (symbole de
départ);

d) R est un ensemble de règles, appelées


règles de production (ou règles de
réécriture), de la forme α → β avec α ∈ V+
et β ∈ V*.
chapitre 4

Remarque

Des règles de la forme α → β1 | β2 | ... | βn

avec n ≥ 1 et pour tout 1 ≤ i ≤ n, β i ∈ V*


peuvent être écrites pour abréger n règles
ayant α en partie gauche, de la forme α →
βi.
chapitre 4

Exemple

• G0=({0, 1}, {S, X}, S, R)


avec R :

R1 : S → 0X1

R2 : 0X → 00X1

R3 : X → ε
chapitre 4

• G1=({0, 1}, {S, X}, S, R)


avec :
R = {S → 0X1 ; 0X → 00X1 ; 0X → 001}
ou
R = {S → 0X1 ; 0X → 00X1 | 001}
chapitre 4

• G2=({0, 1}, {S}, S, R)


avec :
R = {S → 0S1 | 01}

• G3=({0, 1}, {S, X}, S, R)


avec :
R = {S → 0S | OX ; X → 1X | 1}
chapitre 4

La grammaire G0 définit le langage


L(G0)={0n1n|n ≥ 1} sur le vocabulaire terminal
(ou alphabet) A={0,1}. En effet :
Appliquer une règle va consister à remplacer
dans un mot une occurrence du membre
gauche de la règle par le membre droit
correspondant.
A partir de 0X1, on peut obtenir 00X11 en
appliquant R2 : 0X1 =R2 → 00X11
chapitre 4

Définition

Les formes sententielles sont les mots atteints


en prenant l'axiome S comme mot de départ et
en appliquant les règles un nombre fini de fois.
Les suites d'applications de règles sont appelés
"dérivations".
chapitre 4

Exemple

"00X11" (par S =R1 → 0X1=R2 → 00X11)

"01" (par S=R1 → 0X1=R3 → 01)

S : application successive de 0 règles


chapitre 4

Définition
Les mots du langage caractérisé par la
grammaire sont les mots accessibles qui ne
sont composés que de symboles terminaux.

Exemple
"01" (S=R1 → 0X1=R3 → 01)
"0011" (S=R1 → 0X1=R2 → 00X11=R3 → 0011)
"000111" ...
Définition chapitre 4

Soit G = (VT,VN, S, R) une grammaire et V=VTU VN,


alors :
l'ensemble des formes sententielles (ou proto-
phrases) de G est défini récursivement par :
L'axiome "S" est une forme sententielle de G.

Pour tous v, x, y, z ∈ V*, si "xyz" est une forme


sententielle de G et si y → v ∈ R, alors "xvz" est
une forme sententielle de G.
Le langage engendré par G est L(G)={x ∈ V*
| x est une forme sententielle de G et x ∈ VT*}.
chapitre 4

Une grammaire G est peut être utilisée soit pour


générer les phrases du langage L(G) soit pour
déterminer si une phrase donnée appartient ou non
au langage L(G) :

• La génération consiste à produire des chaînes de


symboles par application des règles de la
grammaire à partir de son axiome S.

• La vérification (l'analyse) consiste à retrouver la


succession d'applications de règles qui a permis
d'obtenir un mot en partant de l'axiome S.
Définition chapitre 4

Soit G = (VT,VN, S, R) une grammaire :


La relation «dérive directement de» sur V*
notée =G→ est définie par : ∀z,z’ ∈V*, z=G→ z’
↔ ∃ t, u, v, w ∈ V*, z=uvw et z’=utw et v→ t ∈
R.
si u ∈ VT* (resp. w ∈ VT*) alors uvw =G→ utw
est une dérivation à gauche (resp. à droite).
Intuitivement, on remplace dans uvw le non
terminal v le plus à gauche (resp. à droite) pour
obtenir utw.
chapitre 4

On appelle dérivation de longueur n (n ∈ N)


toute suite s=u0, ...,un de chaînes de V* telle
que u0 =G→ u1 et ... et un-1 =G→ un (ce que
l'on abrège par u0 =G→ ... =G→ un)
Notation
→ sera écrit au lieu de =G→ quand il n y a pas
d’ambigüité sur la grammaire.
=R→ pour désigner explicitement la règle
utilisée.
chapitre 4

a =n→b désigne une dérivation de longueur n.


a =*→b désigne une dérivation de longueur
quelconque. Autrement dit, =*→ est la fermeture
réflexive et transitive de =G→.
a =+→b désigne une dérivation de longueur
supérieure à 1. Autrement dit, =+→ est la
fermeture transitive de =G→.
Si a =*→b, on dit alors que a engendre b ou,
symétriquement, que b dérive de a. Si de plus a
=+→b, on dit "engendre" (resp. "dérive") "de façon
non triviale".
chapitre 4

Exemple
G0 : S → 0X1 → 00X11 → 000X111 → 000111

G1 : S → 0X1 → 00X11 → 000111

G2 : S → 0S1 → 00S11 → 000111

G3 : S → 0S → 00S → 000X → 0001X →


00011X → 000111
chapitre 4

Définition
Deux grammaires G1 et G2 sont dites
équivalentes si L(G1) = L(G2).
Exemple
G4=({0, 1}, {S, X}, S, R) avec R :
R1 : S → 0X1 ; G0
R2 : X → 0X1 ;
R3 : X → ε.
Classification des grammaires chapitre 4

Type 0 : sans contraintes

x → y avec x ∈ V* × VN × V* et y ∈ V*.
Type 1 : contextuelle (sensible au contexte)

- x → y avec |x|≤|y|.
Les productions sont soumises à la contrainte que la
partie droite de la règle doit contenir au mois autant
de symbole que la partie gauche.
Le cas particulier S → ε est permis si S n’apparaît pas
dans la partie droite d’une règle de G.
chapitre 4

- xAy → xBy avec x, y ∈ V*, A ∈ VN et B ∈ V+


tel que |B| ≥ 1.

Les grammaires de type 1 sont dites sensibles au


contexte car leur définition permet le
remplacement de A par B uniquement dans le
contexte précis où A est entouré par les symboles
x et y.
chapitre 4

Type 2 : hors-contexte (algébrique)

X → x avec X ∈ VN et x ∈ V+.

Le membre gauche de la production est un


unique symbole non terminal que l’on peut
réécrire par une chaîne quelconque du
vocabulaire de la grammaire.
chapitre 4

Type 3 : linéaires (régulières à droite


(resp. à gauche)

X → x1 | x2Y (resp. X → x1 | Yx2) avec X, Y ∈ VN


et x1 ∈ VT+, x2 ∈ VT*.
Le membre gauche de la production est un
unique non terminal et le membre de droite est
soit une chaîne de terminaux soit une chaîne de
terminaux suivie par un seul non terminal.
chapitre 4

Ces classes de langage satisfont la relation


d'inclusion stricte suivante :

Langages sans contraintes

cl3 ⊂ cl2 ⊂ cl1 ⊂ cl0


chapitre 4

Dérivations à gauche et à droite


Lorsqu’un mot est engendré par une grammaire, il peut l’être de plusieurs façons. Par
exemple dans la grammaire:
chapitre 4

Le mot abb peut être obtenu par les deux


dérivations :
D.G.

D.D.
chapitre 4

Représentation des grammaires hors contexte

La norme BNF ("Backus-Naur-Form")

Les symboles non terminaux sont encadrés par des


guillemets ("..." ou <<...>>), les symboles terminaux
ne sont pas distingués (parfois les non-terminaux
sont en majuscule et les terminaux en
minuscule).
chapitre 4

L'axiome est la partie gauche de la première règle


énoncée. La disjonction est notée par une barre
verticale ( | ). La flèche des règles est remplacée
par le signe "::=".

Exemple
{S → bA ; A → aA ; A → a}
"S" ::= b"A"
"A" ::= a"A" | a
chapitre 4

les diagrammes de Conway


La partie gauche des règles est notée à gauche
du schéma. Les symboles terminaux sont écrits
dans des cercles et les symboles non
terminaux sont écrits dans des rectangles.
Exemple

{S → bA ; A → aA ; A → a}
Exercice chapitre 4

Traduire ces diagrammes de Conway en une grammaire


hors-contexte. Donnez-la sous la forme BNF

B:
chapitre 4

1) S  aaA | bbB
BNF: « S » ::= aa « A » | bb « B »

2) B  aa | bb | cc | dd
BNF: « B »::= aa | bb | cc | dd

3) A  aaA | bbA | ccA | ddA


BNF:
« A »::= aa « A » | bb « A » | cc « A » | dd « A »
chapitre 4

Arbres de dérivations

L'idée consiste à associer à chaque règle R :


A → X1 ... Xn de la grammaire, où A ∈ VN et ∀
1 ≤ i ≤ n, Xi ∈ V, la structure d'arbre
suivante :
chapitre 4

une dérivation de la forme A =n → Y1...Yi-1 Yi Yi+1 ...


Ym = R → Y1 ... Yi-1 X1...Xm Yi+1 ... Ym est représentée
par l'arbre associé à A =n → Y1... Ym, dans lequel
on remplace le symbole non terminal
correspondant à Yi par l'arbre associé à R.
A

… …
Y1 Yi Ym

X1 ….. Xm
chapitre 4

En considérant les règles :


R1 : A → BaC
R2 : B → b
R3 : C → c,
A =R1 → BaC =R2 → baC =R3 → bac
chapitre 4

Exercice
Soit la grammaire ayant S pour axiome et pour
règles de production :

1) Donner l’arbre de dérivation pour le mot


accacbb.
2) Donner les dérivations à gauche et à droite
de ce mot.
chapitre 4

Solution
1)
chapitre 4

2)
D.G.

D.D.
chapitre 4

Ambiguïté
Une grammaire est dite ambiguë si au moins
un mot dans son langage a plus d’un arbre de
dérivation.
Exemple
G = ({0, 1, … , 9, +, *}, {S, ch},R)
S → ch
Ch → ch + ch | ch * ch
ch → 0 | 1 | 2 | … | 9
chapitre 4

Considérons le mot « 3 * 1 + 5 »
Ce mot possède plus d’un arbre de dérivation.

S S

ch ch

ch + ch ch * ch

ch * ch 3 ch + ch
5

3 1 1 5

(3 * 1) + 5 3 * (1 + 5)
Exercice chapitre 4

Soit la grammaire suivante G :


S ::= «E» E ::= « E » « E »
E ::= ’(’ « E » ’)’ E ::= ε
1– Donner un arbre de dérivation de (()()) pour
cette grammaire.
2– Cette grammaire est-elle ambiguë? Expliquer.
3- Proposer une autre grammaire équivalente qui
ne soit pas ambiguë.
4- Donner un arbre de dérivation de (()()) pour
cette grammaire.
chapitre 4

Solution
S
1)
E

( E )

E E

( E ) ( E )

ε ε
chapitre 4

2)

Oui, elle est ambiguë. En particulier, parce


qu’elle accepte plusieurs arbres de dérivation
pour le mot vide (ε).

E
E E
ε
ε ε
chapitre 4

3) Pour supprimer l’ambiguïté il faut interdire


que la production E ::= E E dérive dans ε. Une
solution, consiste à faire apparaître au moins un
terminal dans la règle.
Pour cela, on propose la fermeture par la règle
E ::= ’(’ E ’)’ en forçant le parenthésage à
gauche. On obtient la grammaire suivante G′ :
S ::= « E »
E ::= ’(’ « E » ’)’ « E »
E ::= ε
chapitre 4

4)
S

( E ) E

( E ) E ε

ε ( E ) E

ε ε
Chapitre 5

LES AUTOMATES
D'ÉTAT FINI
chapitre 5

1. Introduction

L'objectif de ce chapitre est d'introduire


rapidement les automates à travers la
présentation des machines de Turing. Puis,
nous étudierons plus particulièrement un cas
particulier de machine de Turing : les
automates finis.
chapitre 5

2. Machine de Turing
La machine de Turing est composée de :

- d'une unité centrale se trouvant dans un


état qi, pris parmi l'ensemble fini de ses états
internes, noté Q={q1, q2, ..., qn}. Parmi les
états, un état initial (état au lancement de la
machine) et des états finaux (états de la
machine en situation de terminaison). Le
comportement de l'unité centrale est déterminé
par son programme.
chapitre 5

- d'un ruban de taille illimitée divisé en cases,


contenant au départ les données à traiter, et à
l'arrivée les résultats des calculs. Les données
de départ tout comme les résultats sont
représentés sur le ruban à l'aide de symboles
pris dans un alphabet A={a0, a1, a2, ..., am}.
Chaque case ne contient qu'un symbole.
chapitre 5

- d'une tête de lecture-écriture qui assure la


communication entre l'unité centrale et le
ruban. Cette tête n'agit que sur une case à la
fois. Elle peut remplacer le symbole lu par
un autre symbole et déplacer le ruban d'une
case vers la gauche ou vers la droite.
chapitre 5

Structure d’une machine


de Turing
chapitre 5

Le rôle du programme consiste à déterminer,


pour un état qi de la machine et pour un symbole
aj situé devant la tête de lecture-écriture, le
nouvel état dans lequel passe la machine ainsi
que l'opération effectuée sur le ruban.
Le programme est représenté par un ensemble
fini de quintuplets, appelé fonction de
transition. Celle-ci définit les règles d'évolution,
appelées règles de transition, de la forme
(qi,aj, qk, al, dm) ou μ(qi,aj) = (qk, al, dm) où :
chapitre 5

qi ∈ Q est l'état initial ;


aj ∈ A le symbole lu ;
qk ∈ Q le nouvel état ;
al ∈ A ∪ {ε} le caractère à écrire (ε n'écrit rien,
c'est-à-dire laisse le caractère aj sur le ruban) ;
dm ∈ {D, G, C} le sens du déplacement de la
tête avec respectivement D pour aller d'une
case vers la droite, G d'une case vers la gauche
et C pour ne pas se déplacer.
chapitre 5

Définition
On appelle configuration tout couple
symbole/état. Une règle détermine donc pour
une configuration courante, l'action à effectuer
et donc la prochaine configuration.
On appelle configuration initiale tout couple
symbole / état où l'état est un état initial.

On appelle configuration finale tout couple


symbole / état où l'état est un état final.
chapitre 5

Si la machine de Turing est telle qu'il n'existe


pas de règle μ(qi,aj)= (qk, al, dm) pour l'état qi
et le symbole aj de la configuration courante
alors le ruban est dit terminal. Si l'état
courant est un état final alors l'exécution est
réussie et le programme s'est déroulé
normalement. Le cas contraire est une
situation d'échec.
chapitre 5

Définition
La machine de Turing est dite déterministe si
pour toute configuration, il n'existe qu'une
seule fonction de transition applicable, c'est-à-
dire si et seulement si pour μ(x,y)=(z1,t1) et
μ(x,y)=(z2,t2) deux règles, alors z1=z2 et t1=t2.
Dans le cas contraire, la machine est dite non
déterministe (pour une configuration donnée,
plusieurs règles sont applicables).
chapitre 5

3. Automates finis

Un automate fini est une machine de Turing


dont le ruban se déplace toujours vers la
gauche et case par case. Ce ruban est infini à
droite et fini à gauche. Par ailleurs, la tête de
lecture de la machine se contente de lire des
symboles et n'effectue aucune écriture.
chapitre 5

Définition
Un automate fini (AFN) est composé de la
même manière que la machine de Turing.
Généralement non déterministe, son
comportement est cependant plus restreint. Il
est défini par un quintuplet (A, Q, I, F, μ) tel
que :
chapitre 5

A est l'alphabet (vocabulaire), ensemble fini,


non vide de symboles ;

Q est l'ensemble des états possibles pour la


machine (fini et non vide) ;

I ⊆ Q est l'ensemble des états initiaux ou états


de départ ;

F ⊆ Q correspond aux états finaux ou états


d'acceptation ;
chapitre 5

μ la fonction de transition telle que :


μ : A ∪ {ε} × Q → Q.
Pour la configuration courante d'état et de
symbole, μ(aj,qi)=qk signifie qu'on passe dans
l'état qk et que le ruban est déplacé d'une case
vers la gauche.
chapitre 5

Remarque
Au départ, une phrase construite sur le
vocabulaire de l'automate est inscrite sur le
ruban d'entrée et est entourée de symboles ε.
L'unité centrale se trouve dans un des états
initiaux de I et la tête de lecture est placée
devant le symbole le plus à gauche de la
phrase. A partir de cette position, l'automate va
exécuter son programme.
chapitre 5

Remarque
Pour une configuration courante (ai,qj),
l'automate applique une transition μ(ai,qj) →
qk, passe alors dans l'état qk et déplace le
ruban d'une case vers la gauche. L'automate
tel qu'il est défini n'est pas forcément
déterministe.
chapitre 5

L'automate s'exécute jusqu'à ce qu'il arrive à


une situation (at,qn) pour laquelle il n'existe
pas de transition permettant au programme de
poursuivre son calcul. Il suspend alors son
exécution. Si la configuration finale est telle
que at = ε et qn ∈ F alors la phrase inscrite sur
le ruban est acceptée par l'automate. Dans
tous les autres cas, elle est refusée.
chapitre 5

Une façon utile de regarder le non


déterminisme est de considérer qu'il permet à
un automate de "formuler des hypothèses". Si,
dans un état donné, on ne sait pas quoi faire
sur un certain caractère d'entrée, il existe
plusieurs possibilités pour le choix de l'état
suivant.
chapitre 5

4. Représentation des AFN


Les automates, et en particulier leur fonction
de transition, peuvent être représentés de
plusieurs manières : par des graphes orientés
ou des représentations matricielles.

Exemple 1
Soit l'automate T={{a,b}, {1}, {2}, μ} avec :
chapitre 5

μ(1, a) = 1, μ(1, b) = 2, μ(2, a) = 1, μ(2, b) = 2


q0 = 1
F = {2}

La fonction de transition est très souvent représentée


par une "table de transition" (matrice de transition).

μ a b

→1 1 2

*2 1 2
chapitre 5

Les tables de transition sont des tableaux (ou


des matrices) dont les colonnes correspondent
aux symboles et les lignes aux états. La cellule
(li,cj) indique les transitions (ai, qj) → qk.

μ a b

→1 1 2

*2 1 2
chapitre 5

Un AFN peut être aussi représenté par un graphe


orienté et valué, appelé "diagramme de transition"
ou "graphe de transition". Les nœuds
correspondent aux états et les arcs représentent
les transitions possibles (calculées par la fonction
de transition) entre les états.
Ces arcs sont étiquetés par le symbole permettant
cette transition. Les états initiaux sont représentés
par un nœud possédant une flèche entrante sans
origine. Un état final est représenté par un nœud
doublement cerclé.
chapitre 5

i Etat initial F Etat final

x
n Etat quelconque e f (x,e) → f

le langage de cet automate est constitué


exactement des mots composés de a et de b qui
se terminent par un b.
chapitre 5

Exemple 2
Cet automate est défini sur l'alphabet A = {a,b}.

Langage? Automate reconnaissant le langage abA*

L'état initial est l'état 1 et l’état final est 3.


chapitre 5

Exemple 3
Cet automate est défini sur l'alphabet A = {a,b}.

Langage? Automate reconnaissant le langage A*aba


chapitre 5

Exemple 4
Cet automate est défini sur l'alphabet A = {a,b}.

Langage? Automate reconnaissant le langage A*bA*


chapitre 5

Cas particulier
Cet automate est défini sur l'alphabet A = {a,b}.

Langage? Automate reconnaissant le langage A*bA*


chapitre 5

Exemple 5
Soit l'automate T={{a,b,c}, {1}, {6,8}, μ}
avec :
μ sa fonction de transition :
µ(a,1) = 2 ; µ(b,1) = 4 ; µ(a,2) = 5 ;
µ(b,2) = 3 ; µ(c,2) = 2 ; µ(a,3) = 6 ;
µ(b,3) = 4 ; µ(c,3) = 9 ; µ(c,4) = 5 ;
µ(a,5) = 5 ; µ(a,5) = 6 ; µ(c,7) = 4 .
chapitre 5

Les symboles ne donnant aucune transition


depuis un nœud dans un certain état sont alors
à "0" (transition vers un état inexistant).

μ a b c
1 2 4 0
2 5 3 2
3 6 4 0
4 0 0 5
5 5,6 0 0
6 0 0 0
chapitre 5

L'automate T peut être représenté par le graphe


suivant:
chapitre 5

Quelles sont vos remarques?


Etat 7? Etat 8? Etat 9?
chapitre 5

Remarque
Dans certains cas, il est plus facile de
représenter un groupe de transitions par une
notation ensembliste. Par exemple, supposons
que pour un état donné e, nous avons un
passage à l'état f pour les symboles a, b et c.

A = {a, b, c, d}
chapitre 5

Automate T1

Automate T2
chapitre 5

1) Quel est le langage reconnu par l’automate T1?

Tous les mots qui contiennent un “b”.

2) Écrire la table de transition de l’automate


suivant. Quel est le langage reconnu ?
chapitre 5

0 1

→A B A

B B C

*C C C

Cet automate reconnaît les mots qui


contiennent “01”.
chapitre 5

Exemple d'exécution d'un AFN


T1 = {{a,b,c}, {1,2,3,4,5,6},{1},{6}, {(a,1) → 2,
(b,1) → 4, (a,2) → 5, (c,2) → 2, (b,2) → 3, (a,3) →
6, (b,3) → 4, (c,4) → 5, (a,5) → 5, (a,5) → 6}}

aba
bcaaa
acba
acbbcaaa
abaa
abbb
chapitre 6

ANALYSES LEXICALE,
SYNTAXIQUE ET
SEMANTIQUE
Analyse lexicale
chapitre 6

1. Introduction
Les éléments rencontrés dans un programme :
- Identificateur : nom du programme, X, Y, …

- Mots clés : si, sinon, tant que, fin, …

- Constantes : 12, 375, …

- Séparateur : +, -, ., >, <, …


- Commentaires : { }, * *, /* */, …
chapitre 6

Le rôle de l’analyse lexicale est de reconnaître


les caractères du programme, de les regrouper
pour former des unités lexicales et d’éliminer
les caractères inutiles tels que les
commentaires, les espaces, les tabulations …

Unité lexicale : désigne l’ensemble des


lexèmes ayant la même signification
grammaticale.
chapitre 6

Exemples

1) A := B + C , A, B et C sont trois lexèmes de


l’unité lexicale identificateur.

2) Soit le code source x - 2 * y

L’analyse lexicale donnera une séquence d’unités


lexicales comme :

(identificateur, ‘x’) – (nombre, ‘2’) * (identificateur, ‘y’)


chapitre 6

2. Structure d’un analyseur lexical

L’analyseur utilise un programme


squelette commun à tous les
analyseurs lexicaux et une table dans
laquelle est stockée la fonction de
transition de l’automate associé.
chapitre 6

Exemple :

δ a b c Autres

q0 q1 … … …
q1 … q1 q2 …
… … … … …
chapitre 6

Exemple : automate reconnaissant les


commentaires.

{
q0 q1

} Autres que { et }
chapitre 6

Programme 1
Char ← prochain caractère
Etat ← q0
Tant que (char ≠ EOF)
Etat ← δ (Etat, char)
Char ← prochain caractère
Si (Etat Є QF)
Alors accepter
Sinon rejeter
chapitre 6

Exemple :
Soit l’automate suivant :
b
a
q0 q1 Automate A

Le programme 1 peut être utilisé. Ce type


d’analyseur est appelé analyseur à base de
table.
chapitre 6

Remarque :

Ces analyseurs passent beaucoup de


temps à tester et à manipuler la variable
d’état. Ce temps peut être optimisé en
utilisant les analyseurs lexicaux codés
directement.
chapitre 6

Analyseur lexical codé directement :


Exemple :
Soit l’automate A, l’analyseur lexical sera
codé comme :

q0 : Char ← prochain caractère


si (char = ‘a’)
alors goto q1
sinon goto qr
chapitre 6

q1 : Char ← prochain caractère


si (char = ‘b’ | char = ‘c’)
alors goto q1
sinon si (char = ‘EOF’)
alors accepter
sinon goto qr

qr : rejeter
chapitre 6

Remarque :

Cette implémentation devient rapidement


difficile à gérer manuellement mais une fois
automatisé sera plus rapide que l’analyseur
à base de table.
chapitre 6

Conclusion

L’analyseur lexical prépare également le


terrain pour l’analyse syntaxique. Il peut
reconnaître les mots clés du langage. Pour
cela, il y a deux possibilités :
chapitre 6

1) Soit une suite explicite d’états


reconnaissant chaque mot clé doit être
introduite.

2) Soit, les identificateurs doivent être


reconnus et comparés à une table des
symboles contenant les mots clés du
langage.
Analyse syntaxique
chapitre 6

1. Introduction

L’analyseur syntaxique analyse la suite de


symboles issus de l’analyseur lexical et
vérifie si cette suite de symboles est
conforme à la syntaxe du langage définie
par les règles de Backus-Naur.
chapitre 6

Pour cela, l’analyseur syntaxique essaye de


construire l’arbre syntaxique correspondant
au code. Dans cet arbre, les feuilles
correspondent aux symboles issus de
l’analyse lexicale et les nœuds
intermédiaires correspondent aux objets
grammaticaux.
chapitre 6

Remarque

Si l’analyseur syntaxique ne parvient pas à


construire l’arbre syntaxique du programme
compilé alors la syntaxe du programme est
erronée.
Définition chapitre 6

Soient G = (VT, VN, S, P) et x Є VT*

L’analyse syntaxique est le processus


d’établissement d’une correspondance entre
l’axiome S et une chaîne terminale x :
∈ L(G)  construction de l’arbre syntaxique
1) x
associé à la chaîne terminale.

2)∉x L(G)  chaîne refusée.


chapitre 6

BNF
A
n
l
a
e
l Suite de Arbres
x Analyseur
y
i syntaxique
s Symboles Syntaxiques
c
e
a
u
l
r

Erreurs de syntaxe :
Texte refusé

Analyseur syntaxique
chapitre 6

Exemple 1

G = ({0, … ,9}, {<S>, <A>}, S, P)


<S> ::= <A>|<A><S>

x = 2009
x = 2009 chapitre 6

Règles appliquées Arbre syntaxique


<S> ::= <A><S> <S>
<A> ::= 2
<S> ::= <A><S> <A> <S>
<A> ::= 0
2 <A> <S>
<S> ::= <A><S>
<A> ::= 0 <A> <S>
0
<S> ::= <A>
<A> ::= 9 0 <A>

9
chapitre 6

Exemple 2

Les règles de Backus-Naur suivantes


permettent la description d’un langage de
programmation qui contient deux types
d’instructions : instructions permettant
d’opérer des déclarations de variables d’une
part et des instructions de type affectation
d’autre part.
chapitre 6

<programme>::=PROGRAM<identificateur><corps prog.>
<corps prog.>::=<suite de déclar.>DEBUT<suite d’affect.>FIN
<suite de déclar.>::=<déclar.>|<déclar.><suite de déclar.>
<déclar.>::=INT<identificateur>;
<suite d’affect.>::=<affect.>|<affect.><suite d’affect.>

<affect.>::=<identificateur>=<terme>;|<identificateur>=
<terme><opérateur><terme>;
<terme>::=<entier>|<identificateur>
<opérateur>::=+ | - | * | /
<identificateur>::=<lettre> | <lettre><chiffre>
<entier>::=<chiffre> | <entier><chiffre>
<lettre>::=A | B | … | Z <chiffre>::=0 | 1 | … | 9
chapitre 6

La première règle spécifie que le programme


est construit à partir du symbole terminale
PROGRAM suivi d’un objet <identificateur> et
d’un objet <corps prog.>.

Un objet <identificateur> est lui-même décrit


comme étant composé soit d’une lettre seule,
soit d’une lettre suivie d’un chiffre.
chapitre 6

Les lettre admises sont les 26 lettres


majuscules et les chiffres admis sont les
chiffres allant de 0 à 9.

L’objet <corps prog.> est défini comme étant


<suite de déclar.> suivi du
symbole terminal DEBUT,
suivi de <suite d’affect.>
suivi du symbole FIN ...
chapitre 6

Le programme suivant a été écrit en respectant la


syntaxe dictée par ces règles :
PROGRAM Z
INT A;
INT B;
INTg5;
INT C2; Erreur lexicale, prq?
DEBUT
le symbole g ne fait pas
A = 4;
partie de l’alphabet du
B = A / 2;
langage (juste les lettres
C2 = B + A;
majuscules sont admises)
FIN
Ce programme conduit à l’arbre chapitre
suivant :6

<programme>

PROGRAM <corps prog.>


FIN
<Identificateur>
Z
<suite de déclar.>DEBUT
<suite d’affect.>

<suite de déclar.>
<déclar.>
INT <suite de déclar.>
; <déclar.>

<Identificateur> INT <déclar.>


A ;
INT
<Identificateur>
;
B
<Identificateur> C2
suite de l’arbre syntaxique
chapitre :6

<suite d’affect.>

<affect.> ; <suite d’affect.>

= <terme> <suite d’affect.>


<Identificateur>
A <entier>
<Identificateur> <affect.> ;
4
C2
<Identificateur> <affect.> = <terme>
B =
<terme> <terme> <Identificateur>
<terme> A
<entier> <Identificateur>
<Identificateur> <opérateur>
2 B
<opérateur>
A

+
/
chapitre 6

Exemple d’erreur syntaxique


Considérons la phrase suivante : G 5 = 2;
L’analyse lexicale s’est bien passée alors que
l’arbre syntaxique correspondante ne peut pas
être construite.
En effet, la règle de production relative à un
objet de type affectation échoue dans le 2ème
symbole. Le symbole ‘5’ est rencontré à la place
du symbole ‘=‘.
chapitre 6

<corps prog.>

<suite de déclar.> <suite d’affect.>


DEBUT

<affect.>

<identificateur> =

G Non : Erreur

Arbre syntaxique impossible à construire sur l’analyse


de G 5 = 2;
chapitre 6

Conclusion
La construction des arbres syntaxiques fait
apparaître la nécessité d’avoir défini la
grammaire du langage sans ambigüité afin qu’à
aucun moment, une suite de symboles issue de
l’analyse lexicale puisse correspondre à
plusieurs règles de production différentes, ce
qui conduirait à une interprétation du sens
différente à celle voulue par le programmeur.
chapitre 6

Exemple de grammaire ambigüe


Soit G = (VT, VN, S , P)
VT = {if, then, else} , VN = {Bool, Instr}
S = Instr
P : Instr  if bool then instr else instr

Instr  if bool then instr

En se basant sur cette grammaire, la phrase : «if


bool then if bool then instr else instr» est - elle
ambiguë?
chapitre 6

La phrase admet deux arbres syntaxiques différentes.


1er cas <Instr>

if <Bool> then <Instr> else<Instr>

if <Bool> then <Instr>

2ème cas
<Instr>

if <Bool> then <Instr>

if <Bool> then <Instr> else <Instr>


chapitre 6

1ér cas
Le else se rapporte au then de la première
instruction.
2ème cas
Le else se rapporte au then immédiatement
précédent.

Le concepteur du langage veut que


l’instruction soit interprétée comme le 2ème cas.
D’où la nécessité de supprimer l’ambigüité en
changeant les productions.
chapitre 6

Version corrigée
G = (VT, VN, S , P) VT = {if, then, else}
VN = {Bool, Instr-1, Instr-2, Instr} S = Instr-1
P : Instr-1  if bool then instr-1
Instr-1  if bool then instr-2 else Instr-1
Instr-1  Instr

Instr-2  if bool then instr-2 else Instr-2

Instr-2  Instr-1
chapitre 6

Le seul arbre correspondant à la phrase précédente :


if bool then if bool then instr else instr
<Instr-1>

if <Bool> then<Instr-1>

if <Bool> then
<Instr-2> else<Instr-1>

<Instr-1> <Instr>

<Instr>
chapitre 6

Définitions

- Analyseur syntaxique non déterministe :


aucun critère n’est imposé pour choisir la règle
de production à appliquer.

- Analyseur syntaxique déterministe : des


critères sont imposés pour choisir sans
ambigüité la règle de production à appliquer.
chapitre 6

- Analyseur syntaxique unique : pour une


chaîne terminale donnée, un seul arbre
syntaxique est fourni.

- Analyseur syntaxique multiple : plusieurs


arbres syntaxiques possibles pour une même
chaîne terminale donnée.
chapitre 6

- Analyse syntaxique descendante :


L’analyseur cherche, à partir de l’axiome et à
l’aide des règles de la grammaire, à former
la phrase donnée.

- Analyse syntaxique ascendante : L’analyseur


cherche, à partir de la phrase et à l’aide des
règles de la grammaire, à remonter à
l’axiome.
chapitre 6

G = ({a, b, ‘+’}, {S}, S, R)

R: S → S + a | S + b | a | b
Soit x = a + b + b
L’analyse syntaxique essayera de construire l’arbre
de dérivation correspondant :
S
L’analyse syntaxique
ascendante construit S + a

par exemple l’arbre


S + a
suivant :
a
chapitre 6

Les règles sont appliquées au hasard mais le


résultat est erroné. La dernière règle est remplacée
par une autre. Si le résultat est toujours faux, la
règle précédente est analysée.
Trop compliqué

Le concepteur devra donc choisir des


analyseurs syntaxiques déterministes, uniques
et descendantes.

Grammaire LL(K)
chapitre 6

En effet, il existe une classe de grammaire adaptée


à l’analyse descendante déterministe : la classe des
grammaires LL(k).

Le premier L (Left) signifie que l’analyse des


phrases se fait de la gauche vers la droite.

Le deuxième L indique qu’il faut effectuer des


dérivations à gauche avec une inspection de k
symboles terminaux en avance sur le symbole
courant traité.
chapitre 6

La réalisation d’analyseurs syntaxiques pour des


grammaires LL(k) avec k>1 est difficile et ces
grammaires ne sont pas performants.
Les grammaires de type LL(0) sont trop restrictives.

grammaires LL(1).

Le but de cette classe de grammaires est de


toujours connaître la règle de production à
appliquer et ceci en se basant uniquement sur le
terminal suivant non encore traité de la phrase en
cours d’examen.
chapitre 6

CALCUL DE PREMIER
Pour toute chaîne α composée de symboles
terminaux et non-terminaux, on cherche
PREMIER(α):

PREMIER(α) est l’ensemble de tous les


terminaux qui peuvent commencer une chaîne
qui se dérive de α. On cherche toutes les
lettres a telle qu’il existe une dérivation α=*→
aβ (β ∈ V+)
chapitre 6

Exemple
 S → Ba

 B → cP bP P ε
 P → dS

S *→ a alors a ∈ PREMIER(S).

S *→ cPa alors c ∈ PREMIER(S).

S *→ bPa alors b ∈ PREMIER(S).

S *→ dSa alors d ∈ PREMIER(S).


S *→ ε PREMIER(S) = {a, b, c, d}
chapitre 6

Algorithme
1. Si X est un non terminal et X → Y1Y2…Yn est une
production de la grammaire (avec Yi symbole
terminal ou non-terminal) alors :

i) ajouter les éléments de PREMIER(Y1) sauf ε dans


PREMIER(X).

ii) S’il existe j (j ∈ {2, …,n}) tel que pour tout i = 1,


…, j-1 on a ε ∈ PREMIER(Yi), alors ajouter les
éléments de PREMIER(Yj) sauf ε dans PREMIER(X).
chapitre 6

iii) Si pour tout i = 1, …, n, ε ∈ PREMIER(Yi), alors


ajouter ε dans PREMIER(X).

2. Si X est un non terminal et X → ε est une


production alors ajouter ε dans PREMIER(X).

3. Si X est un terminal alors PREMIER(X) = {X}.

4. Recommencer jusqu’à ce qu’on n’ajoute rien de


nouveau dans les ensembles PREMIER.
chapitre 6

Exemple 1

G = ({+, *, (, ), nb, ε}, {E, T, T’, E’, F}, E, P)

P: E → T E’
E’ → + T E’ | ε
T → F T’
T’ → * F T’ | ε
F → (E) | nb
chapitre 6

E’ → ε, ε est ajouté à PREMIER(E’)

PREMIER(E’) = {ε}
Règle 2
T’ → ε, ε est ajouté à PREMIER(T’)

PREMIER(T’) = {ε}

E’ → +TE’, + est donc ajouté à PREMIER(E’)

PREMIER(E’) = {ε , +}
chapitre 6

T’ → *F T’, * est donc ajouté à PREMIER(T’)

PREMIER(T’) = {ε , *}

F → (E), ( est donc ajouté à PREMIER(F)

PREMIER(F) = {(}

F → nb, nb est donc ajouté à PREMIER(F)

PREMIER(F) = {(, nb}


chapitre 6

T → F T’, PREMIER(F) est donc ajouté à PREMIER(T)

PREMIER(T) = {( , nb}

E → TE’, PREMIER(T) est donc ajouté à PREMIER(E)

PREMIER(E) = {(, nb}


chapitre 6

Exemple 2
G = ({a, b, c, d, e, ε}, {S, A, B, C}, S, P)

P: S → ABC
A → aA | ε
B → bB | cB| ε
C → de | da | dA
chapitre 6

A → ε, ε est ajouté à PREMIER(A)

PREMIER(A) = {ε}
Règle 2
B → ε, ε est ajouté à PREMIER(B)

PREMIER(B) = {ε}

A → aA, PREMIER(a) est donc ajouté à PREMIER(A)

PREMIER(A) = {a, ε}
Règle 3)
Règle 1 i)
chapitre 6

B → bB, PREMIER(b) est donc ajouté à PREMIER(B)

PREMIER(B) = {b, ε}
Règle 1 i)
B → cB, PREMIER(c) est donc ajouté à PREMIER(B)

PREMIER(B) = {b, c, ε}

C → dA, PREMIER(d) est donc ajouté à PREMIER(C)

PREMIER(C) = {d}
chapitre 6

S → ABC, PREMIER(A) sauf ε est donc ajouté à


PREMIER(S)

PREMIER(S) = {a} Règle 1 i)


S → ABC et A → ε, PREMIER(B) sauf ε est donc
ajouté à PREMIER(S)
Règle 1 ii)
PREMIER(S) = {a, b, c}

S → ABC et B → ε, PREMIER(C) sauf ε est donc


ajouté à PREMIER(S)

PREMIER(S) = {a, b, c, d}
chapitre 6

CALCUL DE SUIVANT

Pour tout non-terminal A, SUIVANT(A) est


l’ensemble de tous les symboles terminaux a
qui peuvent apparaître immédiatement à
droite de A dans une dérivation : S *→ αAaβ
où α et β sont des chaînes de symboles
grammaticaux.
chapitre 6

Exemple
G = ({a, b, c, d, ε}, {S, B, P}, S, R)

 S → Sc Ba

R:  B → Pa bPb P ε
 P → dS

S→Sc alors c ∈ SUIVANT(S).

S → Ba → Pa → dSa alors a ∈ SUIVANT(S).

S → Ba → bPba → bdSba alors b ∈ SUIVANT(S).


chapitre 6

Algorithme de construction des


ensembles SUIVANT

Pour calculer SUIVANT(A) pour tous les non-


terminaux, appliquer les règles suivantes
jusqu’à aucun terminal ne puisse être ajouté
aux ensembles SUIVANT :
chapitre 6

1. Mettre $ dans SUIVANT(S) où S est l’axiome de


départ de la grammaire et $ est le marqueur
indiquant la fin du texte source.

2. S’il y a une production A → αBβ où B est un non-


terminal, alors le contenu de PREMIER(β) sauf ε
est ajouté à SUIVANT(B).

3. S’il existe une production A → αB ou A → αBβ


telle que ε ∈ PREMIER(β) (ie β*→ ε) alors les
éléments de SUIVANT(A) sont ajoutés à
SUIVANT(B).
chapitre 6

Exemple 1

G = ({+, *, (, ), nb, ε}, {E, T, T’, E’, F}, E, P)

P: E → T E’
E’ → + T E’ | ε
T → F T’
T’ → * F T’ | ε
F → (E) | nb
chapitre 6

E est l’axiome, le symbole $ est donc ajouté à


SUIVANT(E)

SUIVANT(E) = {$}

E → TE’, PREMIER(E’) sauf ε est donc ajouté à


SUIVANT(T)

SUIVANT(T) = {+}

T → F T’, PREMIER(T’) sauf ε est donc ajouté à


SUIVANT(F)

SUIVANT(F) = {*}
chapitre 6

F → (E), le symbole ‘)’ est ajouté à SUIVANT(E)

SUIVANT(E) = {$, )}

E → TE’, SUIVANT(E) est donc ajouté à


SUIVANT(E’)

SUIVANT(E’) = {$, )}

E’ → +TE’ et E’ → ε, SUIVANT(E’) est donc ajouté à


SUIVANT(T)

SUIVANT(T) = {+, $, )}
chapitre 6

T → F T’, SUIVANT(T) est donc ajouté à


SUIVANT(T’)

SUIVANT(T’) = {+, $, )}

T’ → *F T’ et T’ → ε, SUIVANT(T’) est donc ajouté à


SUIVANT(F)

SUIVANT(F) = {*, +, $, )}
chapitre 6

Exercice 1
G = ({+, *, a}, {E}, E, P)

P: E → + EE | * EE | a

Calculer les ensembles PREMIER et SUIVANT pour


chacun des non-terminaux.
chapitre 6

E → + EE, + est donc ajouté à PREMIER(E)

PREMIER(E) = {+}
Règle 1 i)
E → * EE, * est donc ajouté à PREMIER(E)

PREMIER(E) = {+, *}

E → a, a est ajouté à PREMIER(E)

PREMIER(E) = {+, *, a}
chapitre 6

E est l’axiome, le symbole $ est donc ajouté à


SUIVANT(E)

SUIVANT(E) = {$}

E → + EE, PREMIER(E) sauf ε est donc ajouté à


SUIVANT(E)

SUIVANT(E) = {$, +, *, a}
chapitre 6

Exercice 2
G = ({+, *, (, ), a}, {E}, E, P)

P: E → (E) | E + E | E * E | a

Calculer les ensembles PREMIER et SUIVANT pour


chacun des non-terminaux.
chapitre 6

E → (E), ( est donc ajouté à PREMIER(E)

PREMIER(E) = {(}
Règle 1 i)
E → a, a est ajouté à PREMIER(E)

PREMIER(E) = {(, a}
chapitre 6

E est l’axiome, le symbole $ est donc ajouté à


SUIVANT(E)

SUIVANT(E) = {$}

E → E + E | E * E | (E),

SUIVANT(E) = {$, +, *, )}
Table d’analyse chapitre 6

Exemple 1
S → aSbT | cT |d
le mot w = accbbadbc
T → aT | bS | c

La lecture de la première lettre du mot (a) nous


permet d'avancer la construction

S
w = accbbadbc
a S b T
chapitre 6

la deuxième lettre amène à :

S
w = accbbadbc
a S b T

c T
chapitre 6

S
w = accbbadbc
a S b T

c T b S

a S b T
c

d c

L’ arbre de dérivation a été trouvé, donc le mot


appartient au langage.
chapitre 6

Exemple 2
S → aAb
le mot w = acb
A → cd | c

La lecture de la première lettre du mot (a) nous


permet d'avancer la construction

S
w = acb
a A b
chapitre 6

Pour lire le c, Quelle règle il faut prendre?

• Il faut lire aussi la lettre suivante (b).

• Il faut se donner la possibilité de faire des retour


en arrière : la 1ère règle est essayée → un échec,
un retour en arrière s’impose et la deuxième règle
est essayée → réussite.

S
w = acb
a A b

A → cd | c
chapitre 6

Exemple 3
S → aSb | aSc | d

le mot w = aaaaadbbcbbbc

Pour savoir quelle règle utiliser, il faut cette fois-ci


connaître aussi la dernière lettre du mot.
chapitre 6

Exemple 4

E → T E’
E’ → + T E’ | ε
T → F T’
T’ → * F T’ | ε
F → (E) | nb

le mot w = 3*4+10*(5+11)

Quelles sont les règles qui vont être utilisées?


Construction d’analyseur chapitre 6

L'algorithme suivant peut être utilisé pour


construire une table pour l'analyse prédictive d'une
grammaire G. L'idée sous-tendant cet algorithme
est le suivant.
• Soit A → α une production et a dans Premier(α).

• L'analyseur développe A en α chaque fois que le


symbole d'entrée courant est a.
• Une production se produit quand α = ε ou α *→ ε.
Dans ce cas, nous devons également développer A en α
si le symbole d'entrée courant est dans SUIVANT(A) ou
si le $ d'entrée a été atteint et que $ est dans
SUIVANT(A).
chapitre 6

Algorithme

Donnée : une grammaire G.

Résultat : une table d'analyse M pour G.

Méthode :

• Pour chaque production A → α de la grammaire :

• Pour chaque terminal a dans Premier(α),


ajouter A → α à M[A; a]
chapitre 6

• Si ε est dans PREMIER (α) :


• Ajouter A → α à M[A; b] pour chaque
terminal b dans Suivant(A)

• Si $ est dans Suivant(A), ajouter A →


α à M[A; $].

• Faire de chaque entrée indéfinie de M une erreur de


syntaxe.
chapitre 6

Exemple

E → T E’
E’ → + T E’
E’ → ε
T → F T’
T’ → * F T’
T’ → ε
F → (E)
F → nb
Table d’analyse chapitre 6

E → T E’ E’ → ε T’ → *F T’ F → (E)
E’ → +T E’ T → F T’ T’ → ε F → nb

Non- nb + * ( ) $
terminal
E E → TE’ E → TE’
E’ E’→+TE’ E’ → ε E’ → ε
T T → FT’ T → FT’
T’ T’ → ε T’ → ε
T’ → ε T’ →*FT’
F F → nb F → (E)

PREMIER(T) = {(, nb} SUIVANT(E’) = {$, )}

PREMIER(F) = {(, nb} SUIVANT(T’) = {+, $, )}


Analyseur syntaxique dirigé par table
chapitre 6

• Un tampon d'entrée : contient la chaîne à


analyser, suivie de $, symbole utilisé comme
marqueur d'extrémité droite qui indique la fin de la
chaîne d'entrée.
• Une pile : contient une séquence de symboles
grammaticaux, avec $ marquant le fond de pile.
Initialement, la pile contient l'axiome de la
grammaire au dessus du $.

• Une table d'analyse : tableau à deux


dimensions M[A; a] où A est un non-terminal et a
un terminal ou le symbole $.

• Un flot de sortie : ce qu'on récupère.


Principe chapitre 6

L'analyse syntaxique est contrôlée par un


programme qui a le comportement suivant,
sachant que X est le symbole au sommet de la pile,
et a le symbole d'entrée courant. Ces deux
symboles déterminent l'action de l'analyseur. Il y a
trois possibilités :

• Si X = a = $ : l'analyseur s'arrête et annonce la


réussite finale de l'analyse.
• Si X = a ≠ $ : l'analyseur enlève X de la pile et
avance son pointeur d'entrée sur le symbole
suivant.
chapitre 6

• Si X est un non-terminal, le programme consulte


l'entrée M[X; a] de la table d'analyse M. Cette
entrée sera soit une X-production de la grammaire
soit une erreur.
• Si par exemple, M[X; a] = {X → UVW},
l'analyseur remplace X en sommet de pile par
WVU (avec U au sommet). Nous supposerons
que l'analyseur se contente pour tout résultat
d'imprimer la production utilisée.
• Si M[X; a] = erreur , l'analyseur appelle une
procédure de récupération sur l'erreur.
chapitre 6

Algorithme d'analyse
Donnée : une chaîne w et une table d'analyse M
pour une grammaire G.

Résultat : si w est dans L(G), une dérivation


gauche pour w, sinon une indication d'erreur.

Méthode : initialement, l'analyseur est dans une


configuration dans laquelle il y a $S dans la pile,
avec S l'axiome de G au sommet, et w$ dans son
tampon d'entrée.
chapitre 6

Algorithme
• Positionner le pointeur source ps sur le premier
symbole de w$.
• Répéter jusqu‘à ce que X = $.
• Soit X le symbole en sommet de pile et a le
symbole pointé par ps.
• Si X est un terminal ou $ alors :
• Si X = a alors enlever X de la pile et
avancer ps.
• Sinon Erreur()
chapitre 6

• Sinon (X est un non-terminal) :


• Si M[X; a] = X → Y1Y2 … Yn alors
• Debut :
• Enlever X de la pile
• Mettre Yn; Yn-1; … ; Y1 sur la pile (avec Y1 au
sommet)

• Emettre en sortie la production X → Y1Y2 … Yn


• Fin
• Sinon Erreur()
chapitre 6

Exemple précédent
le mot w = 3 + 4 * 5

Pile Entrée Sortie


$E 3+4*5$ E → T E’
$ E’ T 3+4*5$ T → F T’
$ E’ T’ F 3+4*5$ F → nb
$ E’ T’ 3 3+4*5$
$ E’ T’ +4*5$ T’ → ε
$ E’ +4*5$ E’ → + T E’
chapitre 6

Pile Entrée Sortie


$ E’ T + +4*5$
$ E’ T 4*5$ T → F T’
$ E’ T’ F 4*5$ F → nb
$ E’ T’ 4 4*5$
$ E’ T’ *5$ T’ → * F T’
$ E’ T’ F * *5$
$ E’ T’ F 5$ F → nb
$ E’ T’ 5 5$
$ E’ T’ $ T’ → ε
$ E’ $ E’ → ε
$ $ Analyse réussie
chapitre 6

T E’

+ T E’
F T’

F T’ ε
3 ε
* F T’
4

5 ε

Arbre syntaxique pour 3 + 4 *5.


chapitre 6

Exercice
le mot w = (7 + 3)5

Pile Entrée Sortie


$E (7 + 3)5 $ E → T E’
$ E’ T (7 + 3)5 $ T → F T’
$ E’ T’ F (7 + 3)5 $ F → (E)
$ E’ T’ )E( (7 + 3)5 $
$ E’ T’ )E 7 + 3)5 $ E → T E’
$ E’ T’ )E’ T 7 + 3)5 $ T → F T’
chapitre 6

Pile Entrée Sortie


$ E’ T’ )E’ T’ F 7 + 3)5 $ F → nb
$ E’ T’ )E’ T’ 7 7 + 3)5 $
$ E’ T’ )E’ T’ + 3)5 $ T’ → ε
$ E’ T’ )E’ + 3)5 $ E’ → + T E’
$ E’ T’ )E’ T + + 3)5 $
$ E’ T’ )E’ T 3)5 $ T → F T’
$ E’ T’ )E’ T’ F 3)5 $ F → nb
$ E’ T’ )E’ T’ 3 3)5 $
$ E’ T’ )E’ T’ )5 $ T’ → ε
$ E’ T’ )E’ )5 $ E’ → ε
$ E’ T’ ) )5 $
$ E’ T’ 5$ ERREUR
chapitre 6

Remarque
L’algorithme précédent peut il être appliqué à
toutes les grammaires?

Si la table d’analyse comporte des entrées


multiples (plusieurs productions pour une même
case M[A, α]), le choix de la production adéquate
sera difficile.
chapitre 6

Définition
Une grammaire est dite de type LL(1) si la table
d’analyse associée n’a aucune case définie de
façon multiple.

Exemple
S → aAb
A → cd | c
chapitre 6

PREMIER(S) = {a} SUIVANT(S) = {$}

PREMIER(A) = {c} SUIVANT(A) = {b}

Table d’analyse
a b c d $

S S → aAb

A A → cd
A→c
chapitre 6

Remarque
La grammaire n’est pas de type LL(1). En effet,
pour pouvoir choisir entre la production A → cd
et la production A → c, il faut lire la lettre qui
suit celle que l’on pointe (donc deux symboles
de prévision sont nécessaires).
chapitre 6

Théorème
Une grammaire ambiguë ou récursive à gauche ou
non factorisée à gauche n’est pas LL(1).

Récursivité à gauche
Une grammaire est immédiatement récursive à
gauche si elle contient un non-terminal A tel qu’il
existe une production A → Aα où α est une chaîne
quelconque.
chapitre 6

Exemple

S → ScA | B
A → Aa | ε
B → Bb | d | e

Cette grammaire contient plusieurs récursivités à


gauche immédiates.
chapitre 6

Elimination de la récursivité à
gauche immédiate
Remplacer toute règle de la forme A → Aα | β par
les deux règles :

A → β A’

A’ → α A’ | ε

Théorème
La grammaire ainsi obtenue reconnaît le même
langage que la grammaire initiale.
Exemple chapitre 6

S → ScA | B Mot : dbbcaa


A → Aa | ε
S → ScA → BcA → BbcA →
B → Bb | d | e
BbbcA → dbbcA → dbbcAa →
S → B S’ dbbcAaa → dbbcaa

S’ → c A S’ | ε S → BS’ → dB’S’ → dbB’S’ →


A → A’ dbbB’S’ → dbbS’ → dbbcAS’ →
A’ → a A’ | ε dbbcA’S’ → dbbcaA’S’ →
dbbcaaA’S’ → dbbcaaS’ →
B → d B’ | e B’
dbbcaa
B’ → bB’ | ε
chapitre 6

Définition
Une grammaire est récursive à gauche si elle
contient un non-terminal A tel qu’il existe une
production A+→Aα où α est une chaîne quelconque.

Exemple
S → Aa | b S est il récursif à gauche?
A → Ac | Sd | ε S → Aa → Sda

S est récursif à gauche mais non immédiatement.


chapitre 6

Elimination de la récursivité à gauche

Ordonner les non-terminaux A1, A2, … , An


Pour i = 1 à n faire
Pour j = 1 à i - 1 faire
Remplacer chaque production de la forme
Ai → Ajα où Aj → β1 | β2 | … | βp par :
Ai → β1 α | β2 α | … | βp α
fin pour
Éliminer les récursivités à gauche immédiates des
productions Ai
Fin pour
Exemple chapitre 6

S → Aa | b
On ordonne S, A
A → Ac | Sd | ε

i = 1 pas de récursivité immédiate dans S → Aa| b

i = 2 et j = 1 on substitue la production A → Sd
par A → Aad | bd, on obtient A → Ac| Aad | bd| ε
On élimine la récursivité immédiate :

A → bdA’ | A’ S → Aa | b
A’ → cA’ | adA’ | ε A → bdA’ | A’
A’ → cA’ | adA’ | ε
chapitre 6

Factorisation à gauche

Exemple 1

inst → si expr alors inst sinon inst

inst → si expr alors inst

A la vue de l‘unité lexicale si, quelle production va


être utiliser pour développer inst.
chapitre 6

Exemple 2
S → bacdAbd | bacdBcca
A → aD
B → cE
C→…
Au départ pour savoir s’il faut choisir S → bacdAbd
ou S → bacdBcca, il faut lire la 5ième lettre du mot (a
ou c). Dès le départ, quelle production va être
choisie? Ce qui est incompatible avec les
grammaires LL(1).
Cas général chapitre 6

Si A → αβ1 | αβ2 sont deux A-productions et si


l'entrée commence par une chaîne non vide
dérivée de α, nous ne savons pas s'il faut
développer A en αβ1 ou en A en αβ2.

Il est possible de différer cette décision en


étendant A en αA’. Alors après avoir lu la chaîne
dérivée de α, nous étendons A’ en β1 ou en β2.

Factorisation à gauche
A → αA’
A → αβ1 | αβ2
A’ → β1 | β2
Algorithme chapitre 6

Pour chaque non-terminal A, trouver le plus long


préfixe α commun à deux de ses alternatives ou
plus.
Si α ≠ ε, remplacer A → αβ1 | … | α βp | γ1 | … | γp
(où les γi ne commencent pas par α) par les deux
règles :
A → αA’ | γ1 | … | γp
A’ → β1 | … | βp
fin pour
Recommencer jusqu’à ne plus en trouver.
chapitre 6

Exemple
S → aEbS | aEbSeB | a
E → bcB | bca
B → ba
S → aEbSS’ | a
S’ → eB | ε
E → bcE’
E’ → B | a
B → ba
chapitre 6

Exercice
S → abS | abA | aB
A→c
B→d

Factoriser la grammaire suivante.


chapitre 6

On fait une itération avec α= ab et on obtient la


grammaire :

S → abS’ | aB
α= a et la grammaire est :
S’ → S | A
A→c S → aS’’
B→d S’’ → bS’ | B
S’ → S | A
A→c
B→d
Analyse sémantique chapitre 6

1. Introduction
La sémantique d'un langage de programmation est la
description du sens des constructions du langage. Les
phrases syntaxiquement correctes d'un langage de
programmation n'ont pas toutes un sens. Le
compilateur, qui a la charge de traduire un programme
source vers un programme équivalent en langage
machine, doit s'assurer que le programme a bien un
sens (on dit qu'il est correct sémantiquement), avant
d'effectuer la traduction à proprement parler.
Sémantique statique chapitre 6

1 program exemple;
2 var x : integer;
3 t : array [1..10] of integer;
4 procedure p (z : real);
5 var i : integer;
6 Begin
7 z := i;
8 end; (* fin de p *)
9 begin (* program exemple *)
10 readln (i);
11 x := t;
12 p(x, i);
13 end.
chapitre 6

Ligne 7 la variable i est utilisée mais n'est pas


initialisée.

Ligne 10 la variable i est utilisée alors qu'elle n'est


pas déclarée dans le bloc de déclarations
correspondant.

Ligne 11 la variable t qui est un tableau est


affectée à une variable x entière.

Ligne 12 la procédure p est appelée avec deux


paramètres (x et i) alors qu'elle n'a été
déclarée qu'avec un paramètre.
chapitre 6

Une erreur comme celle de la ligne 10 a trait à ce


que l'on appelle la portée des identificateurs :
lorsque l'on déclare un identificateur, cette
déclaration n'est utilisable que dans une certaine
partie du programme. Ici, la variable i, bien que
déclarée dans p, n'est pas déclarée dans le
programme principal.

Une erreur comme celle de la ligne 11 a trait au


contrôle des types : on vérifie que chaque
utilisation d'une variable correspond bien au type
qu'on a déclaré pour cette variable.
chapitre 6

une erreur comme celle de la ligne 12 a trait à la


sémantique de l'appel de procédures et de
fonctions.

Remarque

L'ensemble de ces contrôles correspondent à la


vérification de la sémantique statique du programme,
c'est-à-dire de la partie de la sémantique qui peut
être vérifiée sans exécuter le programme. La
sémantique statique est contrôlée par le compilateur,
qui interdit l'exécution du programme si elle n'est pas
correcte.
Sémantique dynamique chapitre 6

Remarque
Cependant, il n'est pas possible en général
d'assurer que tout ce que fait le programme a
un sens. En d'autres termes, toute la
sémantique d'un langage ne peut être décrite
pas sa sémantique statique.
chapitre 6
program p;
var t : array [1..10] of integer;
i : integer;
function f (n : integer) : integer;
Begin
if n > 2 then f := f (n-1) + f (n-2) else f := n
end; (* f *)
begin (* program p *)
i := 1;
while f(i) < 1000 do 144
Begin
writeln (t[i]); i := i + 1;
end; end.
chapitre 6

Interprétation

L'expression t[i] n'a de sens que si i est dans


l'intervalle [1..10]. Ici, i vaut 1 au début, et est
incrémenté jusqu'à ce que f(i) soit supérieur ou égal
à 1000.

Malheureusement il est impossible de savoir si la


valeur de f(i) sera inférieure à 1000 lorsque i est
inférieur à 10, même en regardant le corps de la
fonction f, à moins de calculer effectivement les
valeurs de f(i), c'est-à-dire d'exécuter le programme.
Remarque
chapitre 6

Cette partie de la sémantique est la sémantique


dynamique car elle ne peut être contrôlée que lors
de l'exécution du programme.

L'un des avantages des langages impératifs est de


diminuer la sémantique dynamique par rapport à
la sémantique statique. Cela a pour effet qu'un
plus grand nombre d'erreurs sémantiques sont
découvertes avant d'exécuter le programme, à la
compilation, et que les erreur d'exécution, qui sont
difficiles à découvrir et à réparer, sont plus rares.
chapitre 6

Génération du code final

Table des symboles

Tout au long des analyses lexicale, syntaxique et


sémantique, le compilateur construit une table
regroupant toutes les informations utiles sur les
objets apparaissant dans le programme compilé
pour en contrôler l’usage et pour aider à sa
traduction.
chapitre 6

La table des symboles permet de trouver, pour


chaque identificateur déclaré, son type, sa taille et
son adresse.

Pour pouvoir effectuer une adresse à chacun des


objets, le compilateur manipule un compteur
d’emplacements, initialisé à 0 pour le premier objet
et incrémenté ensuite de la taille de chaque objet
rencontré.

L’adresse d’un objet est égale à la valeur du


compteur d’emplacements.
chapitre 6

Exemple
PROGRAM Z
Nom de type Taille Adresse
INT A; l’objet (octets)
INT B; A Entier 4 0
INT C2;
DEBUT B Entier 4 4

A = 4;
C Entier 4 8
B = A / 2;
C2 = B + A;
Table des symboles du programme Z
FIN
chapitre 6

Génération du code et optimisation


Génération du code constitue l’étape ultime de la
compilation. Elle consiste à produire dans un fichier
objet le code machine équivalent au code du
langage de haut niveau. Elle se décompose en :

• Génération d’un code intermédiaire.


• Optimisation de ce code intermédiaire.
• Génération du code final.
chapitre 6

Génération du code intermédiaire


La génération du code intermédiaire consiste à
remplacer les phrases reconnues par des macros
plus aisément manipulables.

Les objets sont eux même remplacés par leur


adresse qui leur a été affectée dans la table des
symboles.

N.B.
Les macros ne sont pas des instructions machine,
donc ils restent indépendant de l’architecture de
celle-ci.
chapitre 6

Exemple
Le programme Z sera transformé en :

INIT a b : macro d’initialisation qui initialise l’objet a


avec la valeur b.
DIV a b c : macro qui divise b par c et stocke le résultat
dans a.
ADD a b c : macro qui additionne b avec c et stocke le
résultat dans a.
chapitre 6

Exemple
PROGRAM Z Z:
INT A; (0)
INT B; (4)
INT C2; (8)
DEBUT
A = 4; INIT (0) 4
B = A / 2; DIV (4) (0) 2
C2 = B + A; ADD (8) (4) (0)
FIN STOP
chapitre 6

Optimisation du code intermédiaire


L’optimisation du code vise à produire un code
machine plus performant (un code dont l’exécution
est plus rapide d’une part et d’autre part un code
plus compact dont l’encombrement mémoire est
moindre).

Plusieurs améliorations peuvent être mises en


œuvre. Les plus courantes sont :
chapitre 6

• La réduction des expressions constantes : elle


consiste à effectuer des calculs arithmétiques qui
ne comportent que des opérandes constants et à
remplacer l’expression arithmétique par son
résultat.
Exemple :
L’expression B = A/2; peut être calculée puisque la
valeur de A est connue comme étant égale à 4.
L’expression B = A/2; est donc remplacée par 2.

L’expression C2 = B + A; est donc remplacée par


6.
chapitre 6

PROGRAM Z Z: Z:
INT A; (0) (0)
INT B; (4) (4)
INT C2; (8) (8)
DEBUT
A = 4; INIT (0) 4 INIT (0) 4
B = A / 2; B=2 DIV (4) (0) 2 INIT (4) 2
C2 = B + A; C2 = 6 ADD (8) (4) (0) INIT (8) 6
FIN STOP STOP
chapitre 6

• Simplification des boucles et pré-évaluation des


expressions constantes : elle consiste à sortir les
expressions invariantes des corps de boucles et à
les placer juste devant ceux-ci.

Exemple :

for i = 1 to n j := 3;
boucle for i = 1 to n
j := 3; boucle
i := i + 1; i := i + 1;
fin boucle fin boucle
chapitre 6

• Simplification des boucles et réduction de


puissance des opérateurs : elle consiste à
remplacer au sein d’une boucle une opération
puissante et jugée plus coûteuse telle que la
multiplication par une opération plus simple et
moins coûteuse telle que l’addition.

Exemple :
for i = 1 to n for i = 1 to n
boucle boucle
a := i * 5; a := a + 5;
fin boucle fin boucle
chapitre 6

Génération du code final


L’étape final est celle de génération du code final.
Les macros sont remplacées par les instructions
machine correspondantes et les objets sont
remplacés par leur adresse.

Vous aimerez peut-être aussi