Vous êtes sur la page 1sur 27

SAOUDI Lalia Analyse Syntaxique 2007/2008

III. Analyse syntaxique :


Le rôle principal de l’analyse syntaxique est de vérifier si l’écriture du programme source conforme
avec la syntaxe du langage à compilé. Cette dernière est spécifiée à l’aide d’une grammaire hors
contexte.
Il existe plusieurs méthodes d’analyse appartenant à l’une des deux catégories qui sont l’analyse
descendante et l’analyse ascendante.
Dans l’analyse descendante nous essayons de dériver à partir de l’axiome de la grammaire le
programme source.
D’une façon opposée, l’analyse ascendante établit des réductions sur les chaines à analyser pour
aboutir à l’axiome de la grammaire
1- Grammaires et Arbres de dérivation
On a déjà vu les langages réguliers, qui s’expriment à l aide d’expressions régulières, Mais la plupart
du temps, les langages ne sont pas réguliers et ne peuvent pas s’exprimer sous forme d’ une ER.
Par exemple, le langage des systèmes de parenthèses bien formés ne peut pas s’ exprimer par une ER.
On a donc besoin d’un outil plus puissant : les grammaires.
1.1 Grammaires
Exemples : une expression conditionnelle en PASCAL est : if ( expression) then instruction ;
Par exemple : if (x<10) then a := a + b;
Il faut encore définir ce qu’est une expression et ce qu’est une instruction :
On distingue les
- symboles terminaux : les lettres du langage (if ,then )
-symboles non terminaux : les symboles qu’il faut encore définir (ceux en italique dans les exemples)

Définition : Une grammaire hors contexte (context free grammar, CFG) est un quadruplet
G = (T,NT, S, P) où :
– T est l’ensemble des symboles terminaux du langage. Les symboles terminaux correspondent aux
mots découvert par l’analyseur lexical « unité lexicale ».if ,else sont des terminaux.
– NT est l’ensemble des symboles non-terminaux du langage. Ces symboles n’apparaissent pas dans le
langage mais dans les règles de la grammaire définissant le langage, ils permettent d’exprimer la
structure des règles grammaticales.
– S ϵ NT est appelé l’élément de départ de G (ou axiome de G). Le langage que G décrit (noté L(G))
correspond `a l’ensemble des phrases qui peuvent être dérivées `a partir de S par les règles de la
grammaire.
– P est un ensemble de production (ou règles de réécriture) de la forme N α1 α2… αn avec
αi ϵ (T UNT)*. C’est à dire que chaque élément de P associe un non terminal à une suite de terminaux
et non terminaux. Le fait que les parties gauches des règles ne contiennent qu’un seul non terminal
donne la propriété ”hors contexte” `a la grammaire.
Exemple G = (T,NT, S, P) avec
VT = { il, elle, parle, est, devient, court, reste, sympa, vite }
VN ={ PHRASE, PRONOM, VERBE, COMPLEMENT, VERBETAT, VERBACTION }
S = PHRASE
P = { PHRASE PRONOM VERBE COMPLEMENT
PRONOM il / elle
VERBE VERBETAT / VERBACTION
VERBETAT  est / devient/ reste
VERBACTION  parle / court
COMPLEMENT  sympa / vite }

Quelques éléments grammaticaux de Pascal


Voici quelques règles correspondant à un sous-ensemble de Pascal :
programme  en-tête de prog. Block

Page
17
SAOUDI Lalia Analyse Syntaxique 2007/2008

en-tête de prog.  program ident instruction-list  instruction | instruction ; instruction-list


block  declaration-list instruction-list instruction  begin instruction-list end ...
1.2 Arbre de dérivation syntaxique :
On appelle dérivation l application d’une ou plusieurs règles à partir d’un mot de(VT U VN) +
On notera - une dérivation obtenue par application d’une seule règle de production, et * une
dérivation obtenue par l’application de n règles de production où n => 0.
Sur la grammaire de l’exemple :
PHRASE SUJET VERBE COMPLEMENT *elle VERBETAT sympa
PHRASE * il parle vite
PHRASE *elle court sympa
Remarque : il est possible de générer des phrases syntaxiquement correctes mais qui n’ont pas de sens.
C’est l’analyse sémantique qui permettra d’éliminer ce problème.

Définition :Un arbre de dérivation syntaxique pour la grammaire G de racine Sϵ NT et de feuilles


wϵT* est un arbre ordonné dont la racine est S, les feuilles sont étiquetées par des terminaux formant
le mot w et les nœuds internes par des non terminaux tels que Y est un nœud interne dont les p fils
sont étiquetés par les symboles a1….ap est une production de P
Dérivations gauches et droites :

 Dérivation gauche consiste à réécrire le symbole non-terminal le plus à


gauche à chaque étape.
 Dérivation droite consiste à réécrire le symbole non-terminal le plus à
droite à chaque étape.
Exemple :
Soit la grammaire ayant S pour axiome et pour règles de production
P ={ S aT b /c
T cSS /S}
Un arbre de dérivation pour le mot accacbb est :
SaTbacSSbaccSbaccaTbbaccaSbbaccacbb ( dérivation gauche)
Ou S aTb  acSSb acSaTbbacSaSbb acSacbb accacbb (dérivation droite)
Ces deux suites différentes de dérivations donnent le même arbre de dérivation.
1.3 Ambiguïté

Si une phrase d’un langage L(G) possède deux arbres de dérivations distincts,
alors cette phrase est ambiguë et la grammaire associée est elle-aussi ambiguë.
Exemple d’une grammaire ambiguë
La grammaire de l’expression suivantes est ambiguë ; il ya deux arbres syntaxiques
possibles pour x+x*x
E  E+E / E*E /x
2. ANALYSE DESCENDANTE :
L’analyse descendante, dans laquelle on construit l’arbre en descendant de la racine vers
les feuilles. Cette analyse correspond à un parcours descendant gauche (parce qu’on lit de
gauche à droite). Il s’agit de deviner à chaque étape quelle est la règle qui sert à engendrer le
mot que l’on lit.
Les méthodes déterministes les plus efficaces connues à l’heure actuelle sont : l’analyse
prédictive et la descente récursive ; lorsque le langage d’implémentation dispose de la

Page
18
SAOUDI Lalia Analyse Syntaxique 2007/2008

récursivité, il est souhaitable d’utiliser la descente récursive dans le cas contraire, l’analyse
prédictive affirmera son existence.

2.1-Analyse prédictive :
Cette analyse utilise une table appelée table prédictive, les lignes de cette table sont
indicées par les symboles non terminaux du langage, par contre les colonnes sont indicées par
les symboles terminaux et le symbole #.
Les cases de la table contiennent éventuellement des règles de la grammaire, pour la
construction de cette table deux notions qui sont suivant et début sont nécessaires.
Intuitivement le DEBUT d’une chaine de symboles de la grammaire contient tous les
terminaux et éventuellement ϵ si la chaine est vide qui peuvent apparaitre en tête d’une
chaine de terminaux dérivée à partir de la chaine initiale.
Le SUIVANT d’un Non terminal est un ensemble comportant tous les terminaux ( #
l’indicateur de la fin de chaine inclus) qui peuvent suivre ce Non terminal dans toute chaine
de symboles .
2.1.1 Calcul de DEBUT(X)
Pour toute chaine composée de symboles terminaux et non_terminaux, on cherche PREMIER( α)
l’ensemble de tous les terminaux qui peuvent commencer une chaine qui se dérive de α .
1-si X est un terminal alors DEBUT(X)=X
2- DEBUT (X) = {a | X  a}  {FIRST(Yi) | X  Y1,..Yk et Y1,..,Yi-1 * } 
{ si X   ou si X  Y1,..Yk et   FIRST(Yi)  Yi
2.1.2 Calcul de SUIVANT(X)
Pour tout non_terminal A, on cherche SUIVANT(A), l’ensemble de tous les symboles terminaux a
qui peuvent apparaitre immédiatement à droite de A dans une dérivation
SUIVANT(X)= DEBUT () si Y  X et  /* 
SUIVANT (Y) si Y  X ou (Y  X et   DEBUT ()) 
{#} si X = S (l‘axiome).
Exemple : p={ SBa B cP / bP /P/ P dS }
S B P
Début c,b,a,d c,b,d, d
Suivant #, a a a

2.1.3 Construction de la table d'analyse


Pour chaque production de la forme A   où faire
si a  DEBUT() alors insérer A   dans TableAnalyse[A, a]
Pour chaque production de la forme A  ϵ insérer A  ϵ dans TableAnalyse[A, b]
pour chaque b  SUIVANT(A).
Exemple sur la grammaire:

E  TE’

Page
19
SAOUDI Lalia Analyse Syntaxique 2007/2008

E’  +TE’ | 
T  FT’
T’  *FT’ | 
F  (E) | Id
FIRST(E) = FIRST(T) = FIRST(F) = { (, Id}
FIRST(E') = {+,}
FIRST(T') = {*,}
FOLLOW(E) = FOLLOW(E') = { ), #}
FOLLOW(T) = FOLLOW(T') = {+,),#}
FOLLOW(F) = {+, *, ), #}
Le tableau obtenu est le suivant:

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)

2.1.4 Analyseur syntaxique


Maintenant qu’on a la table, comment l’utiliser pour déterminer si un mot m donné est tel que
S*m ? On utilise une pile.
Algorithme
données : mot m terminé par $, table d’analyse M Initialisation de la pile : S # et un pointeur ps sur
la 1ére lettre de m.
répéter
Soit X le symbole en sommet de pile
Soit a la lettre pointée par ps
Si X est un non terminal alors
Si M[X, a]= X  Y1 ….Yn alors
Enlever X de la pile
Mettre Yn puis Yn-1 puis ….. puis Y1 dans la pile
Emettre en sortie la production X  Y1 ….Yn
Sinon (case vide dans la table)
ERREUR
Finsi
Sinon
Si X = # alors
Si a = # alors ACCEPTER
Sinon ERREUR
Finsi

Page
20
SAOUDI Lalia Analyse Syntaxique 2007/2008

Sinon
Si X =a alors
Enlever X de la pile
Avancer ps
sinon
ERREUR
finsi
finsi
finsi
jusqu’à ERREUR ou ACCEPTER

Exemple : analysez le mot : m= 3 *4 +5 , en utilisant la table prédictive de l’exemple précédent :

On obtient donc l’arbre syntaxique suivant:

Page
21
SAOUDI Lalia Analyse Syntaxique 2007/2008

Donc ce mot n’appartient pas au langage généré par cette grammaire

2.1.5 Grammaire LL(1)

Si la table prédictive est multi définie c à d que si une case occupée par plus d’une règle on dit que la
grammaire n’est pas LL(1) Left-to-right scanning, Leftmost derivation, use 1 symbol lookahea
Définition : Une grammaire G est dite LL(1) si ses règles de production vérifient les conditions
suivantes :

1- Si A α et A β sont deux règles de G alors on doit avoir ou bien

Α*ϵ ou bien β*ϵ mais pas les deux

2-si A α et Aβ sont deux règles de G alors DEBUT(α)∩ DEBUT(β)=Ø

3-si Aα et Aβ sont deux règles de G et si β*ϵ alors SUIVANT(A)∩ DEBUT(α) =Ø

Ces conditions entrainent l’unicité de l’existence d’une règle dans une case de la table prédictive.

Exemple : soit p= { S aAb A cd /c }

Nous avons Premier (S)= {a } , Premier (A)= {c } , Suivant (S)= {# } , Suivant (A)= {b } , ce qui
donne la table d’analyse :

Page
22
SAOUDI Lalia Analyse Syntaxique 2007/2008

Il y a deux réductions pour la case M[A, c], donc ce n’est pas une grammaire LL(1) On ne peut pas
utiliser cette méthode d ‘analyse, pour pouvoir choisir entre la production A cd et la production
A c, il faut lire la lettre qui suit celle que l’on pointe (donc deux symboles de prévision sont
nécessaires).
Conditions nécessaires pour q’une Grammaire Soit LL(1) :

Théorème : Une grammaire ambiguë ou récursive à gauche ou non factorisée à gauche n‘est pas LL(1)
La récursivité à gauche
Une grammaire est récursive à gauche si elle contient un non terminal A tel qu’il existe une dérivation
A  Aα où α est une chaine quelconque.
Elimination de la récursivité à gauche : On peut transformer mécaniquement des grammaires pour
enlever toute récursivité à gauche en autorisant les règles du type A .ϵ

----------

Lorsque la récursivité est indirecte, on déroule les règles jusqu’à ce que l’on rencontre une récursivité directe
et on utilise le même processus :

Exemple :
E  TE’
Soit G la grammaire suivante : E’  +TE’ | 
E- E+T / T  T  FT’
T T* F / F T’  *FT’ | 
F( E) / id
F  (E) | Id
Cette grammaire est récursive à gauche :
Factorisation :

Le bactrack arrive lorsque l’algorithme choisi une mauvaise règle à appliquer. Si l’algorithme
choisissait systématiquement la bonne règle, il n’y aurait jamais besoin de bactracker. C’est à dire que
lorsqu’on aura plusieurs productions pour le même non-terminal qui ont le même préfixe, on va
introduire un nouveau non-terminal pour tous les suffixes suivant ce préfixe, ce qui permettra de
choisir une et une seule règle lorsqu’on veut démarrer par ce préfixe. Par exemple, si on a les règles :

on les remplacera par

Page
23
SAOUDI Lalia Analyse Syntaxique 2007/2008

Conclusion
Si notre grammaire est LL( l) , l’analyse syntaxique peut se faire par l’analyse descendante vue
précédemment . Mais comment savoir que notre grammaire est LL(1) ?
Etant donnée une grammaire
1- la rendre non ambigüe.
Il n’y a pas de méthodes. Une grammaire ambigüe est une grammaire qui a été mal conçue.
2- éliminer la récursivité à gauche si nécessaire
3- la factoriser à gauche si nécessaire
4- construire la table d’analyse
Il ne reste plus qu’a espérer que ça soit LL(1), Sinon il faut concevoir une autre méthode pour
l’analyse syntaxique.
Exemple : grammaire des expressions arithmétiques avec les opérateurs + - / et *
E E+E / E – E / E *E / E/E / (E) / nb
Mais elle est ambiguë. Pour lever l’ambigüité, on considère les priorités classiques des opérateurs et
on obtient ma grammaire non ambigüe :
{E E + T / E – T / T T T * F / T / F / F F  ( E ) / nb }
Après suppression de la récursivité à gauche, on obtient :
{E  TE’
E’  +TE’ |-TE’ | 
T  FT’
T’  *FT’ |/ FT’ | 
F  (E) | nb
Elle est déjà factorisée.

2.2 Analyse par Décente Récursive

Un analyseur par descente récursive est un type d'analyseur descendant dans lequel le programme de
l'analyseur est étroitement lié à la grammaire analysée. Voici les principes de l'écriture d'un tel
analyseur :
1. Chaque groupe de productions ayant le même membre gauche donne lieu à une procédure.
2. Lorsque plusieurs productions ont le même membre gauche, le corps de la procédure
correspondante est une conditionnelle (instruction if ) ou un aiguillage (instruction switch) qui, d'après
le symbole terminal pointé, sélectionne l'exécution des actions correspondant au membre droit de la
production pertinente.
3. Une séquence de symboles S1S2 : : : Sn dans le membre droit d'une production donne lieu, dans la
fonction correspondante, à une séquence d'instructions traduisant les actions reconnaissance de S1 ,
reconnaissance de S2 ,, . . ., reconnaissance de Sn.
4. Si S est un symbole non terminal, l'action « reconnaissance de S » se réduit à l'appel de procédure
S().
5. Si α est un symbole terminal, l'action « reconnaissance de α » consiste à considérer le symbole
terminal de lecture :

Page
24
SAOUDI Lalia Analyse Syntaxique 2007/2008

- s'il est égal à α , faire passer le pointeur sur le symbole suivant.


- sinon, annoncer une erreur (par exemple, afficher α attendu).
L'initialisation de l'analyseur consiste à positionner le pointeur sur le premier terminal de la chaine
d'entrée.
On lance l'analyse en appelant la procédure associée au symbole de départ de la grammaire. Au retour
de cette procédure :
* si le pointeur montre la marque de fin de chaine, l'analyse a réussi,
* sinon la chaine est erronée (on peut par exemple afficher le message : caractères illégaux après une
expression correcte).
Exemple : soit la grammaire :
E  TE’ E’  +TE’ | ε
T  FT’ T’  *FT’ | ε F  (E) | Id
Procedure E( ) begin T( ); Eprime( ); end;
Procedure Eprime( ) begin if entcour = ‘+’ then begin lex( ) ; T( ) ; Eprime( ) ; end; end;
Procedure T( ) begin F( ); Tprime( ); end;
Procedure Tprime( ) begin if entcour = ‘*’ then begin lex( ) ; F( ) ; Tprime( ) ; end; end;
Procedure F( ) begin if entcour = ‘(’ then begin lex( ) ; E( ) ; if entcour = ‘)’ then lex( ) else erreur
end; if entcour = id then lex( ) else erreur; end;
La function lex( ) consiste à fournir la prochaine unite lexical.
Entcour est une variable globale désignant l’entité lexicale courante.
Limitations de l'analyse par descente récursive
La descente récursive est légèrement naïve : elle teste chaque choix de N jusqu'à ce que l'un d'eux
fonctionne. Les méthodes LL(1) sont plus intelligentes : elles prédisent le bon choix directement. La
méthode non-récursive est encore plus efficace car elle utilise des tables et non des tests.
Il faut plusieurs appels avant d'avancer sur un lexème. Cela représente une perte de temps qui peut être
dérangeante. De plus, les tests qui renvoient la valeur False sont en quelque sorte un retour en arrière
sur les lexèmes, ce qui signifie que l'analyse n'est pas réellement déterministe.
Finalement, le traitement des erreurs est quasiment nul. Tout ce que nous sommes en mesure de faire,
c'est de signaler qu'on s'attendait à voir un non-terminal particulier et qu'on a trouvé un lexème
incorrect, avant de devoir purement et simplement abandonner la compilation. Ce n'est réellement pas
pratique pour l'utilisateur.

3. ANALYSE ASCENDANTE :
Principe: construire un arbre de dérivation du bas (les feuilles, les unités lexicales) vers le haut (la
racine l’axiome de départ)
Le modèle général utilisé est le modèle par décalages réductions
- décalage (shift) : décaler d’une lettre le pointeur sur le mot en entrée.
- réduction (reduce) : réduire une chaine par un non terminal en utilisant une des règles de
production.
Nous présentons quatre techniques pour construire la table d’analyse LR pour une grammaire.
Ces méthodes utilisent un programme identique appelé conducteur, cependant le contenu de la table
d’analyse est différent pour chacune des méthodes.
Le programme conducteur :
Programme
Chaine à analyser Table
Conducteur d’analyse
Page
25
SAOUDI Lalia Analyse Syntaxique 2007/2008

Arbre syntaxique

Il utilise une pile dont le contenu spécifie l’état de l’analyse et un vecteur contenant le reste de la
chaine à analyser. Au départ la configuration de l’analyse est la suivante :
S0 a1,a2 …….an #
Etat initial chaine à analyser
Au cours de l’analyse, la configuration varie et devient :
(S0 X1S1X2S2……….. X mSm ai,ai+1,…..an # ) où Sm est au sommet . Chaque Xi est un symbole
de la grammaire et chaque Si est un symbole appelé état , pour passer à la configuration suivante,
l’analyseur consulte la table d’analyse.
La table d’analyse contient deux parties, ACTION et GOTO.
Les types d’action que le simulateur peut rencontrer dans la table sont :
- Décaler ou empiler j ( noté dj )
- Réduire j ( noté rj)
- Accepter ( noté acc)
- Erreur : une erreur est indiquée par une case vide.
Les lignes de la table sont des états de l’automate
Les colonnes sont les symboles de la grammaire avec le #
La case ( sp , ai) indique l’action à entreprendre , si l’action est :
1- Dj : l’analyseur doit empiler l’élément ai ensuite j qui est le numéro de l’état suivant par la
transition j= goto ( sp , ai).
2- Rj : j indique un numéro de règle de la grammaire , à ce moment la partie droite de cette
production apparait au sommet de la pile, il faut substituer la partie droite , par la partie
gauche de la règle, à la suite de cette opération, l’analyseur empile le numéro de l’état de
transition trouvé dans la deuxième partie de la table c.à.d k= goto( spr , A) , où A est le non
terminal apparaissant au sommet de la pile et spr se trouve juste avant A dans la pile
3- Acc , l’analyseur est arrivé à une situation de succés
4- Une case vide : l’analyseur a abouti à un echec.

Algorithme d’analyse LR :
Donnée : une chaine d’entrée w et des tables d’analyse LR .
Résultat : si w est dans L(G), une analyse ascendante de w, sinon, une indication d’erreur
Méthode : Initialement, l’analyseur a S0 en pile, où S0 est l’état initial et w# dans son tampon ,
l’analyseur doit exécuter le programme ci-dessous jusqu’à ce qu’il rencontre soit, ne action accepter
soit erreur.
Initialiser le pointeur source ps sur le premier symbole de w# ;
Répéter indéfiniment début
Soit S l’état en sommet de pile et a le symbole pointé par ps ;
Si action [ S ,a]= décaler S’ alors début
Empiler a puis S’
Avancer ps sur le prochain symbole en entrée
Fin

Page
26
SAOUDI Lalia Analyse Syntaxique 2007/2008

Sinon si action [s,a]= réduire par A β alors début


Dépiler 2 X |β| symboles ;
Soit S’ le nouvel état sommet de la pile ;
Empiler A puis Goto[ S’ , A] ;
Emettre en sortie une identification de la production Aβ ;
Fin
Sinon si action[ S ,a] = accepter alors retourner
Sinon erreur( )
Fin

3.1 Analyseur LR:


L’analyse LR(K) est une technique efficace d’analyse syntaxique ascendante qui peut être utilisée pour
analyser une large classe de grammaire non contextuelle :L : signifie « parcours de l’entrée de la
gauche vers la droite » (left to right scanning of the input », R : signifie « en construisant une
dérivation droite inverse » (constructing a Right most derivation in reverse)et K indique le nombre de
symboles de prévision utilisés pour prendre les décisions d’analyse.
Un certain nombre de raisons rendent l’analyse LR intéressante :
- Les analyseurs LR peuvent reconnaitre toutes les constructions des langages de programmation
décrites par une grammaire non contextuelle.
- La classe des grammaires analysées par les méthodes LR est un sur ensemble strict de la classe
des grammaires LL (1).
- Un analyseur LR peut détecter une erreur de syntaxe aussitôt que possible au cours d’un
parcours de gauche à droite de l’entrée.
La principal inconvénient de la méthode est qu’elle exige de fournir une quantité trop importante de
travail pour construire à la main un analyseur LR pour la grammaire d’un langage de programmation
typique, on a besoin d’un outil spécialisé, heureusement de tels constructeurs sont disponibles-YACC-

Dans cette analyse nous construisons un automate AFD spécifiant les différents états d’avancement
d’analyse.
Un état de l’automate contient un ensemble d’éléments décrivant ce que l’analyse anticipe de
rencontrer à partir de l’instant où l’analyse transite vers cet état
Un élément de cet ensemble est appelé Item LR(0), une fois l’automate élaboré, nous
procédons à la construction de la table d’analyse.
Item LR( 0) :
Un Item LR(0) d’une grammaire G est une production de G avec un point repérant une
position de sa partie droite par conséquent, la production A XYZ fournit les quatre Items :
A.XYZ AX.YZ AXY.Z AXYZ.
La production Aϵfournit uniquement l’Item A.
Intuitivement un item indique la quantité de partie droite qui a été reconnue, à un moment donné.
Par exemple, le premier item ci-dessus indique l’on espère voir en entrée une chaine dérivable depuis
XYZ. Le second Item indique que nous venons de voir en entrée une chaine dérivée de X et que nous
espérons maintenant voir une chaine dérivée de YZ.
Une collection d’ensembles d’items LR(0), fournit la base de la construction des analyseurs SLR.
Pour construire une collection LR(0) nous définissons une grammaire augmentée et deux fonctions,
fermeture (closure) et transition (GOTO).

Page
27
SAOUDI Lalia Analyse Syntaxique 2007/2008

Si G est une grammaire d’axiome S, alors G’, la grammaire augmentée de G, est G avec un nouvel
axiome S‘ et une nouvelle production S’S , la chaine d’entrée est acceptée quand et seulement
quand l’analyseur est sur le point de réduire S’S.
La Fermeture d’un Item LR( 0 )
La closure d’un item [ A α . β] est un ensemble d’items LR (0) déterminé comme suit :
1- L’item LR (0 ) A α . β appartient à la closure.
2- Si [ X α . β] est un item LR( 0) de la closure, si β= BY où B λ est une règle de la
grammaire alors l’item LR(0) [B .λ] doit être ajouté à cette closure.
3- Répéter le pas 2 jusqu’à ce qu’aucun nouvel item LR( 0 )ne soit créé et ajouté à l’ensemble
Exemple 1: considérons la grammaire augmentée des expressions :
E’E
E- E+T / T
T T* F / F
F( E) / id
Si I est l’ensemble formé de l’unique Item [ E’E]alors :Fermeture(I) contient les Items : E’.E

E- .E+T / .T
T .T* F / .F
F.( E) / .id
L’opération transition :
La deuxième fonction utile est GOTO( I,X) où I est un ensemble d’items et X est un symbole de la
grammaire . GOTO( I,X) est définie comme la fermeture de l’ensemble de tous les items A α X. β
tels que A α . Xβ appartienne à I
GOTO( Ii,X)=closure( [A α X. β ])
Exemple2: Si I est l’ensemble des deux Items [E’ E. ], [E E.+ T], alors GOTO( I ,+) consiste
en : EE+. T T.T*F T .F F . (E) F .id
Construction des ensembles d’items
L’algorithme décrit ci-dessous représente la méthode de construction de la collection canonique
d’ensembles d’items LR(0) pour une grammaire augmentée G’ :
Procédure Items(G’) ;
Début
C :={ fermeture ({[S’S]})} ;
Répéter
Pour chaque ensemble d’items I de Cet pour chaque symbole de la grammaire X tel que
GOTO(I,X) soit non vide et non encore dans C faire
Ajouter GOTO(I,X) à C
Jusqu’à ce qu’aucun nouvel ensemble d’items ne puisse plus être ajouté à C
Fin
Exemple 3:La collection canonique d’ensembles d’items LR(0) pour la grammaire de l’exemple 1 est :
I0 :E’.E I5 : Fid. GOTO(I6,F)=I3
E- .E+T / .T I6 : GOTO(I1 ;+) GOTO(I6,( )=I4
T .T* F / .F E- E+.T GOTO(I6,id )= I5
F.( E) / .id T .T* F / .F I10: GOTO(I7,F )

Page
28
SAOUDI Lalia Analyse Syntaxique 2007/2008

I1 : GOTO(I0,E) F.( E) / .id TT*F.


E’E. I7: GOTO( I2,*) GOTO(I7 ,( )=I4
E- E.+T T T* .F GOTO(I7 ,id)=I5
I2: GOTO(I0,T) F.( E) / .id I11: GOTO(I8,))
E- T . I8 : GOTO( I4,E) F(E ).
T T.* F F( E.) GOTO ( I8,+)= I6
I 3 :GOTO( I0 ,F) E- E.+T GOTO ( I9,*)= I7
T F. GOTO ( I4,T)= I2
I4: GOTO (I0, ( ) GOTO ( I4,F)= I3
F(. E) GOTO ( I4,()= I4
E- .E+T / .T GOTO ( I4,id)= I5
T .T* F / .F I9 : GOTO ( I6,T)
F.( E) / .id EE+T. TT.*F
Nous pouvons schématiser ces ensembles d’items LR(0) « états de l’automate »et la fonction GOTO
« arcs de transition »à l’aide d’un automate AFD.

3.2 Analyse SLR( 1 ) Simple LR


La méthode SLR est la moins puissante des trois en termes du nombre de grammaires pour lesquelles
elle réussit, mais elle est la plus simple à implanter.
La méthode SLR est donc un bon point de départ pour étudier l’analyse LR .
Construction de la table d’analyse SLR
La table d’analyse SLR(1) est composée de deux parties ACTION et GOTO.
1 : Construire C={ I0,I1……,In} la collection des ensembles d’items LR( 0 ) pour G’
2 : Si dans Ii, il existe un item LR( 0 ) A α . aβ où a est un terminal et si GOTO( Ii,a)=Ij alors mettre
dans la case (i,a) de la table l’action dj.
3 : Si dans Ii, il existe un item LR( 0 ) S’ S. alors mettre dans la case (i, #) l’action accepter
4 : Si dans Ii, il existe un item LR( 0 ) A α . alors pour chaque symbole appartenant à SUIVANT
(A) mettre dans la case (i,a) de la table l’action rj où j est le numéro de la règle A α de la grammaire.
5 : Si dans Ii, il existe un item LR(0) A α . Xβ où X est un non terminal et si GOTO(Ii,X)=Ij alors
mettre dans la case (i,X) de la table le numéro j.
6 : Toutes les cases vides indiquent l’existence d’une erreur.
Exemple : la table d’analyse SLR(1) de la grammaire G est la suivante :
Id ( ) + * # E T F
0 D5 D4 1 2 3 Analyser la chaine id1+id2*id3
1 D6 ACC 0 id1+id2*id3#
2 R2 R2 D7 R2 0id15 +id2*id3#
3 R4 R4 R4 R4 8 2 3
4 D5 D4
5 R6 R6 R6 R6
6 D5 D4 9 3
7 D5 D4 10
8 D11 D6
9 R1 R1 D7 R1
10 R3 R3 R3 R3

Page
29
SAOUDI Lalia Analyse Syntaxique 2007/2008

11 R5 R5 R5 R5
2.2 Analyse LR(1)
Items valide:
Nous disons que l’item A β1.β2 est valide pour un préfixe viable αβ1 s’il existe une dérivation
S’ αAw  αβ1β2w
Rappelons que dans la méthode SLR, l’état I indique une action réduire par A α à la vue du terminal
a si l’ensemble des items Ii, contient l’item A α. Et a appartient à SUINANT(A). Cependant, dans
certains cas, quand l’état i apparait en sommet de la pile, le préfixe viable β α de la pile est tel que βA
ne peut être suivi par a dans aucune proto-phrase. Par conséquent, réduire par A α est invalide à la
vue de a
On va mettre plus d’informations dans les Items de manière à mieux contrôler les caractères qui
peuvent être arrivés après.
On incorpore l’information supplémentaire dans l’état en redéfinissons les items de façon qu’ils
incluent un symbole terminal comme second composant.

Construction des ensembles d’items LR(1) :

La forme générale d’item devient [Aα.β , a] où A αβ est une règle de la grammaire et ‘a’ un
terminal. ‘a’ est appelé lookhead ou entité de prelecture de l’item LR(1) ; 1 indiquant la longueur du
second composant appelé prévision de l’item.la prévision n’a aucun effet dans un item de la forme
[A α.β , a]avec β≠ϵ, mais un item de la forme [A α. , a] implique une action réduire par Aα
uniquement lorsque le prochain symbole en entrée est a.

La méthode pour construire la collection des ensembles d’items LR(1) valides est essentiellement la
même que celle utilisée pour construire la collection canonique des ensembles d’items LR(0). Nous
avons uniquement besoin de modifier deux procédures Fermeture « closure »et transition « GOTO »

Fermeture :

La closure de l’item LR(1) [A α.β , a] contient

1-l’item LR( 1) ) [A α.β , a] lui même

2-si β= Bγ où B est un non terminal et si Bδ ajouter l’item [B.δ ,b] où b est un terminal de
PREMIER(γa).

3-itérer le pas 2 jusqu’à ce qu’aucun items ne puisse être ajouté.

Transition :

La fonction GOTO( Ii,X) existe si dans Ii, il existe un item de la forme :

[A α.Xβ , a]et dans ce cas elle est égale à la closure de l’item [A αX.β , a]

Exemple :

Soit la grammaire : donnée par :

Page
30
SAOUDI Lalia Analyse Syntaxique 2007/2008

S CC (1) C aC (2) C c (3)


Nous commençons par augmenter cette grammaire par S’S
La fermeture de [S’.S, #] ici on a A= S’, α=ϵ , B=S , γ=ϵ et a= #, la fonction fermeture nous dit
d’ajouter [B.δ ,b] pour chaque production B δ et chaque terminal b de premier (γ a). Puisque γ =ϵ
et a= # b peut uniquement être #,Par conséquent nous ajoutons [S.CC, #]
Nous continuons à calculer Fermeture de [S.CC, #] ici on a A= S, α=ϵ , B=C , γ=C , a= #et
premier(C#)={a,c} nous ajoutons les items :[C.aC,a], [C.aC,c], [C.c,a] [C.c,c]
L’ensemble d’item initial est :
Io : S’- .S ,#
S.CC,#
C.aC, a/c
C.c , a/c
I1= GOTO(Io,S)
S’S., #
Construction de la table LR(1)
1. Construire C= { Io,I1,………In}, la collection des ensembles d’items LR( 1) pour G’

2. L’état i de l’analyseur est construit à partir de Ii, les actions d’analyse pour l’état i sont
déterminées de la façon suivante :

a. Si [A α.aβ , b] est dans Ii, remplir Action [i,a] avec dj où j est tel que GOTO(Ii,a)=Ij

b. Si [A α ., a] est dans Ii, A≠S’ remplir Action[i,a] avec rj où j est le num de la règle
A α dans la grammaire.

c. Si [ S’ S. #] est dans Ii remplir action(i,#) avec accepter

3.les transitions GOTO pour l’état i sont déterminées comme suit : si GOTO(Ii,A)= Ij alors placer
dans la case (i,A) le numéro j.

4. toutes les entrées non définies par les règles 2 et 3 sont remplies avec erreur.

La table ci-dessous représente la table canonique d’analyse de la grammaire étudiée :


a c # S C

0 D3 D4 1 2

1 ACC

2 D6 D7 5

3 D3 D4 8

4 R3 R3

5 R1

6 D6 D7 9

7 R3

8 R2 R2

9 R2

Page
31
SAOUDI Lalia Analyse Syntaxique 2007/2008

Analyser la chaine : aabaab

3.3 Analyse LALR

Nous introduisons la dernière méthode pour construire des analyseurs, la technique LALR( Look A
head LR), cette méthode est souvent utilisée en pratique, parce que les tables obtenues sont
considérablement plus petites que les tables LR canoniques, et satisfait une grande classe de
grammaire.

Construction des tables LALR facile mais gourmande en place :

Donnée : une grammaire augmentée G’


Résultat : les fonctions ACTION et GOTO des tables d’analyse LALR associées à G’
Méthode :
1. Construire C={ Io,I1…..In}, la collection des ensembles d’items LR(1) pour G’.
2. Pour chaque cœur présent parmi les ensembles d’items LR(1), trouver tous les états ayant ce
même cœur et remplacer ces états par leur union (nous rassemblerons les ensembles dont les
items LR(1) ont respectivement les même cœurs. autrement dit ce qui différencient les
ensembles à regrouper seront les lookheads attachés aux items LR(1).
-un item LALR(1) de l’ensemble nouvellement créé aura le même cœur que ceux des items
LR(1) des ensembles regroupés et aura pour lookahead , la réunion des lookaheads des items
LR(1) des ensembles regroupés.
3. Soit C’={Jo,J1………Jm} la collection des ensembles d’items LR(1) résultante. Pour chacun
de ceux-ci, tester les conditions
a. Si [A α.aβ , b] est dans Ii, remplir Action [i,a] avec dj où j est tel que GOTO(Ii,a)=Ij
b. Si [A α ., a] est dans Ii, A≠S’ remplir Action[i,a] avec rj où j est le num de la règle
A α dans la grammaire.
c. Si [ S’ S. #] est dans Ii remplir action(i,#) avec accepter
4. La fonction transition est construite comme suit.
-Si j est l’union de un ou plusieurs ensembles d’items LR(1) c.à.d J=I1 U I2U……… U Ik,
les cœurs de transitions(I1 ,X), transition (I2,X)…, transition(Ik, X) sont les même puisque
I1,I2……Ik ont tous le même cœur . soit K l’union de tous les ensembles d’items ayant le même cœur
que Transition ( I1, X) alors Transition ( J, X)= K.
Exemple :
Reprenons l’exemple de l’analyse LR(1) Les états nouvellement crées sont :
Io : S’. S, # I1: S’-- S., # I4,I7: C c., a/c/#

Page
32
SAOUDI Lalia Analyse Syntaxique 2007/2008

S.CC, # I2: S C.C ,# I5: SCC. , #


C.aC,a/c I3,I6: Ca.C ,a/c/# I8,I9 : C:aC. , a/c/#
C.c , a/c C.aC, a/c/#
C .c, a/c/#
Pour obtenir la table LALR(1), nous superposerons les lignes 3 et 6 ensemble, les lignes 4 et 7
ensemble et lignes 8 et 9 ensemble. Les autres lignes restent inchangées.

Plusieurs cas de conflits peuvent se présenter, étudiant chacun de ces cas :

Cas 1 : présence de deux décalages différents dans une même case :

Ces deux décalages proviennent des ensembles LR(1) qui ont le même cœur d’items, il y aurait conflit
dans ce cas, lorsque les états de transition ne seront pas identiques ou équivalents, or, l’état suivant est
défini comme étant la closure de transition par l’élément se trouvant après le point dans l’item ( qui est
le même dans les deux items LR(1)). D’après la définition de la closure, les états de transition seront
identiques.

Cas 2 : présence d’un décalage et d’une réduction dans une même case.

Ces deux actions proviennent de deux items LR(1) de deux états LR(1) différents ayant les mêmes
cœurs. Mais dans la case de la table LR(1) qui contient la réduction, on aurait eu aussi un décalage
puisque le cœur de l’itemLR(1) provoquant cette réduction est le même que celui qui a provoqué le
décalage dans la case symétrique.

Cette case serait donc multi définie dans la table LR(1) et par conséquent la grammaire ne serait pas
LR(1).

Cas 3 : présence de deux réductions différentes dans une même case.

Le seul conflit possible qui peut se présenter est la présence dans une même case de deux réductions
différentes.

En effet, deux items LR(1) ayant respectivement la forme [AC. ,x] et [ B.C, x] peuvent exister
dans un même ensemble. Maintenant, si on essaye de superposer deux ensembles ayant ces deux
items, il y aurait conflit entre deux réductions dans une même case

Cas 4 : présence d’une erreur et d’une autre action dans une même case .

Le cas (erreur, décalage) ne peut pas se présenter car si on a un décalage dans une case, on aurait eu un
autre décalage dans la case symétrique pour la même raison évoquée dans le cas 1.

Dans ce cas ; si la chaine est correcte syntaxiquement, l’analyse LR(1) et l’analyse LALR (1)
progresseront exactement de la même façon . La seule chose qui diffère réside dans les appellations ou
numérotage des états de transition.

Exemple : La table d’analyse LALR(1) de la grammaire précédente est :

a c # S C Analysons la chaine ccdccd #


0 D36 D47 1 2
1 ACC (0 , ccdccd#)
2 D36 D47 5

Page
33
SAOUDI Lalia Analyse Syntaxique 2007/2008

36 D36 D47 89
47 R3 R3 R3
5 R1
89 R2 R2 R2
Table d’analyse LALR(1)

Analysons maintenant la chaine ccd#

Note : lorsqu’il ya une erreur dans la chaine à analyser , l’analyse LR(1) détectera plus rapidement
cette erreur alors que l’analyse LALR procédera une série de réduction avant de rencontre l’erreur.
4.Analyse par précédence d’opérateurs :
Cette technique peut analyser une petite classe de grammaire, ces grammaires ont la propriété de ne pas avoir de
production dont la partie droite est ni d’avoir deux non terminaux adjacents. Une grammaire vérifiant la dernière
propriété est une grammaire d’opérateurs.
.
Dans
. l’analyse par précédence d’opérateurs, nous définissons trois relations de précédence disjointes < . ,= ,
>, entre certains couples de terminaux.
a <. b : a cède la précédence à b
A=. b : a la même précédence que b
a>. b : a prend la précédence sur b

Habituellement, il ya deux façons de déterminer quelles relation de précédence doivent exister


entre les couples de terminaux, la première méthode est intuitive, elle est fondée sur les
notions traditionnelles d’associativité et de priorité d’opérateurs. Par exemple, si * a une
priorité plus grande que +, on a +<. * et *.>+.

La seconde méthode consiste à construire d’abord une grammaire non ambiguë pour le
langage qui reflète l’associativité et la priorité correcte dans ses arbres d’analyse, il existe une
méthode mécanique pour en dériver les relations de précédence d’opérateurs.

Utilisation des relations de précédence d’opérateurs :

Le but des relations de précédence est de délimiter le manche d’une proto-phrase droite avec
<. Marquant l’extrémité gauche, =. Apparaissant à l’intérieur du manche et .> marquant
l’extrémité droite.

Page
34
SAOUDI Lalia Analyse Syntaxique 2007/2008

Par exemple considérons la prot-phrase droite id+id*id et supposons que les relations de
précédence sont les suivantes :

Id + * #
Id .> .> .>
+ <. .> <. .>
* <. .> .> .>
# <. <. <.
Alors , la chaine dans laquelle les relations de précédence ont été insérées est :
#<. Id .> + <. Id .> * <. Id .> #, on peut déterminer le manche en appliquant le procédé suivant :

1. Parcourir la chaine à partir de l’extrémité gauche jusqu’à rencontrer le premier.>, dans notre
exemple cela se produit entre le premier id et +.

2. Parcourir alors en sens inverse(vers la gauche)en sautant les =. Jusqu’à rencontrer un<. « dans
l’exemple en revient jusqu’au # ».

3. le manche contient tout ce qui se trouve à gauche du premier .> et à droite du <.rencontré à l’étape
2, y compris les non-terminaux intérieurs ou situés aux extrémités , dans notre exemple le manche est
le premier id, donc on peut le remplacer(réduire) par E . A ce point nous avons la proto-phrase droite
E+id*id, après avoir réduit vers E, par un procédé analogue, les id restants, on obtient la proto-phrase
droite E+E*E, considérant maintenant la chaine # +*# obtenue on supprimant les non terminaux. En
insérant les relations de précédence, nous obtenons : #<. +<.*.># qui indique que l’extrémité gauche
du manche se trouve entre + et * et que son extrémité droite se trouve entre * et #, alors le manche est
E*E.

La présentation ci-dessus peut sembler impliquer que la proto phrase droite doit etre parcourue en
entier chaque fois que l’on recherche un manche , ce n’est pas le cas si on utilise une pile pour
mémoriser les symboles d’entrée déjà lus et si les relations de précédence sont utilisées pour guider les
actions de l’analyseur par décalage-réduction.l’idée est peut être formalisée par l’algorithme suivant

Algorithme
Donnée : une chaine d’entrée w et une table de relation de précédence.
Résultat : si w est bien formé, un squelette d’arbre d’analyse

Méthode : Initialement, la pile contient # et le tompon d’entrée la chaine w#


1. Positionner le pointeur source ps sur le premier symbole de w#.
2. Répéter indéfiniment
3. Si # est en sommet de la pile et ps pointe sur # alors
4. Retourner()
5. Sinon début
6. Soient a le symbole terminal en sommet de la pile et b le symbole pointé par ps,
7. Si a<. b ou a= b alors début
8. Décaler b sur la pile, et avancer ps sur le symbole suivant

Page
35
SAOUDI Lalia Analyse Syntaxique 2007/2008

9. Sinon si a.> b alors


10. Répéter
11. Dépiler
12. Jusqu’à ce que le terminal en sommet de pile soit relié par <. Au terminal le plus récemment dépilé
13. Sinon Erreur() :
14. Fin
Détermination des relations de précédence d’opérateurs à partir des associativités et des priorités :
Les règles ci-dessous sont conçues pour sélectionner le manche approprié qui reflète un ensemble donné de
règles d’associativité et de priorité des opérateurs binaires :
1. si l’opérateur ϴ1 a une priorité supérieur à l’opérateur ϴ2, alors on a ϴ1.> ϴ2 et ϴ2<. ϴ1
2. Si ϴ1 et ϴ2 sont des opérateurs d’égale priorité, alors on a ϴ1.> ϴ2 et ϴ2.> ϴ1 si les opérateurs sont
associatifs à gauche ou ϴ1<. ϴ2 et ϴ2<. ϴ1 s’ils sont associatifs à droite :exemple le + et - sont
associatifs à gauche alors on a : + > - et - > +
3. Pour tous les opérateurs ϴ on a ϴ <.Id, id .> ϴ , ϴ <. (, (<.ϴ , ).> ϴ , ϴ .> ), ϴ > # et #<. ϴ, on a
également :
(= ) #< ( #< id (<( id > # )># ( < id id > ) )>)
Exemple : la figure ci-dessous contient les relations de précédence d’opérateurs pour la grammaire:
E E+ E / E – E / E * E /E/E / E ^E / (E) / - E / id
+ - * / ^ Id ( ) #

+ > > < < < < < > >

- > < < < < < > >

* > > > > < < < > >

/ > > > > < < < > >

^ > > > > < < < > >

Id > > > > > > >

( < < < < < < < =

) > > > > > > >

# < < < < < < <

Essayez la table sur l’entrée : id * (id ^id)-id /id


Manches : de façon informelle, un manche de chaine est une sous chaine qui correspond à la partie droite
d’une production et dont la réduction vers le non terminal de la partie gauche de cette production représente une
étape de dérivation droite inverse

5. Analyse des grammaires ambiguës :


Une grammaire ambiguë n’est pas LR, (sa table d’analyse LR(1),SLR(1) ou LALR(1) est multi
définie) ce théorème implique qu’une grammaire ambiguë ne rentre dans aucune des classes
présentées précédemment

Certains types de grammaires ambiguës sont cependant utiles pour spécifier et implanter les langages.

Page
36
SAOUDI Lalia Analyse Syntaxique 2007/2008

Avec une grammaire ambiguë, nous pouvons spécifier les constructions de cas particuliers en ajoutant
prudemment de nouvelles productions à la grammaire.

Précisons que bien que les grammaires que nous utilisons soient ambiguës, nous spécifions dans tous
les cas des règles pour lever ces ambigüités et permettre ainsi un arbre d’analyse unique pour chaque
phrase

Utilisation des priorités et des associativités pour résoudre les actions conflictuelles d’analyse :

Considérons les expressions des langages de programmation.

La grammaire suivante des expressions arithmétiques avec les opérateurs + et * :

E E+E / E*E/ (E)/id……….(1)

Est ambiguë car elle ne spécifie pas ni l’associativité ni la priorité des opérateurs + et *, la grammaire
non ambiguë est :

EE+ T / T TT*F / F F (E) / id……………(2)

Engendre le même langage mais donne à + une priorité plus faible que celle de * et définit une
associativité à gauche pour ces deux opérateurs.

Nous pourrions vouloir utiliser la grammaire 1 plutôt que 2 pour deux raisons :

1. Nous pouvons facilement changer les niveaux d’associativité et de priorités des opérateurs +
et * sans toucher aux productions de 1ni au nombre d’état d’analyseur résultant.

2. L’analyseur pour 2 passe une part substantielle de son temps ) réduire par les productions
ET et TF dont la seule fonction est d’imposer l’associativité et la priorité, l’analyseur
pour 1 ne perdre aucun temps à réduire par ces productions simples.

La grammaire 1 peut être analysée selon deux manières possibles :

- La première consiste à la transformer en une grammaire non ambiguë en considérant


l’associativité et la précédence de chaque opérateur n ensuite à procéder à l’analyse.

- La seconde consiste à analyser la grammaire sans relever son ambigüité et dans une
deuxième étape à résoudre les conflits se trouvant dans la table d’analyse, cette dernière
approche est préférable pour les raisons citées précédemment.

Il reste à résoudre les conflits d’actions apparaissant dans la table d’analyse.

Considérons la collection des ensembles d’items LR(0) de la grammaire (1) augmentée par E’E
I0 : E’ .E
E.E+E
E . E*E
E.(E)/ .id
I1 : E’ E.

Page
37
SAOUDI Lalia Analyse Syntaxique 2007/2008

EE.+E
EE.*E
I2 : E(.E)
E.E+E
E.(E)/ .id
E . E*E
La table SLR(1) générée est la suivante :
Id + * ( ) # E
0 D3 D2 1
1 D4 D5 ACC
2 D3 D2 6
3 R4 R4 R4 R4
4 D3 D2 7
5 D3 D2 8
6 D4 D5 D9
7 R1/D4 R1/D5 R1 R1 R1
8 R2/D4 R2/D5 R2 R2
9 R3 R3 R3 R3

Dans cette table, nous remarquons l’apparition de quatre conflits

Prenons comme exemple Le conflit engendré par I7 entre réduire par EE+E…R1 et décaler + ou *

Essayons de résoudre le conflit apparaissant dans la case (7,+) et ceci en considérant la précédence ou
l’associativité des opérateurs de la grammaire, dans la case indiquée nous avons deux actions r1 et d4,
la présence de r1 signifie qu’au sommet de la pile la chaine E+E qui est la partie droite de la 1iere
règle est présente la présence de d4 signifie qu’il faut empiler le + se trouvant en tête de la chaine.

Nous somme donc devant d’une expression du genre a +b+c, cette expression peut être interprétée
comme (a+b)+c ou a+(b+c) selon l’associativité de l’opérateur +

Si le + est associatif à gauche  l’expression devient (a+b)+cmettre dans la case l’action r1

Passons maintenant à la case (7,*), dans cette case nous avons une réduction par r1 et un décalage d5,
nous somme donc en présence d’une opération du genre a+b*c ; d’après l’ordre de précédence des
opérateurs + et *, a+b*c = a+(b*c ), par conséquent le conflit est résolut en faveur de d5.

Des raisonnements analogues peuvent se produire pour supprimer les conflits apparaissant dans les 2
autres cases.

6.Erreurs syntaxiques
Beaucoup d’erreurs sont par nature syntaxique, Le gestionnaire d’erreur doit :
-indiquer la présence de l’erreur de façon claire et précise.
-traiter l’erreur rapidement pour continuer l’analyse.
-traiter l’erreur le plus efficacement possible de manière à ne pas en créer de nouvelles.

Page
38
SAOUDI Lalia Analyse Syntaxique 2007/2008

Heureusement les erreurs communes (confusion entre deux séparateurs par exemple entre, et ; oubli
de ;) sont simples et un mécanisme simple de traitement suffit en général.

Il existe plusieurs stratégies de récupération sur erreur : mode panique, au niveau du syntagme
, productions d’erreur, correction globale.
Récupération en mode panique :
C’est la méthode la plus simple à implanter. Quand il découvre une erreur, l’analyseur syntaxique
élimine les symboles d’entrée les un après les autres jusqu’à en rencontrer un qui appartienne à un
ensemble d’unités lexicales de synchronisation.
Bien que cette méthode saute en générale une partie considérable du texte source sans en vérifier la
validité, elle a l’avantage de la simplicité et ne peut pas entrer dans une boucle infinie.

Récupération au niveau du syntagme


Quand une erreur est découverte, l’analyseur syntaxique peut effectuer des corrections locales (Par
exemple : remplacer une, par un ; un wihle par un while_ insérer un ;ou une )….Le choix de la
modification à faire n’est pas évident du tout du tout en général. En outre, il faut faire attention à ne
pas faire de modifications qui entrainerait une boucle infinie.
L’inconvénient majeur de cette méthode est qu’il est pratiquement impossible de gérer les situations
dans les quelles l’erreur réelle s’est produite bien avant le point de détection.
On implante cette récupération sur erreur en remplissant les cases vides des tables d’analyse par des
pointeurs vers des routines d’erreur. Ces routines remplacent, insèrent ou suppriment des symboles
d’entrée et émettent les messages appropriées.
Exemple : grammaire des expressions arithmétiques :
(1) E -- E + E (3) E -- ( E )
(2) E-- E * E (4) E -- nb
La table d’analyse LR avec routines d’erreur est :

Les routines d’erreur étant :

Page
39
SAOUDI Lalia Analyse Syntaxique 2007/2008

e1 : (routine appelée depuis les états 0,2,4 et 5 lorsque l on rencontre un opérateur ou la fin de chaine
d’entrée alors qu’on attend un opérande ou une parenthèse ouvrante)
Emettre le diagnostic opérande manquant
Empiler un nombre quelconque et aller dans l’état 3
e2 :( routine appelée depuis les états 0,1,2,4 et 5 à la vue d’une parenthèse fermante)
Emettre le diagnostic parenthèse fermante excédentaire
Ignorer cette parenthèse fermante
e3 : (routine appelée depuis les états 1ou 6 lorsque l’on rencontre un nombre ou une parenthèse
ouvrante alors que l’on attend un opérateur)
Emettre le diagnostic operateur manquant
Empiler +(par exemple) et aller à l’état 4
e4 : (routine appelée depuis l’état qui attend un opérateur ou une parenthèse fermante lorsque l on
rencontre la fin de chaine)
Emettre le diagnostic parenthèse fermante oubliée
Empiler une parenthèse fermante et aller à l’état 9 .
Exemple : sur l’entrée erronnée : id + ) voici la séquence de configurations :
0 id +)#
0 id 3 +) #

Productions d’erreur :
Si l’on a une idée assez précise des erreurs courantes qui peuvent être rencontrées, il est possible
d’augmenter la grammaire du langage avec des productions qui engendrent les constructions erronés.
Par exemple (pour un compilateur C) :
I if E I (erreur : il manque les parenthèses)
I if ( E ) then I
(erreur : il n’ y a de then en C ).
Correction globale:
Dans l’idéal, il est souhaitable que le compilateur effectue aussi peu de changements que possible. Il
existe des algorithmes qui permettent de choisir une séquence minimale de changements
correspondant globalement au cout de correction le plus faible. Malheureusement, ces méthodes sont
trop couteuses en temps et en espace pour être implantées en pratique et ont donc uniquement un
intérêt théorique. En outre, le programme correct le plus proche n’est pas forcément celui que le
programmeur avait en tète ….

7.Constructeurs d’analyseurs syntaxiques :


Le développement manuel d’un compilateur nécessite de gros efforts , de nos jours, il est possible
d’éviter cette tache délicate en faisant intervenir un outil logiciel qui produit le compilateur lui-même.

Page
40
SAOUDI Lalia Analyse Syntaxique 2007/2008

L’utilisateur aura simplement à fournir une source de spécification qui contiendra principalement le
description de la grammaire du langage à compiler

Yacc est un constructeur d’analyseurs LALR qui est largement disponible, Yacc est l’acronyme de «
Yet another compiler-compiler », reflétant la popularité des constructeurs d’analyseurs au début des
années 70 , Yacc est disponible en tant que commande sur le système UNIX et il a été utilisé pour
faciliter l’implantation de certaines de compilateurs.

Constructeur d’analyseurs Yacc :

Un traducteur peut etre construit en utilisant Yacc de la manière suivante :

Spécification Yacc « traduire.y »----- Yacc -------- y.tab.c

y.tab.c ------- compilateur C ----- a. out

donnée ------- a. out ------------- Résultat

On prépare tout d’abord un fichier, par exemple traduire.y, qui contient une spécification du traducteur
pour Yacc. La commande système UNIX : yacc traduire.y produit à partir du fichier traduire.y un
programme C appelé y.tab.c en utilisant la méthode LALR. Le programme y.tab.c est une
implantation d’analyseur LALR écrite en C , complétée par d’autres routines C que l’utilisateurs a
éventuellement écrites, les tables d’analyse LALR sont compressées .

En compilant y.tab.c et en utilisant la bibliothèque ly qui contient le programme d’analyse LR , ce qui


se fait par la commande : cc y.tab.c –ly nous obtenons a.out, le programme objet désiré, qui effectue la
traduction spécifiée par le programme Yacc original.

Un programme source en Yacc comporte trois parties :


Déclaration
%%
Règles de production et de traduction
%%
Bloc principal ;Procédure de l’utilisateur
Dans la première zone, celle réservée pour les définitions, toutes les entités lexicales utilisées pour
décrire la grammaire dans la deuxième partie sont définies.

Ces entités représentent les symboles terminaux de la grammaire, aussi d’autres informations telles
que la précédence et l’associativité des opérateurs.

*Les symboles terminaux utilisables dans la description du langage sont


-des unités lexicales que l on doit impérativement déclarer par %token nom, Par
exemple :
%token MC sinon
%token NOMBRE
-des caractères entre quotes, Par exemple : ‘+’ ,’a’.

Page
41
SAOUDI Lalia Analyse Syntaxique 2007/2008

* Les symboles non terminaux sont les caractères ou les chaines de caractères non déclarées comme
unités
lexicales
yacc fait la différence entre majuscules et minuscules : SI et si ne désignent pas le même objet.
La deuxième zone est utilisée pour la description de la grammaire du langage à compiler. Elle est
constituée de règles de traduction attachée une action de traduction qui est un fragment de programme
écrit dans le langage d’écriture de l’analyseur syntaxique appelé le langage hote. Cette action est
exécutée par l’analyseur à chaque fois qu’il procède à une réduction par la règle correspondante.

-Les règles de production sont des suites d’instructions de la forme :


Non-terminal := production 1 |production2……………|production n ;
Les actions sémantiques sont des instructions en C insérées dans les règles de production. Elles sont
exécutées chaque fois qu’il y a réduction par la production associée.
Le format de la règle de traduction est :

A :: = BCD { action} la barre de sheffer est utilisée pour séparer deux productions d’un même non
terminal

Exemple : A :: = BC {action1}

| CD{action2}

Enfin la troisième zone est utilisée pour l’écriture des procédures de l’utilisateur dont l’appel se fait
dans les actions attachées aux règles de production de la deuxième partie.

- La section du bloc principal doit contenir une fonction yylex,() effectuant l’analyse lexicale du texte,
car
L’analyseur syntaxique l’appelle chaque fois qu’il a besoin du terminal suivant.
Conflit shift-reduce et reduce-reduce :
Lorsque l’analyseur est confronté à des conflits, il rend compte du type et du nombre de conflits
rencontrés :
>bison exempl.y
Conflicts: 6 shift/reduce ,2 reduce_reduce
Il y a un conflit reduce/reduce lorsque le compilateur a le choix entre (au moins) deux productions
pour réduire une chaine. Les coflits shift/reduce apparaissent lorsque le compilateur a le choix entre
réduire par une production et décaler le pointeur sur la chaine d’entrée.
yacc_résoud les conflits de la manière suivante :
 conflit reduc/reduce : la production choisie est celle apparaissant en premier dans la
spécifications.
 coflit shift/reduce : c’est le shift qui est effectué.
Récupération des erreurs :
Lorsque l’analyseur rencontre une erreur, il appelle par défaut la fonction yyerror(char *) qui se
contente d’afficher le message parse error, puis il s’arrête.
Cette fonction peut être redéfinie par l’utilisateur .
Il est possible de traiter de manière plus explicite les erreurs en utilisant le mot clé error.
On peut rajouter dans toute production de la forme A B1|B2…. Une production
A error B

Page
42
SAOUDI Lalia Analyse Syntaxique 2007/2008

Dans ce cas, une production d’erreur sera traitée comme une production classique. On pourra donc lui
associer une action sémantique contenant un message d ‘erreur.
Dés qu’une erreur est rencontrée, tous les caractères sont avalées jusqu’à rencontrer le caractère
correspondant à B.

Page
43