Académique Documents
Professionnel Documents
Culture Documents
Lex Yacc
Lex Yacc
/* fichier calc.y */
%token NOMBRE /* liste des terminaux */
%%
expression: expression ’+’ terme
| expression ’-’ terme
| terme
;
terme: terme ’*’ facteur
| terme ’/’ facteur
| facteur
;
facteur: ’(’ expression ’)’
| ’-’ facteur
| NOMBRE
;
%%
int yyerror(void)
{ fprintf(stderr, "erreur de syntaxe\n"); return 1;}
/* fichier calc.l */
%{
/* fichier dans lequel est defini la macro constante NOMBRE */
#include "calc.tab.h"
%}
%%
[0-9]+ {return NOMBRE;}
[ \t] ; /* ignore les blancs et tabulations */
\n return 0;
. return yytext[0];
%%
/*fichier calc.c */
int main(void)
{
yyparse();
}
◮ $ bison -d calc.y
produit les fichiers :
◮ calc.tab.c qui contient le code en c de l’analyseur
◮ et calc.tab.h qui contient la définition des codes des unités
lexicales, afin qu’elles puissent être partagées par l’analyseur
syntaxique et l’analyseur lexical.
◮ $ flex calc.l
produit le fichier :
◮ lex.yy.c qui contient le code en c de l’analyseur lexical.
◮ $ gcc -o calc calc.c calc.tab.c lex.yy.c
produit l’executable :
◮ calc qui permet d’analyser des expressions arithmétiques.
%token NOMBRE
%%
calcul: expression {printf("%d\n",$1);}
;
expression: expression ’+’ terme {$$ = $1 + $3;}
| expression ’-’ terme {$$ = $1 - $3;}
| terme {$$ = $1;}
;
terme: terme ’*’ facteur {$$ = $1 * $3;}
| terme ’/’ facteur {$$ = $1 / $3;}
| facteur {$$ = $1;}
;
facteur: ’(’ expression ’)’ {$$ = $2;}
| ’-’ facteur {$$ = -$2;}
| NOMBRE {$$ = $1;}
;
%%
%{
#include "calc.tab.h"
%}
%%
[0-9]+ {yylval=atoi(yytext);return NOMBRE;}
[ \t] ; /* ignore les blancs et tabulations */
\n return 0;
. return yytext[0];
%%
◮ exemple 1
$ ./calc
1 + 6 * 4
25
$
◮ exemple 2
$ ./calc
1 / 2
0
$
Par défaut terminaux et non terminaux sont associés à un attribut à
valeur entière.
%{
#include "calc.tab.h"
%}
%%
[0-9]+|[0-9]*\.[0-9]+ {yylval.dval=atof(yytext);return NOMBRE;}
[ \t] ; /* ignore les blancs et tabulations */
\n return 0;
. return yytext[0];
%%
LEX = flex
YACC = bison -d
CC = gcc
calc.tab.c: calc.y
$(YACC) calc.y
lex.yy.c: calc.l
$(LEX) calc.l
Concaténation
ab
| Disjonction
a | b
* Etoile de Kleene
(a|b)*
{n} Répétition n fois
(a|b){3}
? Optionnalité (0 ou 1 fois)
a?
+ Une fois ou plus
a+
() Groupement d’expressions régulières
Modification de la priorité dans une expression
a(b|c)
%{
Partie 1 : déclarations pour le compilateur C
%}
Partie 2 : définitions régulières
%%
Partie 3 : règles
%%
Partie 4 : fonctions C supplémentaires
◮ Dans l’exemple précédent, toutes les règles qui ne sont pas liées à
l’état COMM peuvent aussi s’appliquer dans l’état COMM
◮ Pour éviter ce comportement, on utilise des états exclusifs : une
règle qui n’est liés à aucun état ne s’applique pas dans un état
exclusif.
%x COMM /* l’état COMM est exclusif */
%%
"/*" BEGIN COMM; /* on rentre dans l’état COMM */
<COMM>. ; /* on ignore tout ce qui se trouve */
<COMM>\n ; /* dans les commentaires */
<COMM>"*/" BEGIN INITIAL /* on revient à l’état standard */
%{
#include "syntaxe.tab.h"
union {int ival; char *sval; double fval;} yylval;
%}
%%
si {return SI;}
alors {return ALORS;}
sinon {return SINON;}
\$[A-Za-z]+ {yylval.sval=strdup(yytext);return ID_VAR;}
[0-9]+ {yylval.ival=atoi(yytext);return NOMBRE;}
[A-Za-z]+ {return ID_FCT;}
. {return yytext[0];}
%%
%{
Partie 1 : déclarations pour le compilateur C
%}
Partie 2 : déclarations pour YACC
%%
Partie 3 : schémas de traduction (productions + actions sémant
%%
Partie 4 : fonctions C supplémentaires
◮ Une directive union décrivant les types des valeurs associées aux
symboles terminaux et non terminaux.
◮ Les déclarations des symboles non terminaux, enrichis de leurs
types.
◮ Les symboles terminaux (à l’exception des symboles composés
d’un caractères) enrichis de leurs types.
◮ Les priorités des opérateurs ainsi que leur associativité.
%union {char *sval; int ival; double dval;}
%token <sval> VAR
%token <dval> NOMBRE
%type <dval> expression terme facteur
%left ’+’ ’-’
%left ’*’ ’/’
%nonassoc MOINSU
chaı̂ne à analyser : a ∗ a
a F
* * *
a F T T T T T E
D R R D D R R R
1 S → X
2 S → Y
3 X → a
4 Y → a
1 S → X b
2 S → Y c
3 X → a
4 Y → a
1 S → X
2 S → Y r
3 X → a r
4 Y → a
◮ Une grammaire est LR(k) s’il est possible d’effectuer une analyse
par décalage réduction sans conflit en s’autorisant à lire les k
symboles suivant le symbole courant.
◮ La grammaire suivante n’est pas LR(1) mais elle est LR(2)
1 S → X b c
2 S → Y b d
3 X → a
4 Y → a
◮ John Levine, Tony Mason, Doug Brown, lex & yacc, O’Reilly &
Associates, Inc.
◮ Henri Garreta, Polycopié du cours de compilation.
◮ Andrew Appel, Modern compiler implementation in C.
Cambridge University Press, 1998