void check_if_declared(Node *aux, environment_list *env){ table_element *temp; char *s=(char*)strdup(aux->value.s); lower(s); for(temp = env->locals; temp!=NULL; temp=temp->next){ if(strcmp(temp->name,s)==0){ return; } } if(env->previous!=NULL){ check_if_declared(aux, env->previous); }else{ printf("Line %d, col %d: Symbol %s not defined\n",aux->line,aux->col,aux->value.s); exit(0); } }
/* * Builds the symbol table, creating scopes as needed, and linking them together. * Adds variable and function identifiers to scopes appropriately. */ void build_symbol_table(ast_node root, int level, int sibno, symboltable_t *symtab) { //calculate the scope for the variable/func declaration //calculate the parent for that variable/func declaration //need function to take as input //printf("here \n"); symhashtable_t *hash; /* Depending on node types, go deeper, create sibling scopes, add to hashtable, * or take other appropriate action. */ switch (root->node_type) { ast_node param; int param_offset = 4; int param_count = 0; case SEQ_N: // change main level when see a new sequence level++; break; case FORMAL_PARAMS_N: level++; param_count = 0; insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); // for(param = root->left_child; param != NULL; param = param->right_sibling){ // if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){ // param_count += DEFAULT_ARRAY_PARAM_SIZE; // } // else{ // param_count++; // } // } // printf("PARAM COUNT!!!!! = %d\n", param_count); // // for(param = root->left_child; param != NULL; param = param->right_sibling){ // if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){ // param->snode->offset = param_count * 4; // param->snode->offset -= DEFAULT_ARRAY_PARAM_SIZE; // } // else{ // param->snode->offset = param_count-- * 4; // } // } break; case FUNC_DECLARATION_N: // function declaraions //does hashtable exist with given lvl, siblvl (use find_hashtable) check_if_redef(root, symtab ,level, sibno); hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); // will only insert if it is empty. insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case FUNCTION_N: check_if_declared(root, symtab ,level, sibno); insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case ID_N: /* print the id */ check_if_redef(root, symtab ,level, sibno); //if(root->return_type != 0) { // a non-zero value means that it is a declaration, since only declarations // are assigned a return type when building the abstract syntax tree. if(root->isDecl){ hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); } else { // don't know if previously declared check_if_declared(root, symtab , level, sibno); } insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case ARRAY_TYPE_N: // check for return types! check_if_redef(root, symtab ,level, sibno); //cif(root->return_type != 0) { if(root->isDecl){ hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); } else { check_if_declared(root, symtab , level, sibno); } insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case RETURN_N: insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; default: // printf("at default of switch\n"); assert(symtab->root != NULL); hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } //note: cannot use insert_scope_info here because siblings[level - 1] causes invalid read as level-1 can go negative break; } if(arraylen == level) { arraylen = arraylen + DELTA; siblings = realloc(siblings, sizeof(int) * arraylen); assert(siblings != NULL); for(int k=0; k < DELTA; k++) { siblings[arraylen - (DELTA-k)] = 0; } } /* Recurse on each child of the subtree root, with a depth one greater than the root's depth. */ ast_node child; for (child = root->left_child; child != NULL; child = child->right_sibling) build_symbol_table(child, level, siblings[level], symtab); if(root->node_type == SEQ_N){//} || root->node_type == FORMAL_PARAMS_N){ siblings[level]++; // change sibling level after you're done printing all // subtrees, i.e., after done recursing. } }
void redef_check(ast_node root, int level, int sibno, symboltable_t *symtab) { //calculate the scope for the variable/func declaration //calculate the parent for that variable/func declaration //need function to take as input //printf("here \n"); symhashtable_t *hash; /* Depending on node types, go deeper, create sibling scopes, add to hashtable, * or take other appropriate action. */ switch (root->node_type) { case SEQ_N: // change main level when see a new sequence level++; break; case FORMAL_PARAMS_N: level++; break; case FUNC_DECLARATION_N: // function declaraions //does hashtable exist with given lvl, siblvl (use find_hashtable) if(root->snode != NULL) check_if_redef(root, symtab ,level, sibno); break; case FUNCTION_N: check_if_declared(root, symtab ,level, sibno); break; case ID_N: /* print the id */ if(root->snode != NULL) check_if_redef(root, symtab ,level, sibno); break; case ARRAY_TYPE_N: // check for return types! if(root->snode != NULL) check_if_redef(root, symtab ,level, sibno); break; case RETURN_N: break; default: // printf("at default of switch\n"); assert(symtab->root != NULL); break; } if(arraylen_trash == level) { arraylen_trash = arraylen_trash + DELTA; trash_array = realloc(trash_array, sizeof(int) * arraylen_trash); assert(trash_array != NULL); for(int k=0; k < DELTA; k++) { trash_array[arraylen_trash - (DELTA-k)] = 0; } } /* Recurse on each child of the subtree root, with a depth one greater than the root's depth. */ ast_node child; for (child = root->left_child; child != NULL; child = child->right_sibling) redef_check(child, level, trash_array[level], symtab); if(root->node_type == SEQ_N){//} || root->node_type == FORMAL_PARAMS_N){ trash_array[level]++; // change sibling level after you're done printing all // subtrees, i.e., after done recursing. } }