0% ont trouvé ce document utile (0 vote)
33 vues82 pages

Théorie des langages et compilation

Transféré par

Hicham Elhachami
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
33 vues82 pages

Théorie des langages et compilation

Transféré par

Hicham Elhachami
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Théorie des langages

Théorie des langages et compilation

Jean-Guy Mailly
jean-guy.mailly@parisdescartes.fr

LIPADE - Université Paris Descartes


http://www.math-info.univ-paris5.fr/vjmailly/

1
Théorie des langages et compilation

1. Structure d’un compilateur

2. Analyse lexicale

3. Analyse syntaxique

4. Analyse sémantique

5. Conclusion

2
Structure d’un compilateur
Un compilateur, c’est quoi ?

Un compilateur est un programme qui

• prend en entrée une donnée textuelle source (programme, donnée


xml, fichier de configuration, etc)
• la reconnaı̂t (l’analyse) pour vérifier sa correction
• émet éventuellement un message d’erreur
• le traduit dans un langage cible

programme source Compilateur programme cible

messages d’erreur

4
Les différentes étapes de la compilation
Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

5
Les différentes étapes de la compilation
Partie analyse : sépare les 6= constituants Programme source
du prog. source et produit une
représentation intermédiaire Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

5
Les différentes étapes de la compilation
Partie analyse : sépare les 6= constituants Programme source
du prog. source et produit une
représentation intermédiaire Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code
Partie synthèse : génère le prog. cible à

Programme cible partir de la représentation intermédiaire

5
Analyse lexicale

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

6
Analyse lexicale

• Seul module au contact avec le texte source


• Son but est de reconnaı̂tre les unités lexicales ou lexèmes
• les identificateurs et les mots clefs du langage
• l’affectation et les opérateurs
• Utilise des expressions régulières : automates finis

identificateur

ab := y * x + 20

operateur
affectation nombre

7
Analyse syntaxique

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

8
Analyse syntaxique

• Regroupe les unités lexicales en structures grammaticales en suivant


les règles figurant dans une grammaire
• Résultat représenté par un arbre syntaxique
• La structure hiérarchique d’un programme est exprimée à l’aide de
règles
• Tout identificateur est une expression
• Tout nombre est une expression
• Si expr 1 et expr 2 sont des expressions alors expr 1 ∗ expr 2 est une
expression
• Grammaires hors contexte : automates à pile
:=

ab +

* 20

9
y x
Analyse sémantique

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

10
Analyse sémantique

• Vérifie la présence d’erreurs d’ordre sémantique


• Vérification de typage
• Vérification des déclarations
• Par exemple, si x et y sont des réels :

:=

ab +

* conversion entier -> réel

y x 20

11
Partie synthèse

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

12
Partie synthèse

• Génération du code intermédiaire


• Utilisation de variables temporaires
• Choix de l’ordre pour faire un calcul
• Optimisation du code
• Amélioration du code intermédiaire
• Réduction du nombre de variables et d’instructions
• Génération du code
• Choix des emplacements mémoire pour les variables
• Assignation des variables aux registres

13
Table des symboles

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

14
Table des symboles

• Enregistre les identifiants et les attributs (emplacement mémoire,


type, portée)
• Chaque identifiant (variable) a une entrée dans la table des symboles
• L’analyseur lexical crée une entrée dans la table des symboles à
chaque fois qu’il rencontre un nouvel identificateur
• Par contre, les attributs seront calculés plus tard
• L’analyseur sémantique se sert de la table des symboles pour vérifier
la concordance des types

15
Détection des erreurs

Programme source

Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code

Programme cible

16
Détection des erreurs

• Erreur lexicale : le flot de caractères n’est pas reconnu


• Erreur syntaxique : construction non reconnue par le langage
• Erreur sémantique : problème de typage,...

17
Analyse lexicale
Analyseur lexical et analyseur syntaxique

• L’analyse lexicale produit des lexèmes


• En général à la volée à la demande de l’analyseur syntaxique
• L’analyseur syntaxique demande le prochain lexème à l’analyseur
lexical, qui le reconnaı̂t et retourne un code identifiant ce lexème
• On pourrait imaginer que l’analyse lexicale travaille indépendamment
et fournisse une suite de lexèmes
• mais on n’a pas besoin, en général, d’avoir reconnu tous les lexèmes
pour faire l’analyse syntaxique : la connaissance du lexème courant
suffit pour la plupart des méthodes utilisées
• et malheureusement, pour certains langages (C notamment), la
reconnaissance d’un lexème dépend du contexte grammatical dans
lequel il se trouve

19
Analyse lexicale

• Chaque lexème est un mot d’un langage


• Dans la plupart des cas, langage qui peut être représenté par une
expression régulière,
• par exemple ((A − Z ) + (a − z))((A − Z ) + (a − z) + (0 − 9))∗ pour
reconnaı̂tre des identificateurs du genre X , Compteur , i3, R2D2, . . .
• Langage fini pour de nombreux lexèmes : +, ==, for , . . .
• L’analyseur lexical est donc un (gros) automate fini déterministe qui
reconnaı̂t l’union des langages des lexèmes
• un état terminal correspond à la reconnaissance d’un mot d’un des
langages des lexèmes

20
Fragment d’automate lexical

q2

f
a-z

q1 a-z sauf f q3 a-z

i a-z sauf i 0-9

q0 0-9 q4 . q5 0-9 q6

=
0-9
q7 = q8

21
Analyse lexicale

• Certains lexèmes sont préfixes d’un autre


• +, +=, ++ ; = et ==
• mots-clés et identificateurs (for et forme)
• entiers et réels (3 et 3.14)
• Le principe est de reconnaı̂tre le mot le plus long
• Un état terminal n’implique donc pas toujours l’arrêt de l’automate :
il peut continuer, et éventuellement revenir en arrière au dernier état
final rencontré

22
Reconnaissance contextuelle

• Il existe des langages où une forme lexicale peut correspondre à


différents lexèmes selon le contexte
• selon le contexte gauche : par exemple, if reconnu comme mot-clé
uniquement s’il est au début d’une instruction
• selon le contexte droit : par exemple if reconnu comme mot-clé
uniquement s’il est suivi d’une parenthèse
• Combinaison des deux

23
Problèmes de la reconnaissance contextuelle

• Dans des langages mal définis


• Pour les langages de programmation, dans des langages anciens
(Fortran, partiellement C, . . .)
• Ils ne peuvent en général pas être résolus par le seul analyseur
lexical : les contextes sont le plus souvent des langages
non-contextuels reconnus par l’analyseur syntaxique
→ Donc forte interaction entre les deux analyseurs
• Entraine des problèmes de lisibilité, de fiabilité et des difficultés à la
maintenance et aux extensions
• C’est pourquoi les langages modernes de programmation évitent ces
questions de reconnaissance contextuelle
• Mais pas les langages de script, de description, . . . conçus la plupart
du temps par des non spécialistes des langages

24
Exemple de problème de la reconnaissance contextuelle

• en Fortran, les espaces sont non significatifs


• DO12i = 1.25 : identificateur DO12i, opérateur d’affectation =, réel
1.25
• DO12i = 1,25 : mot-clé DO, etiquette 12, variable i : boucle qui se
termine à l’énoncé étiqueté 12 pour i allant de 1 à 25
• d’après la légende, on aurait perdu une fusée du projet Mercury à
cause d’un ’.’ à la place d’une ’,’ (à moins que ce ne soit l’inverse. . .)
• Dans la plupart des langages de programmation actuels, les espaces
sont significatifs, et les mots-clés sont réservés

25
Générateurs d’analyseurs lexicaux

• Langage C : lex ou flex


• Langage Ada : Alex
• Langage Java : Jflex
• Langage OCaml : OCamllex

26
Construire un analyseur lexical avec lex

compilateur (f)lex
programme source (f)lex lex nom.l nom.yy.c
nom.l flex nom.l

compilateur C
gcc nom.yy.c -ll
nom.yy.c a.out
gcc nom.yy.c -lfl

27
Spécifications en lex

déclarations
%%
règles de traduction
%%
procédures auxiliaires

28
Déclarations

• La section des déclarations comprend des


• déclarations de variables,
• constantes littérales
• définitions régulières
• Une constante littérale est un identificateur qui est déclaré pour
représenter une constante
• Une définition régulière permet d’associer un nom à une expression
régulière

29
Règles de traduction

• Les règles de traduction sont des instructions de la forme :


exp1 action1
exp2 action2
...
expn actionn

• chaque expi est une expression régulière


• chaque actioni est une suite d’instruction en C qui décrit quelle
action l’analyseur lexical devrait réaliser quand un lexème concorde
avec le modèle expi
• Les procédures auxilliaires sont les fonctions facultatives qui
pourraient être utiles dans les actions.

30
Analyseur lexical

• Analyseur lexical activé par l’analyseur syntaxique :


• Lit le texte d’entrée, caractère par caractère
• Cherche le plus long préfixe du texte d’entrée qui corresponde à l’une
des expressions régulières expi
• Exécute alors l’action actioni
• Action : rend le contrôle à l’analyseur syntaxique
• Sinon, l’analyseur lexical continue à chercher d’autres lexèmes
jusqu’à ce qu’une action rende le contrôle à l’analyseur syntaxique
• La recherche répétée de lexèmes jusqu’à un retour explicite permet à
l’analyseur lexical de traiter les espaces et les commentaires de
manière simple
• Seule information retournée à l’analyseur syntaxique : l’unité
lexicale
• Pour passer une valeur d’attribut donnant des informations sur le
lexème, on peut l’affecter à une variable globale appelée yylval.

31
Tableau des expressions régulières (1/2)

expression reconnaı̂t exemple


c tout caractère c qui n’est pas un opérateur a
\c caractère littéral c \+
“s” la chaı̂ne de caractère s “abc*”
r1 r2 r1 suivie de r2 ab
. tout caractère sauf fin de ligne a.b
ˆ début de ligne ^abc
$ fin de ligne abc$
[s] tout caractère appartenant à s [abc]
[^s] tout caractère n’appartenant pas à s [^abc]
r∗ 0 ou plusieurs occurences de r a∗
r+ 1 ou plusieurs occurences de r a+
r? 0 ou 1 occurence de r a?

32
Tableau des expressions régulières (2/2)

expression reconnaı̂t exemple


r{m} m occurences de r a{3}
r{m,n} entre m et n occurences de r a{3,8}
r1 |r2 r1 ou r2 a|b
r1 /r2 r1 si elle est suivie de r2 abc/123
(r) r (a|b)∗
\n retour à la ligne
\t tabulation

33
Exemple – déclarations

%{
/* définitions des constantes littérales */
PPQ, PPE, EGA, DIF, PGQ, PGE, SI, ALORS, SINON, ID, NB, OPREL
%}

/* définitions régulières */
delim [ \n\t]
bl {delim}+
lettre [A-Za-z]
chiffre [0-9]
id {lettre}+ ({lettre}|{chiffre})∗
nombre {chiffre}+ (\.{chiffre}+ )? (E[+\-]? {chiffre}+ )?

%%

34
Exemple – règles de traduction

{bl} {/* pas d’action et pas de retour */}


si {return(SI);}
alors {return(ALORS);}
sinon {return(SINON);}
{id} {yylval = RangerId(); return(ID);}
{nombre} {yylval = RangerNb(); return(NB);}
“<” {yylval = PPQ; return(OPREL);}
“<=” {yylval = PPE; return(OPREL);}
“=” {yylval = EGA; return(OPREL);}
“<>” {yylval = DIF; return(OPREL);}
“>” {yylval = PGQ; return(OPREL);}
“>=” {yylval = PGE; return(OPREL);}

%%

35
Exemple – procédures auxiliaires

RangerId() {
/* Procédure pour ranger dans la table des symboles le lexème
dont le premier caractère est pointé par yytext et dont la
longueur est yyleng et retourner un pointeur sur son entrée */
}

RangerNb() {
/* procédure similaire pour ranger un lexème qui est un
nombre */
}

36
Analyse syntaxique
Qu’est ce que l’analyse syntaxique ?

• L’analyse syntaxique a pour but :


• de vérifier que le texte d’entrée est conforme à la grammaire du
langage source
• d’indiquer les erreurs de syntaxe
• de construire une représentation intermédiaire pour les autres
modules du compilateur
→ arbre de syntaxe abstraite, utilisé par la suite de la compilation
• Ne s’occupe pas des aspects contextuels de la syntaxe
• par exemple détecter l’erreur dans int i; . . .; i = “abcd”;
• c’est le rôle de l’analyse sémantique, qui travaille sur la
représentation intermédiaire
• Représentation unique du texte source → l’analyse doit être
déterministe, si possible linéaire (éviter notamment les retours en
arrière)

38
Types d’analyseurs syntaxiques

• Analyseur syntaxique descendant, ou analyseur prédictif


• Construit l’arbre de dérivation à partir de sa racine et en effectuant
des dérivations en considérant la tête des règles de production et en
faisant des dérivations les plus à gauche
• Famille des analyseurs LL (left scanning, leftmost derivation)
• JavaCC, ANTLR, LLGen, . . .
• Analyseur syntaxique ascendant ou par décalage-réduction
• Construit l’arbre de dérivation à partir de ses feuilles et en
effectuant des dérivations en considérant la partie droite des règles
de production et en faisant des dérivations les plus à gauche
• Famille des analyseurs LR (left scanning, rightmost derivation)
• YACC/Bison

39
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :
S

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :
S →
− aSbT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :
S →
− aSbT →
− acT bT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :
S →
− aSbT →
− acTbT →
− accbT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →
− acTbT →
− accbT →
− accbbS

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →
− acTbT →
− accbT →
− accbbS →
− accbbaSbT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc
⇒ mène à un échec

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :
accbbadbc ←
− acT bbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc ←
− aSbbaSbc

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc ←
− aSbbaSbc ←
− aSbbaSbT

40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc ←
− aSbbaSbc ←
− aSbbaSbT

− aSbbS
40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc ←
− aSbbaSbc ←
− aSbbaSbT

− aSbbS ←
− aSbT
40
Exemple
Soit G = hV , Σ, P, Si avec
• Σ = {a, b, c, d}
• V \ Σ = {S, T }
• 6 règles de production :
• S → aSbT |cT |d
• T → aT |bS|c
• Soit w = accbbadbc
Analyse LL :

S →
− aSbT →− acTbT →
− accbT →
− accbbS →
− accbbaSbT

− accbbadbT →
− accbbadbc

Analyse LR :

accbbadbc ←
− acTbbadbc ←
− aSbbadbc ←
− aSbbaSbc ←
− aSbbaSbT

− aSbbS ←
− aSbT ←−S
40
Constructeur d’analyseur LR yacc/bison

• yacc : Yet Another Compiler Compiler (Unix)


• bison en version libre (Linux)
• 1ère version dans les années 70 par Stephen Curtis Johnson
• Prend une grammaire hors contexte en entrée, produit l’analyseur
correspondant
• Le programme produit est en langage C

41
Construire un analyseur syntaxique avec yacc

compilateur yacc/bison
spécification yacc/bison yacc nom.y
bison nom.y nom.tab.c
nom.y

compilateur C

nom.tab.c gcc nom.tab.c -ly a.out

42
Spécifications en yacc

déclarations
%%
règles de production et routines sémantiques
%%
routines C et bloc principal

43
Déclarations

• La section des déclarations contient 2 parties optionnelles


• 1ère partie : déclarations en C
• délimitées par %{ et %}
• déclarations des variables temporaires utilisées par les règles de
traduction
• procédures de la deuxième et troisième section
• 2nde partie : déclarations d’unités lexicales de la grammaire
• Symboles terminaux :
• unités lexicales, déclarées par %token
%token NOMBRE
• caractères, entre quotes : ’a’, ’+’
• Symboles non terminaux : chaı̂nes de caractères non déclarées
comme unités lexicales

44
Règles de production

• Une règle de production de la grammaire du type :


non-terminal → alt1 | alt2 | . . . | altn
s’écrirait en yacc :
non-terminal : alt1 {action sémantique 1}
| alt2 {action sémantique 2}
...
| altn {action sémantique n}
;
• La partie gauche de la première règle de production est l’axiome de
la grammaire

45
Actions sémantiques

• Une action sémantique est une suite d’instructions en C


• Elles sont exécutées à chaque fois qu’il y a réduction par la
production associée
• Syntaxe d’une action sémantique :
• Symbole $$ référence la valeur de l’attribut associé au non terminal
de la partie gauche de la règle
• Symbole $i représente la valeur associée au ième symbole (terminal
ou non) en partie droite de la règle.
• Exemple :
expr : expr ’+’ term {$$ = $1 + $3}
;

46
Routines annexes

• En langage C
• Un analyseur lexical nommé yylex() doit être fourni
• D’autres procédures comme les routines de récupération d’erreur
peuvent être ajoutées si nécessaire
• L’analyseur lexical yylex() produit des couples formés d’une unité
lexicale et de la valeur de l’attribut associé
• Si une unité lexicale est retournée, elle doit être déclarée dans la
première section de la spécification yacc
• La valeur de l’attribut associée à une unité lexicale est communiquée
à l’analyseur syntaxique par l’intermédiaire de la variable yylval
prédéfinie dans yacc

47
Exemple

• Grammaire des expressions arithmétiques :


E → E + T |T
T → T ∗ F |F
F → (E )|chiffre
• L’unité lexicale chiffre désigne un chiffre unique compris entre 0 et 9

48
Exemple – déclarations et règles de production

%{
#include <ctype.h>
%}
%token CHIFFRES
%%

ligne : expr ’\n’ {printf(%d\n, $1);}


;
expr : expr ’+’ term {$$ = $1 + $3;}
| term
;
term : term ’*’ facteur {$$ = $1 * $3;}
| facteur
;
facteur : ’(’ expr ’)’ {$$ = $2;}
| CHIFFRE
;

%% 49
Exemple – Routines annexes

yylex()
{
int c ;
c = getchar() ;
if (isdigit(c))
{
yyval = c - ’0’ ;
return CHIFFRE ;
}
return c
}

50
Utilisation conjointe de lex et yacc

• lex a été conçu pour produire des analyseurs lexicaux qui peuvent
être utilisés avec des analyseurs syntaxiques faits avec yacc
• Pour utiliser lex, il faut remplacer la routine yylex() par la clause :
#include "lex.yy.c"
• Spécifier chaque action lex de façon à ce qu’elle retourne un
terminal connu de yacc

51
Utilisation conjointe de lex et yacc

• Spécification lex : fichier nom.l


• Spécification yacc : fichier synt.y
• Compilation :
lex nom.l
yacc synt.y
gcc -ly -ll y.tab.c
• On obtient un exécutable a.out qui permet de traduire le langage
désiré

52
Analyse sémantique
Analyse sémantique - pourquoi ?

• Correction syntaxique insuffisante


• Exemple : 3 + true > 2 est syntaxiquement correct
⇒ Nécessité d’une analyse sémantique

54
Analyse sémantique - c’est quoi ?

• Dans le compilateur d’un langage de programmation :


• Calcul d’un arbre abstrait
• Décoré par des informations qui préparent la génération de code (ex :
adresses mémoire)
• Vérifications sémantiques : de type, des déclarations, etc.
• Applications de traitement de données textuelles : calculs divers.

55
Analyse sémantique - comment ?

• L’analyse sémantique calcule des données (ex : types, arbres)


⇒ Comment exprimer ces calculs ?
• Le plus naturel est de le faire en fonction de sa grammaire : on parle
de traduction dirigée par la syntaxe
⇒ On enrichit les grammaires algébriques par 2 concepts :
• données
• calculs
• et on obtient une grammaire attribuée

56
Grammaire attribuée, informellement

• C’est une grammaire algébrique, plus :


• des attributs (les données) associés aux terminaux et non-terminaux
• des règles (ou actions sémantiques) associées aux productions (les
calculs des données)
• Exemple :
• E →E +T
• {E0 .val = E1 .val + T .val}

57
Conclusion
Conclusion

Partie analyse : sépare les 6= constituants Programme source


du prog. source et produit une
représentation intermédiaire Analyseur lexical

Analyseur syntaxique

Analyseur sémantique
Table des
Erreurs
symboles
Générateur de code intermédiaire

Optimisateur de code

Générateur de code
Partie synthèse : génère le prog. cible à

Programme cible partir de la représentation intermédiaire

59

Vous aimerez peut-être aussi