# Compiler HW2 ## 問題 * Func_sig 功能的實作 * Lex 裡要多加 ```"\n" {}``` ,不然總行數(yylineno)會有錯誤 * Casting 的判斷 * 區分int float bool str 的 return * ## Token & Type ```c= /* Token without return */ %token LET MUT NEWLINE %token <s_val> INT FLOAT BOOL STR %token TRUE FALSE %token GEQ LEQ EQL NEQ LOR LAND %token ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN REM_ASSIGN %token IF ELSE FOR WHILE LOOP %token PRINT PRINTLN %token FUNC RETURN BREAK %token ARROW AS IN DOTDOT RSHIFT LSHIFT /* Token with return, which need to sepcify type */ %token <i_val> INT_LIT %token <f_val> FLOAT_LIT %token <s_val> STRING_LIT %token <s_val> ID /* Nonterminal with return, which need to sepcify type */ %type <i_val> primary_expression_1 %type <f_val> primary_expression_2 %type <s_val> primary_expression_3 %type <s_val> type_specifier ``` ## Precedence ```c= %left LOR %left LAND %left EQL NEQ %left '<' '>' GEQ LEQ %left LSHIFT RSHIFT %left '%' %left '+' '-' %left '*' '/' %right '!' %nonassoc LOWER_THAN_ELSE %nonassoc ELSE ``` ## Grammar ``` Grammar1 0 $accept: Program $end 1 Program: GlobalStatementList 2 GlobalStatementList: GlobalStatementList GlobalStatement 3 | GlobalStatement 4 GlobalStatement: FunctionDeclStmt blocks 5 | NEWLINE 6 FunctionDeclStmt: function_head '(' parameter_list ')' 7 | function_head '(' parameter_list ')' arrow_head 8 function_head: FUNC ID 9 arrow_head: ARROW type_specifier 10 left_mark: '{' 11 right_mark: '}' 12 blocks: left_mark statement_list right_mark 13 | blocks left_mark statement_list right_mark 14 parameter_list: %empty 15 | parameter_list_nonempty 16 parameter_list_nonempty: parameter_declaration 17 | parameter_list_nonempty ',' parameter_declaration 18 parameter_declaration: ID ':' type_specifier 19 statement_list: %empty 20 | statement_list statement 21 statement: declaration ';' 22 | assignment_statement ';' 23 | conditional_statement 24 | loop_statement 25 | print_statement ';' 26 | return_statement ';' 27 | break_statement ';' 28 | empty_statement 29 | function_call ';' 30 | expression 31 | left_mark statement_list right_mark 32 function_call: ID '(' term_list ')' 33 empty_statement: NEWLINE 34 loop_statement: WHILE expression blocks 35 | for_loop statement_list right_mark 36 | LOOP blocks 37 for_loop: FOR ID IN ID '{' 38 conditional_statement: IF expression blocks 39 | IF expression blocks ELSE blocks 40 print_statement: PRINT expression 41 | PRINTLN expression 42 return_statement: RETURN expression 43 break_statement: BREAK 44 | BREAK expression 45 expression: primary_expression_1 46 | primary_expression_2 47 | '"' primary_expression_3 '"' 48 | term 49 | expression '+' expression 50 | expression '-' expression 51 | expression '*' expression 52 | expression '/' expression 53 | expression '%' expression 54 | expression LSHIFT expression 55 | expression RSHIFT expression 56 | expression '<' expression 57 | expression '>' expression 58 | expression LEQ expression 59 | expression GEQ expression 60 | expression EQL expression 61 | expression NEQ expression 62 | expression LAND expression 63 | expression LOR expression 64 | '!' expression 65 | '-' expression 66 | '(' expression ')' 67 | '[' expression ']' 68 | function_call 69 | TRUE 70 | FALSE 71 primary_expression_1: INT_LIT 72 | INT_LIT AS type_specifier 73 | primary_expression_1 ',' primary_expression_1 74 | '[' primary_expression_1 ';' primary_expression_1 ']' 75 primary_expression_2: FLOAT_LIT 76 | FLOAT_LIT AS type_specifier 77 | primary_expression_2 ',' primary_expression_2 78 | '[' primary_expression_2 ';' primary_expression_1 ']' 79 primary_expression_3: STRING_LIT 80 | %empty 81 term_list: %empty 82 | term_list_nonempty 83 term_list_nonempty: term 84 | term_list_nonempty ',' term 85 term_ID: ID 86 term_DOTDOT: DOTDOT 87 term: term_ID 88 | ID AS type_specifier 89 | array_term 90 | '&' term_ID '[' primary_expression_1 term_DOTDOT ']' 91 | '&' term_ID '[' primary_expression_1 term_DOTDOT primary_expression_1 ']' 92 | '&' term_ID '[' term_DOTDOT primary_expression_1 ']' 93 array_term: ID '[' primary_expression_1 ']' 94 | ID '[' primary_expression_1 ']' '[' primary_expression_1 ']' 95 type_specifier: INT 96 | FLOAT 97 | BOOL 98 | '&' STR 99 | '[' type_specifier ';' primary_expression_1 ']' 100 declaration: LET ID ':' type_specifier '=' expression 101 | LET ID ':' type_specifier '=' loop_statement 102 | LET MUT ID ':' type_specifier '=' expression 103 | LET ID ':' type_specifier 104 | LET MUT ID ':' type_specifier 105 | LET ID '=' expression 106 | LET MUT ID '=' expression 107 assignment_statement: ID '=' expression 108 | ID ADD_ASSIGN expression 109 | ID SUB_ASSIGN expression 110 | ID MUL_ASSIGN expression 111 | ID DIV_ASSIGN expression 112 | ID REM_ASSIGN expression 113 | array_term '=' expression 114 | array_term ADD_ASSIGN expression 115 | array_term SUB_ASSIGN expression 116 | array_term MUL_ASSIGN expression 117 | array_term DIV_ASSIGN expression 118 | array_term REM_ASSIGN expression ``` ``` Grammar2 ``` ........ ## queue.h ```c= #ifndef QUEUE_H #define QUEUE_H #define NAME_SIZE 64 #include <unistd.h> #include <stdbool.h> typedef struct { int index; char name[NAME_SIZE]; int mutable; char type[10]; int address; int lineno; char func_sig[NAME_SIZE]; char array_type[10]; } SYMBOL; struct node { SYMBOL *data; struct node *next; }; struct queue { struct node *head; size_t size; }; SYMBOL *new_symbol(char *name, int index, int mutable, char *type, int address, int lineno, char *func_sig, char *array_type); typedef struct queue QUEUE; QUEUE *createQueue(void); size_t getQsize(const QUEUE *queue); int enqueue(QUEUE *queue, SYMBOL *element); void printTable(const QUEUE *queue, int table_index); void insertMsg(const QUEUE *queue); void change_func_sig(char *name, const QUEUE *queue, char *type_name); void change_func_sig_return(char *name, const QUEUE *queue, char *type_name); QUEUE *tables[100]; QUEUE *parameter_table; int scope_level; int address; char checktype[10]; bool is_first; char previous_func_name[50]; SYMBOL *find_symbol(char *name, const QUEUE *queue); SYMBOL *find_symbol_from_all(char *name); #endif ``` ## compiler.l ```c= /* Definition section */ %{ #include "compiler_common.h" #include "y.tab.h" /* header file generated by bison */ extern YYSTYPE yylval; #define YY_NO_UNPUT #define YY_NO_INPUT #define XXX printf("not implemented yet!\n") scope_level = 1; address = -1; %} /* Define regular expression label */ letter [a-zA-Z_] digit [0-9] id {letter}+({letter}|{digit})* inumber {digit}+ fnumber ({digit}*\.{digit}+) %x CMT %x STRCOND %option yylineno /* Rules section */ %% "/*" { BEGIN(CMT); } <CMT>"*/" { BEGIN(INITIAL); } <CMT>\n {} <CMT>. {;} "//".* {;} "\"" { BEGIN(STRCOND); return '"'; } <STRCOND>"\"" { BEGIN(INITIAL); return '"'; } <STRCOND>[^\"]* { yylval.s_val = strdup(yytext); return STRING_LIT; } "str" { return STR; } ">>" { return RSHIFT; } "<<" { return LSHIFT; } "+" { return '+'; } "-" { return '-'; } "*" { return '*'; } "/" { return '/'; } "%" { return '%'; } ">" { return '>'; } "<" { return '<'; } ">=" { return GEQ; } "<=" { return LEQ; } "==" { return EQL; } "!=" { return NEQ; } "=" { return '='; } "+=" { return ADD_ASSIGN; } "-=" { return SUB_ASSIGN; } "*=" { return MUL_ASSIGN; } "/=" { return DIV_ASSIGN; } "%=" { return REM_ASSIGN; } "&&" { return LAND; } "||" { return LOR; } "!" { return '!'; } "&" { return '&'; } "|" { return '|'; } '~' { return '~'; } "(" { return '('; } ")" { return ')'; } "[" { return '['; } "]" { return ']'; } "{" { if(scope_level != 1) tables[scope_level] = createQueue(); else tables[scope_level] = parameter_table; scope_level++; return '{'; } "}" { return '}'; } ":" { return ':'; } ";" { return ';'; } "," { return ','; } "->" { return ARROW; } "print" { return PRINT; } "println" { return PRINTLN; } "\.\." { return DOTDOT; } "as" { return AS; } "if" { return IF; } "else" { return ELSE; } "for" { return FOR; } "while" { return WHILE; } "loop" { return LOOP; } "i32" { return INT; } "f32" { return FLOAT;} "bool" { return BOOL; } "true" { return TRUE; } "false" { return FALSE; } "fn" { return FUNC; } "return" { return RETURN; } "let" { return LET; } "in" { return IN; } "mut" { return MUT; } "break" { return BREAK; } "\n" {} {inumber} { yylval.i_val = atoi(yytext); return INT_LIT; } {fnumber} { yylval.f_val = atof(yytext); return FLOAT_LIT; } {id} { yylval.s_val = strdup(yytext); return ID;} <<EOF>> { static int once = 0; if (once++) { yyterminate(); } yylineno++; ; } [ \t]+ {;} %% /* C Code section */ int yywrap(void) { return 1; } ``` ## compiler.y ```c= /* Please feel free to modify any content */ /* Definition section */ %{ #include "compiler_common.h" //Extern variables that communicate with lex #define YYDEBUG 1 int yydebug = 1; extern int yylineno; extern int yylex(); extern FILE *yyin; int yylex_destroy (); void yyerror (char const *s) { printf("error:%d: %s\n", yylineno, s); } extern int yylineno; extern int yylex(); extern FILE *yyin; /* Symbol table function - you can add new functions if needed. */ /* parameters and return type can be changed */ static void create_symbol(int index); static void insert_symbol(char *name, int addr, int mut, char *type, char *func_sig); static void lookup_symbol(); static void dump_symbol(); static void invalid_oper_msg(int lines, char* op); static void undefined_msg(int lines, char* name); /* Global variables */ bool HAS_ERROR = false; bool is_print = false; SYMBOL* target; char print_type[10] = ""; char array_type[10] = ""; int round = 0; char first_type[10] = ""; char second_type[10] = ""; %} /* %error-verbose */ /* Use variable or self-defined structure to represent * nonterminal and token type * - you can add new fields if needed. */ %union { int i_val; float f_val; char *s_val; /* ... */ } /* Token without return */ %token LET MUT NEWLINE %token INT FLOAT BOOL STR %token TRUE FALSE %token GEQ LEQ EQL NEQ LOR LAND %token ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN REM_ASSIGN %token IF ELSE FOR WHILE LOOP %token PRINT PRINTLN %token FUNC RETURN BREAK %token ARROW AS IN DOTDOT RSHIFT LSHIFT /* Token with return, which need to sepcify type */ %token <i_val> INT_LIT %token <f_val> FLOAT_LIT %token <s_val> STRING_LIT %token <s_val> ID /* Nonterminal with return, which need to sepcify type */ %type <i_val> primary_expression_1 %type <f_val> primary_expression_2 %type <s_val> primary_expression_3 %type <s_val> type_specifier %left LOR %left LAND %left EQL NEQ %left '<' '>' GEQ LEQ %left LSHIFT RSHIFT %left '%' %left '+' '-' %left '*' '/' %right '!' %nonassoc LOWER_THAN_ELSE %nonassoc ELSE /* Yacc will start at this nonterminal */ %start Program /* Grammar section */ %% Program : GlobalStatementList ; GlobalStatementList : GlobalStatementList GlobalStatement | GlobalStatement ; GlobalStatement : FunctionDeclStmt blocks | NEWLINE ; FunctionDeclStmt : function_head '(' parameter_list ')' | function_head '(' parameter_list ')' arrow_head ; function_head : FUNC ID { address = -1; printf("func: %s\n" ,$2); insert_symbol($2, -1, -1, "func", "(V)V"); strcpy(previous_func_name, $2); parameter_table = createQueue(); } arrow_head : ARROW type_specifier { change_func_sig_return(previous_func_name, tables[0], checktype); } ; left_mark : '{' { create_symbol(scope_level-1); if(getQsize(tables[scope_level-1]) > 0){ insertMsg(tables[scope_level-1]); } } ; right_mark : '}' { scope_level--; printTable(tables[scope_level], scope_level); tables[scope_level] = NULL; } ; blocks : left_mark statement_list right_mark | blocks left_mark statement_list right_mark ; parameter_list : /* empty */ | parameter_list_nonempty ; parameter_list_nonempty : parameter_declaration | parameter_list_nonempty ',' parameter_declaration ; parameter_declaration : ID ':' type_specifier { SYMBOL* temp = new_symbol($3, getQsize(parameter_table), 0, checktype, address, yylineno + 1, "-", array_type); enqueue(parameter_table, temp); address++; change_func_sig(previous_func_name, tables[0], checktype); } ; statement_list : /* empty */ | statement_list statement ; statement : declaration ';' | assignment_statement ';' | conditional_statement | loop_statement | print_statement ';' | return_statement ';' | break_statement ';' | empty_statement | function_call ';' | expression { printf("breturn\n"); } | left_mark statement_list right_mark ; function_call : ID '(' term_list ')' { target = find_symbol_from_all($1); if(target != NULL){ printf("call: %s%s\n" , target->name, target->func_sig); } else { printf("error\n"); } } ; empty_statement : NEWLINE ; loop_statement : WHILE expression blocks | for_loop statement_list right_mark | LOOP blocks ; for_loop : FOR ID IN ID '{' { // printf("FOR %s IN %s\n", $2, $4); target = find_symbol_from_all($4); if(target != NULL){ strcpy(print_type, target->type); printf("IDENT (name=%s, address=%d)\n" , yylval.s_val, target->address); printf("> Create symbol table (scope level %d)\n", scope_level-1); insert_symbol($2, address, 0, target->array_type, "-"); } else { printf("error\n"); } } ; conditional_statement : IF expression blocks %prec LOWER_THAN_ELSE | IF expression blocks ELSE blocks ; print_statement : PRINT expression { printf("PRINT %s\n" ,print_type); is_print = true; } | PRINTLN expression { printf("PRINTLN %s\n" ,print_type); is_print = true; } ; return_statement : RETURN expression { printf("breturn\n"); } ; break_statement : BREAK | BREAK expression ; expression : primary_expression_1 | primary_expression_2 | '"' primary_expression_3 '"' | term | expression '+' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "ADD"); printf("ADD\n"); } | expression '-' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "SUB"); printf("SUB\n"); } | expression '*' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "MUL"); printf("MUL\n"); } | expression '/' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "DIV"); printf("DIV\n"); } | expression '%' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "REM"); printf("REM\n"); } | expression LSHIFT expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "LSHIFT"); printf("LSHIFT\n"); } | expression RSHIFT expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "RSHIFT"); printf("RSHIFT\n"); } | expression '<' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "LSS"); printf("LSS\n"); } | expression '>' expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "GTR"); printf("GTR\n"); } | expression LEQ expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "LEQ"); printf("LEQ\n"); } | expression GEQ expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "GEQ"); printf("GEQ\n"); } | expression EQL expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "EQL"); printf("EQL\n"); } | expression NEQ expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "NEQ"); printf("NEQ\n"); } | expression LAND expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "LAND"); printf("LAND\n"); } | expression LOR expression { if(strcmp(first_type, second_type)) invalid_oper_msg(yylineno+1, "LOR"); printf("LOR\n"); } | '!' expression %prec '-' { printf("NOT\n"); } | '-' expression { printf("NEG\n"); } | '(' expression ')' | '[' expression ']' | function_call | TRUE { printf("bool TRUE\n"); strcpy(checktype, "bool"); strcpy(print_type, "bool"); } | FALSE { printf("bool FALSE\n"); strcpy(checktype, "bool"); strcpy(print_type, "bool"); } ; primary_expression_1 : INT_LIT { $$ = $1; printf("INT_LIT %d\n", $1); strcpy(checktype, "i32"); strcpy(print_type, "i32"); if(round % 2 == 0){ strcpy(first_type, checktype); } else { strcpy(second_type, checktype); } round++; } | INT_LIT AS type_specifier { $$ = $1; printf("INT_LIT %d\n", $1); printf("i2f\n"); if(round % 2 == 0){ strcpy(first_type, checktype); } else { strcpy(second_type, checktype); } round++; } | primary_expression_1 ',' primary_expression_1 { $$ = $1; strcpy(checktype, "array"); strcpy(print_type, "array"); strcpy(array_type, "i32"); } | '[' primary_expression_1 ';' primary_expression_1 ']' { strcpy(checktype, "array"); strcpy(print_type, "array"); } ; primary_expression_2 : FLOAT_LIT { $$ = $1; printf("FLOAT_LIT %f\n", $1); strcpy(checktype, "f32"); strcpy(print_type, "f32"); } | FLOAT_LIT AS type_specifier { $$ = $1; printf("FLOAT_LIT %f\n", $1); printf("f2i\n"); if(round % 2 == 0){ strcpy(first_type, checktype); } else { strcpy(second_type, checktype); } round++; } | primary_expression_2 ',' primary_expression_2 { $$ = $1; strcpy(checktype, "array"); strcpy(print_type, "array"); strcpy(array_type, "f32"); } | '[' primary_expression_2 ';' primary_expression_1 ']' { strcpy(checktype, "array"); strcpy(print_type, "array"); } ; primary_expression_3 : STRING_LIT { $$ = $1; printf("STRING_LIT \"%s\"\n", $1); strcpy(checktype, "str"); strcpy(print_type, "str"); strcpy(array_type, "str"); } | /* empty */ { $$ = ""; printf("STRING_LIT \"\"\n"); strcpy(checktype, "str"); strcpy(print_type, "str"); strcpy(array_type, "str"); } ; term_list : /* empty */ | term_list_nonempty ; term_list_nonempty : term | term_list_nonempty ',' term ; term_ID : ID { target = find_symbol_from_all(yylval.s_val); if(target != NULL){ strcpy(print_type, target->type); printf("IDENT (name=%s, address=%d)\n" , yylval.s_val, target->address); if(round % 2 == 0){ strcpy(first_type, target->type); } else { strcpy(second_type, target->type); } } else { is_print = false; undefined_msg(yylineno + 1, $1); if(round % 2 == 0){ strcpy(first_type, "undefined"); } else { strcpy(second_type, "undefined"); } } round++; } ; term_DOTDOT : DOTDOT { printf("DOTDOT\n"); } ; term : term_ID | ID AS type_specifier { target = find_symbol_from_all(yylval.s_val); if(target != NULL){ strcpy(print_type, target->type); printf("IDENT (name=%s, address=%d)\n" , yylval.s_val, target->address); if(strcmp(target->type, "i32") == 0 && strcmp(checktype, "f32") == 0) { printf("i2f\n"); if(round % 2 == 0){ strcpy(first_type, "f32"); } else { strcpy(second_type, "f32"); } } else if(strcmp(target->type, "i32") == 0 && strcmp(checktype, "i32") == 0) { printf("i2i\n"); if(round % 2 == 0){ strcpy(first_type, "i32"); } else { strcpy(second_type, "i32"); } } else if((strcmp(target->type, "f32") == 0 && strcmp(checktype, "i32") == 0)) { printf("f2i\n"); if(round % 2 == 0){ strcpy(first_type, "i32"); } else { strcpy(second_type, "i32"); } } else if((strcmp(target->type, "f32") == 0 && strcmp(checktype, "f32") == 0)){ printf("f2f\n"); if(round % 2 == 0){ strcpy(first_type, "f32"); } else { strcpy(second_type, "f32"); } } round++; } else { printf("error\n"); } } | array_term | '&' term_ID '[' primary_expression_1 term_DOTDOT ']' { strcpy(checktype, "str"); strcpy(print_type, "str"); strcpy(array_type, "str"); } | '&' term_ID'[' primary_expression_1 term_DOTDOT primary_expression_1']' { strcpy(checktype, "str"); strcpy(print_type, "str"); strcpy(array_type, "str"); } | '&' term_ID '[' term_DOTDOT primary_expression_1']' { strcpy(checktype, "str"); strcpy(print_type, "str"); strcpy(array_type, "str"); } ; array_term : ID '[' INT_LIT ']' { target = find_symbol_from_all($1); if(target != NULL){ strcpy(print_type, target->type); printf("IDENT (name=%s, address=%d)\n" , $1, target->address); if(round % 2 == 0){ strcpy(first_type, target->type); } else { strcpy(second_type, target->type); } } else { is_print = false; undefined_msg(yylineno + 1, $1); if(round % 2 == 0){ strcpy(first_type, "undefined"); } else { strcpy(second_type, "undefined"); } } printf("INT_LIT %d\n", $3); strcpy(checktype, "array"); strcpy(print_type, "array"); } | ID '[' INT_LIT ']' '[' INT_LIT ']' { printf("INT_LIT %d\n", $3); printf("INT_LIT %d\n", $6); strcpy(checktype, "array"); strcpy(print_type, "array"); } ; type_specifier : INT { strcpy(checktype, "i32"); } | FLOAT { strcpy(checktype, "f32"); } | BOOL { strcpy(checktype, "bool"); } | '&' STR { strcpy(checktype, "str"); } | '[' type_specifier ';' primary_expression_1 ']' { strcpy(checktype, "array");} ; declaration : LET ID ':' type_specifier '=' expression { insert_symbol($2, address, 0, checktype, "-"); } | LET ID ':' type_specifier '=' loop_statement { insert_symbol($2, address, 0, checktype, "-"); } | LET MUT ID ':' type_specifier '=' expression { insert_symbol($3, address, 1, checktype, "-"); } | LET ID ':' type_specifier { insert_symbol($2, address, 0, checktype, "-"); } | LET MUT ID ':' type_specifier { insert_symbol($3, address, 1, checktype, "-"); } | LET ID '=' expression { insert_symbol($2, address, 0, checktype, "-"); } | LET MUT ID '=' expression { insert_symbol($3, address, 1, checktype, "-"); } ; assignment_statement : ID '=' expression { target = find_symbol_from_all($1); if(target != NULL){ printf("ASSIGN\n"); } else { undefined_msg(yylineno + 1, $1); } } | ID ADD_ASSIGN expression { printf("ADD_ASSIGN\n"); } | ID SUB_ASSIGN expression { printf("SUB_ASSIGN\n"); } | ID MUL_ASSIGN expression { printf("MUL_ASSIGN\n"); } | ID DIV_ASSIGN expression { printf("DIV_ASSIGN\n"); } | ID REM_ASSIGN expression { printf("REM_ASSIGN\n"); } | array_term '=' expression | array_term ADD_ASSIGN expression | array_term SUB_ASSIGN expression | array_term MUL_ASSIGN expression | array_term DIV_ASSIGN expression | array_term REM_ASSIGN expression ; %% /* C code section */ int main(int argc, char *argv[]) { if (argc == 2) { yyin = fopen(argv[1], "r"); } else { yyin = stdin; } yylineno = 0; create_symbol(0); tables[0] = createQueue(); yyparse(); dump_symbol(); printf("Total lines: %d\n", yylineno); /* printTable(parameter_table, 0); */ fclose(yyin); return 0; } static void create_symbol(int index) { /* printf("> Create symbol table (scope level %d)\n", 0); */ printf("> Create symbol table (scope level %d)\n", index); } static void insert_symbol(char *name, int addr, int mut, char *type, char *func_sig) { /* printf("> Insert `%s` (addr: %d) to scope level %d\n", "XXX", 0, 0); */ printf("> Insert `%s` (addr: %d) to scope level %d\n", name, addr, scope_level-1); SYMBOL* temp = new_symbol(name, getQsize(tables[scope_level-1]), mut, type, addr, yylineno + 1, func_sig, array_type); enqueue(tables[scope_level-1], temp); address++; } static void lookup_symbol() { } static void dump_symbol() { /* printf("\n> Dump symbol table (scope level: %d)\n", 0); printf("%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "Index", "Name", "Mut","Type", "Addr", "Lineno", "Func_sig"); printf("%-10d%-10s%-10d%-10s%-10d%-10d%-10s\n", 0, "name", 0, "type", 0, 0, "func_sig"); */ printTable(tables[0], 0); } static void invalid_oper_msg(int lines, char* op) { if(round % 2 == 0) printf("error:%d: invalid operation: %s (mismatched types %s and %s)\n", lines, op, first_type, second_type); else printf("error:%d: invalid operation: %s (mismatched types %s and %s)\n", lines, op, second_type, first_type); } static void undefined_msg(int lines, char* name) { printf("error:%d: undefined: %s\n", lines, name); } ```