diff --git a/ps4/src/symbols.c b/ps4/src/symbols.c index f16c305..d39c516 100644 --- a/ps4/src/symbols.c +++ b/ps4/src/symbols.c @@ -51,25 +51,73 @@ void destroy_tables(void) /* Internal matters */ +symbol_t *create_symbol(symtype_t type, node_t *node, symbol_table_t *function_symtable) { + symbol_t *new_symbol = malloc(sizeof(symbol_t)); + new_symbol->type = type; + new_symbol->name = SYMBOL_TYPE_NAMES[type]; + new_symbol->node = node; + new_symbol->function_symtable = function_symtable; + return new_symbol; +} + // Goes through all global declarations, adding them to the global symbol table. // When adding functions, a local symbol table with symbols for its parameters are created. static void find_globals(void) { global_symbols = symbol_table_init(); - // TODO: Create symbols for all global defintions (global variables, arrays and functions), - // and add them to the global symbol table. See the symtype_t enum in "symbols.h" - - // When creating a symbol for a function, also create a local symbol_table_t for it. - // Store this local symbol table in the function symbol's function_symtable field. - // Any parameters the function may have should be added to this local symbol table. - - // TIP: create symbols using malloc(sizeof(symbol_t)), and assigning the relevant fields. - // Use symbol_table_insert() (from "symbol_table.h") to insert new symbols into tables. - - // If a symbol already exists with the same name, the insertion will return INSERT_COLLISION. - // Feel free to print an error message and abort using exit(EXIT_FAILURE), - // but we will not be testing your compiler on invalid VSL. + for (int i = 0; i < root->n_children; i++) { + node_t *top_level_node = root->children[i]; + switch (top_level_node->type) { + case GLOBAL_VARIABLE_DECLARATION: + assert(top_level_node->n_children == 1); + node_t *list = top_level_node->children[0]; + assert(list->type == LIST); + for (int j = 0; j < list->n_children; j++) { + node_t *global = list->children[j]; + switch (global->type) { + case IDENTIFIER: + symbol_t *identifier = create_symbol(SYMBOL_GLOBAL_VAR, global, NULL); + if (symbol_table_insert(global_symbols, identifier) != INSERT_OK) { + fprintf(stderr, "find_globals: insertion collision (identifier)"); + exit(EXIT_FAILURE); + } + break; + case ARRAY_INDEXING: + symbol_t *array = create_symbol(SYMBOL_GLOBAL_ARRAY, global, NULL); + if (symbol_table_insert(global_symbols, array) != INSERT_OK) { + fprintf(stderr, "find_globals: insertion collision (array)"); + exit(EXIT_FAILURE); + } + break; + default: + fprintf(stderr, "find_globals: found global %d", global->type); + break; + } + } + break; + case FUNCTION: + symbol_table_t *function_symtable = symbol_table_init(); + node_t *parameters = top_level_node->children[1]->children[0]; + assert(parameters->type == LIST); + for (int j = 0; j < parameters->n_children; j++) { + symbol_t *param = create_symbol(SYMBOL_PARAMETER, parameters->children[j], NULL); + if (symbol_table_insert(function_symtable, param) != INSERT_OK) { + fprintf(stderr, "find_globals: insertion collision (parameter)"); + exit(EXIT_FAILURE); + } + } + symbol_t *new_symbol = create_symbol(SYMBOL_FUNCTION, top_level_node, function_symtable); + if (symbol_table_insert(global_symbols, new_symbol) != INSERT_OK) { + fprintf(stderr, "find_globals: insertion collision (function)"); + exit(EXIT_FAILURE); + } + break; + default: + fprintf(stderr, "find_globals: found top level %d", top_level_node->type); + break; + } + } } // A recursive function that traverses the body of a function doing the following: