Il existe deux types de récursivité gauche la récursivité directe (RGD) dite également
immédiate et la récursivité indirecte (RGIND) appelée également générale.
G est récursive à gauche si une des règles de production de G est sous forme :
AAα
Elimination de ce type de récursivité
Récrire les règles de type AAa1/…Aan/B1…/Bn avec Bi…ne commencent pas par A
En AB1A’/…/ Bn A’
A’ a1A’/…/anA’/
Ordonner les Ai ∈ Vn .
Pour i de 1 à n faire
{
Pour j de 1 à i − 1 faire
{
Si Ai Aj α existe, la remplacer par : Ai β1 α / β2 α /… / βn α où Aj β1 / β2 /… / βn
}
Eliminer la récursivité directe des Ai-productions
}
Exemple :
G RINDG G RDG G non récursive
S Aa / b S Aa / b S Aa / b
A Ac | Sd | c A Ac/Aad/bd/c A bdA’/cA’
A’ cA’/adA
Pour factoriser une grammaire il faut répéter l’opération pour toutes les règles de production
écrites sous cette forme
Exemple : AabC/aAB/caF AaA’/caF
A’ bC/AB
2.4) Notion d’ensemble début et suivant
Prenons la grammaire Gexp suivante comme exemple illustratif
ETE’
E’+TE’/
TFT’
T’*FT’/
F(E)/idf
a) Construction des ensembles début
Pour toute chaîne X composée de symboles terminaux et non-terminaux, on cherche
l'ensemble de tous les terminaux qui peuvent commencer une chaîne qui se dérive de X
Pour toutes les productions faire
1. Si X est une production de la grammaire alors ajouter à debut(X)
2. Si X a est une production de la grammaire et a est un terminal alors debut(X) = {a}.
3) L’analyse descendante
Principe : construire l'arbre de dérivation du haut (la racine, c'est à dire l'axiome de départ)
vers le bas (les feuilles, c'est à dire les unités lexicales). Cette méthode cherche à construire
une dérivation gauche directement a partir du symbole initial et donc cherche a construire un
arbre de dérivation a partir de la racine avec une exploration en profondeur d'abord de gauche
a droite.
Pour cela, l'analyseur doit pouvoir décider, en s'aidant éventuellement avec les k symboles en
entrée, quelle est la prochaine règle de production à dériver dans la dérivation gauche que l'on
reconstruit.
Les analyseurs à étudier nécessite une grammaire LL(1).
Exemple
Avec Gexp, on obtient la table
idf + * ( ) #
E
E'
T
T'
F idf
Données : chaine de token W qui se termine par le token fin #, une pile, la table d'analyse
Tab et un pointeur ptr sur 1er token de W
Soit X le symbole en sommet de pile
Soit Tk le token pointé par ptr
Repeter
Si X est un non terminal alors
Si Tab[X,Tk]=XY1…Yn alors
debut
depiler X
empiler Yn puis Yn-1 puis ...puis Y1
sinon
ERREUR
Finsi
Sinon
Si X= # alors
Si Tk= # alors ACCEPTER
Sinon ERREUR
Finsi
Sinon
Si X=Tk alors
depiler X de la pile
avancer ptr
Sinon
ERREUR
Finsi
Finsi
Finsi
jusqu'à ERREUR ou chaine acceptée
Exemple :
Reprendre la grammaire Gexp et analyser la chaine W=idf+idf*idf# avec # marque de fin de
chaine.
W L(G)
Pratiquement, chaque non terminal A de la partie gauche d’une règle A α est traduite en
procédure A()
Debut
Fin
Le corps de la procédure est constitué par la traduction de la partie droite α : tout terminal doit
être comparé au sommet de pile et tout non terminal est traduit en un appel à la procédure non
terminal.
Exemple
Reprenons la grammaire Gexp augmentée de ZE # avec E axiome de Gexp et # token
exprimant la marque de fin.
Procedure Z()
Tokcour=lex();
Si tokcour=’#’ alors ecrire (‘chaine vide’)
Sinon
debut
E();
Si tokcour=’#’alors ecrire(‘chaine acceptée’)
Sinon erreur
Fin ;
Fin;
Procedure E()
debut
T() ;
E’()
Fin ;
Procedure E’()
Si tokcour=’+’ alors
Debut
Tokcour=lex() ;
T() ;
E’() ;
fin
Sinon
Si tokcour <> # et tokcour<>’)’ alors erreur ;
fsi
Fin ;
Procedure T’()
Si tokcour=’*’ alors
Debut
Tokcour=lex() ;
F() ;
T’()
Fin ;
Si tokcour <> # et tokcour<>’)’ et tokcour<>’+’ alors erreur
fsi
Fin ;
Procedure T()
debut
F() ;
T’()
Fin ;
Procedure F()
Si tokcour=’(’ alors
Debut
Tokcour=lex()
E() ;
Si tokcour=’)’ alors tokcour=lex()
sinon erreur /*module traitement erreur*/
Fin ;
Sinon si tokcour=idf alors tokcour=lex()
Sinon erreur /*module */
Fin ;
Bibliographie
A. Aho, R. Sethi, J. Ullman . Compilateurs, principes, techniques et outils. PEARSON
Education. 2007