%{ /* * UPEM / Compilation / Projet * Pacien TRAN-GIRARD, Adam NAILI * * TODO : * ------ * - arrays * */ int nb_globals = 0; #include "symbol_table.h" #include #include #include "generator.h" extern int lineno; int yylex(); void yyerror(char *); static Scope scope = GLOBAL; static Type return_type = VOID_T; static int bss_done = 0; static int num_label = 0; static int num_if = 0; static int num_while = 0; static int nb_param[255]; static int num_scope = -1; static int offset = 0; static int is_array = 0; static char fname[64]; %} %union { char caractere; int num; char ident[64]; int type; char comp[3]; char addsub; char divstar; } %token CARACTERE %token NUM %token IDENT %token ORDER EQ %token ADDSUB %token DIVSTAR %token OR AND CONST IF ELSE WHILE RETURN VOID PRINT READC READE %token TYPE %type Exp EB TB FB M E T F Parametres %type LValue Declarateur %left ',' %precedence ')' %precedence ELSE %% Prog: { gen_prologue(); } DeclConsts DeclVars DeclFoncts { gen_epilogue(); } ; DeclConsts: DeclConsts CONST ListConst ';' | ; ListConst: ListConst ',' IDENT '=' Litteral { gen_const($1, $3, scope); } | IDENT '=' Litteral { gen_const($1, $3, scope); } ; Litteral: NombreSigne { $$ = $1; } | CARACTERE { $$ = $1; } ; NombreSigne: NUM { $$ = $1; } | ADDSUB NUM { $$ = $1 == '-' ? - $2 : $2; } ; DeclVars: DeclVars TYPE Declarateurs ';' | ; Declarateurs: Declarateurs ',' Declarateur { if(!is_array){ gen_declaration($3, $0, scope); }else{ gen_tab_declaration($3, scope, offset); } } | Declarateur { if(!is_array){ gen_declaration($1, $0, scope); }else{ gen_tab_declaration($1, scope, offset); } } ; Declarateur: IDENT {strcpy($$,$1);is_array = 0;} | IDENT '[' NUM ']' {offset = $3;strcpy($$,$1);is_array=1;} ; DeclFoncts: DeclFoncts DeclFonct | DeclFonct ; DeclFonct: EnTeteFonct { scope = LOCAL; } Corps { gen_function_end_declaration(fname,return_type,nb_param[num_scope]); scope = GLOBAL; return_type = VOID_T; num_scope--; loc_clean_table(); } ; EnTeteFonct: TYPE IDENT PrologueCont {strcpy(fname,$2); return_type = gen_function_declaration($2, $1);} '(' Parametres ')' { nb_param[++num_scope] = $6 ; scope = GLOBAL;} | VOID IDENT PrologueCont {strcpy(fname,$2); return_type = gen_function_declaration($2, VOID_T);} '(' Parametres ')' { nb_param[++num_scope] = $6 ; scope = GLOBAL; } ; PrologueCont: {scope = LOCAL;gen_prologue_continue(&bss_done);}; Parametres: VOID {$$ = 0;} | ListTypVar { $$ = $1;} ; ListTypVar: ListTypVar ',' TYPE IDENT { gen_declaration($4, $3, scope); $$ = $1+1; } | TYPE IDENT { gen_declaration($2, $1, scope); $$ = 1; } ; Corps: '{' {int i; for(i=1;i<=nb_param[num_scope];i++){fprintf(output, "mov r8, [rbp + %d]\nmov [rbp - %d], r8\n", (nb_param[num_scope]-i+2)*8, i*8);} } DeclConsts DeclVars SuiteInstr '}' ; SuiteInstr: SuiteInstr Instr | ; Instr: Exp ';' | ';' | RETURN Exp ';' { gen_function_return(return_type, $2); } | RETURN ';' { gen_function_return(return_type, VOID_T);} | READE '(' IDENT ')' ';' { gen_reade($3, scope); } | READC '(' IDENT ')' ';' { gen_readc($3, scope); } | PRINT '(' Exp ')' ';' { gen_print($3);} | IF '(' Exp IfHandling')' Instr { gen_if_label($4); } | IF '(' Exp IfHandling')' Instr ELSE IfEndHandling Instr IfElseEndHandling | WHILE {fprintf(output,".upwhile%d:\n",num_while);}'(' Exp {fprintf(output,"pop rax\ncmp rax,0\njz .downwhile%d\n",num_while);}')' Instr {fprintf(output,"jmp .upwhile%d\n.downwhile%d:\n",num_while,num_while);num_while++;} | '{' SuiteInstr '}' ; IfHandling: { gen_if_start($$ = num_if++); }; IfEndHandling: { gen_if_end($-3); }; IfElseEndHandling: { gen_ifelse_end($-5); }; Exp: LValue '=' Exp { if(loc_lookup($1) != TAB){ $$ = gen_assign($1, scope); }else{ $$ = gen_assign_tab($1,scope); } } | EB ; EB: EB OR TB { gen_or($1, $3, num_label++); } | TB ; TB: TB AND FB { gen_and($1, $3, num_label++); } | FB ; FB: FB EQ M { gen_eq($2, $1, $3, num_label++); } | M ; M: M ORDER E { gen_order($2, $1, $3, num_label++); } | E ; E: E ADDSUB T { gen_addsub($2, $1, $3); } | T ; T: T DIVSTAR F { gen_divstar($2, $1, $3); } | F ; F: ADDSUB F { $$ = gen_signed_expr($1, $2); } | '!' F { $$ = gen_negate_expr($2); } | '(' Exp ')' { $$ = $2; } | LValue { if(loc_lookup($1) != TAB){ $$ = gen_value($1, scope); }else{ $$ = gen_value_tab($1,scope); } } | NUM { $$ = gen_num($1, scope); } | CARACTERE { $$ = gen_char($1, scope); } | IDENT '(' Arguments ')' { $$ = gen_function_call($1,$3); } ; LValue: IDENT { gen_check($1, scope); strcpy($$, $1);} | IDENT '[' Exp ']' { gen_check($1, scope); strcpy($$, $1);} ; Arguments: ListExp | {$$ = 0;} ; ListExp: ListExp ',' Exp {$$ = $1 + 1;} | Exp {$$ = 1;} ; %% void yyerror(char *msg){ fprintf(stderr, "%s at line %d\n", msg, lineno); } int main(int argc, char **argv) { char opt; output = stdout; while ((opt = getopt(argc, argv, "o:")) != -1) switch (opt) { case 'o': output = fopen(optarg, "w+"); if (output == NULL) { perror("Error opening output file: "); return -1; } break; default: fputs("Exiting due to invalid option.\n", stderr); return -1; } return yyparse(); }