Vous êtes sur la page 1sur 60

ANALYSE

SYNTAXIQUE

COMPILATION
Fevrier 2021
Table des matières

I - Concepts de base 3

1. L'analyse syntaxique ? C'est quoi, pourquoi et comment ? ................................................................................... 4

1.1. Les activités du processus de compilation ............................................................................................................................ 4

1.2. L'étape de l'analyse syntaxique ............................................................................................................................................. 4

1.3. Grammaire ............................................................................................................................................................................ 6

1.4. Grammaire algébrique ........................................................................................................................................................... 8

1.5. Reconnaissance des mots par une grammaire algébrique .................................................................................................... 9

II - A - LES ANALYSEURS DESCENDANTS 11

1. A- Analyse Syntaxique Descente ............................................................................................................................ 11

1.1. 1- Principes et techniques d'analyse Descendante ............................................................................................................. 13

1.2. 2- Déroulement de l'analyse syntaxique LL ......................................................................................................................... 16

1.3. 3- Construction de l'analyseur descendant .......................................................................................................................... 18

1.4. 4- Conditions de l'analyse descendante LL ......................................................................................................................... 25

1.5. 5- Transformation des grammaires non adéquates pour l'analyse LL ................................................................................. 26

III - B - LES ANALYSEURS ASCENDANTS 27

1. B- Analyse Syntaxique Ascendante ........................................................................................................................ 27

1.1. 1- Principes et techniques d'analyse Ascendante ................................................................................................................ 29

1.2. 2- Principe de base de l'analyse ascendante LR ................................................................................................................. 31

1.3. 3- Construction de l'analyseur ascendant LR ...................................................................................................................... 34

1.4. 3- Déroulement de l'analyse syntaxique Ascendante ........................................................................................................... 49

1.5. 5- Analyse des grammaires ambiguës ................................................................................................................................ 52

1.6. 6-Développement d'un analyseur syntaxique ...................................................................................................................... 54

Conclusion 60
Concepts de base

I Concepts de base

3
Les activités du processus de compilation

1. L'analyse syntaxique ? C'est quoi, pourquoi et comment ?


1.1. Les activités du processus de compilation

L'enchaînement des étapes de la compilation (traduction)

Étapes de Compilation

1.2. L'étape de l'analyse syntaxique

En quoi consiste cette étape ?

Vérifier si les unités lexicales obtenues du code source forme bien les structures du langage utilisé. C'est à dire :

- Est ce que la grammaire du langage utilisé est respectée par le flux des lexème du code source ?

- SI oui une structure de donnée dite "ARBRE SYNTAXIQUE" est générée


- Sinon une erreur est signalée.

La figure ci-après montre les Phases de l'analyse syntaxique.

Phase analyse syntaxique

 Exemple : Pour le flux : A + B *C

Soit la grammaire du langage :

E→E+T|T

T→T*F|F

F → (E) | id

L'analyse lexicale retournera par exemple : id1 + id2 * id3 et l'analyse syntaxique retournera l'arbre syntaxique de
cette chaîne.

4
L'étape de l'analyse syntaxique

Arbre syntaxique

 Exemple : La définition textuelle de la syntaxe de la fonction SUM de MS. EXCEL

La grammaire permettant de décrire la syntaxe de cette fonction

E → SUM ( PARAM )

PARAM → PARAM ; Number | Number

 Définition : L'analyse syntaxique : c'est quoi au juste ?

- Opération qui consiste à reconnaître les mots d'un langage décrit par une grammaire algébrique.

5
Grammaire

- Cette reconnaissance se base sur la notion de dérivation en utilisant les règles de productions de la grammaire.

1.3. Grammaire

 Définition : Rappelons que :

Une grammaire est un quadruplet où :

est l'ensemble de symboles dits TERMINAUX

est l'ensemble de symboles dits NON TERMINAUX,

est L'AXIOME de G,

est l'ensemble des règles de production.

 Complément : Règle de production

Une règle de production est l'opération qui permet la génération des mots par réécriture (substitution). l'ensemble P
peut être définit comme suit :

On dit :

est réécrit en ou est généré par

La production p est noté comme suit :

Il existe une autre forme de notation dite "forme de Backus-Naur" (BNF de l'anglais Backus-Naur Form) utilisée
souvent dans la description des grammaires des langages de programmation.

Dans les productions de la notation BNF :

Les symboles non terminaux sont mis en "<" et ">"

Les symboles terminaux sont mis entre " "

Le MGP (membre gauche de production) est séparé du MDP (membre droit de production) par " : := "

 Exemple : Soit G une grammaire G = < N, T, P, S >

Dans G :

- Les terminaux sont

- Les non terminaux sont N= \{ S, \, A \, \}

- L'axiome est S

- Les règles de production sont :

6
Grammaire

- La notation BNF des règle de productions est :

 Complément : La dérivation et la série de dérivations

Une dérivation est l'application d'une seule règle de production pour passer d'une chaîne de symboles de la
grammaire à une autre chaîne de symboles.

La dérivation est notée :

La série de dérivations est l'application de plusieurs règles consécutivement pour récrire une chaîne en une autre.
Elle est notée

 Complément : Mot dérivé par une grammaire

Soit une grammaire

On dit qu'un mot est généré par G s'il existe une séries de dérivation de à partir de l'axiome S :

Une dérivation pour ce mot à partir de l'axiome est notée :

 Complément : Dérivation la plus à gauche

On parle de dérivation la plus à gauche (LEFTMOST DERIVATION) lorsqu’à chaque étape d'une série de
dérivations on applique une production au non-terminal le plus à gauche.

 Complément : Dérivation la plus à droite

On parle de dérivation la plus à gdroite (RIGHTMOST DERIVATION) lorsqu’à chaque étape d'une série de
dérivations on applique une production au non-terminal le plus à droite.

 Exemple

Soit la chaîne aabb à dériver de l’axiome S d'une grammaire dont les productions

- La série de dérivation la plus à gauche est :

- La série de dérivation la plus à droite est :

7
Grammaire algébrique

 Complément : Langage généré par une grammaire

Soit une grammaire

Le langage L généré ou dérivé par une grammaire G<X,V, P, S> est défini comme suit :

1.4. Grammaire algébrique

 Définition : Grammaires algébriques

Des grammaires classées par Chomsky dans le type 2. Elles ont une restriction au niveau des membres droits et
gauches des productions.

Elles sont dites aussi "Grammaires hors contexte ou à contexte libre"

Une grammaire algébrique est un quadruplet où :

est l'ensemble de symboles dits TERMINAUX

est l'ensemble de symboles dits NON TERMINAUX,

est L'AXIOME de G,

est l'ensemble des règles de production tel que

 Exemple : Grammaire des expressions arithmétiques

Soit G = avec P :

Les productions ayant plusieurs MDPs peuvent s'écrire comme suit :

 Fondamental : Les propriétés des grammaires algébriques utilisables :

Un analyseur syntaxique déterministe se base sur une grammaire propre. Une grammaire dite propre possède les
propriétés suivantes:

- (1) Pas de symboles inutiles : Chaque non terminal et chaque terminal de la grammaire apparaît au moins dans
la dérivation d'un mot du langage

- (2) Pas de productions unitaires: absence de productions de la forme

- (3) Absence d'ε-productions : Si , alors éliminer les productions de la forme avec

8
Reconnaissance des mots par une grammaire algébrique

 Exemple : G1 : Grammaire non propre

 Exemple : G2 : Grammaire propre

1.5. Reconnaissance des mots par une grammaire algébrique

 Définition : Ambiguïté des grammaires algébriques

Une grammaire à contexte libre (type 2) est ambiguë si elle génère (dérive) un langage L ayant au moins un mot
(chaîne de symboles terminaux) possédant deux ou plusieurs arbres syntaxiques.

 Exemple : G est une grammaire ambiguë et la dérivation du mot id + id * id donne deux


arbres syntaxique

Soit G = avec P :

Deux arbre syntaxique (voir figure suivante) pour le mot :

 Attention : Prouver la non ambiguïté ou transformer la grammaire

- L’existence de deux suites de dérivations pour un mot n'induit pas l’existence de deux arbres
syntaxiques.

- On dispose en général des conditions nécessaires mais pas suffisantes pour prouver la non ambiguïtés d'une
grammaire (problème indécidable)

9
Reconnaissance des mots par une grammaire algébrique

Nous pouvons donner une grammaire non ambiguë si on connaît le langage à générer : le langage des expressions
arithmétiques en est un cas.

 Attention : Ambiguïté et non déterminisme

Une grammaire ambiguë induit une analyse syntaxique non déterministe

 Fondamental : PRINCIPE DE FONCTIONNEMENT DE L'ANALYSEUR SYNTAXIQUE

L'analyseur syntaxique doit être déterministe  : Soit le flux d'entrée (le programme) est correct soit il y a une ou
plusieurs erreurs.

 Complément : Méthodes d'analyse syntaxique

Il existe deux démarches pour l'analyse syntaxique d'un flux :

1. Analyse descendante
2. Analyse ascendante

 Méthode : PRINCIPE DE L'ANALYSE DESCENDANTE

- Retrouver le flux entrée en effectuant des dérivations successives en commençant par l'axiome de la grammaire.
- Cela revient à produire l'arbre syntaxique en partant du nœud racine (qui représente l'axiome) et descendre vers
les feuilles (les symboles terminaux)

 Méthode : PRINCIPE DE L'ANALYSE ASCENDANTE

- Retrouver l'axiome de la grammaire en effectuant des dérivations successives inverses (dites réductions)

- Cela revient à produire l'arbre syntaxique en partant des feuilles (les symboles terminaux) pour remonter au
nœud racine (qui représente l'axiome)

10
A - LES ANALYSEURS DESCENDANTS

II A - LES ANALYSEURS
DESCENDANTS

1. A- Analyse Syntaxique Descente


Objectifs

1. Concevoir des grammaires propres respectant les conditions nécessaires pour effectuer une analyse
Syntaxique Descendante
2. Concevoir et Implémenter un Analyseur Syntaxique Descendant

Soit à analyser le flux A + B * C du langage décrit par la grammaire algébrique suivante :

E→E+T|T

T→T*G|G

G → (E) | id

Comme illustré par la figure suivante le flux doit d'abord subir une analyse lexicale qui identifie les unités lexical (
tokens). Ensuite le flux des tokens subira l'analyse syntaxique qui consiste à calculer son arbre syntaxique.

L'analyseur syntaxique doit être déterministe : Soit le flux d'entrée (le programme) est correct soit il y a une ou
plusieurs erreurs.

11
1- Principes et techniques d'analyse Descendante

- Le noyau de L'analyseur syntaxique est un automate à pile permettant de générer l'arbre syntaxique dans
la pile

- Au début de l'analyse la pile est vide et à la fin de l'analyse la pile contiendra les différents membres des
productions utilisées (trace de la dérivation).

12
1 - Définition formelle d'un automate à pile et grammaire algébrique

1.1. 1- Principes et techniques d'analyse Descendante


1.1.1. 1 - Définition formelle d'un automate à pile et grammaire algébrique

 Définition : Automate à pile et grammaire

Une grammaire algébrique est un quadruplet où :

est l'ensemble de symboles dits TERMINAUX

est l'ensemble de symboles dits NON TERMINAUX,

est L'AXIOME de G,

est l'ensemble des règles de production tel que

Un automate à pile est un 7-uplets  :

- X : un alphabet d'entrée qui correspond à l'ensemble des terminaux (unités lexicales)


- Y : un alphabet auxiliaire (de la pile) qui correspond à l'ensemble des non terminaux et terminaux
- S : ensemble des états de l'automate qui corresponds aux étapes de dérivations
- F : ensemble des états finaux qui correspond à l'acceptation et c'est un seul état unique
- A : ensembles des actions possibles de l'automate suite à la lecture d'une unité lexicale et qui corresponde à :

- Avancer : lire la prochaine unité lexicale du flux d'entrée.


- Appliquer une règle de production (dériver) : Empiler / Dépiler un ou plusieurs symboles
membres de la production (mp).

- # : symbole de fin du flux d'entrée et de pile vide

13
2- Les bases de l'analyse syntaxique descendante

1.1.2. 2- Les bases de l'analyse syntaxique descendante

 Définition : Le principe de la méthode d'analyse syntaxique descendante

L'analyse syntaxique descendante est une méthode qui consiste à tenter de reconstruire (dériver) la chaîne à
analyser.

En partant de l'axiome de la grammaire en appliquant des dérivations successives (série de dérivations)

- Si on arrive à générer la chaîne alors elle est dite syntaxiquement correcte (on arrive à recalculer son arbre
syntaxique)
- Sinon elle est rejetée.

Cette catégorie d'analyse est dites : analyse LL (K) pour Left to right scanning using the Leftmost derivation taking
decision by reading k tokens from the input stream:

- Elll se base sur l'analyse de l'entrée de gauche à droite en utilisant la dérivation la plus à gauche après lecture
de k items du flot d'entrée

14
2- Déroulement de l'analyse syntaxique LL

 Conseil : Technique de conception et réalisation d'analyseur LL

Deux techniques pour réaliser un analyseur LL :

1. Analyseur avec table prédictive (nommé souvent analyseur LL(k)) : Il se base sur une table d'analyse conçue
par avance depuis la grammaire du langage à analyser et consulter lors de l'analyse d'une chaîne donnée et Il
possède sa propre pile
2. Analyseur avec descente récursive : il exploite la pile système des appels de procédures et se base sur la
transformation des règles de productions de la grammaire en fonctions/procédures (ou méthodes) récursives
qui s'invoquent entre elles pour réaliser l'analyse d'une chaîne

 Remarque : A propos du paramètre K

- Dans la pratique le paramètre k = 1 : permet d'analyser en lisant un seul caractère de l'entrée.
- Si K dépasse 1 alors l'implémentation devient moins pratique.
- Quelque soit la valeur de K, l'analyse fonctionne de la même façon en prenant k élément du flux d'entrée

15
1. Fonctionnement de l'analyseur LL avec table d'analyse

1.2. 2- Déroulement de l'analyse syntaxique LL


1.2.1. 1. Fonctionnement de l'analyseur LL avec table d'analyse

 Méthode

Soit la grammaire à traiter et :

- M la table d'analyse à construire et M [S, t] est une cellule de cette table


- SP le sommet de la pile de notre analyseur
- Tc le token courant dans le flux des unités lexicales à analyser
- Ts le token suivant dans le flux des unités lexicales à analyser

L'analyseur LL avec la table d'analyse fonctionne comme suit :

1 Empiler (#)
2 Empiler (S)
3 Si (SP in T) && (SP == Tc) && (Tc == "#") "Chaine Acceptée";
4 Si (SP in T) && (SP != Tc) Erreur;
5 Si (SP == Tc) && (Tc != "#")
6 {
7 Depiler();
8 Avancer(Tc) // Tc=Ts;
9 }
10 Si (SP in N)
11 {
12 Si (M[SP,Tc] == " A → X1X2..Xn-1Xn ")
13 // Empiler le MDP de droite à gauche
14 {
15 Depiler();
16 Empiler(Xn);
17 Empiler(Xn-1);
18 .......
19 Empiler(X2);
20 Empiler(X1);
21 }
22 Si (M[SP, Tc]=" ") "ERREUR SYNTAXIQUE"
23 }
24

1.2.2. 2 - Fonctionnement de l'analyseur avec descente récursive

 Méthode

L’analyseur LL avec des procédures (descente récursive) fonctionne comme suit :

Lecture du premier symbole (token) du flux dans la variable tc et lancement de la procédure correspondant à l'axiome
Z : Z() ;

- La procédure Z()  va enchaîner les appels aux autres procédures.


- Si Z() se termine correctement alors la chaîne est acceptée
- Si une des procédures invoquées par de Z s'arrête alors ERREUR

16
Exemple d'analyse LL

1.2.3. Exemple d'analyse LL

 Simulation

Analyser la chaîne "a + b" en utilisant les deux techniques d'analyse précédentes

Avec l'analyse LL(k) prédictive (table d'analyse) conçue à partir de la grammaire :

E→TX

X→+TX|ε

T→GY

Y→*GY|ε

G → ( E ) | id

La chaîne a+b retournera un flux d'unités lexicales suivant : id + id #

 Simulation : 1- Analyse LL(1) avec la table prédictive (table d'analyse)

Contenu de la pile (sommet) la chaîne Action

#E id+id# Dépiler(), empiler(XT)

#XT id+id# Dépiler(), empiler(YG)

#X Y G id+id# Dépiler(), empiler(id)

#XY id id+id# Dépiler(), Avancer()

#XY +id# Dépiler(), Empiler(ε)

#X +id# Dépiler(), Empiler(XT+)

#XT+ +id# Dépiler(), Avancer()

#XT id# Dépiler(), empiler(YG)

#X Y G id# Dépiler(), empiler(id)

#X Y id id# Dépiler(), Avancer()

#X Y # Dépiler(), Empiler(ε)

#X # Dépiler(), Empiler(ε)

# # CHAÎNE ACCEPTÉE

L'analyser du flux des unités lexicales : id+id#

17
3- Construction de l'analyseur descendant

 Simulation : 2- Analyse LL(1) avec la descente récursive (appels de procédures)

Contenu de la pile des appels La chaîne Action

Z() id+id# Appel E()

Z() E() id+id# Appel T()

Z() E() T() id+id# Appel G()

Z() E() T() G() id+id# tc = ts ; retour

Z() E() T() +id# Appel Y()

Z() E() T() Y() +id# retour

Z() E() T() +id# retour

Z() E() +id# Appel X()

Z() E() X() +id# Tc = Ts ; Appel T()

Z() E() X() T() id# Appel G()

Z() E() X() T() G() id# Tc=Ts ; retour

Z() E() X() T() # Appel Y()

Z() E() X() T() Y() # retour

Z() E() X() T() # retour

Z() E() X() # Appel X()

Z() E() X() X() # retour

Z() E() X() # retour

Z() E() # retour

Z() # CHAÎNE ACCEPTÉE

L'analyser du flux des unités lexicales : id+id#

1.3. 3- Construction de l'analyseur descendant

Deux techniques de constructions d’analyseur LL existes :

18
Démarche générale pour la construction d'analyseur LL(1)

- Analyse LL(k) dite aussi descente prédictive : se base sur une table d'analyse calculée par avance à partir
de la grammaire et exploitée lors de l'analyse
- Analyse par descente récursive : se base sur la transformation des règles de productions de la grammaire
en fonctions (ou méthodes) récursives qui s'invoquent entre elles pour réaliser l’arabe syntaxique
(dériver) de la chaîne à analyser

1.3.1. Démarche générale pour la construction d'analyseur LL(1)

 Méthode : Conception de l'analyseur LL

En premier lieu il faut vérification des conditions nécessaires d'une grammaire LL(1), ensuite procéder à la
conception de l'analyseur selon sont la technique choisie :

1. Calculer les ensembles des Débuts et Suivants  pour chaque non terminal de la grammaire, en vérifiant la
satisfaction de la condition nécessaire pour qu'elle soit LL(1)
2. Calculer la table d'analyse et vérifier qu'elle est mono-défini (sinon transformer là) dans le cas de l'analyseur LL
(k) avec table prédictive
3. Écriture des procédures dans le cas de l'analyseur LL(k) avec descente récursive

 Attention

Pour pouvoir reconnaître la fin de la chaîne à analyser (condition d'arrêt de l'analyse) on ajoute à la grammaire une
production de la forme tel que :

- S représente l'axiome de la grammaire à traiter (pour laquelle on construit l'analyseur)


- Z représente le nouvel axiome de la grammaire
- # est un terminal supplémentaire représentant la fin du flux (EOF)

1.3.2. 1- Calcul des ensembles des débuts et suivants

 Méthode : Calcul de l'ensemble des DÉBUTS pour un non terminal de la grammaire

19
2 - Conception de la table d'analyse pour analyseur LL(K)

 Méthode : Calcul de l'ensemble des SUIVANTS pour chaque non terminal de la grammaire

 Exemple

Construire les ensembles des débuts/suivants pour les symbole de la grammaire ci-après :

E→TX

X→+TX|ε

T→GY

Y→*GY|ε

G → ( E ) | id

Symbole DEBUTs SUIVANTs

E id ( #)

X +  ε #)

T id ( #)+

Y *  ε #)+

G ( id #)+*

Table DEBUT et SUIVANTs

1.3.3. 2 - Conception de la table d'analyse pour analyseur LL(K)

 Définition : a) Le principe de la table d'anlayse

1. La table d'analyse est une matrice (exemple en figure ci-après) avec:

- Une colonnes par chaque symbole non terminal  (alphabet ou l'ensemble T): ensemble des unités
lexicales augmenté du symbole # représentant la fin de la chaîne d'entrée. (Les feuilles de l'arbre
syntaxique)
- Une ligne par symbole non terminal (éléments de N) : présente les nœuds de l'arbre syntaxique
- Les cellules (intersection ligne et colonne) : représente référence à la production à utiliser dans la suite
des dérivations qui mènent au terminal en colonne ou restent vide (pour indiquer une erreur)

20
2 - Conception de la table d'analyse pour analyseur LL(K)

 Exemple : Une table d'analyse pour une grammaire (réduite) des expressions arithmétiques

 Méthode : b) Construction de la table d'analyse LL

Soit M la table d'analyse à construire et M[S, t] est une cellule de cette table désignée par le non terminal S et le
terminal t

Soit la forme générale des productions de la grammaire G

1. Pour chaque production de la grammaire p

- Faire 
Pour chaque terminal faire 
Si
- Fin

2. Chaque cellule M [S,t] vide indique une erreur

 Exemple : Construire la table d'analyse LL(1)

Construire la table d'analyse LL pour la grammaire ci-après :

E→TX

X→+TX|ε

T→GY

Y→*GY|ε

G → ( E ) | id

21
3 -Conception des procédures pour l'analyseur par descente récursive

 Simulation : La table d'analyse LL(1)

1.3.4. 3 -Conception des procédures pour l'analyseur par descente récursive

 Définition : a) Le principe de la descente récursive

- Dans cette technique les productions de la grammaire donnent naissance à un ensemble de procédure qui
s'invoque récursivement
- Le point d'entrer (la procédure lancer en premier) correspond à la production de l'axiome Z (ajouté à la
grammaire)
- Pour chaque symbole non terminal de la grammaire on crée une procédure sans paramètre
- Deux variables seront utilisée pour parcourir le Flux des unités lexicales (tokens) :

1. tc : token courant (unité lexicale que l'en vient de lire du flux)
2. ts : token suivant (unité lexicale suivante dans le flux)

 Méthode : b) Création des corps des procédures correspondants aux non terminaux

Soit A un non terminal quelconque de la grammaire MGP d'une production :

L’algorithme suivant montre comment créer le corps de la procédure correspondant au non terminal A.

On définit une procédure nommée A comme suit :

Le terme Traiter ( ) signifie passer à l'écriture des instructions de la procédure selon le MDP

22
3 -Conception des procédures pour l'analyseur par descente récursive

 Méthode : b.1) Traitement des MDPs (appel imbriquer)

L'algorithme suivant montre comment traiter un MDP appartenant à une production donnée.

Le terme Afficher signifie écrire dans le corps de la procédure.

Le terme Coder(X) signifie écrire le corps de les instructions correspondantes au traitement de X1 (ou selon X1)

 Méthode : b.2) Traitements ou écriture des instructions selon la nature du premier symbole
du MDP

Soit un MDP en cours de traitement ayant la forme : avec m sa taille.

L'algorithme suivant montre la démarche d'écriture des instructions de l'analyseur pour chaque symbole Xj au début
d'un MDP en cours de traitement :

 Remarque

Ce n'est pas nécessaire d'écrire l'instruction if (tc=Xj) si le premier symbole de Wi un terminal car nécessairement
tc=Xj du fait que ce test initial est fait dans la procédure A().

 Exemple : Construire les procédures de l'analyse avec descente récursive

Construire les procédures de la descente récursive pour la grammaire ci-après :

E→TX

X→+TX|ε

T→GY

Y→*GY|ε

G → ( E ) | id

23
4- Conditions de l'analyse descendante LL

 Simulation : Les procédures de 'analyseur LL avec descente récursive

On ajoute la production Z → E #.

On donnera ici les procédures correspondants au non terminaux de Z, E, X, T, Y et G

1 Z() {
2 case tc of {
3 "(" , "id" : { E();
4 if (tc == "#") "Chaîne accpetée"
5 else ERREUR SYNTAXIQUE
6 }
7 DEFAULT : ERREUR SYNTAXIQUE
8 }
9}

1 E() {
2 case tc of {
3 "(" , "id" : { T(); X();}
4 DEFAULT : ERREUR SYNTAXIQUE
5 }
6}

1 X() {
2 case tc of {
3 "+" : { tc=ts; T(); X(); }
4
5 "#", ")" : ;
6 DEFAULT : ERREUR SYNTAXIQUE
7 }
8}

1 T() {
2 case tc of {
3 "(" , "id" : { G(); Y();}
4 DEFAULT : ERREUR SYNTAXIQUE
5 }
6}

1 Y() {
2 case tc of {
3 "*" : { tc=ts; G(); Y(); }
4
5 "+", "#", ")" : ;
6 DEFAULT : ERREUR SYNTAXIQUE
7 }
8}

1 G() {
2 case tc of {
3 "(" : { tc=ts;
4 E();
5 if ( tc ==")") tc=ts;
6 else ERREUR SYNTAXIQUE
7 }
8
9 id : tc = ts;
10 DEFAULT : ERREUR SYNTAXIQUE
11 }
12 }

24
1- Les conditions générales pour réaliser l'analyse syntaxique LL

1.4. 4- Conditions de l'analyse descendante LL


1.4.1. 1- Les conditions générales pour réaliser l'analyse syntaxique LL

 Fondamental : Conditions de l'analyse syntaxiques descendantes

- La grammaire du langage doit permettre un analyseur déterministe : elle ne présente pas des conflits lors de
l'analyse d'une chaîne quelconque : c'est le le déterminisme ou non retour arrière qui se traduit par

- La table d'analyse est mono-définie : au plus une règle de production de la grammaire dans les cellules
de la table.
- Une procédure à la fois doit être lancée (dans la cas de la décente récursive)

- Si une grammaire G est LL(1) alors G est non ambiguë : la grammaire ambiguë doit être transformée
- Une grammaire G LL(1) permet de faire une analyse syntaxique descendante sans retour arrière.
- Si, ce n'est pas le cas, il faut transformer la grammaire du langage si elle ne présente pas les conditions qui
mènent à un analyseur déterministe.

1.4.2. 2- Les conditions nécessaires pour qu'une grammaire soit LL(1)

 Texte légal : Condition nécessaires à vérifier lors de la conception de la grammaire

1. Grammaire propre
2. Grammaire non récursive à gauche : la grammaire ne doit pas avoir des productions du type

-  : dite récursivité directe (immédiate)

-  : dite récursivité indirecte

 Attention : La factorisation d'une grammaire est aussi une condition nécessaire à l'analyse LL

Une grammaire G est factorisée à gauche si elle ne possède pas de productions du type :

 Fondamental : Caractéristiques d'une grammaire LL(1)

Une grammaire G = <N,T,S,P> qui vérifie les conditions nécessaires est dite LL(1) si et seulement si pour toute
paire de règles  :

- Pour tout terminal a , ne se dérivent pas toutes les deux en des chaînes commençant par a.
- Une des chaînes au plus se dérive en la chaîne vide.
- Si β ⇒* ε , ne se dérive pas par un terminal de SUIVANT(A) et vice-versa.

 Conseil : Formule de vérification qu'une grammaire est LL(k) , k=1

(1) Calculer deux ensembles :

1. Ensemble des débuts de chaque symbole non terminal :

- DEBUT(X) = {a | X ⇒* a. , a T et }.

25
1.

5- Transformation des grammaires non adéquates pour l'analyse LL

- Si X ⇒* alors DEBUT(X)

2. Ensemble des suivants de chaque symbole non terminal  :

- SUIVANT(X) = {a | S ⇒* }.

(2) Vérifier pour chaque production du type que :

- L'intersection :

1.5. 5- Transformation des grammaires non adéquates pour l'analyse LL


1.5.1. 1- Transformation pour la satisfaction de la condition de non récursivité à gauche

 Méthode : Démarche pour rendre la grammaire non récursive à gauche

- L'algorithme suivant, élimine systématiquement, les récursivités gauches (directes et indirectes) d'une
grammaire.
- Il fonctionne correctement si la grammaire est sans cycle (dérivations A⇒+A et sans production vide A →ε).

1 ORDONNER LES NON TERMINAUX A1, A2, ..., An;


2 For i:=1 To n
3 For j:=1 To i-1
4 Remplacer les productions de la forme Ai→ AjX par les productions
5 de la forme Ai → Y1 X | Y2 X | ... | m X
6 avec Aj→ Y1 | Y2 |...| Ym
7 End
8 Eliminer la récursivité directe (immédiate) des productions de Ai
9 End.

Éliminer la récursivité à gauche immédiate ou directe :

1 Remplacer les productions de la forme A → Aω | β | δ par :


2 A → βA' | δA'
3 A'→ ωA' | ε

1.5.2. 2 - Transformation pour la la satisfaction de la factorisation à gauche

 Méthode : Démarche pour rendre la grammaire factorisée à gauche

Des productions non factorisées à gauche d'une grammaire du type : A → α β1 | α β2 | ... | α βn | γ avec α <> ε sont
remplacées par les productions de type :

A→αX|γ

X → β1 | β2 | ... | βn

26
B - LES ANALYSEURS ASCENDANTS

III B - LES ANALYSEURS


ASCENDANTS

1. B- Analyse Syntaxique Ascendante


Objectifs

1. Concevoir des grammaires propres respectant les conditions nécessaires pour effectuer une analyse
Syntaxique Ascendante
2. Concevoir et Implémenter un Analyseur Syntaxique Ascendante

Soit à analyser le flux A + B * C du langage décrit par la grammaire algébrique suivante :

E→E+T|T

T→T*G|G

G → (E) | id

Comme illustré par la figure suivante le flux doit d'abord subir une analyse lexicale qui identifie les unités lexical (
tokens). Ensuite le flux des tokens subira l'analyse syntaxique qui consiste à calculer son arbre syntaxique.

L'analyseur syntaxique doit être déterministe : Soit le flux d'entrée (le programme) est correct soit il y a une ou
plusieurs erreurs.

27
1- Principes et techniques d'analyse Ascendante

- Le noyau de L'analyseur syntaxique est un automate à pile permettant de générer l'arbre syntaxique dans
la pile

- Au début de l'analyse la pile est vide et à la fin de l'analyse la pile contiendra les différents membres des
productions utilisées

28
1.1-L'analyseur syntaxique est un automate à pile

1.1. 1- Principes et techniques d'analyse Ascendante


1.1.1. 1.1-L'analyseur syntaxique est un automate à pile

 Rappel

L'automate à pile implémentant un analyseur syntaxique réalise les actions suivantes :

1. Lire l'unité lexicale du flux courant (TC pour token courant) : solliciter l'analyseur lexicale pour lui fournir une
unité lexicale
2. Selon les valeurs de TC et du sommet de pile (SP) et du contenu de la table de décision:

- Dépiler et/ou Empiler ou


- Avancer en lisant l'unité lexicale suivante (TC pour token suivant) en sollicitant l'analyseur lexicale ou
- Arrêter si la valeur de SP n'est pas "#" et le contenu de la cellule courante de la table est vide ( ARRÊT
ANORMAL CORRESPONDANT A UNE ERREUR SYNTAXIQUE)
- Arrêter si le SP est "#" (ARRÊT NORMAL CORRESPONDANT A L'ACCEPTATION DE LA CHAÎNE DU
FLUX SOUMIS A L'ANALYSE)

29
1.2- Fondement de la méthode d'analyse syntaxique ascendante

1.1.2. 1.2- Fondement de la méthode d'analyse syntaxique ascendante

 Définition : Le principe de la méthode d'analyse syntaxique ascendante

L'analyse syntaxique Ascendante est une méthode qui consiste à tenter de remplacer la chaîne à analyser par
l'Axiome de la grammaire.

En partant de la chaîne en entrée et en appliquant des réductions successives (série de dérivations inverses qui
consistent à remplacer le MDP par le MGP)

- Si on arrive à remonter à l'axiome de la grammaire alors la chaîne est dite syntaxiquement correcte (car on a
recalculé son arbre syntaxique par réductions)
- Sinon elle est rejetée.

Cette catégorie d'analyse est dites : analyse par décalage/réduction (left to right scanning using shift/reductions)

- Elle se base sur l'analyse de l'entrée de gauche à droite en utilisant les réductions pour atteindre l'axiome de la
grammaire

30
2- Principe de base de l'analyse ascendante LR

 Méthode : Technique de conception et réalisation d'analyseurs Ascendants

Il existent deux techniques principales pour réaliser un analyseurs Ascendants:

1. Analyseur par précédence: Il se base sur une table d'analyse conçue à base d'un ensemble de relations de
précédence qui déterminent si l'automate à pile avance dans la chaîne (décalage ou shift) ou dépile/empile
(réduction ou reduce).
2. Analyseur LR(k): (left to right scanning using Rightmoust reductions taking decision by reading k tokens from
the input stream)  : Il se base sur une table d'analyse conçue à base d'un automate d'état fini déterministe
reconnaissant les MDPs des règles de production de la grammaire. L'automate à pile réduit (empile/dépile)
une fois un MDPs est reconnu par l'AFD.

 Remarque : A propos du paramètre K

- Dans la pratique le paramètre k = 1 : permet d'analyser en lisant un seul caractère de l'entrée.
- Si K dépasse 1 alors l'implémentation devient moins pratique.
- Quelque soit la valeur de K, l'analyse fonctionne de la même façon en prenant k élément du flux d'entrée

 Complément : Les analyseurs par précédence d'opérateur

Cette technique ne couvre pas un large spectre des grammaires. Les grammaires d'opérateurs ne sont utilisables
que pour un petit sous-ensembles des langages de type 2. Parce que on a imposé des restrictions sur les
grammaires. D'où la classe de grammaires qui admettent une telle analyse est restreinte.

Par définition une grammaire d'opérateur si elle ne possède pas de productions de type :

1.
2.

D'où la la restriction de l'ensemble des langages couverts par cette catégorie d'analyseurs.

Les analyseurs syntaxiques utilisant la technique d'analyse LR restent les plus utilisés dans la catégorie des
méthodes d'analyse ascendantes.

Dans la suite de cette partie nous allons décrire uniquement les analyseurs LR

1.2. 2- Principe de base de l'analyse ascendante LR

L'analyse LR est dite aussi une analyse contextuelle.

Elle se base sur le calcul des différents états possibles dans lesquels peut se trouver l'analyseur permettant de
choisir l'action à entreprendre : Empiler+ Avancer (décalage) + dépiler + Empiler(réduction).

Le terme contexte ici désigne donc l'état actuel permettant à l'analyseur de choisir l'action à effectuer.

Le calcul de l'ensemble des états possibles revient à calculer les contextes de chaque règles de production de
la grammaire utilisée.

31
2.1-Contexte LR(k) d'une règle de production

L’ensemble des contextes des différentes règles de productions est reconnu lors de l'analyse à l'aide d'un AFD
(automate d'états finis déterministe).

Construire l'analyseur LR(k) revient donc à :

1. Trouver les contextes LR(k) de la grammaire ;


2. Construire un AFD qui reconnaît les contextes LR(k)

1.2.1. 2.1-Contexte LR(k) d'une règle de production

 Définition : Contexte d'une règle de production

L'état de l’analyseur permettant d'appliquer une réduction avec une règle de production.

Cette état se définit par deux éléments :

1. Le contenu de la pile de l’analyseur : Contexte Gauche noté


2. Ce qui reste à analyser du flux d'entrée : Contexte Droit noté

Formellement on définit le contexte d'une règle de production par un couple (θ , ω) comme suit :

Soit une règle de production p =

Soit une suite de dérivations à droite (rightmost derivations) partant de l'axiome de la grammaire, Z tel que :

Alors :

 : contexte gauche de p

 : contexte droit de p

 Remarque : Relation entre contexte droit d'une règle de production et suivant de son MGP

Si est un contexte de la production  : alors les symboles du contexte droit de cette production sont
dans l'ensemble

 Exemple : le contexte des productions S -> aS|a avec S l'axiome de la grammaire

Soit avec

32
2.1- Les conditions nécessaires pour qu'une grammaire permette une analyse ascendante LR(K)

 Fondamental : Contexte LR(K) d'une règle de production

 Exemple : Les contextes LR(0) et LR(1) des productions S -> aS|a avec S l'axiome de la
grammaire

 Remarque : Contexte LR(0)

Le contexte LR(0) d'une production est tout simplement sont contexte gauche. Il est le contexte Simple LR (SLR(1))

 Remarque : Contexte gauche et production vide

Le contexte gauche d'une production vide est pile vide qui signifie ne rien dépiler (du fait que l'en
dépile rien lorsque on réduit avec cette production)

1.2.2. 2.1- Les conditions nécessaires pour qu'une grammaire permette une analyse ascendante
LR(K)

 Texte légal : Condition nécessaires à vérifier lors de la conception de la grammaire

Contrairement aux analyseurs descendants les analyseurs ascendants ont moins de conditions et nécessitent une
grammaire qui:

1. Ne doit pas contenir de symbole inutiles (l'analyse LR accepte les productions vides, ce qui fait d'elle une large
couverture de grammaires)
2. Ne doit pas contenir des productions ayant les mêmes contextes ou des contextes inclus l'un dans l'autre.

En effet la grammaire du langage doit permettre un analyseur déterministe : elle ne présente pas des conflits lors de
l'analyse d'une chaîne quelconque : c'est le déterminisme qui se traduit par

- La table d'analyse est mono-définie : au plus une règle de production de la grammaire à utiliser

33
3- Construction de l'analyseur ascendant LR

Pour cela la grammaire ne doit pas avoir des productions ayant deux contextes tel que l'un est préfixe de l'autre

 Exemple

Soit avec

On remarque bien que: le contexte

Ceci induit un conflit décaler/réduire (shift/reduce) Donc G n'est pas LR(0)

Par contre On remarque bien que : le contexte

Ceci signifie que G est une grammaire LR(1) car il n'existe pas de contexte identique ou l'un préfixe de l'autre

 Fondamental

- Si une grammaire G est LR alors G est non ambiguë


- La table d'analyse d'une grammaire G, LR est MONODEFINIE
- Une grammaire G, LR permet de faire une analyse syntaxique ascendante sans retour arrière.
- Si, ce n'est pas le cas, il faut transformer la grammaire du langage ou construire des tables d'analyse multi-
définies (donc non LR) ensuite introduire des modifications directement sur la table par l'application de
conventions.

1.3. 3- Construction de l'analyseur ascendant LR

Un analyseur LR(k): (left to right scanning using Rightmoust reductions taking decision by reading k tokens
from the input stream) Il se base sur une table d'analyse conçue à base d'un automate d'état fini déterministe
reconnaissant les contextes des règles de production de la grammaire. L'automate à pile réduit (empile/dépile)
une fois un contexte d'un MDP est reconnu par l'AFD.

La méthode pratique de construction cet automate est la technique des items LR.

1.3.1. 3.1- Démarche générale pour la construction d'analyseurs ascendants LR

 Méthode : Conception de l'analyseur ascendant LR(k)

1. Calculer l'ensemble des Suivants pour chaque non terminal de la grammaire


2. Calculer les contexte LR(k) des MDPs de chaque production
3. Calculer l'AFD reconnaissant ces contextes
4. Calculer la table d'analyse basée sur l'AFD des contextes

34
3.2-Différents techniques d'analyseur LR(k)

 Conseil

Pour pouvoir reconnaître la fin de la chaîne à analyser (condition d'arrêt de l'analyse) on ajoute à la grammaire une
production de la forme tel que :

- S représente l'axiome de la grammaire à traiter (pour laquelle on construit l'analyseur)


- Z représente le nouvel axiome de la grammaire
- # est un terminal supplémentaire représentant la fin du flux à analyser

1.3.2. 3.2-Différents techniques d'analyseur LR(k)

Il existe 3 techniques d'analyse LR qui diffèrent dans le volume de la table d'analyse et par conséquent dans la classe
de grammaire qu'elles couvrent.

1. SLR(1): Simple LR est caractérisés par des contextes . De point


de vue implémentation la table d'analyse obtenue par ces contextes est compacte. Par contre l'analyseur ne
couvre pas toutes les grammaires LR.
2. LR(1) : La technique la plus complète en terme de couverture des grammaires. Son analyseur est plus précis
(il ne réalise pas d'actions inutile) mais sa table est plus grande.
3. LALR(1): Look Ahead LR(1) est un compromis entre SLR(1) et LR(1) avec une table compacte et un
analyseur précis exactement comme LR(1).

- Il existent deux techniques (algorithme) pour construire l'analyseur :

1. La méthode du calcul des contextes de chaque production et passage vers un l'AFD des contextes:
méthodes manuelle qui sert beaucoup plus à vérifier si une grammaire est LR.
2. La méthode des ITEMs LR : méthode pratique automatisable qui permet de calculer intuitivement l'AFD
des contextes sans les calculer explicitement. Elle se base uniquement sur les MDPs et les suivants du
MGP

 Définition : ITEM LR d'une production

Un item est une représentation de l'état de reconnaissance d'un MDP d'une production. Cette état est symbolisé par
un point séparant les symboles du MDP en deux parties :

1. Partie contenant les symboles déjà reconnus (déjà dans la pile) : Elle se situe à gauche du point dans l'ITEM
2. Partie contenant les symboles qui restent à reconnaître : Elle se situe à droite du point dans l'ITEM

Une règle de production engendre un nombre d'items proportionnel à la taille de son MDP et éventuellement cardinal
de l'ensemble des suivant de son MGP.

35
3.2-Différents techniques d'analyseur LR(k)

 Remarque

A chaque technique d'analyse correspond un type d'ITEMS LR:

1. Les items LR(0) correspondent à la technique SLR(1): L'item LR(0) se base uniquement sur les MDPS des
productions de la grammaire
2. Les items LR(1) correspondent à la technique LR(1): L'item LR(1) se base sur les MDPS des productions de
la grammaire ainsi que les suivants du MGP (symboles de préversions)
3. Les items LALR(1) correspondent à la technique  LALR(1): L'item LALR(1) se base sur les MDPS des
productions de la grammaire ainsi que les suivants du MGP (symboles de préversions)

 Exemple : 1- Les ITEM LR(0) d'une production X→ A a B

La production engendre les items suivants :

le début de l'AFD où il n'a rien reconnu ie: état initial

la fin de l'AFD où il a reconnu le MDP ie: état final donc l'analyseur peut réduire avec la production

 Exemple : 2- Les ITEM LR(1) d'une production X→ A a B

Soit le symbole non terminal S et les symboles terminaux

La production engendre les items LR(1) suivants :

le début de l'AFD où il n'a rien reconnu ie: état initial et le symbole de prévision qui doit être
présent en entrée du flux est α

le début de l'AFD où il n'a rien reconnu ie: état initial et le symbole de prévision qui doit être
présent en entrée du flux est β

la fin de l'AFD où il a reconnu le MDP ie: état final donc l'analyseur peut réduire avec la
production lorsque le symbole de prévision α est présent en entrée du flux d'analyse

la fin de l'AFD où il a reconnu le MDP ie: état final donc l'analyseur peut réduire avec la
production lorsque le symbole de prévision β est présent en entrée du flux d'analyse

 Exemple : 3- Les ITEM LALR(1) d'une production X→ A a B

Les items LALR(1) sont calculés à partir des ensembles des items LR(1) qui ont exactement les mêmes parties
gauche et leurs symboles de prévision sont différents

Soit un symbole non terminal X et les symboles terminaux

Soit les items d'une production

36
3.3-Calcul de la table d'analyse LR(k) par la méthode des items

Les items engendrés pour la production sont:

Une autre façon de calculer les items LALR(1) est à partir d'un noyau des items LR(0) et de former des items LR(0)
qui n'ont pas le "point" (".") en début du MDP et ensuite leur ajouter les symboles de prévisions qui sont les suivants
du MGP

Soit la production engendant les items LR(0) suivants :

Le de ses items est:

Après ajout ou propagation des symboles de prévisions on obtient les items LALR(1) suivants:

1.3.3. 3.3-Calcul de la table d'analyse LR(k) par la méthode des items

A-AFD reconnaissant les Contextes LR des MDPs de la grammaire

La construction de la table d'analyse pour les analyseurs LR par la technique des ITEM consiste donc à calculer
l'AFD des contextes LR des MDPs.

Notons cet automate ACM (AFD reconnaissant les Contextes LR des MDPs de la grammaire).

Le calcul de l'ACM revient à définir son état initial S0 et sa fonction de transition T. On se base sur deux opérations

essentielles :

- L'opération FERMETURE des ITEMS : Elle permet de calculer l'ensemble des items qui forment un état de
l'ACM des contextes.
- L'opération GOTO : l'opération de transition d'un état Si à un état Sj.

 Remarque

Chaque technique d'analyse LR possède son propre ACM (AFD reconnaissant les Contextes LR des MDPs de la
grammaire). C'est à dire sa propre collection d'ITEMs LR:

1. SLR(1) se base sur la collection des items LR(0)


2. LR(1) se base sur la collection des items LR(1)
3. LALR(1) se base sur deux types de collections d'items:

- Soit la collection des items LR(1) ayant les même "coeurs" ( exactement les mêmes parties gauche des
items LR(1) avec des symboles de prévision différents)
- Ou bien la collection du noyau des items LR[0] (un ensemble d'items formé uniquement des items qui
n'ont pas le "point" (".") en début de membre droit de production)

37
a) B- NOTION DE FERMETURE DES ITEMS

 Définition : 1- FERMETURE des ITEMS LR(0)

 Exemple : Fermeture d'un ITEM LR(0) d'une production

 Définition : 2- FERMETURE des ITEMS LR(1)

 Exemple : Fermeture d'un ITEM LR(1) d'une production

 Définition : 3- FERMETURE des ITEMS LALR(1)

Un item LALR(1) n'est autre qu'un regroupement des items LR(1) ou LR(0) donc la fermeture d'un item LALR(1) se
calcule de la même manière que la fermeture d'item LR(1).

38
b) C- NOTION DE GOTO (opération de transition)

 Définition : L'opération GOTO dans le cas des items LR(0)

 Exemple

 Définition : L'opération GOTO dans le cas des items LR(1)

 Exemple

39
3.4 -Démarche pour construire la table d'analyse LR

c) D- Collection canonique des ensembles des ITEM

 Définition : Collection canonique ITEMS LR

- La collection canonique des items est formé par les ensembles d'items générées pour une grammaire donnée
en utilisant les opérations FERMTEURE et GOTO.
- La collection des items représente une manière pratique (automatisable) de construire l'ACM (AFD des
Contextes des MDPs de la grammaire.)
- Chaque élément de la collection est un ensemble d'items produit par l'opération fermeture, et il représente un
état de l'ACM.
- La transitions entre deux états de l'ACM est calculée par l'opération GOTO.
- La collections des ITEMs est utilisée pour construire la table d'analyse.

1.3.4. 3.4 -Démarche pour construire la table d'analyse LR

Structure de la table d'analyse LR

- L'analyseur ascendant LR est un automate à pile qui se base dans le choix de l'une de ses actions DÉCALER
ou RÉDUIRE sur la table représentant l'AFD des contextes des MDPs de la grammaire.
- Les tables d'analyse des différentes techniques LR (SLR(k), LR(k) et LALR(k)) ont une structure commune qui
est une matrice composée de:

- Lignes représentent les états de la collections des ITEMs (respectivement LR(0) ou LR(1) ou LALR(1)))
- Deux types de colonnes:

- ACTION celle qui représentent les unités lexicales (symboles terminaux ou Tokens)
- SUCCESSEUR celle qui représentent les non terminaux

- L'intersection d'une ligne et une colonne de type ACTION représente une action de l'automate à pile (
DÉCALER ou RÉDUIRE)
- L'intersection d'une ligne et une colonne de type SUCCESSEUR représente une action de l'automate
ACM (transition à l'état suivant)

- La différence dans des tables d'analyse des techniques  (SLR(k), LR(k) et LALR(k)) réside dans :

- L'insertion de l'action RÉDUIRE dans les suivants du MGP ou dans ses symboles de prévision
uniquement.
- La tailles des tables (nombre de lignes) qui est proportionnelle à la taille de la collections canonique des
items (nombre d'états)

40
a) A- Le cas SLR(1)

 Méthode : a) Construction de la table d'analyse SLR(1)

 Exemple : Construire la table d'analyse SLR(1)

Soit la grammaire G augmentée ayant les productions suivantes : (les productions sont numérotées)

E' → E

(1) E → E + T

(2) E → T

(3) T → T * F

(4) T → F

(5) F → ( E)

(6) F →  i

1- Collection des ITEMS LR(0)

41
2-Table d'analyse SLR(1)

42
b) B - Le cas LR(1)

 Méthode : a) Construction de la table d'analyse LR(1)

 Exemple : Construire la table d'analyse LR(1)

Soit la grammaire G augmentée ayant les productions suivantes : (les productions sont numérotées)

S' → S

(1) S → AA

(2) A → aA

(3) A → b

1- Collection des ITEMS LR(1)

2-Table d'analyse LR(1)

43
c) C- Le cas LALR(1)

 Méthode : a) La table d'analyse LALR(1)

La table d'analyse LALR(1) est une table de taille intermédiaire entre celle de la table LR(1) et celle de SLR(1). Elle
est compacte et plus performante à l'implémentation.

La démarche de construction de la table d'analyse LALR(1) peut se faire de deux manières possibles :

1. Soit à partir de la collection des items LR(1) : regroupement des ensembles des items ayant le même cœurs.
C'est à dire les ensembles qui ont exactement les mêmes parties gauches des items LR(1). Par exemple le
coeur de l'item est
2. Soit à partir de la collection des items LR(0) : propagation des symboles de prévision sur les noyaux d'items LR
(0). C'est à dire un ensemble d'items LR(0) formé des items qui n'ont pas le "point" (".") en début de MDP droit
de production. Par exemple le noyau de l'ensemble d'items
est

- Cette dernière démarche (2) est la plus pratique.

1- Calcul des items LALR(1) par regroupement des ensembles d'items LR(1) ayant un cœur identique

2-Calcul des items LALR(1) à partir du noyau des items LR(0)

44
 Méthode : b) Construction de la table d'analyse LALR(1)

Après calcul de la collection LALR(1) la table se construit comme la table LR(1)

 Exemple : Construire la table d'analyse LALR(1) par les items LR(1)

Soit la grammaire G augmentée ayant les productions suivantes : (les productions sont numérotées)

S' → S

(1) S → AA

(2) S → aA

(3) A → b

1- Collection des ITEMS LR(1)

45
2 - On regroupe les états de la collection des items LR(1) avec le même cour :

3-Table d'analyse LALR(1)

 Exemple : Construire la table d'analyse LALR(1) par les items LR(0)

Soit la grammaire G augmentée ayant les productions suivantes : (les productions sont numérotées)

S' → S

(1) S → aA

(2) S → bAb

(3) S → ab

(4) A → ε

1- Collection des ITEMS LR(0)

46
2-1. Les noyaux LR(0)

2-2. Les items LALR(1) après propagations des symboles de prévision

3-Table d'analyse LALR(1)

47
3- Déroulement de l'analyse syntaxique Ascendante

48
3.1- Fonctionnement de l'analyseur Ascendant

1.4. 3- Déroulement de l'analyse syntaxique Ascendante


1.4.1. 3.1- Fonctionnement de l'analyseur Ascendant

Un analyseur LR fonctionne selon le schéma suivant :

 Méthode : Algorithme d'analyse

Soit la grammaire à traiter et :

- S est un état

- M la table d'analyse à construire et M [S, t] est une cellule de cette table


- SP le sommet de la pile de notre analyseur
- Tc le token courant dans le flux des unités lexicales à analyser
- Ts le token suivant dans le flux des unités lexicales à analyser

L'analyseur SLR(1) fonctionne comme suit :

1 Empiler S0 : (SP= S0);


2 LIRE (TC)
3 Repeter {
4 Si (M[SP,Tc] == "Réduire par A → mdp)
5 {
6 Pour (i=1,j,i++)
7 Depiler(); // j = 2* |mdp| (2 fois la languer du mdp de la production A → mdp)
8 empiler (A);
9 empiler (M(SP,A)) // SP ayant la nouvelle valeur du sommé de pile;
10 }
11 Si (M[SP,Tc] = "DECALER K"
12 {
13 Empiler(Tc);
14 Empiler(K);
15 TC=TS
16 }
17 }
18 Si (M[SP,Tc] == "Accepté (ok)") "Chaîne correconnue"; return;

49
3.1- Fonctionnement de l'analyseur Ascendant

19 Si (M[SP,Tc] == null) "ERREUR SYNTAXIQUE"; return;


20 Jusqu'à Tc='#';
21

 Simulation : EXEMPLE

Analyser la chaîne "a + b * c" en utilisant les l'analyseur SLR(1) construit pour la grammaire suivante :

E→E+T|T

T→T*F|F

F → (E) | i

La table d'analyse est déjà calculé (voir l'exemple SLR(1) ci-dessus) reproduite ici.

L'analyse lexicale de la chaîne retournera un flux d'unités lexicales suivant : i + i * i #

50
5- Analyse des grammaires ambiguës

51
Analyse LR avec une grammaire ambiguë

1.5. 5- Analyse des grammaires ambiguës


1.5.1. Analyse LR avec une grammaire ambiguë

 Méthode

- Si la grammaire est ambiguë alors elle n'est pas LR(K) . Par conséquent la table d'analyse sera multi
définie : conflits décaler/réduire.
- Pour exploiter les grammaires ambiguës dans une analyse LR, on construit les tables d'analyses et on lève les
multi-définitions par des règles comme par exemple les règles de priorité et associativité.
- Les avantages de procéder ainsi sont de réduire les tailles des tables d'analyse et d'accélérer les analyses.

 Exemple

Soit la grammaire ambiguë G:

E → E + E | E * E | (E ) | i

La table d'analyse SLR(1) de G ci-dessous contient des multi-définitions : conflit Décaler/Réduire des cellules (7,+) (7,
*) et (8,+) (8,*).

Les cellules de la tables avec conflits (multidéfinitons) sont résolues en utilisant les priorités et associativités des
opérateurs + et *.

52
6-Développement d'un analyseur syntaxique

53
Le générateur : YACC

1.6. 6-Développement d'un analyseur syntaxique


1.6.1. Le générateur : YACC

 Définition : YACC : Le générateur d'analyseur syntaxique (de compilateur)

Yacc (Yet Another Compiler Compiler) est un outils de génération des analyseurs syntaxique de type LALR(1) pour
des grammaires de type 2.

C'est un standard sur lequel ce sont basé tout les outils du marché comme par exemple la classe PARSER connue
dans les framework de développement (web ou autre).

Dans sa version standard historique il génère le code source écrit en C d'un analyseur syntaxique du langage
engendré par une grammaire donnée. En plus Il est permet aussi d’intégrer le code des actions sémantiques
(opérations à effectuer suite à la reconnaissance des structures du langage).

 Définition : Fonctionnement de YACC

Le concepteur de l'analyseur fournit une description de la grammaire du langage ciblé dans un fichier source dit
programme YACC.

Le générateur YACC vérifie la syntaxe du programme ensuite produit un code source dans langage cible contenant la
fonction d'analyse par défaut nommée YYPARSE()

Fonctionnement global de YACC

 Complément : La forme générale du programme source YACC

Le fichier source d'un programme YACC se compose de 3 sections délimitées par %% :

- Déclarations : regroupe les déclarations nécessaires pour les actions de l’analyseur cible et pour la section des
règles de traduction

- Règles de production : spécifie les règles de production de la grammaire et les actions sémantiques sous forme
d'instructions à exécuter lors de la réduction avec chaque règle (notamment l'action réduire de LALR(1))

- Sous programmes utilisateurs  : regroupes toutes les fonctions et procédures (méthodes si POO) que le
concepteur définies pour le bon fonctionnement de son analyseur. Cette section peut être vide (pour intégrer
l'analyseur comme un module dans une autre application) ou contient la fonction main() qui invoque la fonction
yyparser() qui a son tours invoque la fonction yylex() (l'analyseur lexical)

54
a) Les différentes parties d'un programme source YACC

Le programme source de YACC contient la définition de l'analyseur SYNTAXIQUE qui doit être générée :

- La définition des unités lexicales (tokens) et des symbole terminaux en précisant l'axiome
- Les règles de production de la grammaire dans le forma pro-BNF 
- Éventuellement un ensemble d'instructions, devant chaque règle, à exécuter lors de la réduction par la règle
- Les instructions, fonctions et sous programmes utilisables pour la partie à contrôler par programme de
l'analyseur

i Section : déclaration

 Fondamental : Les types de déclarations

C'est une section obligatoire par laquelle doit commencer le programme. Elle contient 3 types de déclarations :

- Le bloc littéral :

- Commence obligatoirement par "%{" et se termine par "%}" et contient les déclarations globales
(identifiants, structure de données, fonction / méthodes...) .
- Les déclarations du bloc littéral sont écrites dans le langage cible de l'analyseur et sont recopiées telles
quelles dans le fichier de sortie "analyseur.cible".

- Les définitions :

- Si des définitions existent, ce bloc se place après le bloc littéral


- Contient des déclarations utiles pour le programme YACC lui-même :

- Définition de l'axiome : mot clé %START


- Définitions des unités lexicales ou terminaux  : mot clé %TOKEN
- Définition de la priorité et associativité des terminaux : %LEFT %RIGHT
Définition du type de donnée à associée aux valeur des unités lexicale : mot clé %union

 Exemple

1 %{
2 #include <stdlib.h> /* Dloc déclaration */
3 #include <math.h>
4 %}

55
5
6 %token chiffre PLUS /* Définition des terminaux représentant les unités lexicales chiffre([0-
9]dans Lex) et + */
7 %left PLUS /* Le termoinal PLUS est associatif à gauche */
8 %start Z /* Le symbole Z est l'axiom de la gramamire */

ii Section : règles deproduction

 Fondamental : Règle de production et actionsS

Section obligatoire ayant une forme tabulaire dont chaque ligne contient une règle de production délimitée par un  ";"
et contient deux colonnes séparées par un espace (blanc):

- Les règles de production : Formée par le symbole MGP et la partie MDP écrite dans une syntaxe spécifique à
YACC. LE MGP est séparé de ces MDP de  " :" et ses MDP sont séparée par des "|". Les règles de
productions ayant des MGP différents sont séparée par un " ;"
- Les actions  : portion de programme écrite dans le langage cible délimitée par des " { }" traduisant ce que
l'analyseur LALAR(1) produit ne peut pas contrôler. Cette partie peut être vide si le concepteur n'a rien à
contrôler ou généralement des actions sémantiques sont insérées.
Les actions peuvent s’insérer entre deux symbles d'un même MDP (pas toujours à la fin)

 Exemple

1 %%
2
3 E : X PLUS {printf("un MDP vient d'être reconnu ");}; /*1. E c'est l'axiome car il est en
prmeier s'il n'est pas
4 déjà déclaré par %start
5 2. L'action consiste à afficher un
message */
6
7 X : E {prontf("Action inserer entre deux symboles d'un MDP");} X /* Pas d'action après
reconniassance de X
8 | M2 ;
9
10 M2 : id PLUS id {$$=$1+$3;} ; /* l'action calcule lasoome entre les valeur des unités
lexicales du terminal id
11 %%

iii Section : sous-programmes

 Fondamental : Fonctions utilisateurs

Section optionnelle que le concepteur peut laisser vide. Elle contient l'ensemble des fonctions (méthodes) que le
concepteur désire ajouter à l’analyseur cible tel que le programme principal ou des appels des fonctions de diverses
bibliothèques.

 Exemple

1 %%
2 main() {
3
4 yyparser(); // invocation de l'analyseur LALR(1) de la grammaire qui lui invoque en interne
yylex()
5
6}

56
Le programme YACC

1.6.2. Le programme YACC

 Complément : Exemple d'un programme YACC

Le programme YACC suivant génère l'analyseur LALR(1) de la grammaire suivante :

E→E+T|T

T→T*F|F

F → (E) | chiffre

En plus il effectue le calcule de la valeur de l'expression analyser (l'action sémantique)

1 %{
2 #include <ctype.h>
3 %}
4
5 %token chiffre
6
7 %%
8 Ligne : Expr '\n' { printf("%d \n", $1); }
9
10 Expr : Expr '+' Terme { $$ = $1 + $3; }
11 | Terme
12 ;
13 Terme : Terme '*' Facteur { $$ = $1 * $3; }
14 Terme | Facteur
15 ;
16 Facteur : '(' Expr ')' { $$ = $2; }
17 | chiffre
18 ;
19
20 %%
21 main()
22 {
23 yyparse();
24 }
25
26 yylex()
27 {
28 int c; c = getchar();
29 if (isdigit(c)) { yylval = c – '0'; return chiffre ;}
30 return (c);
31 }
32
33 yyerror() {}

La valeur des chiffres sont retournée par l’analyseur lexical (via la variable commune yylval qui est mappée avec $i
selon les mdps) définie dans le même programme par la fonction yylex(). Cette fonction est invoquée
automatiquement par yyparser()

La fonction yyerror() est utilisée pour positionner l'erreur syntaxique lorsque l'analyse échoue. Elle est aussi invoquée
automatiquement par yyparser() lors de l'erreur syntaxique (c'est au concepteur d'écrire les instructions adéquates)

*  *

57
Le programme YACC

Dans la partie 3 du ce chapitre 2, nous avons abordé la méthode d'analyse syntaxique ascendante et les différentes
techniques utilisées pour concevoir et implémenter un tel analyseur.

Le principe de l’analyse ascendante est de partir de la chaîne d'entrée et tenter de retrouver l'axiome de la grammaire
en application des dérivations inverses appelées réductions (remplacer le mdp d'une production par son mgp).

Il existe deux catégories de de méthodes d’analyse ascendantes :

1. Analyseur par précédence : elle se base sur le calcul de relations de précédence

- Précédence d'opérateurs : couvre uniquement un faible spectre des grammaires vue ces conditions très
restrictives. Il se base sur des relations de précédence entre les symboles opérateurs (uniquement des
grammaires d'opérateur)
- Précédence simple : généralisation de l'analyse par précédence pour couvrir d'autre type de grammaire
avec moins de conditions. Il se base sur 3 relations de précédence entre tout les symboles d'une
grammaire.
- Précédence faible  : une analyse plus souple que l'analyse par précédence simple qui se base sur
uniquement deux relations de précédence au lieu de trois.

2. Analyseur contextuel (LR)  : une analyse qui couvre un large spectre de grammaires car elle est moins
restrictive que les l'autre catégorie ou par rapport à l'analyse descendante. Il se base sur la reconnaissance
des contextes des productions.

Nous avons présenté particulièrement l'analyse contextuelle LR (left to right scanning using Rightmoust reductions)
car c'est la technique la plus utilisée par les outils de génération d'analyseurs syntaxiques (YACC) au coté de
l'analyse LL avec descente récursive (JAVACC).

Le principe des analyseurs LR est de construire un AFD reconnaissant les contextes des productions des
grammaires. Un contexte d'une production est un couple (θ,ω) tel qu'à une étape d'analyse l'analyseur aurait déjà
reconnue (dans sa pile) θ et il reste ω à reconnaître.

Il existe 2 Algorithmes pour construire cet AFD :

1. Technique des contextes  : calcule des contextes de chaque production de la grammaire ensuite construit
l'AFD qui les reconnaîtra
2. Techniques des ITEMs : automatisable et utilisée par les outils existant sur le marché. Elle passe par le calcul
de la collection canonique des ensembles d'ITEMs. Chaque ensemble d'item représente un état de l'AFD. Un
item d'une production représente le contexte (θ,ω) de la production à une étape d'analyse
tel que θ = CONTENU_Pile.ω1 et ω=ω2.SUIVANT(A) .

Le calcul de la collection des ensembles d'items se base sur deux opérations :

1. La fermeture d'un ensemble d'items : consiste à regrouper, pour chaque item de l'ensemble, tous les items
engendrés par les productions dont le MGP est le non terminal immédiatement à droite du point dans cet item
(le début du contexte droit de l'item concerné par la fermeture).
Fermeture} ( )= tel que est une production de la grammaire.
Chaque ensemble calculée par la fermeture représente un état de l'AFD.
2. La transition entre un état et un symbole : GOTO (I,X) : consiste à avancer le point de l'item d'un symbole
(passer le point après X) et calculer la fermeture de l'item ainsi obtenu. GOTO} (I,X)= FERMETURE (
) tel que

58
Le programme YACC

La partie 3 présente 3 algorithmes pour calculer la collections des items qui servira à la construction de al table
d'analyse LR :

1. SLR(1) : elle se base sur les items LR(0) qui prennent en compte uniquement les MDP (le contexte gauche
uniquement), d'où la table d'analyse est compacte et l'analyseur ne couvre pas une grande classe de
grammaires
2. LR(1) : elle se base sur les items LR(1) qui prennent en compte les MDP (le contexte gauche) et les symboles
de prévision (le début du contexte droit), d'où la table d'analyse est plus grande et l'analyseur couvre une
classe de grammaires plus large.
3. LALR(1) : elle se base sur le regroupement des ensembles d'items LR(1) qui ont le même cœur (le contexte
gauche) et les symboles de prévision (le début du contexte droit), d'où la table d'analyse est compact telle que
SLR(1) et l'analyseur couvre une classe de grammaires assez large. Elle est utilisée par les outils de
génération d'analyseur tel que YACC.

59
Conclusion

L'analyse Syntaxique est l'étape de la compilation qui permet de vérifier la conformité du code source écrit par le
programmeur à la syntaxe du langage utilisé. Ce langage est décrit par une grammaire de type 2. Les mots du
langages peuvent donc être vérifiés et/ou reconnus par un automate à pile qui permet de recalculer l'arbre syntaxique
du mot en appliquant les règles de production de la grammaire qui décrit le langage. Ce dernier est composé des
éléments suivants:

1. Une tête de lecture du flot d'entrée : suite d'unités lexicales renvoyées par l'analyseur lexical à la demande de
l'analyseur syntaxique
2. Une pile d'analyse : la mémoire de l'automate à pile où sont empiler es symboles des différentes règles de
production de la grammaires qui servent construire l'arbre syntaxique du flot d'entrée.
3. Une table d'analyse : la matrice qui permet à l'automate de choisir l'action à entreprendre, à savoir avancer
dans le flot en demandant une autre unité lexicale ou/et agir sur la pile (dépiler et/ou empiler).

Si l'automate arrive à la fin du flot d'entrée avec une pile vide alors le flot d'unités lexicales est reconnu conforme à
syntaxe du langage et l'historique de la pile révèle son arbre syntaxique. Dans le cas contraire, si l'automate n'arrive
pas à la fin du flot et ne trouve pas d'action à entreprendre dans sa table alors le flot d'unités lexicales est signalé non
conforme à syntaxe du langage et l'historique de la pile révèle l'endroit de l'erreur syntaxique.

La conception de l'analyseur revient à concevoir sa table d'analyse. Il existe deux méthodes majeures d'analyse qui
sont :

- L'analyse descendante : Consiste à démarrer de l'axiome de la grammaire et essayer de retrouver le mot en


effectuant des dérivations en appliquant les règles de production de la grammaire. Cette méthode possèdent
deux techniques d'implementaiton à savoir l'analyse LL ( Left to right scanning using the Leftmost derivation)
par table prédictive et l'analyse LL par descente récursive.
- L'analyse ascendante  : Consiste à démarrer du mot et essayer de retrouver l'axiome de la grammaire en
effectuant des dérivations inverses dites réductions en appliquant les règles de production de la grammaire.
Cette méthode possèdent deux techniques d'implementaiton à savoir l'analyse par précédences et l'analyse
par contextes dite LR (left to right scanning using Rightmoust derivation in reverse -reductions- ). Cette
dernière est la plus utilisée par les produits du marché.

60