Vous êtes sur la page 1sur 10

Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Chapitre 3 Analyse syntaxique


1) Introduction
C’est la deuxième étape de la compilation d'un programme. Le rôle d’un analyseur syntaxique
(souvent appelé parser) est de vérifier la conformité du programme source écrit dans un
langage L1 à la syntaxe du langage L1 (exprimée à l’aide d’une grammaire hors contexte G)
et de produire (en sortie) un arbre syntaxe dont les feuilles sont des tokens produits par
l'analyse lexicale.
Ils existent plusieurs méthodes d’analyse, ce cours porte sur certaines méthodes descendantes
et méthodes ascendantes et la. Une analyse syntaxique repose sur une grammaire hors
contexte (et un automate à pile) et la suite de token codés retournée par l’analyseur lexical.
Certaines grammaires posent problème par leur ambiguïté et/ou leur récursivité à gauche et/ou
leur non factorisation, notions que nous allons rappelées.
2) Concepts de base
2.1 Ambiguïté
Exemple :soit G EE+E/E*E/(E)/idf/cstent
Pour lever l'ambiguïté, on considère les priorités classiques des opérateurs et on obtient la
grammaire G’ équivalente à G avec les hypothèses suivantes
* .> +
+ .> +
* .> *
Autrement dit * et + récursif à gauche et * est plus prioritaire que +
EE+T/T
TT*F/F
F(E)/idf/cstent

2.2 Récursivité à gauche


G est récursive à gauche s’il existe des règles de production de G est sous forme :
(1) AAα ou (2) ABα BAβ

Il existe deux types de récursivité gauche la récursivité directe (RGD) dite également
immédiate et la récursivité indirecte (RGIND) appelée également générale.

2.2.1 Récursivité gauche directe

1 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

G est récursive à gauche si une des règles de production de G est sous forme :
AAα
Elimination de ce type de récursivité
Récrire les règles de type AAa1/…Aan/B1…/Bn avec Bi…ne commencent pas par A
En AB1A’/…/ Bn A’
A’ a1A’/…/anA’/

Exemple la grammaire G’ est RGD

G’’ équivalente à G’ sans RGD s’écrira :


ETE’
E’+TE’/
TFT’
T’*FT’/
F(E)/idf/cstent

2.2.2 Récursivité à gauche indirecte


G est récursive à gauche si une des règles de production de G est sous forme :
AG *Aa
La solution est de passer d’une grammaire RGIND à une grammaire RGD puis éliminer la
récursivité gauche directe des nouvelles règles de production.
Pour ce faire il faut ordonner les non terminaux et faire une suite de substitution selon
l’algorithme qui réécrit une grammaire algébrique propre récursive à gauche G en une
grammaire G’ sans récursivité à gauche, tq. LG = LG′ .

2.2.3 Algorithme de suppression de récursivité gauche


La grammaire G doit être propre, G doit etre sans cycle ni ε-production

Ordonner les Ai ∈ Vn .
Pour i de 1 à n faire
{
Pour j de 1 à i − 1 faire
{
Si Ai  Aj α existe, la remplacer par : Ai β1 α / β2 α /… / βn α où Aj β1 / β2 /… / βn
}
Eliminer la récursivité directe des Ai-productions
}

2 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Exemple :
G RINDG G RDG G non récursive

S  Aa / b S  Aa / b S  Aa / b
A  Ac | Sd | c A  Ac/Aad/bd/c A  bdA’/cA’
A’  cA’/adA

2.3 Factorisation à gauche


Une grammaire est non factorisée si une des règles de production de G est écrite sous cette
forme
A αA1/ αA2/ …/αAn/β1/β2 /…/βn (1)

La règle (1) est réécrite en deux règles équivalentes :


AαA’/ β1/β2 /…/βn
A’ A1/…/An

Pour factoriser une grammaire il faut répéter l’opération pour toutes les règles de production
écrites sous cette forme
Exemple : AabC/aAB/caF AaA’/caF
A’ bC/AB
2.4) Notion d’ensemble début et suivant
Prenons la grammaire Gexp suivante comme exemple illustratif
ETE’
E’+TE’/
TFT’
T’*FT’/
F(E)/idf
a) Construction des ensembles début
Pour toute chaîne X composée de symboles terminaux et non-terminaux, on cherche
l'ensemble de tous les terminaux qui peuvent commencer une chaîne qui se dérive de X
Pour toutes les productions faire
1. Si X  est une production de la grammaire alors ajouter  à debut(X)
2. Si X a est une production de la grammaire et a est un terminal alors debut(X) = {a}.

3 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

3. Si XY1Y2….Yn est une production de la grammaire (avec Y i symbole terminal ou non-


terminal) alors
o ajouter les éléments de debut(Y1) sauf  à debut(X)
o s'il existe j (j=2..n) tel que pour tout i=1..j-1 on a   debut(Yi), alors ajouter les
éléments de debut(Yj) sauf  à debut(X)
o si pour tout i=1..n   debut(Yi), alors ajouter  à debut(X)

Exemple : reprendre Gexp


Debut(E)= debut(TE’)=debut-ε(T)
Debut(E’)=debut(+TE’)  debut(ε)=debut-ε (+)  {ε} = {+, }
Debut(T)=debut-ε (F)={(,idf}
Debut(F)=debut( (E))  debut(idf)= debut-ε( ()  debut(idf)={(,idf}
Debut(T’)=debut(*FT’) debut()=debut-ε (*)  {ε} = {+, }
Debut(E)={(,idf} Debut(E’)={+, } debut(T)={(,idf} debut(T’)={*, } debut(F)={(,idf}

b) Construction des ensembles SUIVANT


Pour tout non-terminal A, on cherche SUIVANT(A) : l'ensemble de tous les symboles
terminaux a qui peuvent apparaître immédiatement à droite de A dans une dérivation :
Pour toutes les productions faire
1. Si S est axiome de la grammaire alors ajouter un marqueur de fin de chaîne (symbole #
par exemple) à SUIVANT(S)
2. S'il existe une production AB et B est un non-terminal, alors ajouter DEBUT()
sauf  à SUIVANT(B),
3. S'il existe une production AB alors ajouter SUIVANT(A) à SUIVANT(B)
4. S'il existe une production AB avec   DEBUT (), alors ajouter SUIVANT(A) à
SUIVANT(B)
Exemple : reprendre Gexp
Suivant(E)= {#}debut-ε())={#,)}
Suivant(E’)= Suivant(E)= {#,)}
Suivant(T)=debut-ε (E’)  Suivant(E’)= {+,#,)}
Suivant(T’)=suivant(T)  suivant(T’)=suivant(T)={+,#,)}
Suivant(F)={*,+,#,)}

4 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

3) L’analyse descendante

Principe : construire l'arbre de dérivation du haut (la racine, c'est à dire l'axiome de départ)
vers le bas (les feuilles, c'est à dire les unités lexicales). Cette méthode cherche à construire
une dérivation gauche directement a partir du symbole initial et donc cherche a construire un
arbre de dérivation a partir de la racine avec une exploration en profondeur d'abord de gauche
a droite.

Pour cela, l'analyseur doit pouvoir décider, en s'aidant éventuellement avec les k symboles en
entrée, quelle est la prochaine règle de production à dériver dans la dérivation gauche que l'on
reconstruit.
Les analyseurs à étudier nécessite une grammaire LL(1).

3.1) Grammaire LL(1)


On appelle grammaire LL(1) une grammaire pour laquelle la table prédictive n'a aucune case
contenant plus d’une règle à appliquer (et donc plus d’une dérivation).
"LL(1)" : L Left to right scanning :on parcourt l'entrée de gauche à droite
L Leftmost derivation on utilise les dérivations gauches
(1) un seul symbole de prévision est nécessaire à chaque nouvelle décision d’action
d'analyse à appliquer.
a) Définition 1
Formellement, une grammaire LL(1) est une grammaire dont les règles de production
vérifient les conditions suivantes :
1. si A et B alors debut( )  debut(B) = 
2. si A et B alors soit  G+  soit G+ 
3. si A et B et G+  alors debut( )  suivant(A)=
b) Définition 2
Une grammaire LL(1) est une grammaire pour laquelle la table prédictive n'a aucune
case contenant plus d’une règle de production à appliquer.
Remarques
1. Une grammaire ambigüe ou récursive à gauche ou non factorisée à gauche n'est pas
LL(1).
2. Une grammaire factorisée qui est ni ambigüe ni récursive à gauche n’est pas forcement
LL(1).

5 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

3.2) Construction de la table prédictive LL(1)


La table d'analyse est un tableau Tab à deux dimensions qui indique pour chaque symbole
non-terminal A et chaque symbole terminal a ou symbole # la règle de production à appliquer.
1. La première ligne contient tous les token de Vt et la première colonne tout les non
terminaux de Vn
2. Pour chaque production A
o pour tout a (avec a≠ )  debut() alors mettre A dans la case Tab[A,a]
o si   debut(), alors pour chaque b  SUIVANT(A), mettre A dans Tab[A,b]
3. Chaque case Tab[A,a] vide est une erreur syntaxique

Exemple
Avec Gexp, on obtient la table

idf + * ( ) #
E

E'

T
T'

F idf

3.3) Analyseur syntaxique descendant


Les deux analyseurs à étudier sont l’analyseur à base de la table prédictive LL(1) et
l’analyseur descente récursive.

3.3.1) Analyseur utilisant la table prédictive LL(1)


L’analyseur utilise la table de prédictive pour savoir si un mot w est généré par la grammaire
et implémente l’algorithme 1. La construction de l’analyseur suit les étapes suivantes :
Augmenter la grammaire en ajouter une règle Zaxiome # avec # token fin Z  Vn
Construire la table prédictive LL(1) pour la grammaire
Implémenter la table prédictive LL(1) et l’algorithme 1.
Algorithme 1

6 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Données : chaine de token W qui se termine par le token fin #, une pile, la table d'analyse
Tab et un pointeur ptr sur 1er token de W
Soit X le symbole en sommet de pile
Soit Tk le token pointé par ptr

Repeter
Si X est un non terminal alors
Si Tab[X,Tk]=XY1…Yn alors
debut
depiler X
empiler Yn puis Yn-1 puis ...puis Y1
sinon
ERREUR
Finsi
Sinon
Si X= # alors
Si Tk= # alors ACCEPTER
Sinon ERREUR
Finsi
Sinon
Si X=Tk alors
depiler X de la pile
avancer ptr
Sinon
ERREUR
Finsi
Finsi
Finsi
jusqu'à ERREUR ou chaine acceptée

Exemple :
Reprendre la grammaire Gexp et analyser la chaine W=idf+idf*idf# avec # marque de fin de
chaine.

7 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Pile Entrée Action


# idf+idf*idf# empiler l’axiome E
#E idf+idf*idf# Depiler E et empiler l’image mirroir de ETE’
# E'T idf+idf*idf# Depiler T et empiler l’image mirroir de TFT’
# E'T'F idf+idf*idf# Depiler F et empiler l’image mirroir de Fidf
# E'T'idf idf+idf*idf# Depiler idf et avancer ptr
# E'T' +idf*idf# Depiler T’ et empiler l’image mirroir de T’Ɛ
# E' +idf*idf# Depiler E’ et empiler l’image mirroir de E’+TE’
# E'T+ +idf*idf# Depiler + et avancer ptr
# E'T idf*idf# Depiler T et empiler l’image mirroir de TFT’
# E'T'F idf*idf# Depiler F et empiler l’image mirroir de Fidf
# E'T'idf idf*idf# Depiler idf et avancer ptr
# E'T' *idf# Depiler T’ et empiler l’image mirroir de T’*FT’
# E'T'F* *idf# Depiler * et avancer ptr
# E'T'F idf# Depiler F et empiler l’image mirroir de Fidf
# E'T'idf idf# Depiler idf et avancer ptr
# E'T' # Depiler T’ et empiler l’image mirroir de T’Ɛ
# E' # Depiler E’ et empiler l’image mirroir de E’Ɛ
# # Chaine acceptée

W  L(G)

3.3.2) Analyseur basé sur une analyse récursive descendante


Dans ces cas, l'algorithme d'analyse syntaxique devient une traduction de l'écriture de la
grammaire. On utilise pour cela autant de procédures récursives qu'il y a de non terminaux.
Pour être efficace la grammaire doit être LL(1) et le langage utilisé doit supporter la
récursivité

Pratiquement, chaque non terminal A de la partie gauche d’une règle A α est traduite en
procédure A()
Debut
Fin

8 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Le corps de la procédure est constitué par la traduction de la partie droite α : tout terminal doit
être comparé au sommet de pile et tout non terminal est traduit en un appel à la procédure non
terminal.
Exemple
Reprenons la grammaire Gexp augmentée de ZE # avec E axiome de Gexp et # token
exprimant la marque de fin.
Procedure Z()
Tokcour=lex();
Si tokcour=’#’ alors ecrire (‘chaine vide’)
Sinon
debut
E();
Si tokcour=’#’alors ecrire(‘chaine acceptée’)
Sinon erreur
Fin ;
Fin;

Procedure E()
debut
T() ;
E’()
Fin ;
Procedure E’()
Si tokcour=’+’ alors
Debut
Tokcour=lex() ;
T() ;
E’() ;
fin
Sinon
Si tokcour <> # et tokcour<>’)’ alors erreur ;
fsi
Fin ;

9 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021


Université M’hamed Bougera de Boumerdes - Faculté des sciences - Département d’informatique

Procedure T’()
Si tokcour=’*’ alors
Debut
Tokcour=lex() ;
F() ;
T’()
Fin ;
Si tokcour <> # et tokcour<>’)’ et tokcour<>’+’ alors erreur
fsi
Fin ;

Procedure T()
debut
F() ;
T’()
Fin ;
Procedure F()
Si tokcour=’(’ alors
Debut
Tokcour=lex()
E() ;
Si tokcour=’)’ alors tokcour=lex()
sinon erreur /*module traitement erreur*/
Fin ;
Sinon si tokcour=idf alors tokcour=lex()
Sinon erreur /*module */
Fin ;

Bibliographie
A. Aho, R. Sethi, J. Ullman . Compilateurs, principes, techniques et outils. PEARSON
Education. 2007

H. Drias, la compilation. OPU. 1988

10 Ce document n’est qu’un support du cours compilation 3eme SI 2020/2021

Vous aimerez peut-être aussi