Vous êtes sur la page 1sur 249

Compilation

SMI/S5
Compilation
Prof. : M. BENADDY
Contenu du cours


Introduction

Analyse lexicale

Travaux pratiques (Lex,Flex)

Analyse syntaxique et sémantique

Travaux pratiques (Yacc)

Génération du code intermédiaire

Optimisation du code

Prof. M. BENADDY Compilation 1 2


Déroulement


25 heures de cours

10 heures de TD

12 heures de TP

Prof. M. BENADDY Compilation 1 3


Evaluation


Note de l'examen final

Note des travaux pratiques et/ou mini projet

Prof. M. BENADDY Compilation 1 4


Références

Compilers: Principles, Techniques, and Tools (2nd
Edition), Alfred V. Aho, Monica S. Lam, Ravi Sethi,
Jeffrey D. Ullman, Addison Wesley ; 2nd edition (2007)

Modern Compiler Implementation in Java, 2nd ed.
Andrew Appel, Cambrdige University Press (2004).

Lex & yacc (2nd Edition 1992), John R. Levine, Tony
Mason and Doug Brown, O'Reilly & Associates, Inc.

Engineering a Compiler Second Edition, Keith D.
Cooper Linda Torczon, Morgan Kaufmann, Elsevier,
Inc. (2012).

Programming Language, Third edition, Michael L. Scott,
2009 by Elsevier Inc.
Prof. M. BENADDY Compilation 1 5
Compilation

Chapitre 1 : Introduction générale

Prof. M. BENADDY Compilation 1 6


Introduction

Au début de l’informatique on programme
directement les ordinateurs en langage machine,

Tâche assez dur,

Solution : utiliser les possibilités de l’informatique
pour faciliter le travail de programmation.

Un ordinateur représente toutes les informations
(données et programmes) par des suites de 0,1,

Le programmeur utilise des langages proches du
langage humain !!

Solution: un traducteur <=> compilateur/
interpréteur
Prof. M. BENADDY Compilation 1 7
Langages compilés/interprétés

Langages compilés : Se sont des langages où
toutes les instructions sont traduites en code
objet avant d’être exécutées cette conversion est
effectuée par un compilateur.

Langages interprétés : Se sont les langages
dont les instructions sont décodées et exécutées
instruction/instruction lors de l’exécution du
programme à l’aide d’un traducteur appelé
interprète.

Prof. M. BENADDY Compilation 1 8


Famille des langages

Langages de bas niveau (1ère et 2ème génération) :

Le langage machine,

L’assembleur.

Langages de haut niveau (3ème génération) :

les langages procéduraux (Fortran, Cobol, Basic, Pascal,
Langage C, …)

les langages orientés objet (SIMULA, C++, Java,
SMALTALK, Object Pascal, EIFFEL, …)

les langages orientés listes (LISP, PROLOG,
PYTHON, ...)

Langages de 4éme génération : se sont des langages créés
pour des applications spécifiques (SQL, NOMAD, …)
Prof. M. BENADDY Compilation 1 9
Famille des langages

Remarque : d'autres classifications peuvent être
adoptés, telles que :

Les langages déclaratifs (C, C++, Java, C#...)

Les langages fonctionnels (ML, HASKELL,…)

Les langages de scripts (Awk, Javascript, Php, Perl,
Python, Ruby, Tcl,...)

Prof. M. BENADDY Compilation 1 10


Les compilateurs

Un compilateur est un programme qui lit le programme écrit
dans un premier langage (langage source) et le traduit en un
programme équivalent écrit dans un autre langage ‘’langage
cible’’ ou langage destination.

La compilation est composée de deux parties essentielles :
l’analyse et la synthèse.

L’analyse : la partition du programme source en ces
constituants et en créant une représentation intermédiaire.

La synthèse : génère le programme cible à partir de la
représentation intermédiaire.

Remarque : au cours du processus de traduction un rôle
important du compilateur est de signaler à l’utilisateur la
présence des erreurs dans le programme source
Prof. M. BENADDY Compilation 1 11
Les compilateurs

Remarque : Pendant l’analyse les opérations de spécifiées
par le programme source sont déterminées et conservées
dans une structure hiérarchique appelée arbre abstrait
chaque nœud de l’arbre représente une opération et les fils
des nœuds représentent les arguments de cette opération.

Exemple : arbre abstrait

T=x+y*z
=
/\
T +
/\
X*
/\
Prof. M. BENADDY
Y z Compilation 1 12
Les compilateurs

Représentation schématique :

Programme écrit Compilateur Programme écrit


en langage source en langage destination

Erreurs

Prof. M. BENADDY Compilation 1 13


Les compilateurs

Phases d'un compilateur

Phases d'analyse
Analyse lexicale
Analyse syntaxique

Table des Analyse sémantique Gestion


symboles Génération du code
Des
intermédiaire erreurs
Optimisation du code
Phases de synthèse
Génération du code objet

Programme cible

Prof. M. BENADDY Compilation 1 14


Les phases d'un compilateur

Analyse lexicale (scanner) : Trouver les mots du programme.

Il décompose le texte du programme en lexème appelé aussi
token ou unité lexicale, les tokens sont classés comme suit :

Les identificateurs : se sont les mots du programme formés
par l’utilisateur pour l’appellation des variables et des
constantes du programme,

Les mots clés : se sont les mots particuliers au langage
ayant un sens bien spécifique, ils sont différents d’un langage
à un autre,

Les constantes,

Les opérateurs : +, -,*,/, ou, et, non, …

Les séparateurs : se sont les caractères de ponctuation telle
que le point virgule ( ;) la virgule (,), …

L’affectation.
Prof. M. BENADDY Compilation 1 15
Les phases d'un compilateur

Analyse lexicale

Exemple : Mots clé Identificateurs Constantes Opérateurs Séparateurs Affectation

For, do, to i, s 1, 10 + ; :=

For i :=1 to 10 do
s :=s+i ;


L’analyseur lexicale remplit également tout les symboles du programme et
qui n’appartient pas au langage comme les identifiants, les constantes, ...,
dans la table des symboles.

Le code produit par la phase lexicale est une chaîne d’unités lexicales,

Une unité lexicale est codifiée par la paire (type, valeur (vallex)) où type
est le type de l’unité lexicale à savoir les identificateurs, les constantes, ...,
vallex est la valeur de l’unité : si l’unité est un identificateur vallex sera une
chaîne de caractères qui forme le nom de cet identificateur.
Prof. M. BENADDY Compilation 1 16
Les phases d'un compilateur

Analyse lexicale

Exemple : l'instruction position = initial + rate*60

Est codifié : <id,1> <=> <id,2> < +> <id,3>*<60>

Remarque : les mots clés ainsi que les séparateurs sont
considérés comme des unités n’ayant pas de valeurs ils
ne seront donc pas codifiés que par le type.

Prof. M. BENADDY Compilation 1 17


Les phases d'un compilateur

Analyse Syntaxique : Appelée aussi analyse hiérarchique ou analyse
grammaticale,

Vérifier si la syntaxe de la chaîne codée est conforme avec celle du
langage à compiler,

Il consiste à trouver les phrases du programme source à partir des mots
donnés par l’analyseur lexical, formellement cela consiste à créer l’arbre
syntaxique, celui-ci décrit la structure du programme.

L’analyseur syntaxique se fait sur la base d’une grammaire.
Généralement la structure hiérarchique d’un programme est exprimée
par des règles récursives.

Exemple :

Un identificateur est une expression,

Une constante est une expression,

Si expression 1 et expression 2 sont des expressions alors (expr1 +
expr2) est une expression (expr1*expr2) l’est aussi.
Prof. M. BENADDY Compilation 1 18
Les phases d'un compilateur

Analyse Syntaxique :

Exemple : soit l’expression

position := initial + rate*60

position, initial, rate → expression

60 → expression

Rate*60 → expression

initial + rate*60 → expression

Prof. M. BENADDY Compilation 1 19


Les phases d'un compilateur

Analyse Syntaxique :

Exemple : soit l’expression

position := initial + rate*60

Prof. M. BENADDY Compilation 1 20


Les phases d'un compilateur

Analyse sémantique : contrôle si le programme source contient des
erreurs sémantiques elle utilise la structure hiérarchique déterminée
par la phase d’analyse syntaxique pour identifier les opérateurs et les
opérandes des expressions ainsi que les instructions.

Cette analyse effectuera quelques contrôles et quelques
modifications de l’arbre syntaxique et contrôles portant par
exemple :

Sur la visibilité des variables c-à-d vérifier qu’ils sont déclarées
et visibles aux endroits où ils sont utilisés.

Sur le mode c-à-d vérifier les types utilisés. Ceci peut
éventuellement amener des modifications de l’arbre syntaxique
par l’ajout de nœuds spéciaux.

Par exemple pour le transtypage d’un entier vers un réel, on
pourrait rajouter un nœud ‘’entier vers réel’’ qui indique qu’une
conversion doit être faite.
Prof. M. BENADDY Compilation 1 21
Les phases d'un compilateur

Analyse sémantique :

Exemple : soit X = X0 + V0*60, sachant que X, X0, V0
sont des réels

L’arbre sémantique correspondant à l’arbre syntaxique
est :

Prof. M. BENADDY Compilation 1 22


Les phases d'un compilateur

Production du code intermédiaire : A partir des analyses
syntaxiques et sémantiques un code simple de bas niveau (proche du
code machine) est généré.

Ce code intermédiaire doit :

Être facile à produire et facile à traduire en langage cible.

Cette représentation intermédiaire peut prendre une grande variété
de forme, les plus utilisées sont :

Le code post fixé : c’est un code dans lequel tout opérateur
apparaît après ses opérandes. C’est un code préconisé car les
opérateurs et les opérandes dans ce code apparaissent dans le
même ordre qu’à l’exécution.

Le code à trois adresses : c’est un code semblable au langage
d’assemblage d’une machine. Il est caractérisé par le fait que
l’instruction contienne en plus un seul opérateur et trois
opérandes.
Prof. M. BENADDY Compilation 1 23
Les phases d'un compilateur

Production du code intermédiaire :

Exemple : id1 = id2 + id3*60
tmp1 = EVR(60)
tmp2 = tmp1*id3
tmp3 = tmp2+id2
id1 = tmp3


Le compilateur doit décider dans quel ordre les opérations
doivent être effectués, exemple : la multiplication précède
l’addition.

Prof. M. BENADDY Compilation 1 24


Les phases d'un compilateur

Optimisation du code : cette phase tante d’améliorer le code intermédiaire de
façon que le code machine résultant s’exécute plus rapidement.

L’optimisation peut se faire soit sur la taille du code soit sur la mémoire utilisée par
le programme soit encore sur le temps d’exécution.

Par exemple un algorithme produira le code intermédiaire en employant une
instruction pour chaque opérateur de la représentation arborescente obtenue
après l’analyse sémantique, bien qu’il y est une meilleure manière d’effectuer le
même calcul avec les deux instructions :

tmp1 = id3 * 60

id1 = tmp1 + id2

le compilateur peut déduire lui même que la conversion de l’entier 60 en réel peut
être effectuée une fois pour toute au moment de la compilation de sorte que l’on
peut éliminer l’opération entier vers réel. tmp3 n’est utilisée qu’une seule fois pour
transmettre sa valeur à id1, on peut donc en toute sécurité substituer id1 à tmp3.

Parmi les optimisations courantes :

Le code constant dans une boucle peut être sorti de celle-ci.
Prof. M. BENADDY Compilation 1 25
Les phases d'un compilateur

Optimisation du code :

Parmi les optimisations courantes :

Le code constant dans une boucle
for(i = 0 ; i<3 ; i++) Opt
peut être sorti de celle-
b = 12 ;
ci. {
scanf(‘’%d’’,&a) ;
for(i = 0 ; i<3 ; i++)
{
b = 12 ; scanf(‘’%d’’,&a) ;
a = a + i ; a = a + i ;
printf(‘’%d’’,a) ; printf(‘’%d’’,a) ;
} }


Les calculs et les transtypages portant uniquement sur
des constantes peuvent être faites à la compilation.

Les parties du code inaccessibles peuvent être
supprimées. If(cond1 || true)
Inst1 ;
Opt Inst1 ;

else inst2 ;

Prof. M. BENADDY Compilation 1 26


Les phases d'un compilateur

Génération du code : cette phase produit le code final
équivalent au programme de départ.

Avant la génération du code il faut connaître la forme du
code final et aussi l’architecture de la machine sur laquelle le
programme sera exécuté.

Généralement le code cible consiste en langage
d’assemblage.

On sélectionne les emplacements mémoire pour chacune
des variables utilisées dans le programme, ensuite les
instructions intermédiaires sont traduites en une suite
d’instructions machines qui effectuent la même tâche,

Prof. M. BENADDY Compilation 1 27


Les phases d'un compilateur

Optimisation du code :

Un aspect crucial de ce processus est l’assignation de
variables aux registres, par exemple en utilisant les registres
R1 et R2 la traduction de l’instruction id1 = id2 + id3*60 est :
MOVF id3,R2 Le F signifie float (réel)
MULF #60.0,R2 # constante interne
MOVF id2,R1
ADDF R2,R1
MOVF R1,id1

Prof. M. BENADDY Compilation 1 28


Les phases d'un compilateur

Synthèse :

Prof. M. BENADDY Compilation 1 29


Les phases d'un compilateur

Gestion de la table des symboles :

Toutes les phases de compilation communiquent des
informations entre elles par l’intermédiaire de la table des
symboles,

Chaque phase installe dans cette table les informations
nécessaires à l’accomplissement des phases ultérieures.
1)L’analyse lexicale insère les identificateurs, les
constantes dans la table des symboles.
2)L’analyse syntaxique est sémantique associe à chaque
identificateur sont type, à chaque fonction son nombre
d’argument et ses arguments, etc.

Prof. M. BENADDY Compilation 1 30


Les phases d'un compilateur

Gestion de la table des symboles :
3) Le générateur du code intermédiaire doit accéder à la table pour repérer le
types des opérandes afin de vérifier la compatibilité des types. Si le langage
permet le mixage des types, une instruction spécifiant une conversion de
type sera générée. Le générateur doit mémoriser le nouveau type de
l’identificateur dans la table des symboles.
4) Lors de l’optimisation du code à tout identificateur résultant par exemple
une expression à éliminer doit être substituée par l’identificateur de
l’expression à garder, le résultat de cette modification doit figurer dans la
table.
5) On doit insérer dans la table des symboles l’information d est remplacée
par a dans la suite du code.
6) Dans la génération du code final on peut associer à chaque identificateur
les registres qui doivent contenir sa valeur.
B = 12 ; opt B = 12 ;
C = 14 ; C = 14 ;
A = B + C ; A = B + C ;
D = B + C ; (id,d)
Prof. M. BENADDY Compilation 1 31
Les phases d'un compilateur

Gestion des erreurs : La gestion des erreurs est une étape
importante du compilateur, il existe deux stratégies :
1)Soit on arrête dés qu’il y a une erreur.
2)Soit on essaie de resynchroniser et de déterminer le plus
précisément possible la cause de l’erreur.

Une bonne gestion des erreurs permet de détecter un
maximum en même temps, ce qui permet de les corriger
avant de réessayer la compilation.

L’inconvénient de cette stratégie est qu’on peut avoir d’autres
messages d’erreurs dues à des erreurs précédentes.

Prof. M. BENADDY Compilation 1 32


Les phases d'un compilateur

Gestion des erreurs :

Chaque phase de compilation détecte son propre type d’erreur :

L’analyse lexicale détecte peu d’erreurs essentiellement les fautes de
frappe, il s’agit de caractères interdits ou ayant une forme illégale pour
le langage (3x, β, ф, ...).

L’analyse syntaxique détecte les erreurs de construction du programme
par exemple : en C une accolade rencontre un point manquant ou
encore fi(x==4) (fi est considéré comme identificateur par l’analyseur
lexical, mais l’analyseur syntaxique dit que cette instruction est illégale.

L’analyse sémantique détecte des erreurs de type, les variables non
déclarées, etc.

L’optimiseur du code peut informer une instruction du programme ne
peut jamais être accessible et par conséquent jamais exécutée.

Le générateur du code objet peut indiquer qu'une valeur créée par le
compilateur est trop grande pour être mémorisée.
Prof. M. BENADDY Compilation 1 33
Les phases d'un compilateur

Regroupement des phases :

Les sections précédentes traite l’organigramme logique
d’un compilateur, pour accélérer le processus de
compilation, les différentes phases sont regroupées en
une phase.

Prof. M. BENADDY Compilation 1 34


Les phases d'un compilateur

Regroupement des phases :

Parties frontale et finale :

Les différentes phases sont souvent remise en une partie frontale
et une partie finale.

La partie frontale est constituées des phases qui dépendent
principalement du langage source, elle comprend l’analyse
lexicale, l’analyse syntaxique, la création de la table des
symboles, l’analyse sémantique, la production du code
intermédiaire et le traitement des erreurs associes à chacune
de ces phases.

La partie finale comprend les portions du compilateur qui
dépendent de la machine cible, on trouve dans cette partie
certains aspects, de l’optimisation du code ainsi que la
production du code objet avec les opérateurs nécessaires de
traitement des erreurs et de gestion de la table des symboles.
Prof. M. BENADDY Compilation 1 35
Les phases d'un compilateur

Regroupement des phases :

Les passes :

Une passe est un module qui rassemble plusieurs phases du
compilateur d’une exécution.

Dans une exécution les différentes phases chevauchent entre
elles (en relation) que leurs activités sont entrelacées durant
l’exécution de cette passe.

Il existe un choix entre deux options d’implantation.
1)La première consiste à l’utilisation d’un sous programme pour
chaque phase du processus, appelé aussi le parallélisme.
2)La 2ème consiste à donner le contrôle d’une phase qui fait
appelle au module des autres phases au moment opportun.
Prof. M. BENADDY Compilation 1 36
Les phases d'un compilateur

Outils de construction de compilateurs :

Les grammaires hors contextes, pour l’analyse
syntaxique, et les expressions régulières, pour l'analyse
lexicale sont deux abstractions les plus utiles utilisés dans
compilateurs modernes.

Lex/Flex (qui converti des déclarations en un programme
d’analyse lexicale).

Yacc (Yet Another Compiler-Compiler), qui convertit une
grammaire en un programme d’analyse syntaxique.

Prof. M. BENADDY Compilation 1 37


Compilation

Chapitre2 : Analyse lexicale


SMI-S5
Compilation
Prof. : M. BENADDY
Introduction (1)

Rôle de l’analyseur lexicale (scanner) : lire les
caractères d’entrée (programme source) et produire
comme résultat une suite d’unités lexicales appelées
TOKENS que l’analyseur syntaxique va utiliser.

Les TOKENS sont constitués au fur et à mesure de la
lecture du texte source, on distingue deux types
d’unités lexicales.

Les unités propres au langage, les mots clés, les
séparateurs, les opérateurs, ...etc.

Les unités personnalisées qui sont crées par le
programmeur (les constantes, les identificateurs...).
Prof. M. BENADDY Compilation 2
Introduction (2)

Table des symboles

Programme Unité lexicale


source Analyseur lexical Analyseur syntaxique
Donner l'unité
lexicale suivante (type, val)

Table des erreurs


Remarque : l’analyseur lexical de certains
compilateurs procèdent à l’élimination dans le
programme source des commentaires et des
espaces qu’apparaissent sous forme de caractères
blancs ou de tabulations ou bien les sauts de lignes.
Prof. M. BENADDY Compilation 3
Unités lexicales, lexèmes, modèles (1)

Token : unité lexicale, est une paire de nom et d’une valeur optionnelle.
Le nom du token est un symbole abstrait qui représente une unité lexicale,
(mot clé, suite de caractère dénotant un identifiant, ...).

Le modèle : est une description de la forme que peut prendre les lexèmes
d’une unité lexicale.

C’est une règle qui décrit l’ensemble des lexèmes pouvant représenter
une unité lexicale particulière dans le programme source.

Dans le cas des mots clés, le modèle est juste une séquence de
caractères qui forme le mot clé.

Pour les identificateurs et d’autres unités lexicales, le modèle est une
structure plus complexes.

Lexème : est une suite de caractères dans le programme sources qui
concorde avec le modèle.

Il est identifié par l’analyseur lexical comme instance d’un token.

Prof. M. BENADDY Compilation 4


Unités lexicales, lexèmes, modèles (2)

Exemple :

Prof. M. BENADDY Compilation 5


Unités lexicales, lexèmes, modèles (3)

Remarques : Dans la plupart des langages de programmation,
les classes suivantes couvrent la majorité des tokens (unités
lexicales).

Un token (unité lexicale) pour chaque mot clé. Le modèle pour
le mot clé est le même que le mot clé.

Les tokens pour les opérateurs, soit individuels soit par classes
(exemple comparaison de l’exemple précédent).

Une unité lexicale pour tous les identificateurs (nom des
variables, des fonctions, des classes, tableaux, structures...).

Une ou plusieurs unités lexicales (tokens) pour les constantes,
les nombres et les chaînes de caractères.

Une unité lexicale pour chaque symbole de ponctuation, tels
que, la virgule, le point virgule, les parenthèses, les
accolades,...
Prof. M. BENADDY Compilation 6
Unités lexicales, lexèmes, modèles (3)

Exemple : float pi = 3.14 ;

La sous chaîne pi est un lexème d’unité lexicale
identificateur, cette unité lexicale est retournée à
l’analyseur syntaxique, le retour est souvent réalisé en
passant un entier correspondant à l’unité lexicale. Le
modèle de l’unité lexicale float est l’unité correspondant à
la simple chaîne float qui vérifie l’orthographe des mots
clés.

Prof. M. BENADDY Compilation 7


Attributs des unités lexicales (1)

L’analyseur lexical réduit les informations sur les unités
lexicales dans les attributs qui leur sont associés.

En pratique une unité lexicale a en général un seul attribut :
un pointeur vers l’entrée dans la table des symboles dans
laquelle l’information sur l’unité lexicale est conservée, le
pointeur devient alors l’attribut de l’entité lexicale.

Prof. M. BENADDY Compilation 8


Attributs des unités lexicales (2)

Exemple : en Fortran E = M * C * * 2 (**désigne la puissance
en Fortran)

Les unités lexicales et les valeurs des attributs sont donnés
par :
<id, pointeur vers l’entrée de la table des symboles associé à E>
<op_affectation>
<id, pointeur vers l’entrée de la table des symboles associé à M>
<op_multiplication>
<id, pointeur vers l’entrée de la table des symboles associé à C>
<op_exposant>
<nombre, valeur entière 2>
Prof. M. BENADDY Compilation 9
Les mots réservés

Certains langages ne tolèrent pas que les mots clés
soient utilisés comme des identificateurs.

Ce qui veut dire que leur signification est prédéfinie et ne
peut pas être changé par le programmeur.

Les mots clés sont installés dans la table des symboles
et quand un identificateur est rencontré il est comparé
avec les mots clés de la table de symboles, s’il coïncide
avec un des mots clés de la table le scanner (analyseur
lexicale) génère le code de ce mot clés, sinon le code de
l’identificateur est transmis.

Exemples : Pascal et C

Prof. M. BENADDY Compilation 10


Les erreurs lexicales

Peu d’erreurs sont détectées au niveau lexicale, car un
analyseur lexical a une vision très localisée du
programme source.

Exemple : si on rencontre la chaîne fi dans un
programme avec fi(i==j) l’analyseur lexical ne peut pas
dire s’il s’agit du mot clé if mal écrit ou d’un identificateur
non déclaré.

Exemple : une variable qui commence par un caractère
non valide (µx, αy, ...) à ce moment-là l’analyseur lexical
déclenche une erreur qui indique la non validité du nom
de la variable.

Prof. M. BENADDY Compilation 11


Spécification des unités lexicales (1)

La procédure d’un analyseur lexical consiste dans un
premier temps en la description des unités lexicales à
l’aide des expressions régulières.

Les expressions régulières sont une notation importante
pour spécifier les modèles, chaque modèle reconnaît un
ensemble de chaînes appelés aussi mots, ces
expressions régulières seront transformées en des
automates qui seront implémentés sur machine.

Prof. M. BENADDY Compilation 12


Spécification des unités lexicales (2)

Mots et langage :

Lettre et mots :

Soit A un ensemble fini appelé alphabet, les éléments de A sont
appelés des lettres, exemple : A={a,b,c,1,3,h}.

Un mot ou une chaîne sur un alphabet est une séquence finie de
symboles extrait de cet ensemble.

On définit A+ l’ensemble des mots non vides comme le plus petit
ensemble tel que :

Pour toute lettre ℓ appartenant à l’alphabet A, ℓ appartiendra à
A+.

Pour tout mot m ϵ A+ et toute lettre ℓ ϵ A, le mot m ℓ ϵ A+, (m ℓ
représente la concaténation du mot m et de la lettre ℓ).

Soit un mot m ϵ A+, on dira que m constitue un mot sur A (mot
fait à partir de l’alphabet A).
Prof. M. BENADDY Compilation 13
Spécification des unités lexicales (3)

Mots et langage :

Opérations sur les langages :

Plusieurs opérations peuvent s’appliquer aux langages.

Pour l’analyse lexicale on s’intéresse principalement à l’union, la
concaténation et la fermeture (de Kleene), on peut aussi généraliser
l’opération d'exponentiation aux langages en définissant L0= { Ԑ },
Li=LLi-1 ainsi Li est la concaténation de L, i-1 fois avec lui même.


Remarque : Ces notations sont employées dans l’écriture des
expressions régulières.
Prof. M. BENADDY Compilation 14
Spécification des unités lexicales (4)

Mots et langage :

Opérations sur les langages :

Exemple :

L = {a, ....,z,A,...,Z}, C={0,...,9}, on peut créer de nouveaux langages à
partir des langages L et C, en appliquant les opérateurs précédents.

L U C est l’ensemble des lettres et des chiffres.

LC est l’ensemble des mots formés d’une lettre suivie d’un chiffre.

L4 est l’ensemble des mots formés de 4 lettres.

L* est l’ensemble de tout les mots de lettres, y compris le mot vide, Ԑ.

L(LUC)* est l’ensemble des mots de lettres et de chiffres commençant
par une lettre.

C+ est l’ensemble des mots qui sont constitués d’au moins d’un chiffre.
Prof. M. BENADDY Compilation 15
Spécification des unités lexicales (5)

Expressions régulières :

On construit une expression régulière à partir d’expressions
régulières plus simples, en utilisant les règles de définition du
langage concerné.

Chaque expression régulière r dénote un langage L(r). Les règles de
définition spécifient comment L(r) est formé en combinant de
manière variée les langages dénotés par les sous-expressions de r.

Les expressions régulières sont construites récursivement à partir
d’expressions régulières plus simples, en utilisant des règles.

Chaque expression régulière r dénote un langage L(r), qui est aussi
définit récursivement à partir des langages dénotés par les sous-
expressions de r.

Les règles qui définissent les expressions régulières sur un alphabet
∑ et les langages dénotés par ces expressions.
Prof. M. BENADDY Compilation 16
Spécification des unités lexicales (6)

Expressions régulières :

Règles :

Ԑ est une expression régulière, et L(Ԑ) = {Ԑ}, le langage
dont le seule membre est le mot vide Ԑ.

Si a est un symbole de ∑, alors a est une expression
régulière, et L(a) = {a}, c-à-d le langage avec une seule
chaîne de caractère, de longueur 1.

Prof. M. BENADDY Compilation 17


Spécification des unités lexicales (7)

Expressions régulières :

Induction :

On suppose que r et s sont deux expressions régulières dénotant
les deux langages L(r) et L(s) respectivement.

Il existe quatre règles d’induction qui permettent de construire des
expressions complexes à partir d’expressions régulières plus
simples.

(r)|(s) est l’expression régulière qui dénote le langage
L(r)UL(s)

(r)(s) est l’expression régulière qui dénote le langage L(r)L(s),

(r)* est l’expression régulière dénotant le langage (L(r))*,

(r) est l’expression régulière qui dénote L(r). Cette règle
signifie qu’on peut ajouter des parenthèses sans changer le
langage qu’elle dénote.
Prof. M. BENADDY Compilation 18
Spécification des unités lexicales (8)

Expressions régulières :

Priorité des opérateurs :

L’opérateur * a la plus haute priorité et est associatif à
gauche.

La concaténation a la deuxième priorité et est associatif à
gauche.

Le ou (|) a la faible priorité.

En considérant ces conventions, par exemple l’expression
régulière (a)|((b)*(c)) est équivalente à a|b*c, les deux
dénotent l’ensemble des mots formés d’un seule ou zéro
a ou bien zéro ou plusieurs b suivi d’un c.

Prof. M. BENADDY Compilation 19


Spécification des unités lexicales (9)

Expressions régulières :

Exemple : soit l’alphabet ∑ ={a,b}

L’expression régulière a|b dénote le langage {a,b}

(a|b)(a|b) dénote {aa,ab,ba,bb}, le langage de mots de longueur
2 sur l’alphabet ∑, une autre expression régulière est aa|ab|ba|
bb.

a* dénote le langage des mots formés de zéro ou plus de a, {Ԑ,
a, aa, aaa, ...}.

(a|b)* dénote l’ensemble des mots formés de zéro ou plusieurs
a ou b, {Ԑ, a, b, aa, ab, ba, bb, aaa, ...}. (a|b)* = (a*b*)*=(a*|b*)*.

a|a*b dénote le langage {a, b, ab, aab, aaab, ...}, c-à-d le mot a
et l’ensemble des mots formés de zéro ou plusieurs a qui
finissent par b.
Prof. M. BENADDY Compilation 20
Spécification des unités lexicales (10)

Expressions régulières :

Remarque : Un langage qui peut être définit par une
expression régulière est appelé un ensemble régulier. Si
deux expressions régulières r et s dénotent le même
ensemble régulier, on dit qu’ils sont équivalents r=s.

Prof. M. BENADDY Compilation 21


Spécification des unités lexicales (11)

Expressions régulières :

Propriétés algébriques des expressions régulières :

Prof. M. BENADDY Compilation 22


Spécification des unités lexicales (12)

Expressions régulières :

Définitions régulières : Une définition régulière est une
suite de définitions de la forme :



Chaque di est un nouveau symbole distinct qui n'appartient
pas à Σ

Chaque ri est une expression régulière sur les symboles : Σ
U {d1,d2,...,di-1}
Prof. M. BENADDY Compilation 23
Spécification des unités lexicales (13)

Expressions régulières :

Définitions régulières :

Exemple 1 : les identificateurs en C sont des mots formés de
lettres, chiffres, et underscore (_). Une définition régulière de
cet ensemble est la suivante :

lettre → A|B|...|Z|a|b|...|z| _
chiffre → 0|1|...|9
id → lettre(lettre|chiffre)*

Prof. M. BENADDY Compilation 24


Spécification des unités lexicales (14)

Expressions régulières :

Définitions régulières :

Exemple 2 : Les nombres non signés (entiers ou réels) sont
des chaînes, comme 5280, 0.01234, 6.336E4, ou 1.89E-4.
La définition régulière de cette catégorie est donnée par
l’expression suivante :

Prof. M. BENADDY Compilation 25


Spécification des unités lexicales (15)

Expressions régulières :

Extensions aux expressions régulières :

Les opérateurs de base (l’union, la concaténation et la
fermeture) ont été introduites par Kleene vers 1950, des
extensions on été ajoutées par la suite pour pouvoir
définir quelques modèles de chaînes.

Les extensions suivantes sont incorporées dans utilitaires
sous UNIX tel que Lex, qui sont utiles dans l’écriture
d’analyseurs lexicaux.

Prof. M. BENADDY Compilation 26


Spécification des unités lexicales (16)

Expressions régulières :

Extensions aux expressions régulières :

L’opérateur unaire + représente, la fermeture positive + de l’expression
régulière et son langage. Si r est une expression régulière, alors (r)+ dénote
le langage (L(r))+. L’opérateur + a la même priorité et associativité que
l’opérateur * (Kleene closure), on peut écrire alors, r* = r+|Ԑ et r+ = rr* =r*r.

Zéro ou une instance : L’opérateur unaire ? signifie ‘’zéro ou une
occurrence’’. C-à-d r ? est équivalente à r|Ԑ, d’une autre façon
L(r?)=L(r)U{Ԑ}. L’opérateur ? a les mêmes priorité et associativité que * et
+.

Classes de caractères : L’expression régulière a1|a2|...|an, où les ai sont des
symboles de l’alphabet, on peut alors les remplacer par [a1a2...an]. quand
a1,a2,...,an forment une séquence logique, c-à-d des lettres majuscules
consécutives, des lettres minuscules, ou des chiffres, on peut les remplacer
par a1-an, (on prend juste le premier et dernier élément séparés par un tiret
-). Par conséquent [abc] ≡ a|b|c, et [a-z] ≡ a|b|...|z.

Prof. M. BENADDY Compilation 27


Spécification des unités lexicales (17)

Expressions régulières :

Extensions aux expressions régulières :

r* = r+|Ԑ et r+ = rr* =r*r Fermeture


r? = r|Ԑ Zéro ou une instance
[abc] ≡ a|b|c, et [a-z] ≡ a|b|...|z Un élément de la classe

Prof. M. BENADDY Compilation 28


Spécification des unités lexicales (18)

Expressions régulières :

Extensions aux expressions régulières :

Exemple  : en utilisant ces formes abrégées réécrire les
expressions régulières suivantes :
lettre → A|B|...|Z|a|b|...|z| _
chiffre → 0|1|...|9
id → lettre(lettre|chiffre)*

Prof. M. BENADDY Compilation 29


Spécification des unités lexicales (19)

Expressions régulières :

Extensions aux expressions régulières :

Exemple  : en utilisant ces formes abrégées réécrire les
expressions régulières suivantes :
lettre → [A-Za-z_]
chiffre → [0-9]
id → lettre(lettre|chiffre)*

Prof. M. BENADDY Compilation 30


Reconnaissance de unités lexicales (1)

Comment utiliser les modèles des unités lexicales, pour
construire un programme qui examinera le texte d’entrée
pour décider si les lexèmes se sont conforme avec les
modèles. Considérons cet exemple :

Prof. M. BENADDY Compilation 31


Reconnaissance de unités lexicales (2)

Les unités lexicales concernées par l’analyseur lexical sont
if, then, else, relop, id, et number, ils sont aussi les
terminaux de la grammaire pour les instructions de
branchement conditionnel.

Les définitions régulières définissant les modèles de ces
unités lexicales sont :

Prof. M. BENADDY Compilation 32


Reconnaissance de unités lexicales (3)

Pour ignorer les commentaires et les blancs l’analyseur
lexical doit les reconnaître pour cela, on définit l’unité lexicale
‘’ws’’ comme suite :


Les caractères blancs (blank), tabulation (tab) et nouvelle
ligne (newline) sont des symboles abstraits utilisés pour
exprimer les caractères ASCII désignant la même chose.

L’unité lexicale ws est reconnue par l’analyseur lexical, mais
elle ne sera pas retournée à l’analyseur syntaxique, mais, on
reprend l’analyse qui suit l’espace blanc.

Prof. M. BENADDY Compilation 33


Reconnaissance de unités lexicales (4)

Le but de l’analyseur lexicale est résumé dans le tableau ci-dessous qui montre
pour chaque lexème ou famille de lexèmes, qu’elle unité lexicale (token) qui
sera retournée à l’analyseur syntaxique ainsi que sa valeur d’attribut.

Lexèmes Nom de l’unité lexicale Valeur de l’attribut

N’importe quel ws - -
if if -
then then -
else else -
N’importe quel id id Pointeur vers la table des symboles
N’importe quel number Pointeur vers la table des symboles
number

< relop LT
<= relop LE
= relop EQ
<> relop NE
> relop GT
Prof. M. BENADDY Compilation 34
>= relop GE
Les automates à états finis (1)


Un reconnaisseur pour un langage est un programme qui prend en
entrée une chaîne x et répond oui si x est une phrase du langage et
non autrement.

On compile une expression régulière en un reconnaisseur en
construisant un diagramme de transition appelé automate fini.

Un automate fini est capable de reconnaître précisément les
ensembles réguliers.

Il existe types d'automates à états finis:

Les automates à états finis non déterministes (AFN) n'ont
aucune restrictions sur les étiquettes de leurs arcs. Un symbole
peut étiqueter plusieurs arcs partant d'un même état, et la chaîne
vide ε est une étiquette possible.

Les automates à états finis déterministes (AFD), pour lesquels,
ne peuvent pas partir plusieurs transitions du même état avec le
même caractère et n'accepte pas d'ε-transition.
Prof. M. BENADDY Compilation 35
Les automates à états finis (2)


Automates finis non déterministes (AFN) :

Un automate fini non déterministe noté AFN, noté par
l'expression aut = <Σ,E,D,F,T> avec :

Un ensemble Σ de symboles d'entrée, l'alphabet du
langage. On considère que la chaîne vide ε, n'est jamais un
membre de Σ.

L'ensemble fini E d'états.

Une fonction de transition qui donne pour chaque état et
pour chaque symbole de ΣU{ε}, l'ensemble des états
suivants T, sous ensemble de ExΣxE.

L'ensemble D sous-ensemble de E, des états de départ.

L'ensemble des états F, sous-ensemble de E, l'ensemble
des états d'acceptation ou états finaux ou états terminaux.
Prof. M. BENADDY Compilation 36
Les automates à états finis (3)


Automates finis non déterministes (AFN) :

Exemple :

Σ = {a,b,c} ; E={1, 2, 3, 4} ; D={1} ; F = {3,4} , T
={(1,a,2), (2,b,3),(1,c,4),(3,c,2)}

Prof. M. BENADDY Compilation 37


Les automates à états finis (4)


Automates finis non déterministes (AFN) :

Graphe d'états :

Un graphe d'états ressemble à un diagramme de
transition, mais dans le cas des AFN, le même caractère
peut étiqueter deux transitions ou plus en sortie d'un
même état et les arcs peuvent être étiquetés par le même
symbole spéciale ε.

Tous les états de départ sont représentés par un cercle où
apparaît une flèche entrante :

Les états terminaux sont représentés par un cercle double

S'il existe un arc étiqueté par a entre l'état i et l'état j, si le
triplet (i, a, j) ϵ T on dessine cet arc comme suite :

Prof. M. BENADDY Compilation 38


Les automates à états finis (5)


Automates finis non déterministes (AFN) :

Graphe d'états :

Exemple : soit le langage (a|b)*abb ; Σ={a,b} ;
E={0,1,2,3} ; D={0} ; F={3} ; T={(0,a,0),(0,b,0),(0,a,1),
(1,b,2),(2,b,3)}

Prof. M. BENADDY Compilation 39


Les automates à états finis (6)


Automates finis non déterministes (AFN) :

Graphe d'états :

Notation :
est équivalent à


si tout état d'un ensemble donné Σ étiquette des
transitions d'un état i vers un état j on notera Σ={a, b, c}

Exemple : Σ = {x, y} ; E ={1, 2 ,3} ; D ={1} ; F ={3} ; T ={(1,
y, 1), (1, x, 2), (2, y, 2), (2, x, 3), (3, x, 3), (3, y, 3)}

Prof. M. BENADDY Compilation 40


Les automates à états finis (7)


Table de transition :

Une autre méthode de représentation d'un automate est la
table des transitions, pour décrire la fonction de transition
T on utilisera une table M indicée par E et Σ, tel que si e ϵ
E, a ϵ Σ, e' ϵ M(e,a) ssi (e, a, e') ϵ T
 Exemple : table de transition correspondante à l'expression
régulière (a|b)*abb

État a b ε
0 {0,1} {0} -
1 - {2} -
2 - {3} -
3 - - -
Prof. M. BENADDY Compilation 41
Les automates à états finis (8)


Acceptation d'une chaîne par un automate :

Un AFN accepte une chaîne d'entrée x ssi il existe un chemin dans le
graphe de transition entre l'état de départ et un état d'acceptation
(final), tel que les étiquettes des arcs le long de ce chemin épellent
(enlever le poile) la chaîne x.

Exemples : La chaîne aabb est acceptée par l'automate de
l'exemple (slide 49) ,en se déplaçant via les états (0,0,1,2,3).

Soit l'automate suivant qui accepte les mots du langage engendrés par
l'expression régulière aa*|bb*

La chaîne aaa est acceptée en se déplaçant via les états (0,1,2,2,2).
les étiquettes de ces arcs sont εaaa = aaa.

Prof. M. BENADDY Compilation 42


Les automates à états finis (9)


Acceptation d'une chaîne par un automate :

Exemples (suite) : soit l'expression régulière a abb et la
+

chaîne x=abb, l'AFN correspondant à cette expression est :


Cet automate n'accepte pas la chaîne x.

Si on considère a*abb, l'automate correspondant est :


Cet automate accepte la chaîne x=abb en parcourant le
chamin 1,2,3,4.
Prof. M. BENADDY Compilation 43
Les automates à états finis (10)

Automates finis déterministes :

Un automate fini déterministe (AFD) est un cas particulier d'un automate fini non
déterministe (AFN) dans lequel :

Aucun état n'a une ε-transition (une transition sur l'entrée ε).

Pour chaque état e et chaque symbole a, il existe un et un seul arc étiqueté a
qui quitte e.

Un AFD a au plus une transition à partir de chaque état sur n'importe quel
symbole, en conséquence il est très facile de déterminer si un AFD accepte une
chaîne d'entrée, étant donné qu'il existe au plus un chemin depuis l'état de départ
étiqueté par cette chaîne.

Si on utilise une table de transition pour représenter un AFD, chaque entrée est un
état singleton.

Un AFN est une représentation abstraite d'un algorithme de reconnaissance des
chaînes d'un langage.

Un AFD est un algorithme concret de reconnaissance de chaînes.

N'importe quel AFN ou expression régulière peuvent être transformées en un AFD.
Prof. M. BENADDY Compilation 44
Les automates à états finis (11)


Simulation d'un AFD :

Soit x une chaîne d'entrée qui se termine par un caractère de fin
de fichier (fdf ou eof), soit e un état de départ et F l'ensemble des
0

états terminaux.

Soit la fonction transiter(e,c) qui donne l'état vers lequel il y a une
transition depuis l'état e sur le caractère d'entrée c, la fonction
carsuiv(x) retourne le prochain caractère de la chaîne d'entrée x.
La simulation d'un AFD est donnée par l'algorithme suivant :
e=e0
c=carsuiv(x)
tant que (c!=fdf){
e = transiter(e,c)
c = carsuiv(x)
}
si (e ϵ F) alors retrouner ''oui''
sinon retourner ''non''
Prof. M. BENADDY Compilation 45
Les automates à états finis (12)


Simulation d'un AFD :

Exercice d'application :

dessiner l'AFD correspondant au langage L((a|b)*abb),
cette automate accepte-t-il la chaîne x=ababb.

Prof. M. BENADDY Compilation 46


Les automates à états finis (13)


Simulation d'un AFD :
 Exercice d'application : dessiner l'AFD correspondant au
langage L((a|b)*abb), cette automate accepte-t-il la chaîne
x=ababb.
 Solution : l'automate correspondant au langage L((a|b)*abb))
est :


Cet automate accepte la chaîne x en parcourant les états
0,1,2,1,2,3

Prof. M. BENADDY Compilation 47


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Il existe de nombreuses stratégies pour construire un
reconnaisseur à partir d'une expression régulière.

Un stratégie qui a été utilisée dans un grand nombre
d'analyseurs lexicaux, consiste à construire un AFN à
partir d'une expression régulière et ensuite convertir l'AFN
en AFD.

Prof. M. BENADDY Compilation 48


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :
 Donnée : une expression régulière r sur l'alphabet Σ.
 Résultat : un AFN N qui accepte L(r).

Méthode : on décompose r en sous expressions
régulières, on construit les AFN pour chacun des
symboles de base de r (soit ε soit les symboles de Σ). on
se guidant de la structure de r on combine récursivement
ces AFN en utilisant les règles de construction ci-dessous,
jusqu’à l’obtention de l'AFN de l’expression complète.

Prof. M. BENADDY Compilation 49


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :

Règles :

L'AFN correspondant à ε est :

Pour chaque symbole a dans Σ construire l'AFN :


On suppose que les AFN des expressions régulières s
et t sont N(s) et N(t), l'AFN correspondant à
l'expression régulière r=s|t est le suivant :
Remarque : Les états de départ et
d'acceptation de N(s) et N(t) ne sont pas les
états de départ et d'acceptation de N(s|t). Ils
sont donc des états ordinaires de ce dernier.
Prof. M. BENADDY Compilation 50
Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :

Règles :

L'AFN correspondant à r=st est le suivant :


l'état de départ de N(s) devient l'état de départ de l'AFN
composé et l'état d'acceptation de N(t) devient l'état
d'acceptation de N(r).

Prof. M. BENADDY Compilation 51


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :

Règles :

L'AFN correspondant à l'expression régulière r=s* est donné
par :


On peut aller de i à f directement en suivant un arc étiqueté ε
qui représente le fait que ε ϵ (L(s))* ou bien en traversant N(s)
une ou plusieurs fois. Pour l'expression régulière (s) l'AFN
correspondant est le même pour l'expression régulière s.
Prof. M. BENADDY Compilation 52
Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :
 Exemple : (a|b)*abb

r1=a

r2=b

Maintenant on peut combiner N(r1) et N(r2), pour
obtenir l'AFN N(r3) pour r3=r1|r2

Prof. M. BENADDY Compilation 53


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :
 Exemple : (a|b)*abb

r4=(r3)* donc l'AFN N(r4) est

Prof. M. BENADDY Compilation 54


Automates à états finis aux expressions régulières


Transformation d'une expression régulière en un AFN :

Algorithme de McNaughton-Yamada-Thompson :
 Exemple : (a|b)*abb
a b

r5=r1r2 l'AFN correspondant à r5 est : 77 8 9


r6=r5r2 l'AFN correspondant à r6 est :


r=r4r6 l'AFN correspondant à (a|b)*abb est :

Prof. M. BENADDY Compilation 55


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Soit les automates suivants :

Aut1


Aut2 :

Prof. M. BENADDY Compilation 56


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

L'automate 1 a deux transitions de l'état 1 sur la chaîne
d'entrée a qui signifie qu'on peut aller vers l'état 1 ou 2.

De même l'automate 2 a deux transitions sur ε à partir de l'état
0.

Dans le cas où la fonction de transition est multivaluée, il est
difficile de simuler un AFN à l'aide d'un programme.

L'acceptation d'une chaîne d'entrée suppose qu'il puisse
exister un chemin étiqueté par cette chaîne qui mène depuis
l'état de départ jusqu'à un état d'acceptation.

Mais il existe dans un AFN plusieurs chemins qui épellent la
même chaîne d'entrée, on doit les prendre en considération
avant de décider d'accepter ou non la chaîne d'entrée.
Prof. M. BENADDY Compilation 57
Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

L'idée générale de la transformation d'un AFN en un AFD est
qu'un état de l'AFD correspond à un ensemble d'états de
l'AFN.

L'AFD utilise un état pour garder trace de tout les états
possibles que l'AFN peut atteindre après avoir lu chaque
symbole d'entrée.

Prof. M. BENADDY Compilation 58


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Algorithme :

Donnée : un AFN

Résultat : un AFD qui accepte le même langage de l'AFN.

Méthode : l'algorithme construit une table de transition
Dtrans pour l'AFD.

Chaque état de l'AFD est un ensemble d'états de l'AFN.
On construit Dtrans de telle manière que l'AFD simulera
tous les déplacements possibles que l'AFN peut effectuer
sur une chaîne d'entrée donnée.

Prof. M. BENADDY Compilation 59


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Algorithme :

Pour garder trace des ensemble des états de l'AFN on
utilisera les opérations suivantes :

Soit e et T tels que e représente un état de l'AFN et T
représente un ensemble d'états de l'AFN.
Opération Description
ε-fermeture(e) Ensemble des états de l'AFN accessibles depuis l'état e
Noté aussi ε-f(e) de l'AFN par des ε-transition uniquement.
ε-fermeture(T) Ensemble des états de l'AFN accessibles depuis un état
Noté aussi ε-f(T) e ϵ T par des ε-transition uniquement.
transiter(T,a) Ensemble des états de l'AFN vers lesquels il existe une
Noté aussi tran(T,a) transition sur a
Prof. M. BENADDY Compilation 60
Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Exemple d'application : soit l'AFN suivant qui accepte le
langage (a|b)*abb

Prof. M. BENADDY Compilation 61


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Exemple d'application :

L'état de départ de l'AFD A=ε-f(0)={0,1,2,4,7}

L'alphabet Σ = {a, b}

B=ε-f(tran(A,a))=ε-f({3,8})={3,1,2,4,6,7,8} => Dtrans(A,a)=B.

C=ε-f(tran(A,b))=ε-f({5})={1,2,4,5,6,7} => Dtrans(A,b)=C.

ε-f(tran(B,a))=ε-f({3,8})={3,1,2,4,6,7,8} => Dtrans(B,a)=B.

ε-f(tran(B,b))=ε-f({5,9})={1,2,4,5,6,7,9} => Dtrans(B,b)=D.

ε-f(tran(C,a))=ε-f({3,8})={3,1,2,4,6,7,8} => Dtrans(C,a)=B.

ε-f(tran(C,b))=ε-f({5})={1,2,4,5,6,7} => Dtrans(C,b)=C.

ε-f(tran(D,a))=ε-f({3,8})={3,1,2,4,6,7,8} => Dtrans(D,a)=B.

ε-f(tran(D,b))=ε-f({5,10})={1,2,4,5,6,7,10} => Dtrans(D,b)=E.

ε-f(tran(E,a))=ε-f({3,8})={3,1,2,4,6,7,8} => Dtrans(E,a)=B.

ε-f(tran(E,b))=ε-f({5})={1,2,4,5,6,7} => Dtrans(E,b)=C.
Prof. M. BENADDY Compilation 62
Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Exemple d'application :

L'état E est l'état de fin de l'AFD car E contient l'état 10 qui
est l'état d'acceptation de l'AFN.

Règle : un état de l'AFD est un état d'acceptation si c'est un
ensemble d'états de l'AFN qui contient au moins un état
d'acceptation de l'AFN.

L'AFD équivalent à l'AFN est :

Prof. M. BENADDY Compilation 63


Automates à états finis aux expressions régulières


Transformation d'un AFN en un AFD :

Exemple d'application :

Table de transition de l'AFD :
États de l'AFN États de a b
l'AFD
{0,1,2,4,7} A B C
{1,2,3,4,6,7,8} B B D
{1,2,4,5,6,7} C B C
{1,2,4,5,6,7,9} D B E
{1,2,3,5,6,7,10} E B C

Prof. M. BENADDY Compilation 64


Automates à états finis aux expressions régulières


Simulation d'un AFN :

Donnée : Étant donné une chaîne x se terminant par un
caractère de fdf (eof), un AFN N disposant d'un état de
départ 0 et d'un ensemble d'états d'acceptation F et une
fonction transiter.

Résultat : réponse oui si N accepte la chaîne et non
autrement.

Méthode : l'algorithme suivant appliqué à x permet de
renvoyer oui si l'AFN accepte x et non autrement.

Prof. M. BENADDY Compilation 65


Automates à états finis aux expressions régulières


Simulation d'un AFN :
E = ε-f({0})
c = carSuiv(x)
tant que (a!=fdf){
E = ε-f(transiter(E,c))
c = carSuiv(x)
}
si(E ∩ F!=Ø) alors retourner oui
sinon retourner non

L'algorithme réalise la construction des sous-ensembles à
l'exécution, il calcule une transition depuis l'ensemble
courant d'états E vers le prochain ensemble d'états.
Implicitement l'algorithme transforme l'AFN en AFD et
détermine si l'AFD accepte-t-il la chaîne d'entrée x.
Prof. M. BENADDY Compilation 66
Automates à états finis aux expressions régulières


Simulation d'un AFN :

Exemple : Soit l'AFN correspondant à (a|b)*abb et la chaîne
d'entrée x = aabb
E = ε-f({0})={0,1,2,4,7}
c = carSuiv(x)=a
E = ε-f(transiter(E,a))={3,1,2,4,6,7,8}
carSuiv(x)=a
E = ε-f(transiter(E,a))={3,1,2,4,6,7,8}
carSuiv(x)=b
E = ε-f(transiter(E,b))={1,2,4,5,6,7,9}
carSuiv(x)=b
E = ε-f(transiter(E,b))={1,2,4,5,6,7,10}
carSuiv(x)=fdf
E ∩ F =10 alors l'AFN accepte la chaîne x=aabb

Prof. M. BENADDY Compilation 67


Minimisation du nombre des états d'un AFD


Étant donné que deux AFD peuvent reconnaître les mots du même langage, le but
de la minimisation du nombre d'états d'un AFD consiste à produire un AFD avec le
minimum d'états possibles.

L'algorithme de minimisation consiste à partitionner les états de l'AFD en des
groupes d'états qui ne peuvent pas être distingués. Chaque groupe d’états qui ne
peuvent pas être distingués est alors fusionné en un état unique.

Initialement la partition consiste en deux groupes :

Les états d'acceptation et les états de non-acceptation.

L'étape fondamentale consiste à prendre un groupe d'état A={e , e , …,e } et un
1 2 k

symbole d'entrée 'a' et regarder si 'a' peut être utilisé pour distinguer des états du
groupe A.

On examine les transitions depuis chaque état e , e , …,e sur l'entrée 'a', si ces
1 2 k

transitions conduisent à des états qui tombent au moins dans deux groupes
différents de la partition courante, alors, on doit diviser A en une collection de
groupes, de sorte que ei et eJ sont dans le même groupe ssi ils partent vers le
même groupe sur le symbole 'a'.

On répète le processus de division de groupe de la partition courante jusqu’à ce
que aucun groupe n'est besoin d'être divisé.
Prof. M. BENADDY Compilation 68
Minimisation du nombre des états d'un AFD


Algorithme de minimisation des états d'un AFD :
 Donnée : un AFD D avec un ensemble d'états E, un
alphabet d'entrée Σ, un état de départ e0 et en ensemble
d'états d'acceptation F.
 Résultats : un AFD D' qui reconnaît le même langage que
D et ayant le peu d'états possibles.

Prof. M. BENADDY Compilation 69


Minimisation du nombre des états d'un AFD


Algorithme de minimisation des états d'un AFD :

Méthode :
1) Construire une partition initiale П de l'ensemble des états avec deux groupes ; les états
d'acceptation F et les états de non-acceptation E-F.
2) Appliquer la procédure suivante à П pour construire une nouvelle partition Пnew
soit Пnew = П
pour chaque groupe G de П {

Partitionner G en sous groupes de manière que deux états s et t de G soient dans le
même sous groupe ssi pour tout symbole d'entrée 'a', les états s et t ont des transitions
sur 'a' vers les états du même groupe de П.

Remplacer G dans Пnew par les sous groupes formés.}
3) si Пnew = П alors Пf = П aller à 4 sinon répéter l'étape 2 avec П =Пnew
4) Choisir un état de chaque groupe de la partition Пf en tant que représentant de ce
groupe. Les représentants seront les états de l'AFD réduit D'.

L'état de départ de D' est le représentant du groupe qui contient l'état de départ e0 de D.

Les états de d'acceptation de D' sont les représentants contenant un état d'acceptation de
D.
5) Si D' contient un état mort, c-à-d un état e qui n'est pas un état d'acceptation et qui a
des transitions vers lui-même sur tout les symboles d'entrée, alors supprimer e de D'.

Prof. M. BENADDY Compilation 70


Minimisation du nombre des états d'un AFD

 Exemple : soit l'AFD correspondant au langage L((a|b)*abb)

Prof. M. BENADDY Compilation 71


Minimisation du nombre des états d'un AFD


Exemple : soit l'AFD correspondant au langage L((a|b)*abb)


La partition initiale П est constituée de deux groupes, {E}{ABCD} le groupe des états
d'acceptation, et le groupe états de non-acceptation.

Pour construire la partition Пnew le groupe {E} est constitué d'un seul état donc, il ne peut pas
être découpé.
 Le groupe {ABCD} sur le symbole a chacun des 4 états a une transition vers B, ce qui ne les
distingue pas.
 Sur le symbole b A,B et C ont une transition vers les états du groupe {ABCD}, tandis que D a
une transition vers E qui est membre d'un autre groupe.

Dans la partition Пnew le groupe {ABCD} doit être découpé en 2 nouveaux sous groupes {ABC}
{D}. donc dans l'étape suivante la partition Пnew = {ABC}{D}{E}.
Prof. M. BENADDY Compilation 72
Minimisation du nombre des états d'un AFD

 Exemple : soit l'AFD correspondant au langage L((a|b)*abb)


Retour à 2 avec la partition {ABC}{D}{E} les groupes {D}{E} sont singleton, donc
ils ne peuvent pas être découpés.
 Sur le symbole a aucun découpage. Sur le symbole b, A et C ont une transition sur B
tandis que B a une transition vers D membre d'un autre groupe. D'où Пnew = {AC}{B}{D}
{E}.

Retour à 2 avec la nouvelle partition :

Sur le symbole a, A et C conduisent vers le même état B.

Sur le symbole b, A et C conduisent vers le même état C.

Par conséquent A et C constituent le même groupe d'où la partition finale Пf ={AC}
{B}{D}{E}.
Prof. M. BENADDY Compilation 73
Minimisation du nombre des états d'un AFD

 Exemple : soit l'AFD correspondant au langage L((a|b)*abb)



Si on choisit A comme représentant du groupe {AC}, B, D et
E pour les groupes singletons, on obtient alors l'automate
réduit dont la table des transitions est :

A est l'état de départ et E est l'état d'acceptation, le graphe
d'état correspondant est :

État a b
A B A
B B D
D B E
E B A

Prof. M. BENADDY Compilation 74


Le générateur d’analyseur lexicale Lex/Flex


Lex/Flex est un outil de génération automatisée d’analyseur
lexical, à partir de la spécification des expressions régulières
pour décrire les modèles des unités lexicales.

Lex/Flex transforme les modèles (expressions régulières et
définitions régulières) en entrée en un diagramme de
transition et génére le code source correspondant, dans un
fichier appelé lex.yy.c, qui simule le diagramme de transition
généré.

Ce fichier écrit en langage C doit être compilé par le
compilateur du C pour produire un exécutable qui sera
l'analyseur lexical du langage décrit par les modèles en
question.

Prof. M. BENADDY Compilation 75


Le générateur d’analyseur lexicale Lex/Flex


Plusieurs langages dérivés de Lex existent :

Flex produit du code écrit en C/C++

Jlex/JFlex produit du code écrit en Java

Lecl produit du code écrit en Caml

ml-lex produit du code en ML

alex produit du code écrit en Haskell

tcl-tcLex produit du code écrit en tcl

Prof. M. BENADDY Compilation 76


Le générateur d’analyseur lexicale Lex/Flex


Utilisation de Lex :

Un fichier lex.l écrit en langage Lex, qui décrit l’analyseur
lexical à générer est présenté au compilateur Lex en
entrée.

Le compilateur Lex transforme lex.l en un programme
écrit en C dans un fichier appelé lex.yy.c.

Ce fichier est compilé par le compilateur C et produit un
fichier exécutable a.out qui est le fichier du compilateur
exécutable, il prendra en paramètre un fichier écrit dans le
langage source et produira en sortie une séquence des
unités lexicales.

Prof. M. BENADDY Compilation 77


Le générateur d’analyseur lexicale Lex/Flex


Utilisation de Lex :

Prof. M. BENADDY Compilation 78


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Un fichier de description pour Lex est formé de trois
parties, séparées par des lignes contenant seulement  %%,
aligné à gauche, selon le schéma suivant :
// Parties déclarations
%{ //(variables, constantes, bibliothèques C, etc.)
%}
//expressions régulières, définitions régulières
%%
// Partie productions (expressions régulières)
%%
// code de service (fonctions utilitaires)

Prof. M. BENADDY Compilation 79


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

La partie déclarations comporte les déclarations des
variables, des structures, des unions, des déclarations
régulières, des déclaration des bibliothèques en C…

La partie productions, les déclarations prennent la forme
suivante :
m 1 {action } 1 Les m sont des expressions régulières ou
i

m 2 {action } 2 des définitions régulières de la partie


... ... déclaration.
m i {action }
i

... ... Les actioni sont les actions à réaliser par


m n {action }
n l’analyseur lexical si un lexème est accepté
par mi. Généralement écrites en langage C,
mais d’autres langages peuvent être utilisés.

Prof. M. BENADDY Compilation 80


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

La 3ème partie contient des fonctions qui peuvent être
utilisées dans les actions de la 2ème partie.

Eventuellement ces fonctions peuvent être compilées
séparément et chargées avec l'analyseur lexical.

Cette partie peut aussi contenir la fonction principale
main pour une éventuelle exécution du programme
produit.

Remarque :

Un fichier source en Lex doit avoir l'extension .l
(exemple.l).

Seulement la partie production est obligatoire dans
Lex.
Prof. M. BENADDY Compilation 81
Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Exemple 1 : Un programme Lex qui affiche le contenu de
son entrée standard vers l'écran.
%%
.|\n ECHO;
%%

Exemple 2 : un programme Lex qui supprime tout les
espaces et tabulations.

%%
[ \t] {/* supprime les espaces et tabulations */}
bye {exit(0);}

Prof. M. BENADDY Compilation 82


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Exemple 3 : Un programme Lex qui reconnaît les verbes
en anglais.

On considère la liste des verbes suivants :
is am are were
was be being been
do does did will
would should can could
has have had go

Prof. M. BENADDY Compilation 83


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Exemple 3 : Un programme Lex qui reconnaît les verbes
en anglais.
%{ will I
/* would I
* programme Lex qui reconnaît les verbes en Anglais should I
*/ can I
%} could I
%% has I
[\t ]+ /* ignorer les espaces et tabulations */ have I
is I had I
am l go {printf(''%s : is a verb\n'',
are I yytext);}
were I [a-zA-Z]+ {printf(''%s:is not a
was I verb\n'', yytext);}
be l .|\n {ECHO ; /* autres choses
beingbeen I ou retour à la ligne */}
do I %%
does I main()
did I {
Prof. M. BENADDY Compilation yylex() ; 84
}
Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Remarques :

yylex() : la fonction principale du programme écrit en
LEX.

yytext : pointeur sur le début de la chaîne analysée
(unité lexicale)

Exécution :

Lex : lex verbes.l  produit un fichier lex.yy.c

gcc : gcc -o verbes lex.y.c -ll (ll : library lex)

Flex : flex verbes.l produit un fichier lex.yy.c

gcc : gcc -o verbes lex.yy.c -lfl (lfl : library fast lex)

Prof. M. BENADDY Compilation 85


Le générateur d’analyseur lexicale Lex/Flex


Structure d’un programme Lex :

Exercice d'application : écrire un programme en lex qui
reconnaît les identificateurs, mot clés et opérateurs en
PASCAL

Prof. M. BENADDY Compilation 86


Le générateur d’analyseur lexicale Lex/Flex
%{
/*definitions des constantes "<" {printf("relop LT\n");}
LT, LE, EQ, NE, GT, GE, "<=" {printf("relop LE\
IF, THEN, ELSE, ID, NUMBER, RELOP*/ n");}
%} "=" {printf("relop EQ\
/*definitions régulières*/ n");;}
delim [ \t\n] "<>" {printf("relop NE\
ws {delim}+ n");}
letter [A-Za-z] ">" {printf("relop GT\n");}
digit [0-9] ">=" {printf("relop GE\
id {letter}({letter}|{digit})* n");}
number (\+|\-)?{digit}+(\.{digit}+)? . {printf("non reconnue %s\
(E[+-]?{digit}+)? n",yytext);}
%% %%
{ws} {/*no action and no return*/} int main(int argc,char
if {printf("mot clé IF\n");} *argv[])
then {printf("mot clé TEHN\n");} {
else {printf("mot clé ELSE\n");} yyin=fopen(argv[1],"r");
{id} {printf("identificateur %s\ yylex();
n",yytext);} fclose(yyin);
{number} {printf("nombre %s\ return 0;
n",yytext);} }
Prof. M. BENADDY Compilation 87
Compilation

Chapitre3 : Analyse syntaxique

SMI/S5
Compilation
Prof. : M. BENADDY
Introduction

L'analyse syntaxique (A.S.) est l'une des
opérations majeures d'un compilateur, qui
consiste à indiquer si un texte est
grammaticalement correcte

et à en tirer une représentation interne qu'on
appelle arbre syntaxique (arbre d'analyse),

l'A.S. obtient une chaîne d'unité lexicale de
l'analyse lexicale et vérifie que la chaîne peut être
engendrée par la syntaxe du langage source,
celle-ci est spécifiée par une grammaire.

Prof. M. BENADDY Compilation 2


Introduction

Table des Symboles

Programme Unité lexicale Arbre


Source Analyse Lexicale Analyse Syntaxique Syntaxique
Lire prochaine
Unité Lexicale

Table des erreurs

Prof. M. BENADDY Compilation 3


Introduction

Il existe trois types généraux d'analyseurs syntaxiques :

Méthodes universelles

Descendantes (construction de l'arbre syntaxique
en partant de la racine vers les feuilles)

Et ascendantes (construction de l'arbre syntaxique
en partant des feuilles vers la racine).

Les méthodes d'analyse universelles tel l'algorithme
de Cocke-Younger-Kasami et l'algorithme d'Earley,
ces méthodes sont peu utilisées dans la production
de compilateurs, pour leur inefficacité.

Prof. M. BENADDY Compilation 4


Grammaire hors contexte

Une grammaire G est donnée sous forme d'un quadruplet <V, ∑,R,S> où :

V est un vocabulaire appelé aussi alphabet, c-à-d un ensemble fini de symboles.

∑⊆V Est l'ensemble des symboles terminaux, c-à-d les symboles de base du
langage à partir desquels les chaînes sont formées. L'expression d'unité lexicale
est synonyme de terminal quand on parle de grammaire pour les langages de
programmation.

V-∑ est l'ensemble des symboles non terminaux, c-à-d les variables
syntaxiques qui dénotent un ensemble de chaînes qui aident à spécifier le
langage engendré par la grammaire.

R est l'ensemble des règles de production de la grammaire, qui spécifie la
manière dont les terminaux et les non-terminaux qui peuvent être combinés
pour former des chaînes. Chaque règle de production consiste en un non
terminal suivi d'une flèche suivie d'une chaîne formée de terminaux et non-
terminaux.
 S⊂∑−V Est l'axiome de la grammaire, c-à-d un symbole non terminal particulier
tel que l'ensemble des chaînes qu'il dénote est le langage défini par la
grammaire.

Prof. M. BENADDY Compilation 5


Grammaire hors contexte

Exemple : Soit la grammaire constituée des productions
suivantes :
exp → exp op exp
exp → (exp)
exp → -exp
exp → id
op → +
op → -
op → *
op → /
Les symboles terminaux sont +, -, *, /, id, ()
Les symboles non-terminaux sont exp, op, …

Prof. M. BENADDY Compilation 6


Grammaire hors contexte

Notation :

Les symboles suivants sont des terminaux :

Les lettres minuscules du début de l'alphabet a, b, c, …

Les opérateurs +, -, *, /

Les symboles de ponctuation (() , ; …)

Les chiffres 0, à 9

Les lettres minuscules représentants les chaînes terminales x, u, v, w, …

Les symboles suivants sont des non-terminaux :

Les lettres majuscules de l'alphabet A, B, C,

La lettre S désigne un axiome

Les lettres majuscules de la fin de l'alphabet X, Y, Z représentent les symboles terminaux
et non terminaux.

Les lettres grecque α, β, δ, … représentent les chaînes de symboles grammaticaux. Une
production générique peut être écrite de la façon suivante : A → α, où A est la tête et α
est le corps.

Le mot vide s'exprime par ε
E → E A E | (E) | -E | a
A→+|-|*| /
Prof. M. BENADDY Compilation 7
Grammaire hors contexte

Dérivation :

L'idée de dérivation est de traiter une règle de production comme une
règle de réécriture dans laquelle le non-terminal en partie gauche est
remplacé par la chaîne en partie droite de la règle de production.

Exemple, soit la grammaire suivante : E → E + E | E * E | (E)| -E | a

la règle E → -E signifie qu'une expression précédée d'un signe –
est aussi une expression, cette expression peut engendrer des
expressions plus complexes en remplaçant l'occurrence de E par
-E. Cette action peut être décrite par E => -E et se lit E se dérive
en -E

La règle E → (E) nous permet de remplacer E par (E) dans une
chaîne quelconque de symboles grammaticaux

E * E => (E) * E, E * E => E * (E)

Prof. M. BENADDY Compilation 8


Grammaire hors contexte

Dérivation :

On peut prendre un E unique et appliquer répétitivement les règles
de production dans un ordre quelconque est obtenir une séquence
de remplacement.

E => (E) => -(E) => -(a)

Si α1=>α2=>α3=>...=>αn on dit que α1 se dérive en αn

Le symbole => signifie se dérive en une seule étape.

Le symbole =*> signifie se dérive en 0, une ou plusieurs étapes, alors on
peut écrire E =*> -(a)

De même le symbole =+> signifie se dérive en une ou plusieurs étapes.

Prof. M. BENADDY Compilation 9


Grammaire hors contexte

Dérivation : Exemples : Soit la grammaire suivante définit dans l'exemple
précédent :

La chaîne -(a+a) est une phrase de la grammaire car on a les dérivations
suivantes : E => -E => -(E) => -(E+E) => -(a+E) => -(a+a) et note alors E = *>-
(a+a)

E =*> (cte + a) est fausse car cte ne fait pas partie de l'alphabet.

E =*> -(a - a) est fausse car (E – E) ne fait pas partie de l'alphabet,

On a aussi E => -E => -(E) => -(E+E) => -(E + -E) = *> -(a + -a)

À chaque étape de la dérivation on doit faire 2 choix. Il faut choisir le non-
terminal à remplacer, par exemple dans la grammaire de l'exemple précédent, la
dérivation peut se poursuivre comme suite : E => E + E => E + a => a + a

On constate qu'on a changé le non-terminal droite. Si on considère les
dérivations dans lesquelles seul le non-terminal gauche est remplacé, de telles
dérivations sont appelées dérivations gauches et on peut écrire : E = *>g (a + a)

la définition reste valide pour les dérivations droites et on note E = *>d (a + a)
Prof. M. BENADDY Compilation 10
Grammaire hors contexte

L'arbre syntaxique : Un arbre syntaxique ou un arbre d'analyse est une
représentation graphique des dérivations successives aboutissants à une
expression du langage, par exemple l'arbre syntaxique correspondant à la
phrase a – (a + a) est donné par le graphe suivant :
E
/|\
E - E
| / | \
a ( E )
/ | \
E + E
| |
a a
Prof. M. BENADDY Compilation 11
Grammaire hors contexte

Ambiguïté : Une grammaire est dite ambiguë s'il existe plusieurs
arbres syntaxiques de dérivation distincts, autrement dit c'est une
grammaire qui produit plus d'une dérivation gauche ou bien droite
pour la même phrase.

Pour certains types d'analyseurs il est nécessaire de rendre la
grammaire non ambiguë car on ne peut pas déterminer de façon
unique l'arbre syntaxique associé à une phrase dérivant d'une
grammaire ambiguë. Soit la phrase a + a*a
E =*> a + a * a E E =*> a + a * a E
E => E + E /|\ E => E * E /|\
E => E + E * E E + E E => E+ E * E E *E
E => a + E * E | / | \ E => a + E * E / | \ |
E => a + a * E a E * E E => a + a * E E + E a
E => a + a * a | | E => a + a * a | |
a a a a

Prof. M. BENADDY Compilation 12


Grammaire hors contexte

Ambiguïté : Si on tient compte du faite que l'opérateur * est
prioritaire que l'opérateur + alors l'ambiguïté est levée on optera
pour l'arbre syntaxique suivante :
E
/|\
E *E
/ | \ |
E + E a
| |
a a

Prof. M. BENADDY Compilation 13


Grammaire hors contexte

Grammaire hors contexte versus expressions régulières :

La grammaire est une notation efficace que les expressions
régulières.

Une construction qui peut être décrite par une expression
régulière peut être décrite par une grammaire mais pas le
contraire.

Alternativement chaque langage régulier, est un langage hors
contexte, le contraire étant incorrecte

Exemple : l'expression régulière (alb)*abb et la grammaire


Décrivent le même langage, qui est l'ensemble des mots
formés de a et b qui se terminent par abb
Prof. M. BENADDY Compilation 14
Écriture d'une grammaire

Expressions régulières vers grammaire hors contexte :

Une grammaire qui reconnaît un langage comme un AFN peut être
construite à partir celle-ci.

La grammaire de l'exemple précédent est construite à partir de l'AFN
suivant

 Pour chaque état i de l'AFN créer un non terminale A i


 Si un état i a une transition vers un état j sur l'entrée a, ajouter la production Ai →
aAj.
 Si l'état i par vers l'état j sur ε, ajouter la production A i → Aj
 Si i est un état d'acceptation ajouter Ai →ε
 Si Ai est l'état de départ de l'AFN, alors Ai est l'axiome de la grammaire.
Prof. M. BENADDY Compilation 15
Écriture d'une grammaire

Élimination de la récursivité à gauche :

Une grammaire est récursive à gauche si elle contient au
moins un non terminal A telle qu’il existe une dérivation.
A => Aα => βα (α chaîne)
A =+> Aα

Les méthodes d’analyse descendante ne peuvent pas
fonctionner avec une grammaire récursive à gauche on a donc
besoin d’une transformation grammaticale qui élimine cette
récursivité à gauche.

On peut éliminer une production récursive en la réécrivant.

Prof. M. BENADDY Compilation 16


Écriture d'une grammaire

Élimination de la récursivité à gauche :

Considérons le non-terminal A dans les deux
productions

A → Aα|β où α et β sont deux suites de terminaux et de
non-terminaux qui ne commencent pas par A.

On peut obtenir les mêmes productions en réécrivant
les productions définissant A de la manière suivante
A → βA'
A' → αA'|ε
où A' est un nouveau non-terminal.

Cette réécriture n’altère pas l’ensemble des chaînes
dérivables depuis A.
Prof. M. BENADDY Compilation 17
Écriture d'une grammaire

Élimination de la récursivité à gauche :

Exemple : Éliminer la récursivité à gauche de la
grammaire suivante :
E → E+T|T
T → T*F|F
F → (E)|id

Prof. M. BENADDY Compilation 18


Écriture d'une grammaire

Élimination de la récursivité à gauche :

Exemple : Éliminer la récursivité à gauche de la
grammaire suivante :
E → E+T|T E → TE'
T → T*F|F E' → +TE'|ε
Solution T → FT'
F → (E)|id
T' → *FT'|ε
F → (E) | id

Prof. M. BENADDY Compilation 19


Écriture d'une grammaire

Élimination de la récursivité à gauche :

D’une manière générale quelque soit le nombre
de production de A :
A → Aα | Aα |…| Aα |β |β |…|β
1 2 n 1 2 m

A → β1A'| β2A'|…| βmA'


A' → α1A'| α2 A'|…| αn A'| ε

Prof. M. BENADDY Compilation 20


Écriture d'une grammaire

Factorisation à gauche : La factorisation à gauche
est une transformation grammaticale utile pour obtenir une
grammaire convenant à l’analyse prédictive.

En générale si on a la production

A → αβ1| αβ2 et si l’entrée commence par une chaîne non vide
dérivée de α, on ne saura pas si il faut développer A en αβ 1 ou αβ2
cependant il est possible de faire une factorisation à gauche telle
que A → αA', A' → β1| β2

D’une façon générale si on a A → αβ |…| αβ |δ où δ
1 n

représente toute chaînes qui ne commence pas par α


alors on aura

A → αA' |δ  A' non-terminal

A' → β |…|β1 n

Prof. M. BENADDY Compilation 21


Écriture d'une grammaire

Factorisation à gauche :

Exemple : Factoriser :
S → iEtS | iEtSeS | a
E→b

Prof. M. BENADDY Compilation 22


Écriture d'une grammaire

Factorisation à gauche :

Exemple : Factoriser :
S → iEtS | iEtSeS | a
E→b

S → iEtSS' | a
S' → eS|ε
E→b

Prof. M. BENADDY Compilation 23


Processus d'analyse

L’analyse descendante : dans laquelle on construit
l’arbre en descendant de la racine vers les feuilles, c-à-d
on essaie à partir de l’axiome de la grammaire de dériver
le programme source, il s’agit de dériver à chaque étape
qu’il est la règle qui sert à engendrer le mot qu’on lit.

L’analyse ascendante : dans laquelle on construit l’arbre
syntaxique en montant des feuilles vers la racine, elle
correspond au parcours inverse du parcours descendant,
c-à-d on établit des réductions sur la chaîne à analyser
pour aboutir à l’axiome de la grammaire. Cette méthode
est puissante mais plus complexe à mettre en œuvre que
l’analyse descendante.

Prof. M. BENADDY Compilation 24


L’analyse descendante

L'analyse descendante : On effectue la
construction descendante d’un arbre syntaxique
en partant de la racine, étiqueté par l’axiome, et
en relisant de manière répétitive les deux étapes
suivantes :

Au nœud n étiqueté par le non-terminal A, choisir une
des règles de production définissant A et construire
les fils de n avec les symboles en partie droite de la
production.

Déterminer le prochain nœud où un sous-arbre doit
être construit.

Prof. M. BENADDY Compilation 25


L’analyse descendante

L'analyse descendante :

Exemple : l'arbre syntaxique de la chaîne id + id * id
E → TE'
E' → +TE'|ε
T → FT'
T' → *FT'|ε
F → (E) | id

Prof. M. BENADDY Compilation 26


L’analyse descendante

L'analyse descendante :

Exemple : l'arbre syntaxique de la chaîne id + id * id
E → TE'
E' → +TE'|ε
T → FT'
T' → *FT'|ε
F → (E) | id

Prof. M. BENADDY Compilation 27


L’analyse descendante

L'analyse descendante :

Exemple : l'arbre syntaxique de la chaîne id + id * id
E → TE'
E' → +TE'|ε
T → FT'
T' → *FT'|ε
F → (E) | id

Prof. M. BENADDY Compilation 28


L’analyse descendante

L'analyse descendante récursive : L’analyse
syntaxique par descente récursive est une méthode
d’analyse syntaxique descendante dans laquelle on
exécute un ensemble de procédure récursive pour traiter
l’entrée en question. Cette analyse peut impliquer des
retours arrière.

Exemple : Soit la grammaire définit par S → cAd , A →
ab|a et soit la chaîne W = cad

Prof. M. BENADDY Compilation 29


L’analyse descendante

L'analyse descendante récursive :

Exemple : Soit la grammaire définit par S → cAd , A →
ab|a et soit la chaîne W = cad

Pour construire de façon descendante un arbre
d’analyse syntaxique pour la chaîne W on construit
initialement un arbre qui contient un seul nœud S.

Un pointeur d’entrée repère c, le premier symbole de W.
on utilise alors la première règle de production de S,
pour aboutir à l’arbre suivant :
S
/|\
c A d
Prof. M. BENADDY Compilation 30
L’analyse descendante

L'analyse descendante récursive :

Exemple : Soit la grammaire définit par S → cAd , A → ab|a et
soit la chaîne W = cad

La feuille la plus à gauche étiquetée c correspond au premier
symbole de W.

Par conséquent on avance le pointeur d’entrée sur a, seconde
symbole de W et on considère la feuille étiquetée a on peut
développer A en utilisant la deuxième règle pour obtenir l’arbre
suivant :
S
/|\
c Ad
/\
a b
Prof. M. BENADDY Compilation 31
L’analyse descendante

L'analyse descendante récursive :

Exemple : Soit la grammaire définit par S → cAd , A → ab|a et soit
la chaîne W = cad

On a une concordance avec le second symbole d’entrée a, et on
compare d avec la feuille suivante étiquetée b comme b != d on
signale un échec et on retourne à A pour voir s’il existe une autre
alternative non encore essayer.

En retournant à A on doit remettre le pointeur d’entrée en position 2.
On essaie la seconde alternative de A et on obtient l’arbre suivant :
S
/|\
c Ad
|
a

Prof. M. BENADDY Compilation 32


L’analyse descendante

Notion de premier et de suivant :

La construction d'un analyseur syntaxique descendant est facilitée, car deux
fonctions associées à une grammaire G sont premier() et suivant().

Ces fonctions nous permettent si possible de remplir les entrées de la table
d'analyse descendante pour la grammaire G.

Premier : Si α est une chaîne de symboles grammaticaux premier de α
désigne l'ensemble des terminaux qui commencent les chaînes qui se
dérivent de α.

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

Si X est un non-terminal et que X → Y1Y2....Yk est une producrion pour
k>=1, alors ajouter a à premier(X) si pour certain i, a Є premier(Yi), et ε
est dans premier(Yi),...,premier(Yi-1) ; c-à-d que Y1Y2....Yi-1=*> ε. Si ε
Є premier(Yj) pour j=1,2,…,k, alors ajouter ε à premier(X). la règle
s'applique ainsi de suite sur tout les éléments de la production.

Si α=*> ε alors ε est aussi dans l'ensemble premier(α).

Prof. M. BENADDY Compilation 33


L’analyse descendante

Notion de premier et de suivant :

Suivant : Pour chaque symbole non-terminal A, suivant(A) définit l'ensemble
des terminaux qui peuvent apparaître immédiatement à droite de A dans toute
chaînes de symboles constituant les règles de production.

Si A est le symbole le plus à droite d'une chaîne alors le symbole $ est
ajouté à l'ensemble suivant de A. pour déterminer suivant(A) où A est non-
terminal il faut suivre les étapes suivante jusqu'à ce que aucun élément ne
puisse être ajouté à suivant(A) :

si A est l'axiome de la grammaire alors ajouter $ à suivant de A.

si la règle X → AaB є G si a est un terminal alors ajouter a à suivant(A).

si X → αA est une règle de la grammaire, alors ajouter l'ensemble
suivant(X) à suivant(A).

si A → αBβ est une règle de la grammaire le contenu de premier(β) à
l'exception de ε est ajouté à suivant(B).

si il existe une règle de la grammaire A → αBβ tel que premier(β) contient
ε, les éléments de suivant(A) sont ajoutés à suivant(B).
Prof. M. BENADDY Compilation 34
L’analyse descendante

Notion de premier et de suivant :

Exemple : Soit la grammaire suivante :
E → TE'
E' → +TE' | ε
T → FT'
T' → *FT' | ε
F → (E)|id

Déterminer premier(E), premier(E'), premier(T'),
suivant(E), suivant(E'), premier(T), suivant(T),
suivant(T'), suivant(F), premier(F)

Prof. M. BENADDY Compilation 35


L’analyse descendante

Notion de premier et de suivant :

Exemple : Soit la grammaire suivante :

E → TE' , E' → +TE' | ε , T → FT' , T' → *FT' | ε , F → (E)|id

premier(E)=premier(T)=premier(F)={(,id}, premier(E')={+,ε},
premier(T')={*,ε}, suivant(E)={),$}, suivant(E')={), $}

Puisque E est un axiome alors $ є suivant(E) puisque F →
(E) de la ) є suivant(E).

La règle E → TE' et la 3ème étape de la construction de
suivant on a suivant(E) є suivant(E') d'où suivant(E) =
suivant(E') ={),$} suivant(T)={+,),$}=suivant(T')

Pour suivant(T) on a la règle E' → +TE' et E' => ε c-à-d que
premier(E') à l'exception de ε є suivant(T) suivant(F)={*,+,),$}

Prof. M. BENADDY Compilation 36


Grammaire LL(1)

Une grammaire dont la table d’analyse n’a aucune
entrée définit de façon multiple est appelée une
grammaire LL(1).

Le premier L désigne le parcours de l’entrée de gauche
à droite (Letf to right scanning), le second L signifie
dérivation gauche (Left most derivation) le (1) indique
qu’on utilise un seul symbole d’entrée à chaque étape
nécessitant la prise d’une décision d’action d’analyse.

Prof. M. BENADDY Compilation 37


Grammaire LL(1)

Une grammaire G est dite LL(1) si ses règles de production
vérifient les conditions suivantes :

Si A → α et A → β sont deux règles de G alors on doit avoir
soit α=*>ε soit β=*>ε et non pas les deux

Si A → α et A → β sont deux règles de G alors
premier(β)∩premier(α)=ø

Si A → α et A → β sont deux règles de G et si ε est dans
premier(β) ou dans premier(α) alors suivant(A)∩premier(α)=ø

Ces conditions entraînent l’unicité d’existence d’une règle
dans une entrée de la table d’analyse prédictive.

En plus de ces conditions une grammaire est LL(1) si toute
ses règles de production sont non récursives à gauche et
factorisables.
Prof. M. BENADDY Compilation 38
Grammaire LL(1)

Algorithme de Construction de la table d'analyse prédictive :

Données : la grammaire G

Résultat : table d'analyse prédictive M pour G

Méthode :

pour chaque règle de la production A → α de la grammaire
procéder aux étapes :

pour chaque a dans premier(α) placer la règle A → α dans la
position M(A,a)

si ε є premier(α), placer A → α dans M(A,b) pour chaque
terminal b qui є suivant(A).

si ε є premier(α) et $ є suivant(A) placer la règle A → α dans
M(A,$)

faire de chaque entrée non définit de M dans la table une erreur.
Prof. M. BENADDY Compilation 39
Grammaire LL(1)

Algorithme de Construction de la table d'analyse prédictive :

Exemple : soit la grammaire définit par les règles suivantes :
E → TE' , E' → +TE' | ε , T → FT' , T' → *FT' | ε , F → (E)|id

premier(TE')=premier(T)={id,(} c-à-d M(E,id)=E → TE', M(E,( ) = E → TE'

E' → +TE' premier(+TE')={+} c-à-d M(E',+)= E' → +TE'

E' → ε , suivant(E')={),$} donc M(E',) ) = E' → ε et M(E',$) = E' → ε

T → FT', premier(FT') = premier(F) = {(,id} donc M(T,( )= T → FT' et M(T,id)
= T → FT'

T' → *FT' , premier(*FT') = {*} donc M(T',*) = T' → *FT'

T' → ε , suivant(T')={+, ) , $}donc M(T',+) = T' → ε, M(T',) )= T' → ε et m(T',
$)=T' → ε

F → (E) , premier((E))={(} alors M(F,( )= F → (E)

F → id , premier(id)={id} alors M(F,id)= F → id

Prof. M. BENADDY Compilation 40


Grammaire LL(1)

Algorithme de Construction de la table d'analyse
prédictive :

Exemple : soit la grammaire définit par les règles suivantes :
E → TE' , E' → +TE' | ε , T → FT' , T' → *FT' | ε , F → (E)|id
Non- Symbole d'entrée
terminal
id + * ( ) $

E E → TE' E → TE'

E' E' → +TE' E' → ε E' → ε

T T → FT' T → FT'

T' T' → ε T' → *FT' T' → ε T' → ε

F F → id F → (E)

Prof. M. BENADDY Compilation 41


Analyse id+id*id
Grammaire LL(1)

Algorithme de Construction de la table d'analyse
prédictive :

Exercices d'application :Donner les premier, suivant et les tables
prédictive ?
1. soit la grammaire suivante : 2. soit la grammaire suivante
E → E+T|T S → iEtSS' |a
T → T*F|F S' → eS | ε
F → (E)|id E→b

Prof. M. BENADDY Compilation 42


Grammaire LL(1)

Analyse prédictive :

L'analyseur syntaxique prédictive possède un tampon d'entrée, une pile, une
table d'analyse prédictive et un flot de sortie.

Le tampon d'entrée contient la chaîne à analyser suivie du symbole $, qui est
utilisé comme marqueur d’extrémité droite indiquant la fin de la chaîne d'entrée.

La pile contient une séquence de symboles grammaticaux avec le symbole $
marquant la fin de la chaîne de la pile. La table d'analyse est une table à deux
dimensions qu'on notera M(A,a) où A est un non-terminal et a est un terminal
ou bien le symbole $.

Les éléments de la table contiennent éventuellement des règles de la
grammaire :
a|+|b|$
X
Y
Programme d'analyse Flot de sortie (arbre
Z syntaxique)
prédictive
$
Table d'analyse prédictive
Prof. M. BENADDY Compilation 43
Grammaire LL(1)

Algorithme d'analyse prédictive :

Avant de commencer l'analyse d'une chaîne de caractères, il faut convertir la
grammaire décrivant le langage qui accepte la chaîne à analyser en une
grammaire LL(1), ensuite construire la table prédictive de cette dernière.
L'analyse syntaxique est contrôlée par un programme qui a le comportement
suivant :

On considère X le symbole en sommet de la pile et a le symbole courant de la
chaîne à analyser. Ces deux symboles déterminent l'axiome de l'analyseur. Il
existe trois possibilités :

Si X = a = $, l'analyseur s'arrête et annonce le résultat final 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.

Si X est non-terminal le programme d'analyse consulte l'entrée M(X,a) de la
table d'analyse prédictive, cette entrée sera soit une X production de la
grammaire soit une erreur.

Prof. M. BENADDY Compilation 44


Grammaire LL(1)

Algorithme d'analyse prédictive : L'algorithme permettant de faire
l'analyse syntaxique prédictive est le suivant :
positionner le pointeur pt sur le premier symbole de w$
répéter
soit X le symbole en sommet de la pile et a le symbole repéré par
pt
si X est un terminal ou $ alors
si X = a alors
enlever X de la pile, avancer pt
sinon si X = $ alors succès
sinon alors erreur
sinon
si M(X,a)= X → Y1Y2... Yk alors
début
enlever X de la pile
mettre Y1Y2... Yk avec Y1 au sommet
fin
sinon erreur
jusqu'à X = $ (pile vide)
Prof. M. BENADDY Compilation 45
Grammaire LL(1)

Algorithme d'analyse prédictive :
Exemple : Soit la chaîne w= id+id*id et la grammaire
suivante :
E → TE'
E' → +TE' | ε
T → FT'
T' → *FT' | ε
F → (E)|id

Prof. M. BENADDY Compilation 46


Grammaire LL(1)
Épile Pile Entrée Action
E$ id+id*id$ E → TE'
TE'$ id+id*id$ T → FT'
FT'E'$ id+id*id$ F → id
id T'E'$ id+id*id$ Dépiler id
id T'E'$ +id*id$ T' → ε
id E'$ +id*id$ E' → +TE'
id +TE'$ +id*id$ Dépiler +
id+ TE'$ id*id$ T → FT'
Table Analyse
id+ FT'E'$ id*id$ F → id
id+ idT'E'$ id*id$ Déplier id
id+id T'E'$ *id$ T' → *FT'
id+id *FT'E'$ *id$ Dépiler *
id+id* FT'E' id$ F → id
id+id* idT'E'$ id$ Dépiler id
id+id*id T'E'$ $ T' → ε
id+id*id E'$ $ E' → ε
id+id*id $ $ Accepter
Prof. M. BENADDY Compilation 47
Grammaire LL(1)

Algorithme d'analyse prédictive : L'arbre correspondant :
E
/ \
/ \
T E'
/ \ /| \
F T' + T E'
| | / \ |
id ε F T' ε
| /|\
id * F T'
| |
id ε
Exercice d'application : appliquer l'algorithme sur la chaîne (a+b) * (c +
d) avec a,b,c,d sont des identificateurs. Donner l'arbre syntaxique
correspondant.
Prof. M. BENADDY Compilation 48
L’analyse ascendante

Principe : construire un arbre de dérivation du bas (les
feuilles, c-à-d les unités lexicales) vers le haut (la racine,
c-à-d l'axiome de départ).

Exemple : w = id * id
E → E+T|T
T → T*F|F
F →( E ) | id

Prof. M. BENADDY Compilation 49


L’analyse ascendante

Le modèle général utilisé est le modèle par décalages-
réductions c'est à dire que l'on ne s'autorise que deux
opérations :

décalage (shift) : décaler d'une lettre le pointeur sur le
mot en entrée

réduction (reduce) : réduire une chaîne (suite
consécutive de terminaux et non terminaux à gauche
du pointeur sur le mot en entrée et finissant sur ce
pointeur) par un non-terminal en utilisant une des
règles de production

Prof. M. BENADDY Compilation 50


L’analyse ascendante

Le modèle décalages-réductions est une analyse dans
laquelle une pile contient les symboles de grammaire et un
tampon d'entrée contient le reste de la chaîne à analyser.

$ est utilisé pour marquer le bas de la pile et aussi
l'extrémité droite de l'entrée. Classiquement, lorsqu'il est
question de l'analyse ascendante, nous montrons le haut de
la pile sur la droite, plutôt que sur la gauche comme nous
l'avons fait pour l'analyse descendante. Au départ, la pile est
vide, et la chaîne w est sur l'entrée, comme suit :
Pile Entrée
état initial $ w$
état final $S $

Prof. M. BENADDY Compilation 51


L’analyse ascendante

Les opérations permises sont :

Décalage : le symbole d'entrée courant est inséré
dans la pile,

Réduction : on reconnaît sur le sommet de la pile une
partie droite d’une production Y → Xk-j...Xj, on l’enlève
et on la remplace par sa partie gauche Y

Acceptation : Annoncer la réussite de l'analyse.

Erreur : Découverte d'une erreur de syntaxe ou appel
d'une routine de récupération d'erreur.

Prof. M. BENADDY Compilation 52


L’analyse ascendante

Exemple : w = id1 * id2
E → E+T|T
T → T*F|F
Pile Entrée Action
F →( E ) | id $ id1*id2$ Décalage
Arbre syntaxique $id1 *id2$ Réduction par F → id
$F *id2$ Réduction par T → F
id1 * id2
| | | $T *id2$ Décalage
F | | $T* id2$ Décalage
| | | $T*id2 $ Réduction par F → id
T * F $T*F $ Réduction par T → T*F
\ | / $T $ Réduction par E → T
T
$E $ Accepter
|
E

Prof. M. BENADDY Compilation 53


L’analyse LR

L'analyse LR(k) est l'un des analyseurs les plus utilisés
des analyses ascendantes, L signifie analyse de gauche
à droite (Left to right) de l'entrée, le R pour la
construction des dérivations à droite en inverse, et le k
pour le nombres des symboles d'entrée dans la
recherche pour les décisions d'analyse.

On distingue différents types d'analyse LR : SLR (Simple
LR), LR canonique (Canonical LR) et LALR (Look Ahead
LR).

Les générateurs d'analyseurs syntaxiques implémentent
cette méthode (spécialement LALR pour Yacc).

Prof. M. BENADDY Compilation 54


L’analyse SLR

Les items d'un automate LR(0) :

Question : comment savoir quand décaler et quand
réduire ?

L'analyseur LR effectue les décisions de décalage-
réduction par le maintient des états d'analyse pour savoir
l'endroit où on est dans l'analyse. Les états représentent un
ensemble d'items.

Un item LR(0), (ou item) d’une grammaire G est une
production de G avec un point repérant une position de sa
partie droite.

Exemple : la production A → XYZ fournit 4 items :

A → ·XYZ A → X·YZ A → XY·Z A → XYZ·

La production A →ε fournit uniquement l’item A → ·
Prof. M. BENADDY Compilation 55
L’analyse SLR

Les items d'un automate LR(0) :

Un item peut être codé par un couple d’entiers, le
premier pour le numéro de la production, le second pour
la position du point.

Intuitivement, un item indique la « quantité » de la partie
droite qui a été reconnue à un moment donné au cours
du processus d’analyse.

Par exemple le premier item (A →·XYZ ) indique que l’on
espère voir en entrée une chaîne dérivable depuis XYZ.

Le second item (A→X·YZ ) indique que nous venons de
voir en entrée une chaîne dérivée de X et que nous
espérons maintenant voir une chaîne dérivée de YZ.

Prof. M. BENADDY Compilation 56


L’analyse SLR

Idée : L’idée de base de la méthode SLR est de construire tout d’abord, à
partir de la grammaire, un AFD pour prendre les décisions d'analyse. Cet
automate est appelé automate LR(0). Les items sont regroupés en
ensembles qui constituent les états de l’analyseur SLR.

Une collection d’ensembles d’items LR(0) que nous appellerons
collection LR(0) canonique, fournit la base de la construction des
analyseurs SLR.

Pour construire la collection LR(0) canonique pour une grammaire,
nous définissons une grammaire augmentée et deux fonctions :
Fermeture et Transition.

Si G est une grammaire d’axiome S, alors la grammaire augmentée de
G est G' avec un nouvel axiome S' et une nouvelle production S' → S.

Le but de cette nouvelle production initiale est d’indiquer à l’analyseur
quand il doit arrêter l’analyse et annoncer que la chaîne d’entrée a été
acceptée. Plus précisément la chaîne d’entrée est acceptée quand et
seulement quand l’analyseur est sur le point de réduire S' → S.
Prof. M. BENADDY Compilation 57
L’analyse SLR

Fermeture (closure) : Si I est un ensemble d’items pour une
grammaire G, Fermeture(I) est l’ensemble d’items construit à partir de I
par les deux règles :
1) Initialement, placer chaque item de I dans Fermeture(I).
2) Si A → α·Bβ est dans Fermeture(I) et B → γ est une production,
ajouter l’item B → ·γ à Fermeture(I) s’il ne s’y trouve pas déjà.

Nous appliquons cette règle jusqu’à ce qu’aucun nouvel item ne
puisse plus être ajouté à Fermeture(I).

Intuitivement, si A → α·Bβ est dans Fermeture(I) cela indique qu’à un
certain point du processus d’analyse, nous pourrions voir se présenter
dans l’entrée une sous-chaîne dérivable depuis Bβ comme entrée.

Si B → γ est une production, nous supposons que nous pourrions
également voir, à ce moment là, une chaîne dérivable depuis γ.

Pour cette raison, nous ajoutons également B → ·γ à Fermeture(I ).
Prof. M. BENADDY Compilation 58
L’analyse SLR

Algorithme :
SetOfItems Fermeture(I){
J = I ;
repeat
for(chaque item A → α·Bβ dans J)
for(chaque production B → γ dans G)
si(B → ·γ n'est pas encore dans J)
ajouter B → ·γ à J ;
jusqu'à ce qu'aucun item ne peut plus être ajouter à J ;
return J ;
}
Prof. M. BENADDY Compilation 59
L’analyse SLR

Exemple : soit la grammaire E' → E ; E → E + T | T ;
T → T * F | F ; F → (E) | id

Si I = {[E' → ·E]}, alors Fermeture(I) contient les items :
Fermeture(I)={E' → ·E,E → ·E + T,E → ·T,T → ·T * F,
T → ·F, F → ·(E), F → ·id}

Explication : conformément à la première règle, E' → ·E est dans


Fermeture(I). puisqu'il existe un E immédiatement à droite du point, nous
ajoutons les productions de E avec des points dans la fin gauche : E →
·E+T et E → ·T. Comme T est immédiatement dans la droite du point du
dernier item, donc ajouter T → ·T*F et T → ·F. Par la suite F se trouve à
droite du point donc ajouter F → ·(E) et F → ·id.

Prof. M. BENADDY Compilation 60


L’analyse SLR

Transition (goto) : La deuxième fonction utile est
Transition(I,X) où I est un ensemble d’items et X est un
symbole de la grammaire.

Transition(I,X) est définie comme la fermeture de l’ensemble
de tous les items [A → αX·β] tels que [A → α·Xβ] appartient à I

Exemple : Si I = {[E → E·], [E → E·+T]}, alors Transition(I ,+)
consiste en :
E → E +·T Explication : Nous calculons Transition(I,+) en cherchant dans I les
items ayant + immédiatement à droite du point. E → E · ne convient
T → ·T * F pas, E → E·+T répond au critère. Nous faisons franchir le + au point
afin d’obtenir {[E → E + ·T ]}, puis nous calculons Fermeture sur cet
T → ·F ensemble.

F → ·(E)
F → ·id
Prof. M. BENADDY Compilation 61
L’analyse SLR

Algorithme de construction des items :

Donnée : grammaire augmentée G'

Résultats : une collection canonique d’ensembles d’items LR(0) C pour la
grammaire G'

Méthode : exécuter les instructions suivantes pour ajouter les transitions sur tous les
symboles à partir de l’axiome.
void items(G'){
C = fermetrure({[S' →·S]} ;
repeat
for(chaque ensemble d'items I dans C)
for(chaque symbole X de la grammaire)
si(Transition(I,X) est non vide et n'est pas encore dans C)
ajouter Transition(I,X) à C ;
until aucun nouvel ensemble d'items ne peut plus être ajouté à C
}
Prof. M. BENADDY Compilation 62
L’analyse SLR

Algorithme de construction des items :

Donnée : soit la grammaire E' → E ; E → E + T | T ;
T → T * F | F ; F → (E ) | id

Initialiser C = Fermeture({[E' → E]})

Soit I0 = Fermeture({[E' → E]})={[E' → ·E], [E → ·E+T],
[E → ·T], [T →·T * F], [T → ·F], [F → ·(E)], [F → ·id]}

I1=Transition(I0,E)={[E' → E·], [E → E·+T]}

I2=Transition(I0,T)={[E → T·], [T → T·*F]}

I3=Transition(I0,F)={[T → F·]}

I4=Transition(I0,()={[F → (·E)], [E → ·E+T], [E → ·T], [T
→·T * F], [T → ·F], [F → ·(E)], [F → ·id]}
Prof. M. BENADDY Compilation 63
L’analyse SLR

Algorithme de construction des items :

Donnée : soit la grammaire E' → E ; E → E + T | T ; T → T * F | F ; F → (E ) | id

I5=Transition(I0,id)={[F → id·]}

I6=Transition(I1,+)={[E → E+·T], [T → ·T * F], [T → ·F], [F → ·(E )], [F → ·id]}

I7=Transition(I2,*)={[T → T*·F], [F → ·(E)], [F → ·id]}

I8=Transition(I4,E)={[F → (E·)], [E → E·+T]}

Transition(I4,T)={E → T·], [T →T· * F]}=I2

Transition(I4,F)={[T → F·]}=I3

Transition(I4,()={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T → ·F], [F → ·(E)], [F
→ ·id]}=I4

Transition(I4,id)={[F → id·]}=I5

I9=Transition(I6,T)={[E → E+T·], [T → T· * F]}

Transition(I6,F)={[T → F·]}=I3

Transition(I6,()={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T → ·F], [F → ·(E)], [F
→ ·id]}=I4

Transition(I6,id)={[F → id·]}=I5
Prof. M. BENADDY Compilation 64
L’analyse SLR

Algorithme de construction des items :

Donnée : soit la grammaire E' → E ; E → E + T | T ; T
→ T * F | F ; F → (E ) | id

I10=Transition(I7,F)={[T → T*F·]}

Transition(I7,()={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T
* F], [T → ·F], [F → ·(E)], [F → ·id]}=I4

Transition(I7,id)={[F → id·]}=I5

I11=Transition(I8,))={[F → (E)·]}

Transition(I8,+)=[E → E+·T], [T → ·T * F], [T → ·F], [F →
·(E )], [F → ·id]=I6

Transition(I9,*)={[T → T*·F], [F → ·(E)], [F → ·id]}=I7
Prof. M. BENADDY Compilation 65
L’analyse SLR

L'AFD construit pour la fonction Transition :
L'état de départ de l'automate
LR(0) est Fermeture({[S' →
·S]}), avec S' le symbole de
départ de la grammaire
augmentée. Tous les états
sont des états d'acceptation.
Les décisions de décalage-
réduction peuvent se faire
comme suit. Supposons que
la chaîne γ formée des
symboles de la grammaire
parcourt l'AFD LR(0) depuis
l'état de départ 0 vers un état
j. Alors décaler vers un
symbole a si l'état j a une
transition sur a. sinon, on
choisit réduire, les items dans
l'état j indiqueront quelle
production à utiliser.

Prof. M. BENADDY Compilation 66


L’analyse SLR

L'AFD construit pour la fonction Transition :

AFD avec liste des items de


chaque état

Prof. M. BENADDY Compilation 67


L’algorithme d'analyse LR

Schéma d'un analyseur LR :
Tampon d'entrée (Input)
a1 … ai ... aN $
Sm

Xm Programme
Pile
Flot de sortie (Output)
... d’analyse LR

$
Action Successeur

Un analyseur LR est constitué : (GOTO)

D'un tampon d’entrée

D'un flot de sortie

D'une pile

D'un programme pilote

Des tables d’analyse divisées en deux parties (Action et Successeur).

Remarque : Le programme pilote d'analyse LR est le même pour tous les analyseurs
LR (SLR, LR canonique, LALR), seul les tables d'analyse changent d'un analyse à un
autre.
Prof. M. BENADDY Compilation 68
L’algorithme d'analyse LR

Structure de la table d'analyse LR :

La pile contient une séquence d'états, s0s1...sm, où sm est au sommet de la pile.

Dans la méthode SLR, la pile contient les états de l'AFD LR(0) ; les méthodes
LR canonique et LALR sont similaires.

La table d'analyse consiste en deux parties : la fonction Action d'analyse et la
fonction Successeur.

La fonction Action prend comme arguments un état i et un terminale a (ou $ le
marqueur de fin). La valeur de Action[i,a] peut prendre 4 formes :
a) décaler vers j, où j est un état. L'action prise par l'analyseur décale a dans
la pile, mais il utilise l'état j à ça place pour représenter a.
b) réduire A → β. L'action de réduire β par la tête A.
c) accepter
d) erreur

La fonction Successeur est la même que la fonction Transition définie pour les
états des items, si Transition[Ii,A] = Ij alors Successeur[i,A]=j, avec i,j des états
de l'AFD et A un non terminale.
Prof. M. BENADDY Compilation 69
L’algorithme d'analyse LR

Comportement d'un analyseur LR :

Une configuration d’un analyseur LR est un couple (pile, tampon d'entrée)
dont le premier composant est le contenu de la pile et dont le second
composant est la chaîne d’entrée restant à analyser : (S0 X1S1X2S2 . . .
XmSm, aiai+1 . . . an$) qui représente la proto-phrase droite
X1X2. . .Xmaiai+1 . . .an$ (avec Si est un état représentant Xi un symbole de
la grammaire).
 L'action suivante de l'analyseur est de déterminer par la lecture de a i, le
symbole d'entrée courant, et Sm, l'état au sommet de la pile, ensuite
consulter l'entrée Action[Sm,ai] dans la table des actions. Les
configurations résultantes après chacun des quatre types d'action sont :

Si Action[Sm,ai]=décaler S, l'analyseur exécute une action décaler
atteignant la configuration (S0X1S1X2S2 . . . XmSm ai S, ai+1 . . . an$).
L'analyseur a à la fois empilé le symbole d'entrée courant ai et le
prochain état S, qui est donné par Action[Sm,ai], ai+1 devient le symbole
d'entrée courant.
Prof. M. BENADDY Compilation 70
L’algorithme d'analyse LR

Comportement d'un analyseur LR :

Si Action[Sm,ai]=réduire par A → β, alors l'analyseur exécute une action
réduire, atteignant la configuration : (S0 S1S2 . . . Sm-rAS, ai ai+1 . . . an$),
avec r est la longueur de β et S=Successeur[Sm-r ,A].

L'analyseur ici dépile r états et r symboles, et met ainsi l'état S m-r au
sommet de la pile.

L'analyseur empile alors S=Successeur[Sm-r,A]. le symbole courant
en entrée n'est pas changé par une action réduire.

Pour les analyseurs LR, Xm-r+1 . . . Xm, la séquence de symboles
grammaticaux correspondant aux dépilés, correspondra toujours à
β, le symbole à droite de la production réduite.

Le résultat d'un analyseur LR est généré après une action réduire
en exécutant une action sémantique associée à la production
considérée.

Dans notre cas on supposera que la sortie est uniquement formée
par la liste des productions par lesquelles on a réduit.
Prof. M. BENADDY Compilation 71
L’algorithme d'analyse LR

Comportement d'un analyseur LR :
 Si Action[Sm,ai] = accepter, l’analyseur a terminé.
 Si Action[Sm,ai] = erreur, l’analyseur a découvert une
erreur et appelle une routine de récupération sur
erreur.

L’algorithme d’analyse LR est résumé dans le diapos (
73) suivant.

Tous les analyseurs LR se comportent de la même
façon la seule différence entre deux analyseurs LR
est dans les champs Action et Successeur de la table
d'analyse.

Prof. M. BENADDY Compilation 72


L’algorithme d'analyse LR

Algorithme d'un analyseur LR :

Donnée : une chaîne d’entrée w avec une table
d’analyse LR et les fonctions Action et Successeur
pour une grammaire G.

Résultat : si w est dans L(G), une analyse
ascendante de w (étapes de réductions) ; sinon une
indication d’erreur.

Méthode : initialement, l’analyseur a S0 en sa pile, où
S0 est l’état initial, et w$ dans son tampon d’entrée.
L’analyseur exécute le programme ci-après (diapo 74)
jusqu’à ce qu’il rencontre soit une action accepter soit
une action erreur.
Prof. M. BENADDY Compilation 73
L’algorithme d'analyse LR

Algorithme d'un analyseur LR :
Considérer a comme étant le premier symbole de w$
while(1){/*répéter inifiniment*/
considérer S l'état au sommet de la pile,
if(Action[S,a] = décaler t){
empiler t et a ; /*mettre t et a dans la pile*/
a = symbole suivant ;
}else if(Action[S,a]=réduire A → β){
Dépiler β de la pile ;
t = nouveau sommet de la pile;
Empiler A et Successeur[t,A] dans la pile ;
afficher la production A → β ;
}else if(Action[S,a]=accept) break ; /*analyse
términé*/
else appel routine de traitement d'erreur ;
}
Prof. M. BENADDY Compilation 74
L’algorithme d'analyse LR

Algorithme d'un analyseur LR : exemple : soit la grammaire
suivante
(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
(5) F → (E)
(6) F → id

Le codage des actions et le suivant :

di signifie décaler et empiler l’état i.

rj signifie réduire par la production j (ici de 1 à 6).

acc signifie accepter.

une entrée vide signifie erreur.
Prof. M. BENADDY Compilation 75
L’algorithme d'analyse LR

Algorithme d'un analyseur LR : exemple :
(1) E → E + T
État Action Successeur (2) E → T
id + * ( ) $ E T F (3) T → T * F
0 d5 d4 1 2 3
(4) T → F
1 d6 acc
(5) F → (E)
2 r2 d7 r2 r2
3 r4 r4 r4 r4 (6) F → id
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3
7 d5 d4 10
8 d6 d11
9 r1 d7 r1 r1
10 r3 r3 r3 r3
11 r5 r5 r5 r5

Prof. M. BENADDY Compilation 76


L’algorithme d'analyse LR

Algorithme d'un analyseur LR : exemple : sur l'entrée
id*id+id la pile et le tampon sont :
État Action Successeur Pile Tampon d'entrée Action
id + * ( ) $ E T F (1) 0 id*id+id$ d5
0 d5 d4 1 2 3 (2) 0 id 5 *id+id$ r par F → id
1 d6 acc (3) 0 F 3 *id+id$ r par T → F
(4) 0 T 2 *id+id$ d7
2 r2 d7 r2 r2
(5) 0 T 2 * 7 id+id$ d5
3 r4 r4 r4 r4
(6) 0 T 2 * 7 id 5 +id$ r par F → id
(7) 0 T 2 * 7 F 10 +id$ r par T → T * F
4 d5 d4 8 2 3 (8) 0 T 2 +id$ r par E → T
5 r6 r6 r6 r6 (9) 0 E 1 +id$ d6
(10) 0 E 1 + 6 id$ d5
6 d5 d4 9 3 (11) 0 E 1 + 6 id 5 $ r par F → id
7 d5 d4 10 (12) 0 E 1 + 6 F 3 $ r par T → F
8 d6 d11 (13) 0 E 1 + 6 T 9 $ r par E → E + T
(14) 0 E 1 $ accepter
9 r1 d7 r1 r1

10 r3 r3 r3 r3 (1) E → E + T
(2) E → T
11 r5 r5 r5 r5
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 77
(6) F → id
Construction de la table d'analyse SLR

La méthode SLR commence par les items LR(0) et
l'automate LR(0).

On augmente la grammaire G en G', avec un nouveau
axiome S'.

On construit C la collection canonique des ensembles
d'items pour G' avec leur fonction de transition.

Les entrées Action et Successeur dans la table d'analyse
sont construites en utilisant l'algorithme suivant (diapo
79).

Il est nécessaire de savoir suivant(A) pour chaque non-
terminal de la grammaire.

Prof. M. BENADDY Compilation 78


Construction de la table d'analyse SLR

Algorithme : construction table SLR.

Donnée : une grammaire augmentée G'.

Résultat : table d'analyse SLR des fonctions Action et Successeur pour G'.

Méthode :
1) Construire la collection C ={I0,I1,...,In} des ensemble des items de LR(0)
pour G'.
2) l'état i est construit à partir de Ii, Les actions d'analyse pour l'état i sont
déterminées comme suit :
(a) Si [A → α·aβ] (a doit être un terminal) est dans Ii et Transition(Ii,a)=Ij,
donc Action[i,a]=décaler j.
(b) Si [A → α·] (A ≠ S') est dans Ii , donc Action[i,a]=réduire A → α pour
chaque a dans Suivant(A).
(c ) Si [A → S·] est dans Ii , donc Action[i,$]=accepter.

Si les règles précédentes engendrent des actions conflictuelles, nous disons
que la grammaire n’est pas SLR(1). Dans ce cas, l’algorithme échoue et ne
produit pas d’analyseur.
Prof. M. BENADDY Compilation 79
Construction de la table d'analyse SLR

Algorithme : construction de la table SLR.

Méthode :
1)...
2)...
3)On construit les transitions Successeurs pour l’état i
pour tout non-terminal A en utilisant la règle : si
Transition(Ii,A) = Ij alors Successeur[i, A] = j.
4)Toutes les entrées non définies par les règles 2 et 3
sont positionnées à « erreur ».
5)L’état initial de l’analyseur est celui qui est construit à
partir de l’ensemble d’items contenant [S' → ·S].

Prof. M. BENADDY Compilation 80


Construction de la table d'analyse SLR

La table d'analyse des fonctions Action et Successeur
déterminée par l'algorithme précédent est appelée table
SLR(1) pour G.

Un analyseur LR qui utilise la table SLR(1) pour G est
appelé un analyseur SLR(1) pour G, et une grammaire
ayant une table SLR(1) est dite SLR(1).

Habituellement on omit le (1) après SLR puisque ne
nous traitons pas les analyseurs qui acceptent plus d'un
symbole en entrée.

Prof. M. BENADDY Compilation 81


Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I0={[E' → ·E],[E → ·E+T|·T], [T →·T * F|·F], [F → ·(E)|
·id]}

Transition(I0,id)=I5 donc A[0,id]=d5
Transition[I0,(]=I4 donc A[0,(]=d4
Transition[I0,E]=I1 donc Successeur[I0,E]=1
Transition[I0,T]=I2 donc Successeur[I0,T]=2
Transition[I0,F]=I3 donc Successeur[I0,F]=3
État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3
(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 82
(6) F → id
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I0={[E' → ·E],[E → ·E+T|·T], [T →·T * F|·F], [F → ·(E)|
·id]}

Transition(I0,id)=I5 donc A[0,id]=d5

Transition[I0,(]=I4 donc A[0,(]=d4
Transition[I0,E]=I1 donc Successeur[I0,E]=1
Transition[I0,T]=I2 donc Successeur[I0,T]=2
Transition[I0,F]=I3 donc Successeur[I0,F]=3
État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 83
(6) F → id
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I0={[E' → ·E],[E → ·E+T|·T], [T →·T * F|·F], [F → ·(E)|
·id]}

Transition(I0,id)=I5 donc A[0,id]=d5

Transition[I0,(]=I4 donc A[0,(]=d4

Transition[I0,E]=I1 donc Successeur[0,E]=1
Transition[I0,T]=I2 donc Successeur[I0,T]=2
Transition[I0,F]=I3 donc Successeur[I0,F]=3
État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 84
(6) F → id
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I0={[E' → ·E],[E → ·E+T|·T], [T →·T * F|·F], [F → ·(E)|
·id]}

Transition(I0,id)=I5 donc A[0,id]=d5

Transition[I0,(]=I4 donc A[0,(]=d4

Transition[I0,E]=I1 donc Successeur[0,E]=1

Transition[I0,T]=I2 donc Successeur[0,T]=2
Transition[I0,F]=I3 donc Successeur[I0,F]=3
État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2

(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 85
(6) F → id
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I0={[E' → ·E],[E → ·E+T|·T], [T →·T * F|·F], [F → ·(E)|
·id]}

Transition(I0,id)=I5 donc A[0,id]=d5

Transition[I0,(]=I4 donc A[0,(]=d4

Transition[I0,E]=I1 donc Successeur[0,E]=1

Transition[I0,T]=I2 donc Successeur[0,T]=2

Transition[I0,F]=I3 donc Successeur[0,F]=3
État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
Prof. M. BENADDY Compilation (5) F → (E) 86
(6) F → id
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I1={[E' → E·], [E → E·+T]}

Transition[I1,+]=I6 donc A[1,+]=d6

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc

(1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 87
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I1={[E' → E·], [E → E·+T]}

Transition[I1,+]=I6 donc A[1,+]=d6

E' →E· donc A[1,$]=accepte

État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
(1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 88
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I2={[E → T·], [T → T·*F]}

Transition[I2,*]=I7 donc A[2,*]=d7

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
(1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 89
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I2={[E → T·], [T → T·*F]}

Transition[I2,*]=I7 donc A[2,*]=d7

Suivant(E)={$,+,)} alors A[2,+]=A[2,$]=A[2,)]=réduire/2

État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
(1) E→E+T
2 r2 d7 r2 r2 (2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 90
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I3={[T → F·]}

Suivant(T)={$,+,*,)} alors A[3,$]=A[3,*]=A[3,)]=A[3,+]=
réduire/4

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4

(1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 91
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I4={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T →
·F], [F → ·(E)], [F → ·id]}

Transition[I4,id]=I5 donc A[4,id]=d5

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
(1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 92
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I4={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T →
·F], [F → ·(E)], [F → ·id]}

Transition[I4,id]=I5 donc A[4,id]=d5

Transition[I4,(]=I4 donc A[4,(]=d4

État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3 (1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 93
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I4={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T →
·F], [F → ·(E)], [F → ·id]}

Transition[I4,id]=I5 donc A[4,id]=d5

Transition[I4,(]=I4 donc A[4,(]=d4

Transition[I4,E]=I8 Successeur[4,E]=8

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
(1) E→E+T
4 d5 d4 8 2 3 (2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 94
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I4={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T →
·F], [F → ·(E)], [F → ·id]}

Transition[I4,id]=I5 donc A[4,id]=d5

Transition[I4,(]=I4 donc A[4,(]=d4

Transition[I4,E]=I8 Successeur[4,E]=8

Transition[I4,T]=I2 Successeur[4,T]=2

État Action Successeur

id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4 (1) E→E+T
(2) E→T
4 d5 d4 8 2 3 (3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 95
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I4={[F → (·E)], [E → ·E+T], [E → ·T], [T →·T * F], [T →
·F], [F → ·(E)], [F → ·id]}

Transition[I4,id]=I5 donc A[4,id]=d5

Transition[I4,(]=I4 donc A[4,(]=d4

Transition[I4,E]=I8 Successeur[4,E]=8

Transition[I4,T]=I2 Successeur[4,T]=2

Transition[I4,F]=I3 Successeur[4,F]=3

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
(1) E→E+T
4 d5 d4 8 2 3 (2) E→T
(3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 96
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I5={[F → id·]}

Suivant(F)={+,*,$,)} donc A[5,+]=A[5,*]=A[5,$]=A[5,)]=r6

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
(1) E→E+T
4 d5 d4 8 2 3 (2) E→T
(3) T→T*F
5 r6 r6 r6 r6 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 97
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I6={[E → E+·T], [T → ·T * F], [T → ·F], [F → ·(E )], [F → ·id]}

Transition[I6,id]=I5 alors A[6,id]=d5

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
(1) E→E+T
5 r6 r6 r6 r6 (2) E→T
(3) T→T*F
6 d5 d4 9 3 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 98
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I6={[E → E+·T], [T → ·T * F], [T → ·F], [F → ·(E )], [F → ·id]}

Transition[I6,id]=I5 alors A[6,id]=d5

Transition[I6,(]=I4 alors A[6,(]=d4

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
(1) E→E+T
5 r6 r6 r6 r6 (2) E→T
(3) T→T*F
6 d5 d4 9 3 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 99
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I6={[E → E+·T], [T → ·T * F], [T → ·F], [F → ·(E )], [F → ·id]}

Transition[I6,id]=I5 alors A[6,id]=d5

Transition[I6,(]=I4 alors A[6,(]=d4

Transition[I6,T]=T9 alors Successeur[6,T]=9

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
(1) E→E+T
5 r6 r6 r6 r6 (2) E→T
(3) T→T*F
6 d5 d4 9 3 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 100
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I6={[E → E+·T], [T → ·T * F], [T → ·F], [F → ·(E )], [F → ·id]}

Transition[I6,id]=I5 alors A[6,id]=d5

Transition[I6,(]=I4 alors A[6,(]=d4

Transition[I6,T]=I9 alors Successeur[6,T]=9

Transition[I6,F]=I3 alors Successeur[6,F]=3

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
(1) E→E+T
5 r6 r6 r6 r6 (2) E→T
(3) T→T*F
6 d5 d4 9 3 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 101
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I7={[T → T*·F], [F → ·(E)], [F → ·id]}

Transition[I7,id]=I5 alors A[7,id]=d5

Transition[I7,(]=I4 alors A[7,(]=d4

Transition[I7,F]=I10 alors Successeur[7,F]=10

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6 (1) E→E+T
6 d5 d4 9 3 (2) E→T
(3) T→T*F
7 d5 d4 10 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 102
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I8={[F → (E·)], [E → E·+T]}

Transition[I8,+]=I6 alors A[8,+]=d6

Transition[I8,)]=I11 alors A[8,)]=d11

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3 (1) E→E+T
(2) E→T
7 d5 d4 10 (3) T→T*F
(4) T→F
8 d6 d11 (5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 103
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I9={[E → E+T·], [T → T· * F]}

Transition[I9,*]=I7 alors A[9,*]=d7

Suivant(E)={+,),$} alors A[9,+]=A[9,)]=A[9,$]=r1
État Action Successeur
id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3
7 d5 d4 10
(1) E→E+T
8 d6 d11 (2) E→T
(3) T→T*F
9 r1 d7 r1 r1 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 104
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I10={[T → T*F·]}

Suivant(T)={*,+,),$} alors A[10,*]=A[10,+]=A[10,)]=A[10,$]=r3

État Action Successeur


id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3
7 d5 d4 10
8 d6 d11
(1) E→E+T
9 r1 d7 r1 r1 (2) E→T
10 r3 r3 r3 r3 (3) T→T*F
(4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 105
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I11={[F → (E)·]}

Suivant(F)={*,+,),$} alors A[11,*]=A[11,+]=A[11,)]=A[11,$]=r5
État Action Successeur
id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3
7 d5 d4 10
8 d6 d11
9 r1 d7 r1 r1
(1) E→E+T
10 r3 r3 r3 r3 (2) E→T
(3) T→T*F
11 r5 r5 r5 r5 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 106
Construction de la table d'analyse SLR

Exemple :soit la grammaire G' définit précédemment

I11={[F → (E)·]}

Suivant(F)={*,+,),$} alors A[11,*]=A[11,+]=A[11,)]=A[11,$]=r5
État Action Successeur
id + * ( ) $ E T F

0 d5 d4 1 2 3

1 d6 acc
2 r2 d7 r2 r2
3 r4 r4 r4 r4
4 d5 d4 8 2 3
5 r6 r6 r6 r6
6 d5 d4 9 3
7 d5 d4 10
8 d6 d11
9 r1 d7 r1 r1
(1) E→E+T
10 r3 r3 r3 r3 (2) E→T
(3) T→T*F
11 r5 r5 r5 r5 (4) T→F
(5) F → (E)
Prof. M. BENADDY Compilation (6) F → id 107
Limites des grammaires SLR

Remarque : chaque grammaire SLR(1) est une grammaire non ambiguë,
mais il existe des grammaires non ambiguë qui ne sont pas SLR(1). Soit la
grammaire G définit par :
S→L=R|R
L → *R | id
R→L

qui code l’affectation et l’accès à la valeur d’un pointeur. Les ensembles d’items
de cette grammaire sont :

I0={[S' → ·S],[S → ·L = R],[S → ·R], [L → ·*R],[L → ·id],[R → ·L]}, I1={[S' →
S·]}, I2={[S → L· = R],[R → L·]}, I3={[S → R·]}, I4={[L → *·R],[R → ·L],[L → ·*R],
[L → ·id]}, I5={[L → id·]}, I6={[S → L = ·R],[R → ·L], [L → ·*R],[L → ·id]}, I7={[L
→ *R·]}, I8={[R → L·]}, I9={[S → L = R·]}

L'ensemble I2 d’items de cette grammaire contient : I2={[S → L· = R],[R → L·]} .
l'item S → L· = R donne A[2,=]=d6, alors que Suivant(R) contient =, la
deuxième action est alors A[2,=]=réduire par R → L, la grammaire G n'est donc
SLR(1) et est non ambiguë => conflit de réduire/décaler sur =. la méthode SLR
est incapable de décider quelle action prendre sur =
Prof. M. BENADDY Compilation 108
Limites des grammaires SLR

Les méthodes canoniques LR(1) et LALR, vont réussir sur une
plus vaste collection de grammaires, y compris la grammaire
précédente.

Dans la pratique, les langages de programmation ont des
grammaires LALR(1).

Yacc et Cup construisent des tables pour une grammaire LALR(1).

Prof. M. BENADDY Compilation 109


Générateur d'analyseur syntaxique Yacc

Grammaire y.tab.h
programme.y yacc y.tab.c

y.tab.c
lex.yy.c Compilateur C (gcc) a.out

Texte à analyser Résultat


a.out

Prof. M. BENADDY Compilation 110


Générateur d'analyseur syntaxique Yacc

Yacc signifie : Yet another compiler-compiler, la première version
de yacc date des années 1970 créée par S.C. Johnson. Yacc est
disponible comme une commande du système UNIX, et est
utilisée pour aider dans l'implémentation des compilateurs.

Un programme yacc doit être contenu dans un fichier ayant
l'extension « .y ». Il a la même structure en trois parties comme
lex. Une première partie de déclarations, une seconde partie
contient les règles de traduction de l'analyseur syntaxique, et une
troisième partie qui contient du code écrit en C qui sera copié
dans le programme qui sera généré.
%{ déclarations C
%}
Déclarations Yacc
%%
règles de traduction
%%
routines écrites en C
Prof. M. BENADDY Compilation 111
Générateur d'analyseur syntaxique Yacc

Partie des déclarations : Elle contient deux sections optionnelles.

La première contient des déclarations ordinaires en C (variables
bibliothèques, unions, …) délimitées par %{ et %}.

Une seconde section qui contient les déclarations de tokens et
d'associativité/priorité des opérateurs.

L'axiome avec %start

Les tokens de la grammaire avec %token

Les opérateurs en précisant leur associativité par %left,
%right,%nonssoc

Remarques :

Le symbole % doit être à la première colonne

Les symboles de la grammaire qui ne sont pas déclarés dans la
section de déclarations sont considérés comme des non-
terminaux.
Prof. M. BENADDY Compilation 112
Générateur d'analyseur syntaxique Yacc

Partie des règles de traduction : Cette partie vient après la
partie déclarations (optionnelle) après les premiers %%, cette
partie contient les règles de production.

Chaque règle consiste en une production de la grammaire
associée avec une action sémantique.

Un ensemble de production écrites de la façon suivante :
<tête> → <corps>1 | <corps>2 | … | <corps>n

peuvent être écrite en Yacc comme suit :
<tête> : <corps>1 {<action sémantique>1}
| <corps>2 {<action sémantique>2}
| …
| <corps>n {<action sémantique>n}
;

Prof. M. BENADDY Compilation 113


Générateur d'analyseur syntaxique Yacc

Partie des règles de traduction :

Dans une production Yacc, une chaîne de caractères ou de chiffres
non déclarés entre quottes ('''') comme des tokens sont considérés
comme des non-terminaux.

Un caractère entre simples quottes 'c' est considéré comme un
symbole terminal c. Les corps alternatifs sont séparés par une barre
verticale (|) et un point virgule (;) suit chaque tête avec ses
dérivations et ses actions sémantiques.

Le premier token est considéré comme le token de départ (axiome).

Une action sémantique Yacc est une séquence d'instructions écrites
en langage C.

Dans une action sémantique le symbole $$ fait référence à la valeur
d'attribut associé au non-terminal de la tête (gauche), tandis que $i
fait référence à la valeur associée avec le i symbole de la
ème

grammaire (terminal ou non-terminal) du corps.


Prof. M. BENADDY Compilation 114
Générateur d'analyseur syntaxique Yacc

Partie routines écrites en C : :

Cette partie contient des routines écrites en C.

Elle doit contenir la fonction d'analyse lexicale yylex()
dans le cas où Lex est utilisé pour produire l'analyseur
lexical, il suffit d'inclure le fichier lex.yy.c par :
#include ''lex.yy.c''

Dans cette partie, des procédures de traitement d'erreur
peuvent être introduites si nécessaire.

Elle contient la fonction main(), qui ne doit pas être
introduite dans le fichier Flex.

Prof. M. BENADDY Compilation 115


Générateur d'analyseur syntaxique Yacc

Exemple : Considérons la grammaire des expressions
arithmétiques suivante :
S → E fin
E → E+T | T
T→T*F|F
F → (E) | nbre

Prof. M. BENADDY Compilation 116


Générateur d'analyseur syntaxique Yacc

Exemple : Partie déclarations

Les tokens de la grammaire


Les non terminaux de la grammaire
+ et – sont associative à gauche et ont la priorité la plus basse
* et / sont associative à gauche et ont la priorité la plus haute
S est l'axiome sinon le premier symbole sera désigné comme axiome
de la grammaire

Prof. M. BENADDY Compilation 117


Générateur d'analyseur syntaxique Yacc

Exemple : règles de traduction

Prof. M. BENADDY Compilation 118


Générateur d'analyseur syntaxique Yacc

Exemple : Routines en C

Prof. M. BENADDY Compilation 119


Générateur d'analyseur syntaxique Yacc

Exemple : L'analyseur lexical

Prof. M. BENADDY Compilation 120


Générateur d'analyseur syntaxique Yacc

Exemple : Exécution
Produit parser.tab.h et parser.tab.c

Produit lex.yy.c

Compilation

Compilation et lien

Exécution

Prof. M. BENADDY Compilation 121


Générateur d'analyseur syntaxique Yacc

Exemple : Exécution

Prof. M. BENADDY Compilation 122


Analyse sémantique

Un constituant important de l'analyse sémantique
est le contrôle de type, un contrôleur de type
vérifie que le type d'une construction correspond
bien au type attendu par son contexte.

Par exemple l'opérateur arithmétique modulo
nécessite des opérandes entières, le contrôleur de
type doit vérifier que les opérandes de modulo
sont de type entier.

De façon similaire le contrôleur de type doit vérifier
que toute fonction définit par l'utilisateur est utilisée
avec le bon nombre d'arguments et de type
correcte.
Prof. M. BENADDY Compilation 123
Analyse sémantique

Dans la plupart des langages les types peuvent être soit
des types de base soit des types construits :

les types de base sont les types atomiques sans structure
interne ou dont la structure interne n'est pas accessible aux
programmeurs. Par exemple entier, réel, …

les types construits à partir des types de base ou d'autres types
construits comme les tableaux, les structures, les fonctions, …

Le type de toute construction d'un langage est dénotée
par une expression de type.

On introduit dans les contrôleurs de type un symbole de
typage qui est une collection de règles permettant
d'associer des expressions de type aux diverses parties
du programme.
Prof. M. BENADDY Compilation 124
Analyse sémantique

Exemple :
P → D ; E
D → D ; D | id : T
T → caractères | entier | tableau [nb] de T
E → nb | id | E mod E | E [E]
var T : array [1..4] of integer ;

Prof. M. BENADDY Compilation 125

Vous aimerez peut-être aussi