# 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);
}
```