salut à tous !
voilà mon problème, pour notre projet de fin de semestre en master informatique, nous devons par groupe de 8 créer un compilateur / interprèteur d'un langage appelé minijaja dont la grammaire peut être consultée ici : http://lifc.univ-fcomte.fr/~bouquet/Enseignement/Compilation/minijaja.html
nous avions le choix entre l'utilisation d'un parser javaCC / jjTree ou Flex et Bison. C'est sur ce deuxième élément que s'est porté notre choix : nous utilisons donc Flex et Bison sous un environnement Linux.
voici le contenu de mon fichier utilisé par Flex : terminaux.l
voici le contenu de mon fichier utilisé par Bison : terminaux.y
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 %{ #include "terminaux.tab.h" extern int yylval; %} %x COMMENTS %% "class" { return CLASS; } "{" { return BEGINBLOCK; } "}" { return ENDBLOCK; } "==" { return EQUAL; } "=" { return ASSIGN; } "!" { return NOT; } "+=" { return PLUSEQUAL; } ";" { return SEMICOLON; } "[" { return LEFTBRACKET; } "]" { return RIGHTBRACKET; } "final" { return FINAL; } ")" { return RIGHTPARENTHESE; } "(" { return LEFTPARENTHESE; } "main" { return MAIN; } "," { return COMMA; } "++" { return PLUSPLUS; } "return" { return RETURN; } "if" { return IF; } "else" { return ELSE; } "while" { return WHILE; } "-" { return MINUS; } "&&" { return AND; } "||" { return OR; } ">" { return GREATER; } "+" { return PLUS; } "*" { return MULT; } "/" { return DIVIDE; } "true" { return TRUE; } "false" { return FALSE; } "void" { return VOID; } "int" { return INTEGER; } "boolean" { return BOOLEAN; } [0-9]+ { /*yylval = atoi(yytext);*/ return NUMBER; } [a-zA-Z_][0-9a-zA-Z_]* { return IDENTIFIER; } [ \t]+ { ; /* espaces vierges */ } (\r?\n) { ; /* ligne vide : reconnait les CR-LF (windows) et les LF (unix) */ } "//".*\n { ; /* commentaires */ } "/*" { BEGIN COMMENTS; } <COMMENTS>. | <COMMENTS>\n { ; } <COMMENTS>"*/" { BEGIN 0; } . { /*yyerror("illegal token");*/ } %%
voici les commandes que j'exécute pour tester la grammaire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 %{ #include <stdio.h> void yyerror(char * msg) { fprintf(stderr, "%s\n", msg); } %} /* l'element par lequel commence l'analyse, ce ne doit pas etre un token */ %start root %token CLASS %token BEGINBLOCK %token ENDBLOCK %token EQUAL %token ASSIGN %token NOT %token PLUSEQUAL %token SEMICOLON %token LEFTBRACKET %token RIGHTBRACKET %token FINAL %token RIGHTPARENTHESE %token LEFTPARENTHESE %token MAIN %token COMMA %token PLUSPLUS %token RETURN %token IF %token ELSE %token WHILE %token MINUS %token AND %token OR %token GREATER %token PLUS %token MULT %token DIVIDE %token TRUE %token FALSE %token VOID %token INTEGER %token BOOLEAN %token NUMBER %token IDENTIFIER %% root: classe ; classe: CLASS ident BEGINBLOCK decls methmain ENDBLOCK ; ident: IDENTIFIER ; decls: | decl SEMICOLON decls ; decl: var | methode ; vars: | var SEMICOLON vars ; var: typemeth ident vexp | typemeth ident LEFTBRACKET exp RIGHTBRACKET | FINAL type ident vexp ; vexp: | ASSIGN exp ; methode: typemeth ident LEFTPARENTHESE entetes RIGHTPARENTHESE BEGINBLOCK vars instrs ENDBLOCK ; methmain: MAIN BEGINBLOCK vars instrs ENDBLOCK ; entetes: | entete COMMA entetes | entete ; entete: type ident ; instrs: | instr SEMICOLON instrs ; instr: ident1 ASSIGN exp | ident1 PLUSEQUAL exp | ident1 PLUSPLUS | ident LEFTPARENTHESE listexp RIGHTPARENTHESE | RETURN exp | IF exp BEGINBLOCK instrs ENDBLOCK | IF exp BEGINBLOCK instrs ENDBLOCK ELSE BEGINBLOCK instrs ENDBLOCK | WHILE exp BEGINBLOCK instrs ENDBLOCK ; listexp: | exp COMMA listexp | exp ; exp: NOT exp1 | MINUS exp1 | exp AND exp1 | exp OR exp1 | exp1 ; exp1: exp1 EQUAL exp2 | exp1 GREATER exp2 | exp2 ; exp2: exp2 PLUS terme | exp2 MINUS terme | terme ; terme: terme MULT fact | terme DIVIDE fact | fact ; fact: ident1 | ident LEFTPARENTHESE listexp RIGHTPARENTHESE | TRUE | FALSE | NUMBER | LEFTPARENTHESE exp RIGHTPARENTHESE ; ident1: ident | ident LEFTBRACKET exp RIGHTBRACKET ; typemeth: VOID | type ; type: INTEGER | BOOLEAN ; %% main() { yyparse(); }
comme vous pouvez le voir, la génération de l'analyseur s'effectue très bien en C. seulement, notre projet doit utiliser du C++, c'est une contrainte du cahier des charges. Est il possible de créer cet analyseur en C++ depuis Flex et Bison ? j'ai vaguement entendu parler de Flex++ et Bison++, est une bonne solution ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 ~/compil2 $ flex terminaux.l && bison -d terminaux.y ~/compil2 $ gcc -o test lex.yy.c terminaux.tab.c -ll ~/compil2 $ ./test class C { /* un commentaire * sur plusieurs lignes. */ int x = 2; int y = 3; int somme(int a, int b) { return x + y; }; main { int z = somme(x, y); } } ~/compil2 $
Nous devrons stocker l'arbre syntaxique, et pour cela notre structure (en cours de développement) sera faite en C++. J'avais éventuellement pensé à appeler les fonctions de création de la structure (C++) depuis l'analyseur (C). Est ce possible ?
avez vous déjà utilisé ces outils ? que me conseillez vous ? J'espère que vous pourrez m'aider car c'est très important, sans cet analyseur, nous ne pourrons pas avancer dans notre projet.
Partager