diff options
-rw-r--r-- | doc/rapport.md | 7 | ||||
-rw-r--r-- | src/generator.c | 81 | ||||
-rw-r--r-- | src/symbol_table.c | 42 |
3 files changed, 72 insertions, 58 deletions
diff --git a/doc/rapport.md b/doc/rapport.md index d1c0226..28f8446 100644 --- a/doc/rapport.md +++ b/doc/rapport.md | |||
@@ -96,6 +96,13 @@ Dans les langages tel que le C, l'associativité se fait à gauche. | |||
96 | On déclare donc `%left ,` pour l'indiquer à Bison. | 96 | On déclare donc `%left ,` pour l'indiquer à Bison. |
97 | 97 | ||
98 | 98 | ||
99 | # Analyse sémantique | ||
100 | |||
101 | Le compilateur gère l'analyse sémantique. | ||
102 | Par exemple l'opération `tab[1] * 3` est légale mais `'a' * 'b'` ne l'est pas. La grammaire l'accepte, mais l'analyse sémantique à parti des attributs interdits. | ||
103 | |||
104 | |||
105 | |||
99 | # Génération de code cible | 106 | # Génération de code cible |
100 | 107 | ||
101 | ## Gestion de la mémoire | 108 | ## Gestion de la mémoire |
diff --git a/src/generator.c b/src/generator.c index bb95e08..601f482 100644 --- a/src/generator.c +++ b/src/generator.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "generator.h" | 6 | #include "generator.h" |
7 | 7 | void yyerror(char *); | |
8 | // ----- GLOBAL FUNCTIONS ----- | 8 | // ----- GLOBAL FUNCTIONS ----- |
9 | 9 | ||
10 | void gen_prologue() { | 10 | void gen_prologue() { |
@@ -21,7 +21,6 @@ void gen_prologue_continue(int *bss_done) { | |||
21 | fprintf(output, "format_int_in: db \"%%d\", 0\n"); | 21 | fprintf(output, "format_int_in: db \"%%d\", 0\n"); |
22 | fprintf(output, "format_char_in: db \"%%c\", 0\n\n"); | 22 | fprintf(output, "format_char_in: db \"%%c\", 0\n\n"); |
23 | fprintf(output, "section .bss\n"); | 23 | fprintf(output, "section .bss\n"); |
24 | |||
25 | fprintf(output, "globals: resq %d\n", nb_globals); | 24 | fprintf(output, "globals: resq %d\n", nb_globals); |
26 | fprintf(output, "section .text\n\nglobal _start\n"); | 25 | fprintf(output, "section .text\n\nglobal _start\n"); |
27 | fprintf(output, "\nprinte: ;print needs an argument in rax\n"); | 26 | fprintf(output, "\nprinte: ;print needs an argument in rax\n"); |
@@ -121,8 +120,8 @@ void gen_function_end_declaration(const char name[], int return_type, | |||
121 | 120 | ||
122 | void gen_function_return(Type expect, Type actual) { | 121 | void gen_function_return(Type expect, Type actual) { |
123 | if (actual != expect) { | 122 | if (actual != expect) { |
124 | fprintf(stderr, "Return type mismatch at line %d.\n", lineno); | 123 | yyerror("Return type mismatch"); |
125 | exit(1); | 124 | return; |
126 | } | 125 | } |
127 | if (actual != VOID_T) | 126 | if (actual != VOID_T) |
128 | fprintf(output, "pop rax\n"); | 127 | fprintf(output, "pop rax\n"); |
@@ -180,12 +179,12 @@ void gen_check(const char name[], Scope scope) { | |||
180 | // ----- READ AND PRINT FUNCTIONS ----- | 179 | // ----- READ AND PRINT FUNCTIONS ----- |
181 | void gen_reade(const char name[], Scope scope) { | 180 | void gen_reade(const char name[], Scope scope) { |
182 | if (is_read_only(name, scope)) { | 181 | if (is_read_only(name, scope)) { |
183 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 182 | yyerror("Symbol is read only"); |
184 | exit(1); | 183 | return; |
185 | } | 184 | } |
186 | 185 | ||
187 | if (loc_lookup(name) != INT) { | 186 | if (loc_lookup(name) != INT) { |
188 | fprintf(stderr, "Need to be a INT in the reade() function\n"); | 187 | yyerror("Need to be a INT in the reade() function"); |
189 | return; | 188 | return; |
190 | } | 189 | } |
191 | int l_addr = loc_get_addr(name); | 190 | int l_addr = loc_get_addr(name); |
@@ -200,12 +199,12 @@ void gen_reade(const char name[], Scope scope) { | |||
200 | 199 | ||
201 | void gen_readc(const char name[], Scope scope) { | 200 | void gen_readc(const char name[], Scope scope) { |
202 | if (is_read_only(name, scope)) { | 201 | if (is_read_only(name, scope)) { |
203 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 202 | yyerror("Symbol is read only"); |
204 | exit(1); | 203 | return; |
205 | } | 204 | } |
206 | 205 | ||
207 | if (loc_lookup(name) != CHAR) { | 206 | if (loc_lookup(name) != CHAR) { |
208 | fprintf(stderr, "Need to be a CHAR in the readc() function\n"); | 207 | yyerror("Need to be a CHAR in the readc() function"); |
209 | return; | 208 | return; |
210 | } | 209 | } |
211 | int l_addr = loc_get_addr(name); | 210 | int l_addr = loc_get_addr(name); |
@@ -232,7 +231,7 @@ void gen_print(int type) { | |||
232 | fprintf(output, "call printe\n"); | 231 | fprintf(output, "call printe\n"); |
233 | break; | 232 | break; |
234 | default: | 233 | default: |
235 | fprintf(stderr, "Error print, supposed to have type CHAR or INT or TAB\n"); | 234 | yyerror("Error print, supposed to have type CHAR or INT or TAB"); |
236 | } | 235 | } |
237 | } | 236 | } |
238 | 237 | ||
@@ -267,8 +266,8 @@ int gen_assign(const char ident[], Scope scope) { | |||
267 | int g_addr = glo_get_addr(ident); | 266 | int g_addr = glo_get_addr(ident); |
268 | 267 | ||
269 | if (is_read_only(ident, scope)) { | 268 | if (is_read_only(ident, scope)) { |
270 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | 269 | yyerror("Symbol is read only"); |
271 | exit(1); | 270 | return loc_lookup(ident); |
272 | } | 271 | } |
273 | 272 | ||
274 | switch (scope) { | 273 | switch (scope) { |
@@ -293,20 +292,26 @@ int gen_assign_tab(const char ident[], Scope scope) { | |||
293 | int g_addr = glo_get_addr(ident); | 292 | int g_addr = glo_get_addr(ident); |
294 | 293 | ||
295 | if (is_read_only(ident, scope)) { | 294 | if (is_read_only(ident, scope)) { |
296 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | 295 | yyerror("Symbol is read only"); |
297 | exit(1); | 296 | return loc_lookup(ident); |
298 | } | 297 | } |
299 | 298 | ||
300 | switch (scope) { | 299 | switch (scope) { |
301 | case GLOBAL: | 300 | case GLOBAL: |
302 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", g_addr, ident); | 301 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
302 | "rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", | ||
303 | g_addr, ident); | ||
303 | return glo_lookup(ident); | 304 | return glo_lookup(ident); |
304 | case LOCAL: | 305 | case LOCAL: |
305 | if (l_addr != -1) { | 306 | if (l_addr != -1) { |
306 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,rbp\nsub rax,rcx\npop QWORD [rax - %d] ;%s\n", l_addr, ident); | 307 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
308 | "rax,rbp\nsub rax,rcx\npop QWORD [rax - %d] ;%s\n", | ||
309 | l_addr, ident); | ||
307 | return loc_lookup(ident); | 310 | return loc_lookup(ident); |
308 | } else { | 311 | } else { |
309 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", g_addr, ident); | 312 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
313 | "rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", | ||
314 | g_addr, ident); | ||
310 | return glo_lookup(ident); | 315 | return glo_lookup(ident); |
311 | } | 316 | } |
312 | default: | 317 | default: |
@@ -315,8 +320,8 @@ int gen_assign_tab(const char ident[], Scope scope) { | |||
315 | } | 320 | } |
316 | 321 | ||
317 | void gen_or(int left, int right, int idx) { | 322 | void gen_or(int left, int right, int idx) { |
318 | check_expected_types(left, INT,TAB); | 323 | check_expected_types(left, INT, TAB); |
319 | check_expected_types(right, INT,TAB); | 324 | check_expected_types(right, INT, TAB); |
320 | 325 | ||
321 | fprintf(output, ";a OR c\n"); | 326 | fprintf(output, ";a OR c\n"); |
322 | fprintf(output, "pop rax\n"); | 327 | fprintf(output, "pop rax\n"); |
@@ -333,8 +338,8 @@ void gen_or(int left, int right, int idx) { | |||
333 | } | 338 | } |
334 | 339 | ||
335 | void gen_and(int left, int right, int idx) { | 340 | void gen_and(int left, int right, int idx) { |
336 | check_expected_types(left, INT,TAB); | 341 | check_expected_types(left, INT, TAB); |
337 | check_expected_types(right, INT,TAB); | 342 | check_expected_types(right, INT, TAB); |
338 | 343 | ||
339 | fprintf(output, ";a AND c\n"); | 344 | fprintf(output, ";a AND c\n"); |
340 | fprintf(output, "pop rax\n"); | 345 | fprintf(output, "pop rax\n"); |
@@ -351,8 +356,8 @@ void gen_and(int left, int right, int idx) { | |||
351 | } | 356 | } |
352 | 357 | ||
353 | void gen_eq(const char op[], int left, int right, int idx) { | 358 | void gen_eq(const char op[], int left, int right, int idx) { |
354 | check_expected_types(left, INT,TAB); | 359 | check_expected_types(left, INT, TAB); |
355 | check_expected_types(right, INT,TAB); | 360 | check_expected_types(right, INT, TAB); |
356 | 361 | ||
357 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); | 362 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); |
358 | 363 | ||
@@ -368,8 +373,8 @@ void gen_eq(const char op[], int left, int right, int idx) { | |||
368 | } | 373 | } |
369 | 374 | ||
370 | void gen_order(const char op[], int left, int right, int idx) { | 375 | void gen_order(const char op[], int left, int right, int idx) { |
371 | check_expected_types(left, INT,TAB); | 376 | check_expected_types(left, INT, TAB); |
372 | check_expected_types(right, INT,TAB); | 377 | check_expected_types(right, INT, TAB); |
373 | 378 | ||
374 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); | 379 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); |
375 | 380 | ||
@@ -389,8 +394,8 @@ void gen_order(const char op[], int left, int right, int idx) { | |||
389 | } | 394 | } |
390 | 395 | ||
391 | void gen_addsub(char op, int left, int right) { | 396 | void gen_addsub(char op, int left, int right) { |
392 | check_expected_types(left, INT,TAB); | 397 | check_expected_types(left, INT, TAB); |
393 | check_expected_types(right, INT,TAB); | 398 | check_expected_types(right, INT, TAB); |
394 | 399 | ||
395 | switch (op) { | 400 | switch (op) { |
396 | case '+': | 401 | case '+': |
@@ -405,8 +410,8 @@ void gen_addsub(char op, int left, int right) { | |||
405 | } | 410 | } |
406 | 411 | ||
407 | void gen_divstar(char op, int left, int right) { | 412 | void gen_divstar(char op, int left, int right) { |
408 | check_expected_types(left, INT,TAB); | 413 | check_expected_types(left, INT, TAB); |
409 | check_expected_types(right, INT,TAB); | 414 | check_expected_types(right, INT, TAB); |
410 | 415 | ||
411 | switch (op) { | 416 | switch (op) { |
412 | case '*': | 417 | case '*': |
@@ -423,7 +428,7 @@ void gen_divstar(char op, int left, int right) { | |||
423 | } | 428 | } |
424 | 429 | ||
425 | int gen_signed_expr(char op, int type) { | 430 | int gen_signed_expr(char op, int type) { |
426 | check_expected_types(type, INT,TAB); | 431 | check_expected_types(type, INT, TAB); |
427 | switch (op) { | 432 | switch (op) { |
428 | case '+': | 433 | case '+': |
429 | fprintf(output, ";+F\n"); | 434 | fprintf(output, ";+F\n"); |
@@ -439,7 +444,7 @@ int gen_signed_expr(char op, int type) { | |||
439 | } | 444 | } |
440 | 445 | ||
441 | int gen_negate_expr(int type) { | 446 | int gen_negate_expr(int type) { |
442 | check_expected_types(type, INT,TAB); | 447 | check_expected_types(type, INT, TAB); |
443 | fprintf(output, ";!F\npop rax\nxor rax,1\npush rax\n"); | 448 | fprintf(output, ";!F\npop rax\nxor rax,1\npush rax\n"); |