• Aucun résultat trouvé

SAOUDI Lalia Analyse Syntaxique 2007/2008

N/A
N/A
Protected

Academic year: 2022

Partager "SAOUDI Lalia Analyse Syntaxique 2007/2008"

Copied!
27
0
0

Texte intégral

(1)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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

(2)

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

(3)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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(Y

i

) | X  Y

1

,..Y

k

et Y

1

,..,Y

i-1

* }  { si X   ou si X  Y

1

,..Y

k

et   FIRST(Y

i

)  Y

i

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’

(4)

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

(5)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page 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:

(6)

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 :

(7)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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 :

Soit G la grammaire suivante : E- E+T / T  T T* F / F

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

E  TE’

E’  +TE’ |  T  FT’

T’  *FT’ | 

F  (E) | Id

(8)

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 :

(9)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

- 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

A

SCENDANTE

:

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 : Chaine à analyser

Programme Conducteur

Table d’analyse

(10)

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

(11)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page 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).

(12)

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 )

(13)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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

1 D6 ACC

2 R2 R2 D7 R2

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

Analyser la chaine id1+id2*id3

0 id1+id2*id3#

0id15 +id2*id3#

(14)

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 :

(15)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page 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

(16)

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/#

(17)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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

0 D36 D47 1 2

1 ACC

2 D36 D47 5

Analysons la chaine ccdccd #

(0 , ccdccd#)

(18)

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.

(19)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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

(20)

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.

(21)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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.

(22)

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 D 3 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.

(23)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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 :

(24)

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.

(25)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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’.

(26)

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

(27)

SAOUDI Lalia Analyse Syntaxique 2007/2008

Page

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.

Références

Documents relatifs

les cours Automates et Calculabilit´ e en majeure M1 pour les grammaires formelles, et Compilation en majeure M2 pour les analyseurs syntaxiques... Sch´ ema g´

Pour cela, il su¢ t d’établir l’existence d’un couple (x; y) qui ne satisfait pas la

On peut utiliser

ajouts sont facultatifs dans la chaîne où ils figurent, c’est-à-dire, leur présence n’est pas nécessaire pour que cette chaîne soit bien formée : la chaîne

L’étape principale consiste à prendre un groupe d’états par exemple A= {e1,e2…ek} et un symbole a, et à étudier les transitions des états de A sur a, si ces

Un arbre syntaxique pour une définition S-attribuée peut toujours être décoré en évaluant les règles sémantiques pour les attributs de chaque nœud du bas vers le haut,

Dans l’équivalence structurelle des expressions de type, ou bien les deux expressions sont le même type de base, ou bien elles sont formées en appliquant le même constructeur à

Pour d´eriver un analyseur syntaxique d’une grammaire non-contextuelle ´ecrite dans le style EBNF :.. Introduire une fonction def A: Unit pour chaque