Newer
Older
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "mcc/ast.h"
#include "mcc/symbol_table_parse.h"
#include "utils/unused.h"
// ------------------------------------------------------------ Variable
int mcc_symbol_table_add_variable_declaration(
struct mcc_ast_declaration *declaration,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec) {
assert(declaration);
assert(symbol_table);
assert(ec);
struct mcc_symbol *vs = mcc_symbol_new_symbol_variable(declaration->ident->i_value, declaration->type);
// check if already declared
if(mcc_symbol_table_get_symbol(symbol_table, vs->variable_name, false) == NULL) {
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
mcc_symbol_table_insert_symbol(symbol_table, vs);
return 0;
} else {
mcc_symbol_table_add_error(ec, mcc_symbol_table_new_error(&(declaration->node.sloc),
MCC_SEMANTIC_ERROR_VARIABLE_ALREADY_DECLARED));
return 1;
}
}
// ------------------------------------------------------------ Array
// returns 1 if error
int mcc_symbol_table_check_array_declaration_size(
struct mcc_ast_declaration *declaration,
struct mcc_symbol_table_error_collector *ec) {
if(declaration->arr_literal != NULL) {
// check if size is int
if(declaration->arr_literal->type != MCC_AST_DATA_TYPE_INT) {
mcc_symbol_table_add_error(
ec,
mcc_symbol_table_new_error(&(declaration->node.sloc), MCC_SEMANTIC_ERROR_ARRAY_SIZE_DEFINITION));
return 1;
}
}
return 0;
}
int mcc_symbol_table_add_array_declaration(
struct mcc_ast_declaration *declaration,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec) {
assert(declaration);
assert(symbol_table);
assert(ec);
if(mcc_symbol_table_check_array_declaration_size(declaration, ec) == 1) {
return 1;
}
struct mcc_symbol *vs = mcc_symbol_new_symbol_array(
declaration->ident->i_value,
declaration->type,
declaration->arr_literal->i_value);
vs->symbol_type = MCC_SYMBOL_TYPE_ARRAY;
// check if already declared
if(mcc_symbol_table_get_symbol(symbol_table, vs->variable_name, false) == NULL) {
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
// add array declaration to symbol table
mcc_symbol_table_insert_symbol(symbol_table, vs);
return 0;
} else {
mcc_symbol_table_add_error(ec, mcc_symbol_table_new_error(&(declaration->node.sloc),
MCC_SEMANTIC_ERROR_ARRAY_ALREADY_DECLARED));
return 1;
}
}
// ---------------------------------------------------------- Statement
int mcc_symbol_table_parse_compound_statement(
struct mcc_ast_statement *statement,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec
) {
assert(statement);
assert(statement->type == MCC_AST_STATEMENT_TYPE_COMPOUND);
assert(symbol_table);
assert(ec);
struct mcc_ast_statement_list *stl = statement->statement_list;
if(stl == NULL){
return 0;
}
while(stl->statement != NULL ) {
int create_new = 0;
if (stl -> statement -> type == MCC_AST_STATEMENT_TYPE_COMPOUND) {
create_new = 1;
}
int statement_result = mcc_symbol_table_parse_statement(
stl->statement,
symbol_table,
ec,
create_new
);
if(statement_result == 1) {
return 1;
}
if (stl->next == NULL){
break;
} else{
stl = stl->next;
}
}
return 0;
}
int mcc_symbol_table_parse_statement(
struct mcc_ast_statement *statement,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec,
int create_new) {
assert(statement);
assert(symbol_table);
assert(ec);
struct mcc_symbol_table *table = symbol_table;
if (create_new) {
table = mcc_symbol_table_create_inner_table(symbol_table,"COMPOUND_STMT");
}
switch(statement->type) {
case MCC_AST_STATEMENT_TYPE_RETURN:
case MCC_AST_STATEMENT_TYPE_EXPRESSION:
return mcc_symbol_table_validate_expression(statement->expression, table, ec);
case MCC_AST_STATEMENT_TYPE_WHILE:
if(mcc_symbol_table_validate_expression(
if (mcc_symbol_table_validate_condition_to_type_bool(
statement -> while_condition,
ec
) == 0) {
return mcc_symbol_table_parse_statement(
statement->while_stmt, table, ec, 1);
} else {
return 1;
}
} else {
return 1;
}
case MCC_AST_STATEMENT_TYPE_IF:
if (mcc_symbol_table_validate_condition_to_type_bool(
statement -> if_condition,
ec
) == 0) {
return mcc_symbol_table_parse_statement(
} else {
return 1;
}
} else {
return 1;
}
case MCC_AST_STATEMENT_TYPE_DECL:
if (statement->declaration->arr_literal != NULL) {
// array declaration
return mcc_symbol_table_add_array_declaration(statement->declaration, table, ec);
return mcc_symbol_table_add_variable_declaration(statement->declaration, table, ec);
return mcc_symbol_table_validate_assignment_semantic(statement->assignment, table, ec);
case MCC_AST_STATEMENT_TYPE_ASSGN_ARR:
return mcc_symbol_table_validate_assignment_array(statement->assignment, table, ec);
case MCC_AST_STATEMENT_TYPE_COMPOUND:
return mcc_symbol_table_parse_compound_statement(
statement,
ec
);
default:
return 0;
}
}
// ---------------------------------------------------------- Function
int mcc_symbol_table_parse_function(
struct mcc_ast_function *func_def,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec
) {
assert(func_def);
assert(symbol_table);
assert(ec);
// create new scope and parse function
struct mcc_symbol_table *sub_table = mcc_symbol_table_create_inner_table(symbol_table,func_def->identifier->i_value);
// add params to sub table
if (func_def -> parameter != NULL && func_def -> parameter -> parameters -> size > 0) {
struct mcc_ast_parameter *p = func_def -> parameter;
for (int i = 0; i < p -> parameters -> size; i++) {
struct mcc_ast_declaration *declaration = p -> parameters -> arr[i];
// at this point symbol table is still empty -> adding won't result in an error
if (declaration -> arr_literal != NULL) {
// array declaration
mcc_symbol_table_add_array_declaration(declaration, sub_table, ec);
} else {
// variable declaration
mcc_symbol_table_add_variable_declaration(declaration, sub_table, ec);
}
}
}
int valid_function_body = mcc_symbol_table_parse_statement(func_def -> statement, sub_table, ec, 0);
if (valid_function_body == 0) {
// valid function body - check if return type of non-void function is correct
if (func_def -> return_type != MCC_AST_DATA_TYPE_VOID) {
valid_function_body = mcc_symbol_table_validate_statement_return(
func_def -> statement,
func_def -> return_type,
sub_table,
ec
);
}
}
return valid_function_body;
}
int mcc_symbol_table_add_function_declaration(
struct mcc_ast_function *func_def,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec) {
assert(symbol_table);
assert(ec);
assert(func_def);
struct mcc_symbol *fs = mcc_symbol_new_symbol_function(
func_def->identifier->i_value,
func_def->return_type,
func_def->parameter);
// check if already declared
if(mcc_symbol_table_get_symbol(symbol_table, fs -> variable_name, true) == NULL) {
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
mcc_symbol_table_insert_symbol(symbol_table, fs);
return 0;
} else {
// already declared - create already declared error message
mcc_symbol_table_add_error(ec, mcc_symbol_table_new_error(&(func_def->node.sloc),
MCC_SEMANTIC_ERROR_FUNC_ALREADY_DECLARED));
return 1;
}
}
// ---------------------------------------------------------- Program
void mcc_add_builtin_function(
struct mcc_symbol_table *symbol_table,
char *variable_name,
enum mcc_ast_data_type return_type,
enum mcc_ast_data_type param_type) {
struct mcc_symbol *symbol = malloc(sizeof(*symbol));
symbol -> variable_name = variable_name;
symbol -> data_type = return_type;
symbol -> symbol_type = MCC_SYMBOL_TYPE_BUILTIN_FUNCTION;
symbol -> func_arguments = mcc_create_dynamic_array(5);
if (param_type != MCC_AST_DATA_TYPE_VOID) {
struct mcc_symbol_function_argument *fp = malloc(sizeof(*fp));
fp -> arg_type = param_type;
mcc_add_to_array(symbol -> func_arguments, fp);
}
symbol_table -> inner_tables -> arr[0] = NULL;
mcc_symbol_table_insert_symbol(symbol_table,symbol);
}
void mcc_symbol_table_add_builtins(struct mcc_symbol_table *symbol_table) {
mcc_add_builtin_function(symbol_table,"print_nl",MCC_AST_DATA_TYPE_VOID,MCC_AST_DATA_TYPE_VOID);
mcc_add_builtin_function(symbol_table,"print",MCC_AST_DATA_TYPE_VOID,MCC_AST_DATA_TYPE_STRING);
mcc_add_builtin_function(symbol_table,"print_int",MCC_AST_DATA_TYPE_VOID,MCC_AST_DATA_TYPE_INT);
mcc_add_builtin_function(symbol_table,"print_float",MCC_AST_DATA_TYPE_VOID,MCC_AST_DATA_TYPE_FLOAT);
mcc_add_builtin_function(symbol_table,"read_int",MCC_AST_DATA_TYPE_INT,MCC_AST_DATA_TYPE_VOID);
mcc_add_builtin_function(symbol_table,"read_float",MCC_AST_DATA_TYPE_FLOAT,MCC_AST_DATA_TYPE_VOID);
}
int mcc_symbol_table_parse_program(
struct mcc_ast_program *program,
struct mcc_symbol_table *symbol_table,
struct mcc_symbol_table_error_collector *ec) {
assert(program);
int function_parse = 0;
for(int i = 0; i < program -> function_def -> size; i++) {
function_parse = mcc_symbol_table_add_function_declaration(program -> function_def -> arr[i], symbol_table, ec);
if (function_parse) break;
}
// if everything so far ok
if (function_parse == 0) {
// parse all functions
for(int i = 0; i < program-> function_def -> size; i++) {
function_parse = mcc_symbol_table_parse_function(program->function_def -> arr[i], symbol_table, ec);
if (function_parse) break;
}
}
return function_parse;
}
struct mcc_symbol_table *mcc_symbol_table_build_program(struct mcc_ast_program *program, struct mcc_symbol_table_error_collector *ec) {
assert(program);
struct mcc_symbol_table *st = mcc_symbol_table_new_table(NULL);
mcc_symbol_table_add_builtins(st);
if (mcc_symbol_table_parse_program(program, st, ec) == 0) {
// check if main exists
if (mcc_symbol_table_validate_main(program, st, ec) == 0) {
return st;
} else {
return NULL;
}
} else {
return NULL;
}
}
struct mcc_symbol_table *mcc_symbol_table_build_function(struct mcc_ast_function *function, struct mcc_symbol_table_error_collector *ec) {
assert(function);
struct mcc_symbol_table *st = mcc_symbol_table_new_table(NULL);
mcc_symbol_table_add_builtins(st);
int parse_function = mcc_symbol_table_add_function_declaration(function, st, ec);
if (parse_function == 0) {
if (mcc_symbol_table_parse_function(function, st, ec) == 0) {
return st;
} else {
// handle error collection
return NULL;
}
} else {
// handle error collection
return NULL;
}
}