minic 词法单元建立
1 #include <stdio.h> 2 #include "symbol_table_def.h" 3 //前面的那个词法和文法说明只是大概的说明,现在又有了改动,把指针运算符改为了@,把取地址运算符改为了$ 4 //但是类型声明的时候的指针类型仍然是* 5 //现在所有的符号都用了,除了让人恶心的逗号和问号 6 //现在开始定义词法单元的枚举类型 7 enum lex_type 8 { 9 name,//代表字符串,包括所有的关键字和变量声明 10 delimit,//代表分号,以及大括号 11 char_type,//代表字符 12 an_operator,//代表操作符 13 constant,//代表常量 14 string_phrase,//代表字符串 15 new_line//代表换行,因为在处理的时候换行是一个很重要的符号 16 }; 17 enum basic_operator_type 18 { 19 array_op=9,//代表数组分量运算 20 parenthesis,//代表括号 21 p_str_sub,//代表结构体指针分量运算 22 str_sub,//代表结构体分量运算 23 not,//代表! 24 bit_rev,//代表~ 25 get_adr,//代表$ 26 get_mem,//代表@ 27 type_cast,//代表强制类型转换 28 negative,//代表负号运算 29 get_size,//代表sizeof 30 multi,//代表乘法 31 div,//代表除法 32 module,//代表模 33 add,//代表加法 34 minus,//代表减法 35 left_shift,//左移 36 right_shift,//右移 37 larger,//大于 38 smaller,//小于 39 lar_eqa,//大于等于 40 sma_eqa,//小于等于 41 equal,//等于 42 nequal,//不等于 43 bit_and,//& 44 bit_xor,//^ 45 bit_or,//| 46 and,//&& 47 or// || 48 }; 49 50 struct first_lex_token 51 { 52 enum lex_type current_lex_type;//在第一遍处理的时候我们把所有的词素分为前面所说的六种 53 char* token_name; 54 }; 55 struct first_token_chain//这个链表将所有的词法单元串联起来 56 { 57 struct first_lex_token* current_first_token; 58 struct first_token_chain* next; 59 }; 60 struct first_token_chain* first_chain_head=NULL;//这里是所有节点的头节点 61 struct first_token_chain* first_chain_tail=NULL;//这里是所有节点的末尾节点,为了插入用. 62 //在第一趟处理的时候我们开两个2000个字节的缓冲区,用来读文件,并不断的切换 63 //为了表明文件的结束,我们找来了我们的老朋友 '17' ,我们用这个字符来表示缓冲区的文件末尾 64 char end_of_file=17; 65 char* buff_zone[2];//这个代表两个缓冲区 66 int buffer_pointer;//这个代表在缓冲区内的偏移 67 int file_read_byte;//这个代表在读取文件到缓冲区的时候,读取了多少个字符 68 int buff_zone_index;//代表使用的是那一个缓冲区 69 char* current_buff;//这个代表当前的缓冲区 70 int seek_begin(void ) 71 { 72 //吃掉所有的空格和制表符 73 while(buffer_pointer<2000) 74 { 75 switch(*(buffer_zone[buffer_zone_index]+buffer_pointer)) 76 { 77 case 17: 78 return -1;//直接返回,文件已经处理完毕了 79 break; 80 case ' ': 81 buffer_pointer++; 82 break; 83 case '\t': 84 buffer_pointer++; 85 break; 86 default: 87 break; 88 } 89 } 90 if(buffer_pointer==2000)//越过缓冲区了 91 { 92 buffer_zone_index=1-buffer_zone_index;//切换缓冲区 93 current_buff=buff_zone[buff_zone_index]; 94 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 95 if(file_read_byte!=2000)//如果碰到文件的结束了 96 { 97 *(current_buff+file_read_byte)=17;//标记为文件末尾 98 //因为我们遇到的是字符文件,所以不会出现17这个字符 99 } 100 buffer_pointer=0; 101 //重新开始读取输入,这里我们默认制表符和空格符不会占用整个缓冲 102 //吃掉所有的空格和制表符 103 while(buffer_pointer<2000) 104 { 105 switch(buffer_zone[buffer_zone_index]+buffer_pointer) 106 { 107 case 17: 108 return -1;//直接返回,文件已经处理完毕了 109 break; 110 case ' ': 111 buffer_pointer++; 112 break; 113 case '\t': 114 buffer_pointer++; 115 break; 116 default: 117 break; 118 } 119 } 120 } 121 122 return 1;//代表正常的返回 123 } 124 int lex_char_type(char current)//返回当前字符的前缀集 125 { 126 char test; 127 test=current; 128 if((test>='a'&&test<='z')||(test>='A'&&test<='Z')||(test=='_')) 129 { 130 return 1;//代表名字 131 } 132 else 133 { 134 if(test>='0'&&test<='9') 135 { 136 return 2;//数字 137 } 138 else 139 { 140 if(test==';'||test=='{'||test=='}') 141 { 142 return 3;//代表分隔符 143 } 144 else 145 { 146 if(test=='\'') 147 { 148 return 4;//代表字符 149 } 150 else 151 { 152 if(test=='\"') 153 { 154 return 5;//代表字符串 155 } 156 else 157 { 158 return 6;//代表运算符 159 } 160 } 161 } 162 } 163 } 164 } 165 166 167 168 void first_procedure(FILE* input_file_name) 169 { 170 char* temp_name;//代表词法单元的内容 171 int token_length;//代表读取的词法单元的长度 172 int lex_mode;//代表开始字符所处的token种类 173 int seek_return; 174 char current_char; 175 int for_i,for_j; 176 struct first_lex_token* temp_token; 177 struct first_token_chain token_chain_node; 178 current_buff=malloc(sizeof(char)*4000); 179 buff_zone[0]=current_buff; 180 buff_zone[1]=current_buff+2000; 181 //这里我们其实上把一个4000的缓冲区分裂为两个缓冲区了,这样可以让这两个缓冲区的空间连续 182 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 183 if(file_read_byte!=2000)//如果碰到文件的结束了 184 { 185 *(current_buff+file_read_byte)=17;//标记为文件末尾 186 //因为我们遇到的是字符文件,所以不会出现17这个字符 187 } 188 buff_zone_index=0;//首先使用第一个缓冲区 189 buffer_pointer=0; 190 seek_return=seek_begin(); 191 while(seek_return!=-1)//只要还没有到达末尾 192 { 193 current_char=*(buff_zone[buff_zone_index]+buffer_pointer); 194 lex_mode=lex_char_type(current_char); 195 switch(lex_mode) 196 { 197 case 1://代表名字 198 token_length=0; 199 while((current_char>='a'&¤t_char<='z')||(current_char>='A'&¤t_char<='Z')||current_char=='_') 200 { 201 token_length++; 202 buffer_pointer++; 203 if(buffer_pointer==2000) 204 { 205 buff_zone_index=1-buff_zone_index; 206 current_buff=buff_zone[buff_zone_index]; 207 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 208 if(file_read_byte!=2000)//如果碰到文件的结束了 209 { 210 *(current_buff+file_read_byte)=17;//标记为文件末尾 211 //因为我们遇到的是字符文件,所以不会出现17这个字符 212 } 213 buffer_pointer=0; 214 } 215 current_char=current_buff[buffer_pointer]; 216 } 217 temp_name=malloc(sizeof(char)*(token_length+1)); 218 if(token_length<=buffer_pointer) 219 { 220 for(for_i=0;for_i<token_length;for_i++) 221 { 222 temp_name[for_i]=current_buff[buffer_pointer-token_length+for_i]; 223 } 224 } 225 else 226 { 227 current_buff=buff_zone[1-buff_zone_index]; 228 for_j=token_length-buffer_pointer; 229 for(for_i=0;for_i<for_j;for_i++) 230 { 231 temp_name[for_i]=current_buff[2000-for_j+for_i]; 232 } 233 current_buff=buff_zone[buff_zone_index]; 234 for(for_i=0;for_i<buffer_pointer;for_i++) 235 { 236 temp_name[for_j+for_i]=current_buff[for_i]; 237 } 238 } 239 temp_name[token_length]='\0'; 240 temp_token=malloc(sizeof(struct first_lex_token)); 241 temp_token->token_name=temp_name; 242 if(strcmp("sizeof",temp_name)==0) 243 { 244 temp_token->current_lex_type=an_operator; 245 } 246 else 247 { 248 temp_token->current_lex_type=name; 249 } 250 break; 251 case 2://对应数字常量的情况 252 token_length=0; 253 while((current_char>='0'&¤t_char<='9')||(current_char>='A'&¤t_char<='F')||\ 254 (current_char>='a'&¤t_char<='f')||current_char=='x'||current_char=='X'||current_char=='.') 255 { 256 token_length++; 257 buffer_pointer++; 258 if(buffer_pointer==2000) 259 { 260 buff_zone_index=1-buff_zone_index; 261 current_buff=buff_zone[buff_zone_index]; 262 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 263 if(file_read_byte!=2000)//如果碰到文件的结束了 264 { 265 *(current_buff+file_read_byte)=17;//标记为文件末尾 266 //因为我们遇到的是字符文件,所以不会出现17这个字符 267 } 268 buffer_pointer=0; 269 } 270 current_char=current_buff[buffer_pointer]; 271 } 272 temp_name=malloc(sizeof(char)*(token_length+1)); 273 if(token_length<=buffer_pointer) 274 { 275 for(for_i=0;for_i<token_length;for_i++) 276 { 277 temp_name[for_i]=current_buff[buffer_pointer-token_length+for_i]; 278 } 279 } 280 else 281 { 282 current_buff=buff_zone[1-buff_zone_index]; 283 for_j=token_length-buffer_pointer; 284 for(for_i=0;for_i<for_j;for_i++) 285 { 286 temp_name[for_i]=current_buff[2000-for_j+for_i]; 287 } 288 current_buff=buff_zone[buff_zone_index]; 289 for(for_i=0;for_i<buffer_pointer;for_i++) 290 { 291 temp_name[for_j+for_i]=current_buff[for_i]; 292 } 293 } 294 temp_name[token_length]='\0'; 295 temp_token=malloc(sizeof(struct first_lex_token)); 296 temp_token->token_name=temp_name; 297 temp_token->current_lex_type=constant; 298 break; 299 case 3://对应分隔符 300 temp_name=malloc(sizeof(char)*2); 301 temp_name[0]=current_buff[buffer_pointer]; 302 temp_name[1]='\0'; 303 buffer_pointer++; 304 if(buffer_pointer==2000) 305 { 306 buff_zone_index=1-buff_zone_index; 307 current_buff=buff_zone[buff_zone_index]; 308 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 309 if(file_read_byte!=2000)//如果碰到文件的结束了 310 { 311 *(current_buff+file_read_byte)=17;//标记为文件末尾 312 //因为我们遇到的是字符文件,所以不会出现17这个字符 313 } 314 buffer_pointer=0; 315 } 316 current_char=current_buff[buffer_pointer]; 317 temp_token=malloc(sizeof(struct first_lex_token)); 318 temp_token->token_name=temp_name; 319 temp_token->current_lex_type=delimit; 320 break; 321 case 4://对应字符 322 token_length=0; 323 buffer_pointer++; 324 if(buffer_pointer==2000) 325 { 326 buff_zone_index=1-buff_zone_index; 327 current_buff=buff_zone[buff_zone_index]; 328 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 329 if(file_read_byte!=2000)//如果碰到文件的结束了 330 { 331 *(current_buff+file_read_byte)=17;//标记为文件末尾 332 //因为我们遇到的是字符文件,所以不会出现17这个字符 333 } 334 buffer_pointer=0; 335 } 336 current_char=current_buff[buffer_pointer]; 337 while(current_char!='\'') 338 { 339 token_length++; 340 buffer_pointer++; 341 if(buffer_pointer==2000) 342 { 343 buff_zone_index=1-buff_zone_index; 344 current_buff=buff_zone[buff_zone_index]; 345 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 346 if(file_read_byte!=2000)//如果碰到文件的结束了 347 { 348 *(current_buff+file_read_byte)=17;//标记为文件末尾 349 //因为我们遇到的是字符文件,所以不会出现17这个字符 350 } 351 buffer_pointer=0; 352 } 353 current_char=current_buff[buffer_pointer]; 354 } 355 temp_name=malloc(sizeof(char)*(token_length)); 356 if(token_length<=buffer_pointer) 357 { 358 for(for_i=0;for_i<token_length;for_i++) 359 { 360 temp_name[for_i]=current_buff[buffer_pointer-token_length+for_i]; 361 } 362 } 363 else 364 { 365 current_buff=buff_zone[1-buff_zone_index]; 366 for_j=token_length-buffer_pointer; 367 for(for_i=0;for_i<for_j;for_i++) 368 { 369 temp_name[for_i]=current_buff[2000-for_j+for_i]; 370 } 371 current_buff=buff_zone[buff_zone_index]; 372 for(for_i=0;for_i<buffer_pointer;for_i++) 373 { 374 temp_name[for_j+for_i]=current_buff[for_i]; 375 } 376 } 377 buffer_pointer++; 378 if(buffer_pointer==2000) 379 { 380 buff_zone_index=1-buff_zone_index; 381 current_buff=buff_zone[buff_zone_index]; 382 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 383 if(file_read_byte!=2000)//如果碰到文件的结束了 384 { 385 *(current_buff+file_read_byte)=17;//标记为文件末尾 386 //因为我们遇到的是字符文件,所以不会出现17这个字符 387 } 388 buffer_pointer=0; 389 } 390 temp_name[token_length-1]='\0'; 391 if(temp_name[0]=='\\')//处理转义字符 392 { 393 switch(temp_name[1]) 394 { 395 case 'n': 396 temp_name[0]='\n'; 397 temp_name[1]='\0'; 398 break; 399 case 't': 400 temp_name[0]='\t'; 401 temp_name[1]='\0'; 402 break; 403 case '0': 404 temp_name[0]='\0'; 405 break; 406 case '\\': 407 temp_name[1]='\0'; 408 break; 409 case '\'': 410 temp_name[0]='\''; 411 temp_name[1]='\0'; 412 break; 413 case '\"': 414 temp_name[0]='\"'; 415 temp_name[1]='\0'; 416 break; 417 default: 418 break; 419 } 420 } 421 temp_token=malloc(sizeof(struct first_lex_token)); 422 temp_token->token_name=temp_name; 423 temp_token->current_lex_type=constant; 424 break; 425 case 5://代表字符串 426 token_length=0; 427 buffer_pointer++; 428 if(buffer_pointer==2000) 429 { 430 buff_zone_index=1-buff_zone_index; 431 current_buff=buff_zone[buff_zone_index]; 432 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 433 if(file_read_byte!=2000)//如果碰到文件的结束了 434 { 435 *(current_buff+file_read_byte)=17;//标记为文件末尾 436 //因为我们遇到的是字符文件,所以不会出现17这个字符 437 } 438 buffer_pointer=0; 439 } 440 current_char=current_buff[buffer_pointer]; 441 while(1) 442 { 443 while(current_char!='\"') 444 { 445 token_length++; 446 buffer_pointer++; 447 if(buffer_pointer==2000) 448 { 449 buff_zone_index=1-buff_zone_index; 450 current_buff=buff_zone[buff_zone_index]; 451 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 452 if(file_read_byte!=2000)//如果碰到文件的结束了 453 { 454 *(current_buff+file_read_byte)=17;//标记为文件末尾 455 //因为我们遇到的是字符文件,所以不会出现17这个字符 456 } 457 buffer_pointer=0; 458 } 459 current_char=current_buff[buffer_pointer]; 460 } 461 if(buffer_pointer==0)//判断是否是字符串的结尾 462 { 463 if(*(buff_zone[1-buff_zone_index]+1999)!='\\') 464 { 465 break; 466 } 467 else 468 { 469 token_length++; 470 buffer_pointer++; 471 //继续下次循环 472 } 473 } 474 else 475 { 476 if(current_buff[buffer_pointer-1]!='\\') 477 { 478 break; 479 } 480 else 481 { 482 token_length++; 483 buffer_pointer++; 484 if(buffer_pointer==2000) 485 { 486 buff_zone_index=1-buff_zone_index; 487 current_buff=buff_zone[buff_zone_index]; 488 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 489 if(file_read_byte!=2000)//如果碰到文件的结束了 490 { 491 *(current_buff+file_read_byte)=17;//标记为文件末尾 492 //因为我们遇到的是字符文件,所以不会出现17这个字符 493 } 494 buffer_pointer=0; 495 } 496 current_char=current_buff[buffer_pointer]; 497 } 498 } 499 500 501 502 } 503 temp_name=malloc(sizeof(char)*(token_length+1)); 504 if(token_length<=buffer_pointer) 505 { 506 for(for_i=0;for_i<token_length;for_i++) 507 { 508 temp_name[for_i]=current_buff[buffer_pointer-token_length+for_i]; 509 } 510 } 511 else 512 { 513 current_buff=buff_zone[1-buff_zone_index]; 514 for_j=token_length-buffer_pointer; 515 for(for_i=0;for_i<for_j;for_i++) 516 { 517 temp_name[for_i]=current_buff[2000-for_j+for_i]; 518 } 519 current_buff=buff_zone[buff_zone_index]; 520 for(for_i=0;for_i<buffer_pointer;for_i++) 521 { 522 temp_name[for_j+for_i]=current_buff[for_i]; 523 } 524 } 525 temp_name[token_length]='\0'; 526 buffer_pointer++; 527 temp_token=malloc(sizeof(struct first_lex_token)); 528 temp_token->token_name=temp_name; 529 temp_token->current_lex_type=string_phrase; 530 break; 531 case 6://代表操作符 532 temp_name=malloc(sizeof(char)*2); 533 temp_name[0]=current_buff[buffer_pointer]; 534 temp_name[1]='\0'; 535 buffer_pointer++; 536 if(buffer_pointer==2000) 537 { 538 buff_zone_index=1-buff_zone_index; 539 current_buff=buff_zone[buff_zone_index]; 540 file_read_byte=fread(current_buff,sizeof(char),2000,input_file_name); 541 if(file_read_byte!=2000)//如果碰到文件的结束了 542 { 543 *(current_buff+file_read_byte)=17;//标记为文件末尾 544 //因为我们遇到的是字符文件,所以不会出现17这个字符 545 } 546 buffer_pointer=0; 547 } 548 temp_token=malloc(sizeof(struct first_lex_token)); 549 temp_token->token_name=temp_name; 550 temp_token->current_lex_type=an_operator; 551 break; 552 default: 553 printf(" un_recognised type\n"); 554 break; 555 } 556 token_chain_node=malloc(sizeof(struct first_token_chain)); 557 token_chain_node->next=NULL; 558 token_chain_node->current_first_token=temp_token; 559 if(token_chain_tail==NULL) 560 { 561 token_chain_tail=token_chain_node; 562 token_chain_head=token_chain_node; 563 } 564 else 565 { 566 token_chain_tail->next=token_chain_node; 567 token_chain_tail=token_chain_node; 568 } 569 seek_return=seek_begin(); 570 } 571 } 572