minic 符号表
1 #include <stdio.h> 2 #include <string.h> 3 #include <malloc.h> 4 typedef struct _array_description 5 { 6 int array_size;//代表当前层的最高索引,即上界 7 struct _array_description* next;//代表下一级 8 }array_description,*parray_description; 9 //注意我们把最低层的放在最前面,这样有利于下标的处理 10 11 typedef struct _basic_type_pattern 12 { 13 char* faction_name;//代表类型名字 14 int pointer_layer;//代表指针的级数,我们限制为8级,即只占一个字节,其他三个字节以后再使用,先留着 15 parray_description array_layer;//这里是数组描述,以链表串起多级数组 16 char* pattern_name;//代表分量的类型 17 }basic_type_pattern,*pbasic_type_pattern; 18 typedef struct _composition_list//这个是复合结构的产生式,包括联合、结构、函数 19 { 20 pbasic_type_pattern current;//当前的分量 21 struct _composition_list* next;//下一个分量的指针 22 }composition_list,*pcomposition_list; 23 typedef struct _type_description 24 { 25 pcomposition_list current_gen_list;//代表当前的产生式的体,也是函数参数的列表 26 int type_type;//1为函数,2为结构,3为联合,4为基础类型 27 char* name;//当前类型的名字 28 void* function_zone;//这个代表了函数相关的域,其中有三个域,类型链表,变量链表,动作链表 29 //这三个域都是需要后面定义的类型,所以我们目前把他作为一个void类型的指针来处理 30 int return_pointer ;//代表返回值的指针层数 31 char* return_name;//代表返回值的类型 32 }type_description,*ptype_description;//类型声明的体 33 typedef struct _type_avl_tree 34 { 35 struct _type_description* current_type_body;//产生体链表的头节点 36 //因为有交叉引用。。。 37 int tree_depth;//当前树的高度,这个域是用来计算平衡因子的 38 struct _type_avl_tree* left;//左子树 39 struct _type_avl_tree* right;//右子树 40 }type_avl_tree,*ptype_avl_tree;//这里是整个的类型avl树 41 42 ptype_avl_tree type_tree_head=NULL;//先初始化为空 43 ptype_avl_tree tree_node_stack[100];//这个栈是为了插入和删除用的,以及用来平衡树高 44 //前面的结构都是对应于类型符号表的,采取的是avl 45 //下面开始介绍变量符号表,采取的是hash 46 //对于变量符号表,我们首先需要考虑一个变量所包括的域,其实这些域在定义类型符号表的时候都使用过了 47 //即basic_type_pattern这个结构体,已经有我们所需要的所有的东西,对于hash值一样的变量,我们通过一个链表串接起来 48 //而这个链表结构我们现在都有了 49 //现在我们唯一需要的就是hash表的空间以及hash的方法,这里我们分配400个表项,因为397刚好是质数 50 //hash函数我们直接采用累加法,最简单的 51 typedef struct _var_hash_node 52 { 53 char* var_name; 54 int pointer_layer;//代表指针的级数,我们限制为8级,即只占一个字节,其他三个字节以后再使用,先留着 55 parray_description array_layer;//这里是数组描述,以链表串起多级数组 56 struct _type_description* var_type;//代表变量的类型 57 }var_hash_node,*pvar_hash_node; 58 typedef struct _var_hash_chain 59 { 60 pvar_hash_node current_var; 61 struct _var_hash_node next_var; 62 }var_hash_chain,*pvar_hash_chain; 63 pvar_hash_chain var_hash_table[400];//注意我们要在后面把这个全都初始化为空 64 void generation_free(void* generation_body)//释放生成体链表所占的空间 65 { 66 pcomposition_list temp_com_list_before,temp_com_list_after; 67 pbasic_type_pattern temp_basic_pattern; 68 parray_description temp_array_layer_before,temp_array_layer_after; 69 temp_com_list_before=(pcomposition_list)generation_list;//转换一下指针 70 while(temp_com_list_before!=NULL) 71 { 72 temp_com_list_after=temp_com_list_before->next; 73 temp_basic_pattern=temp_com_list_before->current; 74 free(temp_basic_pattern->faction_name); 75 temp_array_layer_before=temp_basic_pattern->array_layer; 76 while(temp_array_layer_before!=NULL) 77 { 78 temp_array_layer_after=temp_array_layer_before->next; 79 free(temp_array_layer_before); 80 temp_array_layer_before=temp_array_layer_after; 81 }//释放所有的数组空间 82 free(temp_com_list_before); 83 temp_com_list_before=temp_com_list_after; 84 }//释放所有的分量 85 }//现在所有的都释放完成了 86 87 88 89 void insert_var_hash(pvar_hash_node new_var)//在hash表中插入一个表项 90 { 91 int string_hash; 92 int for_i; 93 char* current_name; 94 pvar_hash_chain temp_link;//用来串接链表 95 current_name=new_var->var_name; 96 for_i=0; 97 string_hash=0; 98 while(current_name[for_i]!='\0') 99 { 100 string_hash+=current_name[for_i]; 101 } 102 string_hash=string_hash%397;//取模 103 temp_link=malloc(sizeof(struct _var_hash_chain)); 104 temp_link->next_var=var_hash_table[string_hash]; 105 temp_link->current_var=new_var; 106 var_hash_table[string_hash]=temp_link; 107 } 108 void delete_var_hash(char* current_name)//这里其实我们不管具体的name,因为,删除的时候我们是一起删除的 109 { 110 int string_hash; 111 int for_i; 112 pvar_hash_chain temp_link;//用来串接链表 113 for_i=0; 114 string_hash=0; 115 while(current_name[for_i]!='\0') 116 { 117 string_hash+=current_name[for_i]; 118 } 119 string_hash=string_hash%397;//取模 120 temp_link=var_hash_table[string_hash]->next_var; 121 free(var_hash_table[string_hash]); 122 var_hash_table[string_hash]=temp_link; 123 } 124 125 pvar_hash_node search_var_hash(char* current_name)//通过名字来查找变量符号表 126 { 127 int string_hash; 128 int for_i; 129 pbasic_type_pattern result; 130 pvar_hash_node temp_link;//用来串接链表 131 for_i=0; 132 string_hash=0; 133 while(current_name[for_i]!='\0') 134 { 135 string_hash+=current_name[for_i]; 136 } 137 string_hash=string_hash%397;//取模 138 temp_link=var_hash_table[string_hash]; 139 while(temp_link!=NULL) 140 { 141 result=temp_link->current_var; 142 if(strcmp(result,current_name)==0) 143 { 144 return result; 145 } 146 else 147 { 148 temp_link=temp_link->next_var; 149 } 150 } 151 return NULL; 152 } 153 154 void modify_node_depth(ptype_avl_tree current)//修改节点的高度 155 //由于这个操作需要做很多判断,不修改成函数的话,其他函数将会很长,所以做成一个函数 156 { 157 if(current->left!=NULL) 158 { 159 if(current->right!=NULL) 160 { 161 current->tree_depth=1+(current->left->tree_depth+current->right->tree_depth+1)/2; 162 } 163 else 164 { 165 current->tree_depth=1+current->left->tree_depth; 166 } 167 } 168 else 169 { 170 if(current->right!=NULL) 171 { 172 current->tree_depth=1+current->right->tree_depth; 173 } 174 else 175 { 176 current->tree_depth=1; 177 } 178 } 179 } 180 void avl_rotate_left( ptype_avl_tree father, ptype_avl_tree current)//将avl树左旋 181 { 182 ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//这命名碉堡了有木有 183 if(father==NULL)//如果旋转的是头节点 184 { 185 temp_node_one=current->right; 186 type_tree_head=current->right;//修改头节点 187 temp_node_two=temp_node_one->left; 188 current->right=temp_node_two; 189 type_tree_head->left=current; 190 //至此节点之间的关系修改完毕 191 //现在开始修改两个节点的高度 192 modify_node_depth(current);//修改高度有先后顺序的,先修改下面的,后修改上面的 193 modify_node_depth(temp_node_one) 194 } 195 else 196 { 197 temp_node_one=current->right; 198 current->right=temp_node_one->left; 199 temp_node_one->left=current; 200 if(father->left==current) 201 { 202 father->left=temp_node_one; 203 } 204 else 205 { 206 father->right=temp_node_one; 207 } 208 modify_node_depth(current); 209 modify_node_depth(temp_node_one); 210 mpdify_node_depth(father); 211 //这里需要修改三个节点 212 } 213 } 214 void avl_rotate_right(ptype_avl_tree father, ptype_avl_tree current)//右旋节点 215 { 216 ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//这命名碉堡了有木有 217 if(father==NULL)//如果旋转的是头节点 218 { 219 temp_node_one=current->left; 220 type_tree_head=current->left;//修改头节点 221 temp_node_two=temp_node_one->right; 222 current->left=temp_node_two; 223 type_tree_head->right=current; 224 //至此节点之间的关系修改完毕 225 //现在开始修改两个节点的高度 226 modify_node_depth(current);//修改高度有先后顺序的,先修改下面的,后修改上面的 227 modify_node_depth(temp_node_one) 228 } 229 else 230 { 231 temp_node_one=current->left; 232 current->left=temp_node_one->right; 233 temp_node_one->right=current; 234 if(father->right==current) 235 { 236 father->right=temp_node_one; 237 } 238 else 239 { 240 father->left=temp_node_one; 241 } 242 modify_node_depth(current); 243 modify_node_depth(temp_node_one); 244 mpdify_node_depth(father); 245 //这里需要修改三个节点 246 } 247 } 248 249 void insert_avl_node(ptype_description new_type_node)//插入一个新的节点 250 { 251 ptype_avl_tree temp_node_one,temp_node_two,temp_node_three,new_node; 252 ptype_description temp_type_description; 253 int stack_pointer=0; 254 int compare_result=0;//这个变量会被复用,在插入时作为字符串比较的结果,在平衡时作为高度差。 255 int original_depth;//这个用来记录节点原来的高度 256 tree_node_stack[0]=NULL;//哨兵节点,在旋转的时候有用 257 new_node=malloc(sizeof(struct _type_avl_tree)); 258 new_node->current_gen_list=new_type_node; 259 new_node->left=NULL; 260 new_node->right=NULL; 261 new_node->tree_depth=1; 262 if(type_tree_head==NULL) 263 { 264 type_tree_head=new_node; 265 return 0; 266 } 267 else 268 { 269 temp_node_one=type_tree_head; 270 while(temp_node_one!=NULL) 271 { 272 stack_pointer++; 273 tree_node_stack[stack_pointer]=temp_node_one; 274 temp_type_description=(ptype_description)temp_node_one->current_type_body; 275 compare_result=strcmp(new_type_node->name,temp_type_description->name); 276 if(compare_result<0) 277 { 278 temp_node_one=temp_node_one->left; 279 } 280 else 281 { 282 temp_node_one=temp_node_one->right; 283 } 284 }//这个栈记录了插入所经过的路径 285 temp_node_one=tree_node_stack[stack_pointer]; 286 if(compare_result<0) 287 { 288 temp_node_one->left=new_node; 289 } 290 else 291 { 292 temp_node_one->right=new_node; 293 } 294 //现在节点关系已经建立了,开始平衡树高度了 295 while(stack_pointer>0)//遍历整个栈,来寻找需要平衡的节点 296 //注意,这里跳出循环的条件是,某个节点在修改后高度没有改变,这样就没有必要再去修改了 297 //或者启用了平衡操作,启用平衡操作之后可以确保高度没有改变,因此可以退出 298 { 299 temp_node_one=tree_node_stack[stack_pointer]; 300 original_depth=temp_node_one->tree_depth; 301 modify_tree_depth(temp_node_one); 302 if(original_depth==temp_node_one->tree_depth) 303 { 304 return 0; 305 } 306 else 307 { 308 compare_result=temp_node_one->left->tree_depth-temp_node_one->right->tree_depth; 309 if(compare_result==2)//如果左边比右边高2 310 { 311 //这个时候需要考虑是要进行两次旋转还是一次旋转 312 if(tree_node_stack[stack_pointer+1]->right==tree_node_stack[stack_pointer+2]) 313 //这种情况我们需要做两次旋转 314 { 315 avl_rotate_left(tree_node_stack[stack_pointer],tree_node_stack[stack_pointer+1]); 316 } 317 avl_rotate_right(tree_node_stack[stack_pointer-1],tree_node_stack[stack_pointer]); 318 //第二次旋转 319 return 0; 320 } 321 else 322 { 323 if(compare_result==-2) 324 { 325 if(tree_node_stack[stack_pointer+1]->left==tree_node_stack[stack_pointer+2]) 326 { 327 avl_rotate_right(tree_node_stack[stack_pointer],tree_node_stack[stack_pointer+1]); 328 } 329 avl_rotate_left(tree_node_stack[stack_pointer-1],tree_node_stack[stack_pointer]); 330 return 0; 331 } 332 else 333 { 334 //这里继续向上传递 335 stack_pointer--; 336 } 337 } 338 } 339 } 340 //至此所有的插入及平衡都做完了 341 } 342 } 343 344 void delete_avl_node(char* avl_node_name)//这里我们要求已经做过参数检查了,挂了自己撞墙去 345 { 346 ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//神一样的命名方法 347 ptype_description temp_type_description; 348 int stack_pointer=0; 349 int compare_result=0; 350 int original_depth=0; 351 temp_node_one=type_tree_head; 352 tree_node_stack[0]=NULL;//哨兵 353 temp_type_description=(ptype_description)temp_node_one->current_type_body; 354 compare_result=strcmp(avl_node_name,temp_type_description->name); 355 while(compare_result!=0) 356 { 357 stack_pointer++; 358 tree_node_stack[stack_pointer]=temp_node_one; 359 if(compare_result>0) 360 { 361 temp_node_one=temp_node_one->right; 362 } 363 else 364 { 365 temp_node_one=temp_node_one->left; 366 } 367 temp_type_description=(ptype_description)temp_node_one->current_type_body; 368 compare_result=strcmp(avl_node_name,temp_type_description->name); 369 }//找到对应的节点 370 if(temp_node_one->left==NULL||temp_node_one->right==NULL)//如果有删除的节点只有一个或零个子节点 371 { 372 if(stack_pointer==0)//如果是头节点,且只有不多于1个的子节点 373 { 374 type_tree_head=temp_node_one->left|temp_node_one->right;//这里就不需要考虑空节点了,这里已经考虑过了 375 free(temp_node_one); 376 return 0;//直接返回 377 }//这里就不需要平衡了 378 else//如果不是头节点 379 { 380 temp_node_two=tree_node_stack[stack_pointer]; 381 if(temp_node_two->left==temp_node_one) 382 { 383 temp_node_two->left=temp_node_one->left|temp_node_one->right; 384 } 385 else 386 { 387 temp_node_two->right=temp_node_one->left|temp_node_one->right; 388 }//修正好所有的节点关系 389 } 390 } 391 else//有两个子节点,选择后继来处理 392 { 393 temp_node_two=temp_node_one->right; 394 while(temp_node_two!=NULL) 395 { 396 stack_pointer++; 397 tree_node_stack[stack_pointer]=temp_node_two; 398 temp_node_two=temp_node_two->left; 399 } 400 temp_node_two=tree_node_stack[stack_pointer]; 401 temp_node_one->current_generate_body=temp_node_two->current_generate_body; 402 //这样就把这个节点复制过去了 403 //现在我们要删除这个新的节点 404 stack_pointer--;//最后一个点抛弃,因为我们要删除这个点 405 //现在我们开始修改好节点关系,修改完之后再去平衡 406 if(temp_node_one->right==temp_node_two)//这个是特殊情况 407 { 408 temp_node_one->right=temp_node_two->right; 409 } 410 else 411 { 412 tree_node_stack[stack_pointer]->left=temp_node_two->right; 413 }//这里修正好所有的节点关系,然后再开始平衡 414 415 416 417 418 419 420 } 421 //现在开始进行平衡 422 while(stack_pointer>0) 423 { 424 //这里跳出循环的条件是某个节点的高度没有变化,调用平衡处理之后,还是有可能影响上面的节点 425 //所以还是需要处理其他的点,因此平衡处理不是跳出循环的条件 426 temp_node_three=tree_node_stack[stack_pointer]; 427 original_depth=temp_node_three->tree_depth; 428 modify_node_depth(temp_node_three); 429 if(temp_node_three->tree_depth==original_depth) 430 { 431 //如果子树的高度不变,则不需要继续处理了 432 return 0; 433 } 434 else//这里平衡操作不需要做第二次旋转,一次旋转就足够了 435 { 436 compare_result=temp_node_three->left->tree_depth-temp_node_three->right->tree_depth; 437 if(compare_result==2) 438 { 439 rotate_avl_right(tree_node_stack[stack_pointer-1],tree_node_stack[stack_pointer]); 440 stack_pointer--; 441 } 442 else 443 { 444 if(compare_result==-2) 445 { 446 rotate_avl_left(tree_node_stack[stack_pointer-1],tree_node_stack[stack_pointer]); 447 stack_pointer--; 448 } 449 else 450 { 451 stack_pointer--; 452 } 453 } 454 } 455 } 456 return 0; 457 } 458 ptype_description search_avl_tree(char* target_name)//在当前avl树中寻找是否有相应的名字的节点 459 { 460 ptype_avl_tree result;//作为遍历树的指针 461 ptype_description return_result;//作为返回的节点 462 int compare_result;//比较的时候的返回结果 463 result=type_tree_head; 464 while(result!=NULL) 465 { 466 return_result=(ptype_description)result->current_type_body; 467 compare_result=strcmp(target_name,return_result->name); 468 if(compare_result==0) 469 { 470 break;//不需要继续找了 471 } 472 else 473 { 474 if(compare_result<0) 475 { 476 result=result->left; 477 } 478 else 479 { 480 result=result->right; 481 } 482 } 483 } 484 return return_result; 485 } 486 487 488 489