这一次增加的对结构体的支持, 但是还不很完善.
下面具体讲讲:
1.只允许在全局空间里面声明结构体(在局部的话, 需要局部作用于失效的时候也销毁结构体声明, 可搞), 形式如下:
1 struct mm 2 { 3 int x, y; 4 char ppp; 5 };
2.暂时不支持一边声明结构体一边定义一个相应的变量(这个也可搞), 例如:
1 struct mm 2 { 3 int x, y; 4 char ppp; 5 }m; //this is not supported yet
3.允许在全局空间和局部空间里面声明结构体, 同时允许初始化, 也允许使用{1, 2, 3}形式对结构体进行赋值.
也允许相同类型的结构体之间进行赋值(初始化时{}里面一定要足够, 下次处理一下不够的情况).如下:
1 struct mm 2 { 3 int x, y; 4 char ppp; 5 }; 6 mm a; 7 mm a1 = {1, 2, 'm'}; 8 struct mm b; 9 struct mm b = {1, 1, 'c'}; 10 b = {1, 2, 'c'};
4.不允许结构体里面声明函数, 不允许匿名的结构体(函数的就先别想了, 匿名肯定可以).
----------------------------------------------------------------------------------------------------------------------------
对于结构体的实现, 就是用一个vector<var> 来模拟的, 然后在全局层面存一个已经声明的struct的数组, 效率肯定不高,
因为真正的C++里面, 结构体底层就是一块内存, 使用推算member在结构体里面的位移来使用结构体的, 效率很好, 但是我们是在用C++来解释C++, 所以搞那么底层反而无趣了..
程序的耦合度进一步增大了, 现在我看这代码就像一坨翔了, 哈哈, 下一次一定好好重构一下..
估计下一次修改, 应该会改进对struct的支持, 同时适当重构一下代码.
翠花, 上代码:

1 //mccommon.h 2 3 4 /************************************************************************/ 5 /* mccommon.h, 头文件里面声明了Minicpp使用的函数, 声明主要使用的 6 * 最新修改时间2012-9-15, 主要增加了var.cpp里面函数的声明 */ 7 /************************************************************************/ 8 9 #include <vector> 10 using namespace std; 11 const int MAX_T_LEN = 128; // max token length 12 const int MAX_ID_LEN = 31; // max identifier length 13 const int PROG_SIZE = 10000; // max program size 14 const int NUM_PARAMS = 31; // max number of parameters 15 16 // Enumeration of token types. 17 enum tok_types { UNDEFTT, DELIMITER, IDENTIFIER, 18 NUMBER, KEYWORD, TEMP, STRING, BLOCK, TYPE 19 }; 20 21 // Enumeration of internal representation of tokens. 22 //大部分指定的是C++里面的关键字, 当然cout和cin也被加进来了 23 enum token_ireps { UNDEFTOK, ARG, BOOL, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, STRUCT, FALSE, TRUE, SWITCH, 24 CASE, IF, ELSE, FOR, DO, WHILE, BREAK, 25 RETURN, COUT, CIN, END, ENDL, DEFAULT, CONTINUE, NONE 26 }; 27 28 29 //上面两个枚举的区别是上面的比较广义,指代各种token的类型, 比如block, 这个是不会是关键字的, 30 //下面的可以理解成就是关键字 31 struct var; 32 struct struct_type 33 { 34 struct_type() 35 { 36 type_name[0] = '\0'; 37 data.clear(); 38 } 39 char type_name[MAX_ID_LEN + 1]; 40 vector<var> data; 41 }; 42 43 //这是个匿名的var结构体, 存储了变量的类型和值, 但是是个匿名的, 44 //类似python里面的变量的引用的概念 45 struct anonymous_var 46 { 47 token_ireps var_type; // data type, 这里只用那些数据类型, 包括struct 48 long int_value; 49 double float_value; 50 struct_type struct_value; 51 }; 52 53 // This structure encapsulates the info 54 // associated with variables. 55 struct var 56 { 57 char var_name[MAX_ID_LEN + 1]; // name 58 anonymous_var value; 59 }; 60 61 62 63 64 // This structure encapsulates function info. 65 struct func_type 66 { 67 char func_name[MAX_ID_LEN + 1]; // name 68 token_ireps ret_type; // return type 69 char *loc; // location of entry point in program 70 }; 71 72 // Enumeration of two-character operators, such as <=. 73 //这里注意从1开始, 以免用到0出现误解. 74 enum double_ops { LT = 1, LE, GT, GE, EQ, NE, LS, RS, INC, DEC }; 75 76 // These are the constants used when throwing a 77 // syntax error exception. 78 // 79 // NOTE: SYNTAX is a generic error message used when 80 // nothing else seems appropriate. 81 enum error_msg 82 { 83 SYNTAX, NO_EXP, NOT_VAR, DUP_VAR, DUP_FUNC, 84 SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF, 85 TYPE_EXPECTED, RET_NOCALL, PAREN_EXPECTED, 86 WHILE_EXPECTED, QUOTE_EXPECTED, DIV_BY_ZERO, 87 BRACE_EXPECTED, COLON_EXPECTED, UNSUPPORTED_TYPE, MORE_MEMBER_THAN_EXPECTED 88 //最后加了一个UNSUPPORTED_TYPE, 是因为最近只支持一些简单的内建类型 89 }; 90 91 //下面这些是全局变量, 用来控制解析的, 估计以后如果重构的话就是parser类的主要成员变量. 92 extern char *prog; // current location in source code 93 extern char *p_buf; // points to start of program buffer 94 95 extern char token[MAX_T_LEN + 1]; // string version of token 96 extern tok_types token_type; // contains type of token 97 extern token_ireps tok; // internal representation of token 98 99 extern anonymous_var ret_value; // function return value 100 101 extern bool breakfound; // true if break encountered 102 extern bool continuefound;//true if continue encountered 103 104 // Exception class for Mini C++. 105 class InterpExc 106 { 107 error_msg err; 108 public: 109 InterpExc(error_msg e) 110 { 111 err = e; 112 } 113 error_msg get_err() 114 { 115 return err; 116 } 117 }; 118 119 // Interpreter prototypes. 120 void prescan(); 121 void decl_global(); 122 void decl_struct_type();//完成结构体的声明. 123 void dump_struct_type(); //这个函数在控制台输出所有目前已经声明的结构体的内容. 124 bool is_struct_type(char* type_name); //在全局声明的struct里面找, 看是不是一个已经声明的struct 125 bool get_struct_type_by_name(char* struct_name, struct_type& s_type); 126 void decl_struct(); 127 bool get_member_var(char* p, anonymous_var*& v); 128 bool get_type_by_name(char* vname, char* type_name); 129 void call(); 130 void putback(); 131 void decl_local(); 132 void exec_if(); 133 void find_eob(); 134 void exec_for(); 135 void exec_switch(); 136 void get_params(); 137 void get_args(); 138 void exec_while(); 139 void exec_do(); 140 void exec_cout(); 141 void exec_cin(); 142 void assign_var(char *var_name, anonymous_var value); 143 bool load_program(char *p, char *fname); 144 145 146 anonymous_var find_var(char *s); 147 void interp(); 148 void func_ret(); 149 char *find_func(char *name); 150 bool is_var(char *s); 151 token_ireps find_var_type(char *s); 152 void find_eol(); 153 154 155 // Parser prototypes, 这些函数主要用来parse表达式. 156 void eval_exp(anonymous_var &value); 157 void eval_exp0(anonymous_var &value); 158 void eval_exp1(anonymous_var &value); 159 void eval_exp2(anonymous_var &value); 160 void eval_exp3(anonymous_var &value); 161 void eval_exp4(anonymous_var &value); 162 void eval_exp5(anonymous_var &value); 163 void atom(anonymous_var &value); 164 void sntx_err(error_msg error); 165 void putback(); 166 bool isdelim(char c); 167 token_ireps look_up(char *s); 168 anonymous_var find_var(char *s); 169 tok_types get_token(); 170 int internal_func(char *s); 171 bool is_var(char *s); 172 void init_struct(char* struct_name, anonymous_var& value); 173 174 175 // "Standard library" prototypes, 这几个函数里面是调用了一下C++的库函数, 封装了一下. 176 anonymous_var call_getchar(); 177 anonymous_var call_putchar(); 178 anonymous_var call_abs(); 179 anonymous_var call_rand(); 180 181 182 183 //下面这些是为了支持多种类型二增加的一些函数. 184 //在var.cpp里面实现. 185 anonymous_var add(anonymous_var &a, anonymous_var &b); 186 anonymous_var sub(anonymous_var &a, anonymous_var &b); 187 anonymous_var mul(anonymous_var &a, anonymous_var &b); 188 anonymous_var div(anonymous_var &a, anonymous_var &b); 189 void cin_var(anonymous_var &v); 190 void cout_var(anonymous_var &v); 191 bool is_valid_simple_type(token_ireps ti); 192 void init_var(anonymous_var &v); 193 void neg_var(anonymous_var &v); 194 bool zero(double x); 195 void abs_var(anonymous_var &v); 196 int cmp(anonymous_var &a, anonymous_var &b); 197 bool is_float_type(token_ireps type); 198 bool is_int_type(token_ireps type); 199 bool get_bool_val(anonymous_var &v); 200 void adaptive_assign_var(anonymous_var &a, anonymous_var &b); 201 202 203 //var.cpp 204 /******************************************************************** 205 var.cpp, 主要是为了增加对多种数值类型的支持而添加的 206 目前支持bool, char, short, int, long, float, double 207 基本只使用long和double进行结算. 208 **********************************************************************/ 209 210 #include <iostream> 211 #include <cmath> 212 #include <cassert> 213 #include "mccommon.h" 214 using namespace std; 215 216 extern vector<struct_type> struct_decls; 217 218 inline bool zero(double x) 219 { 220 const double EPS = 1e-9; 221 return abs(x) < EPS; 222 } 223 bool is_int_type(token_ireps type) 224 { 225 if(type >= BOOL && type <= LONG) return true; 226 return false; 227 } 228 bool is_float_type(token_ireps type) 229 { 230 if(type >= FLOAT && type <= DOUBLE) return true; 231 else return false; 232 } 233 bool check_valid_type(anonymous_var &val) 234 { 235 if(!(is_int_type(val.var_type) || is_float_type(val.var_type))) return false; 236 return true; 237 } 238 anonymous_var add(anonymous_var &a, anonymous_var &b) 239 { 240 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 241 anonymous_var res; 242 if(a.var_type > b.var_type) res.var_type = a.var_type; 243 else res.var_type = b.var_type; 244 245 if(is_int_type(res.var_type)) 246 { 247 res.int_value = a.int_value + b.int_value; 248 } 249 else 250 { 251 if(is_int_type(a.var_type)) 252 { 253 res.float_value = double(a.int_value) + b.float_value; 254 } 255 else if(is_int_type(b.var_type)) 256 { 257 res.float_value = a.float_value + double(b.int_value); 258 } 259 else 260 { 261 res.float_value = a.float_value + b.float_value; 262 } 263 } 264 return res; 265 } 266 267 anonymous_var sub(anonymous_var &a, anonymous_var &b) 268 { 269 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 270 anonymous_var res; 271 if(a.var_type > b.var_type) res.var_type = a.var_type; 272 else res.var_type = b.var_type; 273 274 if(is_int_type(res.var_type)) 275 { 276 res.int_value = a.int_value - b.int_value; 277 } 278 else 279 { 280 if(is_int_type(a.var_type)) 281 { 282 res.float_value = double(a.int_value) - b.float_value; 283 } 284 else if(is_int_type(b.var_type)) 285 { 286 res.float_value = a.float_value - double(b.int_value); 287 } 288 else 289 { 290 res.float_value = a.float_value - b.float_value; 291 } 292 } 293 return res; 294 295 } 296 297 anonymous_var mul(anonymous_var &a, anonymous_var &b) 298 { 299 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 300 anonymous_var res; 301 302 if(a.var_type > b.var_type) res.var_type = a.var_type; 303 else res.var_type = b.var_type; 304 305 if(is_int_type(res.var_type)) 306 { 307 res.int_value = a.int_value * b.int_value; 308 } 309 else 310 { 311 if(is_int_type(a.var_type)) 312 { 313 res.float_value = double(a.int_value) * b.float_value; 314 } 315 else if(is_int_type(b.var_type)) 316 { 317 res.float_value = a.float_value * double(b.int_value); 318 } 319 else 320 { 321 res.float_value = a.float_value * b.float_value; 322 } 323 } 324 return res; 325 } 326 327 anonymous_var div(anonymous_var &a, anonymous_var &b) 328 { 329 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 330 anonymous_var res; 331 if(a.var_type > b.var_type) res.var_type = a.var_type; 332 else res.var_type = b.var_type; 333 334 if(is_int_type(b.var_type)) 335 { 336 if(0 == a.int_value) throw InterpExc(DIV_BY_ZERO); 337 } 338 else 339 { 340 if(zero(b.float_value)) throw InterpExc(DIV_BY_ZERO); 341 } 342 343 if(is_int_type(res.var_type)) 344 { 345 res.int_value = a.int_value / b.int_value; 346 } 347 else 348 { 349 if(is_int_type(a.var_type)) 350 { 351 res.float_value = double(a.int_value) / b.float_value; 352 } 353 else if(is_int_type(b.var_type)) 354 { 355 res.float_value = a.float_value / double(b.int_value); 356 } 357 else 358 { 359 res.float_value = a.float_value / b.float_value; 360 } 361 } 362 return res; 363 } 364 365 366 //因为现在我只用long 和double来存储表示所有的数值类型, 367 //在从控制台读取内容的时候会不方便, 现在先用 368 void cin_var(anonymous_var &v) 369 { 370 switch (v.var_type) 371 { 372 case BOOL: 373 { 374 bool tmp_var; 375 cin >> tmp_var; 376 v.int_value = tmp_var; 377 break; 378 } 379 case CHAR: 380 { 381 char tmp_var; 382 cin >> tmp_var; 383 v.int_value = tmp_var; 384 break; 385 } 386 case SHORT: 387 { 388 short tmp_var; 389 cin >> tmp_var; 390 v.int_value = tmp_var; 391 break; 392 } 393 case INT: 394 { 395 int tmp_var; 396 cin >> tmp_var; 397 v.int_value = tmp_var; 398 break; 399 } 400 case LONG: 401 { 402 long tmp_var; 403 cin >> tmp_var; 404 v.int_value = tmp_var; 405 break; 406 } 407 case FLOAT: 408 { 409 float tmp_var; 410 cin >> tmp_var; 411 v.float_value = tmp_var; 412 break; 413 } 414 case DOUBLE: 415 { 416 double tmp_var; 417 cin >> tmp_var; 418 v.float_value = tmp_var; 419 break; 420 } 421 default: 422 throw InterpExc(UNSUPPORTED_TYPE); 423 break; 424 } 425 } 426 427 428 //输出的时候, 要先转化成相应的类型, 然后再打印 429 void cout_var(anonymous_var &v) 430 { 431 switch(v.var_type) 432 { 433 case BOOL: 434 cout << bool(v.int_value != 0); 435 break; 436 case CHAR: 437 cout << char(v.int_value); 438 break; 439 case SHORT: 440 cout << short(v.int_value); 441 break; 442 case INT: 443 cout << int(v.int_value); 444 break; 445 case LONG: 446 cout << long(v.int_value); 447 break; 448 case FLOAT: 449 cout << float(v.float_value); 450 break; 451 case DOUBLE: 452 cout << double(v.float_value); 453 break; 454 default: 455 throw InterpExc(UNSUPPORTED_TYPE); 456 break; 457 } 458 } 459 460 bool is_valid_simple_type(token_ireps ti) 461 { 462 return ti >= BOOL && ti <= DOUBLE; 463 } 464 465 void init_var(anonymous_var &v) 466 { 467 v.int_value = 0; 468 v.float_value = 0.0; 469 v.struct_value.data.clear(); 470 //v.struct_value.type_name[0] = '\0'; 471 if(0 == strcmp(v.struct_value.type_name, "")) return; 472 473 //如果是个结构体, 我们已经获得了结构体的名字了, 可以拿来指导初始化. 474 int sz = struct_decls.size(); 475 for(int i = 0; i < sz; i++) 476 { 477 if(strcmp(v.struct_value.type_name, struct_decls[i].type_name) == 0) 478 { 479 int len = struct_decls[i].data.size(); 480 for(int j = 0; j < len; j++) 481 { 482 var member_var = struct_decls[i].data[j]; 483 v.struct_value.data.push_back(member_var); 484 } 485 } 486 } 487 } 488 489 void neg_var(anonymous_var &v) 490 { 491 if(is_int_type(v.var_type)) 492 { 493 v.int_value = -v.int_value; 494 } 495 else if(is_float_type(v.var_type)) 496 { 497 v.float_value = v.float_value; 498 } 499 else 500 { 501 throw InterpExc(UNSUPPORTED_TYPE); 502 } 503 } 504 505 void abs_var(anonymous_var &v) 506 { 507 if(is_int_type(v.var_type)) 508 { 509 v.int_value = abs(v.int_value); 510 } 511 else if(is_float_type(v.var_type)) 512 { 513 v.float_value = abs(v.float_value); 514 } 515 else 516 { 517 throw InterpExc(UNSUPPORTED_TYPE); 518 } 519 } 520 521 522 523 int cmp(anonymous_var &a, anonymous_var &b) 524 { 525 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 526 if(is_int_type(a.var_type)) 527 { 528 if(is_int_type(b.var_type)) 529 { 530 if(a.int_value == b.int_value) return 0; 531 if(a.int_value < b.int_value) return -1; 532 return 1; 533 } 534 else if(is_float_type(a.var_type)) 535 { 536 if(zero(a.int_value - b.float_value)) return 0; 537 if(a.int_value < b.float_value) return -1; 538 return 1; 539 } 540 } 541 else 542 { 543 if(is_int_type(b.var_type)) 544 { 545 if(zero(a.float_value - b.int_value)) return 0; 546 if(a.float_value < b.int_value) return -1; 547 return 1; 548 } 549 else 550 { 551 if(zero(a.float_value - b.float_value)) return 0; 552 if(a.float_value < b.float_value) return -1; 553 return 1; 554 } 555 } 556 return 0; 557 } 558 559 bool get_bool_val(anonymous_var &v) 560 { 561 bool bool_val = false; 562 if(is_int_type(v.var_type)) 563 { 564 bool_val = v.int_value != 0; 565 } 566 else if(is_float_type(v.var_type)) 567 { 568 bool_val = !zero(v.float_value); 569 } 570 else 571 { 572 throw InterpExc(UNSUPPORTED_TYPE); 573 } 574 return bool_val; 575 } 576 577 578 //这个函数适配性地进行了赋值. 579 void adaptive_assign_var(anonymous_var &a, anonymous_var &b) 580 { 581 if(a.var_type == STRUCT && b.var_type == STRUCT) 582 { 583 584 assert(0 == strcmp(a.struct_value.type_name, b.struct_value.type_name)); 585 assert(a.struct_value.data.size() == b.struct_value.data.size()); 586 int sz = b.struct_value.data.size(); 587 for(int i = 0; i < sz; i++) 588 { 589 adaptive_assign_var(a.struct_value.data[i].value, b.struct_value.data[i].value); 590 } 591 return; 592 } 593 if(!check_valid_type(a) || !check_valid_type(b)) throw InterpExc(UNSUPPORTED_TYPE); 594 595 if(is_int_type(a.var_type)) 596 { 597 if(is_int_type(b.var_type)) 598 { 599 a.int_value = b.int_value; 600 } 601 else 602 { 603 a.int_value = int(b.float_value); 604 } 605 } 606 else 607 { 608 if(is_int_type(b.var_type)) 609 { 610 a.float_value = double(b.int_value); 611 } 612 else 613 { 614 a.float_value = b.float_value; 615 } 616 } 617 } 618 619 //parser.cpp 620 621 /********************************************************************* 622 parser.cpp 用来递归下降地解析表达式, 使用anonymous_var类型传递中间结果 623 *********************************************************************/ 624 625 626 // Recursive descent parser for integer expressions. 627 // 628 #include <iostream> 629 #include <cstring> 630 #include <cstdlib> 631 #include <cctype> 632 #include "mccommon.h" 633 634 using namespace std; 635 636 // This structure links a library function name 637 // with a pointer to that function. 638 struct intern_func_type 639 { 640 char *f_name; // function name 641 anonymous_var (*p)(); // pointer to the function 642 } intern_func[] = 643 { 644 "getchar", call_getchar, 645 "putchar", call_putchar, 646 "abs", call_abs, 647 "rand", call_rand, 648 "", 0 // null terminate the list 649 }; 650 651 // Keyword lookup table. 652 // Keywords must be entered lowercase. 653 // 定义关键字, 对应一个tok的id, 能提高些效率 654 struct commands 655 { 656 char command[20]; 657 token_ireps tok; 658 } com_table[] = 659 { 660 "if", IF, 661 "else", ELSE, 662 "for", FOR, 663 "do", DO, 664 "while", WHILE, 665 "bool", BOOL, 666 "char", CHAR, 667 "short", SHORT, 668 "int", INT, 669 "long", LONG, 670 "float", FLOAT, 671 "double", DOUBLE, 672 "return", RETURN, 673 "switch", SWITCH, 674 "break", BREAK, 675 "case", CASE, 676 "cout", COUT, 677 "cin", CIN, 678 "endl", ENDL, 679 "default", DEFAULT, 680 "continue", CONTINUE, 681 "true", TRUE, 682 "false", FALSE, 683 "struct", STRUCT, 684 "", END // mark end of table 685 }; 686 687 //eval_exp不根据之前读到的信息来操作, 是在eval_exp函数里面, 读到什么就调用相应的处理过程. 688 // Entry point into parser. 689 void eval_exp(anonymous_var &value) 690 { 691 get_token(); 692 693 if(!*token) 694 { 695 throw InterpExc(NO_EXP); 696 } 697 698 //对于空语句给予一个默认的设置. 699 if(*token == ';') 700 { 701 value.var_type = BOOL; // empty expression 702 value.int_value = false; 703 return; 704 } 705 706 eval_exp0(value); 707 //这里会把处理完之后读出来的token再返回去. 708 709 putback(); // return last token read to input stream 710 } 711 712 713 // Process an assignment expression. 714 void eval_exp0(anonymous_var &value) 715 { 716 717 //这个函数前面已经调用了get_token了, 所以你看到函数开始的时候没有调用get_token 718 //对于每一种处理, 其实在哪里调用get_token都可以, 只不过如果你要在函数内部调一次的话 719 // 你在外面putback一下就可以 720 // temp holds name of var receiving the assignment. 721 char temp[MAX_ID_LEN + 1]; 722 723 tok_types temp_tok; 724 725 if(token_type == IDENTIFIER) 726 { 727 if(is_var(token)) // if a var, see if assignment 728 { 729 strcpy(temp, token); 730 temp_tok = token_type; 731 get_token(); 732 if(*token == '=') // is an assignment 733 { 734 735 get_token(); 736 737 if(*token == '{') //专门处理一下对于结构体之间的赋值. 738 { 739 740 putback(); 741 char type_name[64]; 742 get_type_by_name(temp, type_name); 743 init_struct(type_name, value); 744 } 745 else 746 { 747 //printf("putback\n"); 748 //printf("%s tttttt\n", token); 749 //putback(); 750 eval_exp0(value); // get value to assign 751 } 752 assign_var(temp, value); // assign the value 753 754 return; 755 } 756 else // not an assignment 757 { 758 putback(); // restore original token 759 strcpy(token, temp); 760 token_type = temp_tok; 761 } 762 } 763 } 764 eval_exp1(value); 765 } 766 767 // Process relational operators. 768 void eval_exp1(anonymous_var &value) 769 { 770 771 anonymous_var partial_value; 772 char op; 773 char relops[] = 774 { 775 LT, LE, GT, GE, EQ, NE, 0 776 }; 777 778 eval_exp2(value); 779 780 op = *token; 781 if(strchr(relops, op)) 782 { 783 get_token(); 784 eval_exp2(partial_value); 785 786 switch(op) // perform the relational operation 787 { 788 case LT: 789 { 790 int res = cmp(value, partial_value); 791 value.var_type = BOOL; 792 value.int_value = res < 0; 793 break; 794 } 795 case LE: 796 { 797 int res = cmp(value, partial_value); 798 value.var_type = BOOL; 799 value.int_value = res <= 0; 800 break; 801 } 802 case GT: 803 { 804 int res = cmp(value, partial_value); 805 value.var_type = BOOL; 806 value.int_value = res > 0; 807 break; 808 } 809 case GE: 810 { 811 int res = cmp(value, partial_value); 812 value.var_type = BOOL; 813 value.int_value = res >= 0; 814 break; 815 } 816 case EQ: 817 { 818 int res = cmp(value, partial_value); 819 820 value.var_type = BOOL; 821 value.int_value = (res == 0); 822 break; 823 } 824 case NE: 825 { 826 int res = cmp(value, partial_value); 827 value.var_type = BOOL; 828 value.int_value = !(res == 0); 829 break; 830 } 831 } 832 } 833 } 834 835 // Add or subtract two terms. 836 void eval_exp2(anonymous_var &value) 837 { 838 839 char op; 840 anonymous_var partial_value; 841 char okops[] = 842 { 843 '(', INC, DEC, '-', '+', 0 844 }; 845 846 eval_exp3(value); 847 848 while((op = *token) == '+' || op == '-') 849 { 850 get_token(); 851 852 if(token_type == DELIMITER && 853 !strchr(okops, *token)) 854 throw InterpExc(SYNTAX); 855 856 eval_exp3(partial_value); 857 858 859 860 switch(op) // add or subtract 861 { 862 case '-': 863 { 864 value = sub(value, partial_value); 865 break; 866 } 867 case '+': 868 { 869 value = add(value, partial_value); 870 break; 871 } 872 } 873 } 874 } 875 876 // Multiply or divide two factors. 877 void eval_exp3(anonymous_var &value) 878 { 879 char op; 880 anonymous_var partial_value; 881 char okops[] = 882 { 883 '(', INC, DEC, '-', '+', 0 884 }; 885 886 eval_exp4(value); 887 888 while((op = *token) == '*' || op == '/' 889 || op == '%') 890 { 891 get_token(); 892 893 if(token_type == DELIMITER && 894 !strchr(okops, *token)) 895 throw InterpExc(SYNTAX); 896 897 eval_exp4(partial_value); 898 899 switch(op) // mul, div, or modulus 900 { 901 case '*': 902 { 903 value = mul(value, partial_value); 904 break; 905 } 906 907 case '/': 908 { 909 //判断除零异常在程序里面做了 910 value = div(value, partial_value); 911 break; 912 } 913 case '%': 914 { 915 anonymous_var tmp = div(value, partial_value); 916 tmp = mul(partial_value, tmp); 917 value = sub(value, tmp); 918 break; 919 } 920 } 921 } 922 } 923 924 // Is a unary +, -, ++, or --. 925 void eval_exp4(anonymous_var &value) 926 { 927 char op; 928 char temp; 929 930 op = '\0'; 931 if(*token == '+' || *token == '-' || 932 *token == INC || *token == DEC) 933 { 934 temp = *token; 935 op = *token; 936 get_token(); 937 value = find_var(token); //这里也处理结构体的成员变量.. 938 //处理前缀++, --要把变化反应到变量身上. 939 if(temp == INC) 940 { 941 anonymous_var tmp_var; 942 tmp_var.int_value = 1; 943 tmp_var.var_type = value.var_type; 944 value = add(value, tmp_var); 945 assign_var(token, value); //这个token也包括了对结构体成员变量的处理. 946 get_token(); 947 return; 948 } 949 if(temp == DEC) 950 { 951 anonymous_var tmp_var; 952 tmp_var.int_value = 1; 953 tmp_var.var_type = value.var_type; 954 value = add(value, tmp_var); 955 assign_var(token, value); 956 get_token(); 957 return; 958 } 959 } 960 961 eval_exp5(value); 962 if(op == '-') 963 { 964 neg_var(value); 965 } 966 } 967 968 // Process parenthesized expression. 969 void eval_exp5(anonymous_var &value) 970 { 971 if((*token == '(')) 972 { 973 get_token(); 974 975 eval_exp0(value); // get subexpression 976 977 if(*token != ')') 978 throw InterpExc(PAREN_EXPECTED); 979 get_token(); 980 } 981 else 982 atom(value); 983 } 984 985 // Find value of number, variable, or function. 986 //增加一个处理功能, 处理浮点数, 但目前只允许***.***的形式, 不允许科学技术法. 987 void atom(anonymous_var &value) 988 { 989 int i; 990 char temp[MAX_ID_LEN + 1]; 991 992 switch(token_type) 993 { 994 case IDENTIFIER: 995 i = internal_func(token); 996 if(i != -1) 997 { 998 // Call "standard library" function. 999 value = ((*intern_func[i].p)()); 1000 } 1001 else if(find_func(token)) 1002 { 1003 // Call programmer-created function. 1004 call(); 1005 value = ret_value;//目前函数还只支持int返回值 1006 } 1007 else 1008 { 1009 1010 //在这里处理了后缀++, -- 1011 value = find_var(token); // get var's value 1012 strcpy(temp, token); // save variable name 1013 1014 // Check for ++ or --. 1015 get_token(); 1016 if(*token == INC || *token == DEC) 1017 { 1018 anonymous_var tmp_val = find_var(temp); 1019 value = tmp_val; 1020 if(*token == INC) 1021 { 1022 anonymous_var one; 1023 one.int_value = 1; 1024 one.var_type = tmp_val.var_type; 1025 tmp_val = add(tmp_val, one); 1026 assign_var(temp, tmp_val); 1027 } 1028 else 1029 { 1030 anonymous_var one; 1031 one.int_value = 1; 1032 one.var_type = tmp_val.var_type; 1033 tmp_val = sub(tmp_val, one); 1034 assign_var(temp, tmp_val); 1035 } 1036 1037 } 1038 else putback(); 1039 } 1040 1041 get_token(); 1042 return; 1043 case NUMBER: // is numeric constant 1044 //这里对浮点和整型类型做个判断 1045 //printf("in number %s\n", token); 1046 if(strchr(token, '.')) 1047 { 1048 1049 value.var_type = DOUBLE; 1050 value.float_value = atof(token); 1051 } 1052 else 1053 { 1054 value.var_type = INT; 1055 value.int_value = atoi(token); 1056 } 1057 get_token(); 1058 1059 return; 1060 1061 //char constant 1062 case DELIMITER: // see if character constant 1063 if(*token == '\'') 1064 { 1065 value.var_type = CHAR; 1066 value.int_value = *prog; 1067 prog++; 1068 if(*prog != '\'') 1069 throw InterpExc(QUOTE_EXPECTED); 1070 1071 prog++; 1072 get_token(); 1073 1074 return ; 1075 } 1076 if(*token == ')') return; // process empty expression 1077 else throw InterpExc(SYNTAX); // otherwise, syntax error 1078 case KEYWORD: 1079 { 1080 if(0 == strcmp(token, "true")) 1081 { 1082 //cout << "jackieddddd" << endl; 1083 value.var_type = BOOL; 1084 value.int_value = 1; 1085 } 1086 else if(0 == strcmp(token, "false")) 1087 { 1088 value.var_type = BOOL; 1089 value.int_value = 0; 1090 } 1091 else 1092 { 1093 throw InterpExc(SYNTAX); 1094 } 1095 get_token(); 1096 break; 1097 } 1098 default: 1099 throw InterpExc(SYNTAX); // syntax error 1100 } 1101 } 1102 1103 // Display an error message. 1104 void sntx_err(error_msg error) 1105 { 1106 char *p, *temp; 1107 int linecount = 0; 1108 1109 static char *e[] = //这里的显示信息, 是跟头文件里面定义的错误flag顺序一致的 1110 { 1111 "Syntax error", 1112 "No expression present", 1113 "Not a variable", 1114 "Duplicate variable name", 1115 "Duplicate function name", 1116 "Semicolon expected", 1117 "Unbalanced braces", 1118 "Function undefined", 1119 "Type specifier expected", 1120 "Return without call", 1121 "Parentheses expected", 1122 "While expected", 1123 "Closing quote expected", 1124 "Division by zero", 1125 "{ expected (control statements must use blocks)", 1126 "Colon expected", 1127 "Unsupported type yet", 1128 "More struct member that expected" 1129 }; 1130 1131 // Display error and line number. 1132 cout << "\n" << e[error]; 1133 p = p_buf; 1134 while(p != prog) // find line number of error 1135 { 1136 p++; 1137 if(*p == '\r') 1138 { 1139 linecount++; 1140 } 1141 } 1142 cout << " in line " << linecount << endl; 1143 1144 temp = p; 1145 while(p > p_buf && *p != '\n') p--; 1146 1147 // Display offending line. 1148 while(p <= temp) 1149 cout << *p++; 1150 1151 cout << endl; 1152 } 1153 1154 // Get a token. 1155 tok_types get_token() 1156 { 1157 1158 char *temp; 1159 1160 token_type = UNDEFTT; 1161 tok = UNDEFTOK; 1162 1163 temp = token; 1164 *temp = '\0'; 1165 1166 // Skip over white space. 1167 while(isspace(*prog) && *prog) ++prog; 1168 1169 // Skip over newline. 1170 while(*prog == '\r') 1171 { 1172 ++prog; 1173 ++prog; 1174 // Again, skip over white space. 1175 while(*prog && isspace(*prog)) ++prog; 1176 } 1177 1178 // Check for end of program. 1179 if(*prog == '\0') 1180 { 1181 *token = '\0'; 1182 tok = END; 1183 return (token_type = DELIMITER); 1184 } 1185 1186 // Check for block delimiters. 1187 if(strchr("{}", *prog)) 1188 { 1189 *temp = *prog; 1190 temp++; 1191 *temp = '\0'; 1192 prog++; 1193 return (token_type = BLOCK); 1194 } 1195 1196 // Look for comments. 1197 if(*prog == '/') 1198 if(*(prog + 1) == '*') // is a /* comment 1199 { 1200 prog += 2; 1201 1202 //这个循环很给力 1203 do // find end of comment 1204 { 1205 while(*prog != '*') prog++; 1206 prog++; 1207 } 1208 while (*prog != '/'); 1209 prog++; 1210 return (token_type = DELIMITER); 1211 } 1212 else if(*(prog + 1) == '/') // is a // comment 1213 { 1214 prog += 2; 1215 // Find end of comment. 1216 while(*prog != '\r' && *prog != '\0') prog++; 1217 if(*prog == '\r') prog += 2; 1218 return (token_type = DELIMITER); 1219 } 1220 1221 // Check for double-ops. 1222 if(strchr("!<>=+-", *prog)) 1223 { 1224 switch(*prog) 1225 { 1226 case '=': 1227 if(*(prog + 1) == '=') 1228 { 1229 prog++; 1230 prog++; 1231 *temp = EQ; 1232 temp++; 1233 *temp = EQ; 1234 temp++; 1235 *temp = '\0'; 1236 } 1237 break; 1238 case '!': 1239 if(*(prog + 1) == '=') 1240 { 1241 prog++; 1242 prog++; 1243 *temp = NE; 1244 temp++; 1245 *temp = NE; 1246 temp++; 1247 *temp = '\0'; 1248 } 1249 break; 1250 case '<': 1251 if(*(prog + 1) == '=') 1252 { 1253 prog++; 1254 prog++; 1255 *temp = LE; 1256 temp++; 1257 *temp = LE; 1258 } 1259 else if(*(prog + 1) == '<') 1260 { 1261 prog++; 1262 prog++; 1263 *temp = LS; 1264 temp++; 1265 *temp = LS; 1266 } 1267 else 1268 { 1269 prog++; 1270 *temp = LT; 1271 } 1272 temp++; 1273 *temp = '\0'; 1274 break; 1275 case '>': 1276 if(*(prog + 1) == '=') 1277 { 1278 prog++; 1279 prog++; 1280 *temp = GE; 1281 temp++; 1282 *temp = GE; 1283 } 1284 else if(*(prog + 1) == '>') 1285 { 1286 prog++; 1287 prog++; 1288 *temp = RS; 1289 temp++; 1290 *temp = RS; 1291 } 1292 else 1293 { 1294 prog++; 1295 *temp = GT; 1296 } 1297 temp++; 1298 *temp = '\0'; 1299 break; 1300 case '+': 1301 if(*(prog + 1) == '+') 1302 { 1303 prog++; 1304 prog++; 1305 *temp = INC; 1306 temp++; 1307 *temp = INC; 1308 temp++; 1309 *temp = '\0'; 1310 } 1311 break; 1312 case '-': 1313 if(*(prog + 1) == '-') 1314 { 1315 prog++; 1316 prog++; 1317 *temp = DEC; 1318 temp++; 1319 *temp = DEC; 1320 temp++; 1321 *temp = '\0'; 1322 } 1323 break; 1324 } 1325 1326 if(*token) return(token_type = DELIMITER); 1327 } 1328 1329 // Check for other delimiters. 1330 if(strchr("+-*^/%=;:(),'", *prog)) 1331 { 1332 *temp = *prog; 1333 prog++; 1334 temp++; 1335 *temp = '\0'; 1336 return (token_type = DELIMITER); 1337 } 1338 1339 // Read a quoted string. 1340 if(*prog == '"') 1341 { 1342 //printf("in string jackie\n"); 1343 prog++; 1344 while(*prog != '"' && *prog != '\r' && *prog) 1345 { 1346 // Check for \n escape sequence. 1347 if(*prog == '\\') 1348 { 1349 if(*(prog + 1) == 'n') 1350 { 1351 prog++; 1352 *temp++ = '\n'; 1353 } 1354 } 1355 else if((temp - token) < MAX_T_LEN) 1356 *temp++ = *prog; 1357 1358 prog++; 1359 } 1360 if(*prog == '\r' || *prog == 0) 1361 throw InterpExc(SYNTAX); 1362 prog++; 1363 *temp = '\0'; //temp是token的滑动指针.. 1364 //printf("%s string\n", token); 1365 return (token_type = STRING); 1366 } 1367 1368 // Read an integer number, or float 1369 //由于现在还没加入结构体和类, 所以直接这样判断'.'还是可以的, 不过会有隐患, 要记得~ 1370 if(isdigit(*prog) || *prog == '.') 1371 { 1372 while(isdigit(*prog) || *prog == '.') //!isdelim(*prog), 这个是原来的判断.. 1373 { 1374 if((temp - token) < MAX_ID_LEN) 1375 *temp++ = *prog; 1376 prog++; 1377 } 1378 *temp = '\0'; 1379 return (token_type = NUMBER); 1380 } 1381 1382 // Read identifier or keyword. 1383 if(isalpha(*prog)) 1384 { 1385 while(!isdelim(*prog)) 1386 { 1387 if((temp - token) < MAX_ID_LEN) 1388 *temp++ = *prog; 1389 prog++; 1390 } 1391 token_type = TEMP; 1392 } 1393 1394 *temp = '\0'; 1395 1396 // Determine if token is a keyword or identifier. 1397 if(token_type == TEMP) 1398 { 1399 tok = look_up(token); // convert to internal form 1400 if(tok) token_type = KEYWORD; // is a keyword 1401 else token_type = IDENTIFIER; 1402 } 1403 //还是不要搞下面的内容了, 因为struct关键字本身的tok就是STRUCT 1404 //if(token_type == IDENTIFIER && is_struct_type(token)) 1405 //{ 1406 // //printf("jackie struct %s\n", token); 1407 // tok = STRUCT; 1408 //} 1409 1410 // Check for unidentified character in file. 1411 if(token_type == UNDEFTT) 1412 throw InterpExc(SYNTAX); 1413 1414 return token_type; 1415 } 1416 1417 // Return a token to input stream. 1418 void putback() 1419 { 1420 char *t; 1421 t = token; 1422 for(; *t; t++) prog--; 1423 } 1424 1425 // Look up a token's internal representation in the 1426 // token table. 1427 token_ireps look_up(char *s) 1428 { 1429 int i; 1430 1431 // See if token is in table. 1432 for(i = 0; *com_table[i].command; i++) 1433 { 1434 if(!strcmp(com_table[i].command, s)) 1435 return com_table[i].tok; 1436 } 1437 1438 return UNDEFTOK; // unknown command 1439 } 1440 1441 // Return index of internal library function or -1 if 1442 // not found. 1443 int internal_func(char *s) 1444 { 1445 int i; 1446 1447 for(i = 0; intern_func[i].f_name[0]; i++) 1448 { 1449 if(!strcmp(intern_func[i].f_name, s)) return i; 1450 } 1451 return -1; 1452 } 1453 1454 // Return true if c is a delimiter. 1455 bool isdelim(char c) 1456 { 1457 if(strchr(" !:;,+-<>'/*%^=()", c) || c == 9 || 1458 c == '\r' || c == 0) return true; 1459 return false; 1460 } 1461 1462 1463 //minicpp.cpp 1464 1465 /*********************************************************************** 1466 minicpp.cpp 主函数在这里, 对于for, if while switch等的实现也写在了这里. 1467 ************************************************************************/ 1468 #include <iostream> 1469 #include <fstream> 1470 #include <new> 1471 #include <stack> 1472 #include <vector> 1473 #include <cstring> 1474 #include <cstdlib> 1475 #include <cctype> 1476 #include "mccommon.h" 1477 1478 using namespace std; 1479 1480 char *prog; // current execution point in source code 1481 char *p_buf; // points to start of program buffer 1482 1483 // This vector holds info for global variables. 1484 vector<var> global_vars; 1485 1486 // This vector holds info for local variables 1487 // and parameters. 1488 vector<var> local_var_stack; 1489 1490 // This vector holds info about functions. 1491 vector<func_type> func_table; 1492 1493 // Stack for managing function scope. 1494 1495 stack<int> func_call_stack; 1496 1497 vector<struct_type> struct_decls;//用来存储struct类型的定义.. 1498 1499 // Stack for managing nested scopes. 1500 //整形的栈, 存储的是本函数压栈之前栈的大小. 1501 stack<int> nest_scope_stack; 1502 1503 char token[MAX_T_LEN + 1]; // current token 1504 tok_types token_type; // token type 1505 token_ireps tok; // internal representation 1506 1507 anonymous_var ret_value; // function return value 1508 1509 bool breakfound = false; // true if break encountered 1510 bool continuefound = false; 1511 1512 1513 1514 1515 int main(int argc, char *argv[]) 1516 { 1517 if(argc != 2) 1518 { 1519 cout << "Usage: minicpp <filename>\n"; 1520 return 1; 1521 } 1522 1523 // Allocate memory for the program. 1524 try 1525 { 1526 p_buf = new char[PROG_SIZE]; 1527 } 1528 catch (bad_alloc exc) 1529 { 1530 cout << "Could Not Allocate Program Buffer\n"; 1531 return 1; 1532 } 1533 1534 // Load the program to execute. 1535 if(!load_program(p_buf, argv[1])) return 1; 1536 1537 // Set program pointer to start of program buffer. 1538 prog = p_buf; 1539 1540 try 1541 { 1542 // Find the location of all functions 1543 // and global variables in the program. 1544 prescan(); 1545 1546 // Next, set up the call to main(). 1547 1548 // Find program starting point. 1549 prog = find_func("main"); 1550 1551 // Check for incorrect or missing main() function. 1552 if(!prog) 1553 { 1554 cout << "main() Not Found\n"; 1555 return 1; 1556 } 1557 1558 // Back up to opening (. 1559 prog--; 1560 1561 // Set the first token to main 1562 strcpy(token, "main"); 1563 1564 // Call main() to start interpreting. 1565 call(); 1566 } 1567 catch(InterpExc exc) 1568 { 1569 sntx_err(exc.get_err()); 1570 return 1; 1571 } 1572 catch(bad_alloc exc) 1573 { 1574 cout << "Out Of Memory\n"; 1575 return 1; 1576 } 1577 1578 return ret_value.int_value; 1579 } 1580 1581 // Load a program. 1582 bool load_program(char *p, char *fname) 1583 { 1584 int i = 0; 1585 1586 ifstream in(fname, ios::in | ios::binary); 1587 if(!in) 1588 { 1589 cout << "Cannot Open file.\n"; 1590 return false; 1591 } 1592 1593 do 1594 { 1595 *p = in.get(); 1596 p++; 1597 i++; 1598 } 1599 while(!in.eof() && i < PROG_SIZE); 1600 1601 if(i == PROG_SIZE) 1602 { 1603 cout << "Program Too Big\n"; 1604 return false; 1605 } 1606 1607 // Null terminate the program. Skip any EOF 1608 // mark if present in the file. 1609 if(*(p - 2) == 0x1a) *(p - 2) = '\0'; 1610 else *(p - 1) = '\0'; 1611 1612 in.close(); 1613 1614 return true; 1615 } 1616 1617 // Find the location of all functions in the program 1618 // and store global variables. 1619 void prescan() 1620 { 1621 char *p, *tp; 1622 char temp[MAX_ID_LEN + 1]; 1623 token_ireps datatype; 1624 func_type ft; 1625 1626 // When brace is 0, the current source position 1627 // is outside of any function. 1628 int brace = 0; 1629 1630 p = prog; 1631 1632 do 1633 { 1634 // Bypass code inside functions, brace==0, 保证了现在是在全局作用域 1635 while(brace) 1636 { 1637 get_token(); 1638 if(tok == END) //在这里挂了一次, 因为有"{{"这样的字符串.. 1639 { 1640 throw InterpExc(UNBAL_BRACES); 1641 } 1642 if(0 == strcmp(token, "{")) brace++; 1643 if(0 == strcmp(token, "}")) brace--; 1644 } 1645 1646 tp = prog; // save current position 1647 get_token(); 1648 1649 if(tok == STRUCT) //在这里处理结构体的声明. 1650 { 1651 char* ttp = prog; //这里用来做这一次回退的, 当然这么搞其实已经很乱了.. 1652 get_token(); 1653 if(token_type == IDENTIFIER) 1654 { 1655 get_token(); 1656 if(0 == strcmp(token, "{"))//如果是这样就是一个声明, 否则可能是一个类似 struct mm a;这样的定义 1657 { 1658 prog = tp; 1659 decl_struct_type(); 1660 } 1661 else 1662 { 1663 //printf("%s jackiessss\n", token); 1664 prog = ttp; 1665 decl_global(); 1666 } 1667 } 1668 } 1669 else if(is_valid_simple_type(tok) || is_struct_type(token)) // See if global var type or function return type. 1670 { 1671 1672 datatype = tok; // save data type 1673 get_token(); 1674 1675 if(token_type == IDENTIFIER) 1676 { 1677 strcpy(temp, token); 1678 get_token(); 1679 1680 if(0 != strcmp(token, "(")) // must be global var 1681 { 1682 prog = tp; // return to start of declaration 1683 decl_global(); 1684 } 1685 else if(*token == '(') // must be a function 1686 { 1687 // See if function already defined. 1688 for(unsigned i = 0; i < func_table.size(); i++) 1689 if(!strcmp(func_table[i].func_name, temp)) 1690 throw InterpExc(DUP_FUNC); 1691 1692 ft.loc = prog; 1693 ft.ret_type = datatype; 1694 strcpy(ft.func_name, temp); 1695 func_table.push_back(ft); 1696 1697 do 1698 { 1699 get_token(); 1700 } 1701 while(0 != strcmp(token, ")")); 1702 // Next token will now be opening curly 1703 // brace of function. 1704 } 1705 else putback(); 1706 } 1707 } 1708 else 1709 { 1710 if(0 == strcmp(token, "{")) brace++; 1711 if(0 == strcmp(token, "}")) brace--; 1712 } 1713 } 1714 while(tok != END); 1715 if(brace) 1716 { 1717 throw InterpExc(UNBAL_BRACES); 1718 } 1719 prog = p; 1720 } 1721 1722 // Interpret a single statement or block of code. When 1723 // interp() returns from its initial call, the final 1724 // brace (or a return) in main() has been encountered. 1725 1726 //对于interp我做了一个小改动, 如果执行语句里面有break, 那么就在推出interp之前让程序把整个block的代码都走一遍, 但是不执行了 1727 //这样, 以后调用interp的程序就不用再为break后面的语句做清理工作了. 1728 //在interp里面, 遇到{}会产生一个新的名字空间, 遇到int 和char还会declare一个local变量 1729 void interp() 1730 { 1731 //printf("interp\n"); 1732 anonymous_var value; 1733 int block = 0; 1734 char *tmp_prog = NULL; 1735 //break语句会对外面的控制流程造成影响, 但是continue不会, 它只会不让本次循环后面的语句不执行. 1736 //但是还是要维护一个全局的continue, 因为本block需要知道子block里面是不是有continue; 1737 do 1738 { 1739 if(breakfound || continuefound) 1740 { 1741 1742 //如果这是个{}包含的块, 那么就用find_eob把整个块吃掉 1743 if(block && tmp_prog) 1744 { 1745 1746 prog = tmp_prog; 1747 find_eob(); 1748 } 1749 else 1750 { 1751 //对于知识一条语句的块, 在break跳出之前吃掉这个分号 1752 get_token(); 1753 1754 } 1755 return; 1756 } 1757 1758 token_type = get_token(); 1759 1760 //printf("%s token\n", token); 1761 //对于那些exec_while, exec_while那个向前看的token是在这里读出来的 1762 //跟eval_exp没有关系. 1763 1764 // See what kind of token is up. 1765 if((token_type == IDENTIFIER || 1766 *token == INC || *token == DEC) && !is_struct_type(token)) 1767 { 1768 // Not a keyword, so process expression. 1769 putback(); // restore token to input stream for 1770 // further processing by eval_exp() 1771 eval_exp(value); // process the expression 1772 //eval_exp和exec_while是相同的层次, 在interp看到向前看字符的时候, 就会递归调用相应的过程. 1773 if(0 != strcmp(token, ";")) 1774 { 1775 throw InterpExc(SEMI_EXPECTED); 1776 } 1777 } 1778 else if(token_type == BLOCK) // block delimiter? 1779 { 1780 if(0 == strcmp(token, "{")) // is a block 1781 { 1782 putback(); 1783 tmp_prog = prog; 1784 get_token(); 1785 block = 1; // interpreting block, not statement 1786 // Record nested scope. 1787 nest_scope_stack.push(local_var_stack.size()); 1788 //nest_scope_stack里面存的是上一个block的stack的位置, 1789 //用户恢复栈. 1790 } 1791 else // is a }, so reset scope and return 1792 { 1793 // Reset nested scope. 1794 local_var_stack.resize(nest_scope_stack.top()); 1795 nest_scope_stack.pop(); 1796 return; 1797 } 1798 } 1799 else if(is_valid_simple_type(tok) || is_struct_type(token) || tok == STRUCT) 1800 { 1801 if(tok != STRUCT) putback(); //如果tok 是STRUCT那么就不吐回去那个token, 当做不以struct开始一个结构体定义就可以了.. 1802 decl_local(); 1803 } 1804 else // is keyword 1805 switch(tok) 1806 { 1807 case RETURN: // return from function call, 不要在这里清理局部作用域了, call里面做了处理. 1808 /*if(block) 1809 { 1810 local_var_stack.resize(nest_scope_stack.top()); 1811 nest_scope_stack.pop(); 1812 }*/ 1813 func_ret(); 1814 return; 1815 case IF: // process an if statement 1816 exec_if(); 1817 break; 1818 case ELSE: // process an else statement 1819 find_eob(); // find end of else block 1820 // and continue execution 1821 break; 1822 case WHILE: // process a while loop 1823 exec_while(); 1824 break; 1825 case DO: // process a do-while loop 1826 exec_do(); 1827 break; 1828 case FOR: // process a for loop 1829 exec_for(); 1830 1831 break; 1832 case BREAK: // handle break 1833 breakfound = true; 1834 // Reset nested scope. 1835 //这里要特判一下是不是从一个block里面的break, 因为在我修改之后, for while的循环体现在可以是 1836 //一个单个的语句了 1837 if(block) 1838 { 1839 local_var_stack.resize(nest_scope_stack.top()); 1840 nest_scope_stack.pop(); 1841 } 1842 break; 1843 case CONTINUE: 1844 { 1845 continuefound = true; 1846 if(block) 1847 { 1848 local_var_stack.resize(nest_scope_stack.top()); 1849 nest_scope_stack.pop(); 1850 } 1851 break; 1852 } 1853 case SWITCH: // handle a switch statement 1854 exec_switch(); 1855 break; 1856 case COUT: // handle console output 1857 exec_cout(); 1858 //cout << "breakfuond :" << breakfound << endl; 1859 break; 1860 case CIN: // handle console input 1861 exec_cin(); 1862 break; 1863 case END: 1864 exit(0); 1865 1866 } 1867 } 1868 while (tok != END && block); 1869 return; 1870 } 1871 1872 1873 //可以使用map优化. 1874 // Return the entry point of the specified function. 1875 // Return NULL if not found. 1876 char *find_func(char *name) 1877 { 1878 unsigned i; 1879 unsigned len = func_table.size(); 1880 for(i = 0; i < len; i++) 1881 if(!strcmp(name, func_table[i].func_name)) 1882 return func_table[i].loc; 1883 1884 return NULL; 1885 } 1886 1887 // Declare a global variable, including struct variable. 1888 void decl_global() 1889 { 1890 token_ireps vartype; 1891 var v; 1892 get_token(); // get type 1893 vartype = tok; // save var type 1894 char struct_name[64] = ""; 1895 if(is_struct_type(token)) 1896 { 1897 vartype = STRUCT; 1898 strcpy(struct_name, token);//乳沟是个结构体, 那么就在这里把结构体类型的名字给出, 1899 //后面初始化的时候根据这个名字对结构体进行初始化 1900 } 1901 anonymous_var value; 1902 // Process comma-separated list. 1903 do 1904 { 1905 get_token(); // get name 1906 //printf("%s name\n", token); 1907 1908 v.value.var_type = vartype; 1909 strcpy(v.var_name, token); 1910 if(vartype == STRUCT) strcpy(v.value.struct_value.type_name, struct_name); 1911 init_var(v.value); // init to 0, or init the struct_type considering the struct name. 1912 1913 // See if variable is a duplicate. 1914 unsigned sz = global_vars.size(); 1915 for(unsigned i = 0; i < sz; i++) 1916 if(!strcmp(global_vars[i].var_name, token)) 1917 throw InterpExc(DUP_VAR); 1918 1919 global_vars.push_back(v); 1920 1921 //printf("%s jjjjj\n", token); 1922 putback(); 1923 eval_exp(value); //这个eval_exp会实现赋值, 这里value只是个哑元, 我们不用 1924 get_token(); 1925 } 1926 while(*token == ','); 1927 1928 if(*token != ';') 1929 { 1930 throw InterpExc(SEMI_EXPECTED); 1931 } 1932 } 1933 1934 // Declare a local variable. 1935 void decl_local() 1936 { 1937 token_ireps vartype; 1938 var v; 1939 get_token(); // get type 1940 //printf("%s local\n", token); 1941 vartype = tok; // save var type 1942 char struct_name[64] = ""; 1943 if(is_struct_type(token)) 1944 { 1945 //printf("decl_local, %s\n", token); 1946 vartype = STRUCT; 1947 strcpy(struct_name, token);//乳沟是个结构体, 那么就在这里把结构体类型的名字给出, 1948 //后面初始化的时候根据这个名字对结构体进行初始化 1949 } 1950 anonymous_var value; 1951 1952 // Process comma-separated list. 1953 do 1954 { 1955 get_token(); // get var name 1956 v.value.var_type = vartype; 1957 strcpy(v.var_name, token); 1958 if(vartype == STRUCT) strcpy(v.value.struct_value.type_name, struct_name); 1959 init_var(v.value); // init to 0, or init the struct_type considering the struct name. 1960 1961 // See if variable is already the name 1962 // of a local variable in this scope. 1963 if(!local_var_stack.empty()) 1964 for(int i = local_var_stack.size() - 1; 1965 i >= nest_scope_stack.top(); i--) 1966 { 1967 if(!strcmp(local_var_stack[i].var_name, token)) 1968 throw InterpExc(DUP_VAR); 1969 } 1970 1971 strcpy(v.var_name, token); 1972 local_var_stack.push_back(v); 1973 putback(); 1974 eval_exp(value);//这个eval_exp会实现赋值, 这里value只是个哑元, 我们不用 1975 get_token(); 1976 } 1977 while(*token == ','); 1978 1979 if(*token != ';') throw InterpExc(SEMI_EXPECTED); 1980 } 1981 1982 // Call a function. 1983 void call() 1984 { 1985 char *loc, *temp; 1986 int lvartemp; 1987 1988 // First, find entry point of function. 1989 loc = find_func(token); 1990 1991 if(loc == NULL) 1992 throw InterpExc(FUNC_UNDEF); // function not defined 1993 else 1994 { 1995 // Save local var stack index. 1996 lvartemp = local_var_stack.size(); 1997 1998 //get_args 和get_params先后调用 , 进行了一下替换 1999 get_args(); // get function arguments 2000 temp = prog; // save return location 2001 2002 func_call_stack.push(lvartemp); // push local var index 2003 2004 prog = loc; // reset prog to start of function 2005 get_params(); // load the function's parameters with 2006 // the values of the arguments 2007 2008 interp(); // interpret the function 2009 2010 prog = temp; // reset the program pointer 2011 2012 if(func_call_stack.empty()) throw InterpExc(RET_NOCALL); 2013 2014 // Reset local_var_stack to its previous state. 2015 2016 //这里的resize会把后面的刚刚压入栈的变量删掉. 2017 local_var_stack.resize(func_call_stack.top()); 2018 func_call_stack.pop(); 2019 } 2020 } 2021 2022 // Push the arguments to a function onto the local 2023 // variable stack. 2024 void get_args() 2025 { 2026 anonymous_var value, temp[NUM_PARAMS]; 2027 int count = 0; 2028 var vt; 2029 2030 count = 0; 2031 get_token(); 2032 if(*token != '(') throw InterpExc(PAREN_EXPECTED); 2033 2034 // Process a comma-separated list of values. 2035 do 2036 { 2037 eval_exp(value); 2038 temp[count] = value; // save temporarily 2039 get_token(); 2040 count++; 2041 } 2042 while(*token == ','); 2043 count--; 2044 2045 // Now, push on local_var_stack in reverse order. 2046 for(; count >= 0; count--) 2047 { 2048 vt.value = temp[count]; 2049 local_var_stack.push_back(vt); 2050 } 2051 } 2052 2053 // Get function parameters. 2054 2055 //在这个函数里面实现了从实参到形参的转化工作, 不错. 2056 void get_params() 2057 { 2058 var *p; 2059 int i; 2060 2061 i = local_var_stack.size() - 1; 2062 2063 // Process comma-separated list of parameters. 2064 do 2065 { 2066 get_token(); 2067 p = &local_var_stack[i]; 2068 if(*token != ')' ) 2069 { 2070 if(is_valid_simple_type(tok)) 2071 throw InterpExc(TYPE_EXPECTED); 2072 2073 p->value.var_type = tok; 2074 get_token(); 2075 2076 // Link parameter name with argument already on 2077 // local var stack. 2078 strcpy(p->var_name, token); 2079 get_token(); 2080 i--; 2081 } 2082 else break; 2083 } 2084 while(*token == ','); 2085 2086 //在这里判了一下, 看最后一个读到的是不是')' 2087 if(*token != ')') throw InterpExc(PAREN_EXPECTED); 2088 } 2089 2090 // Return from a function. 2091 void func_ret() 2092 { 2093 anonymous_var value; 2094 2095 //value = 0; 2096 2097 // Get return value, if any. 2098 //目前设定是只支持int返回值. 2099 eval_exp(value); 2100 2101 ret_value = value; 2102 } 2103 2104 // Assign a value to a variable. 2105 void assign_var(char *vname, anonymous_var value) 2106 { 2107 //printf("assign %s\n", vname); 2108 //first check if it's a member of a struct 2109 bool b_contains_dots = false; 2110 int len = strlen(vname); 2111 for(int i = 0; i < len; i++) 2112 { 2113 if(vname[i] == '.') 2114 { 2115 b_contains_dots = true; 2116 break; 2117 } 2118 } 2119 if(b_contains_dots) 2120 { 2121 anonymous_var* vp = NULL; 2122 get_member_var(vname, vp); 2123 adaptive_assign_var(*vp, value); 2124 return; 2125 } 2126 // First, see if it's a local variable. 2127 // 2128 if(!local_var_stack.empty()) 2129 for(int i = local_var_stack.size() - 1; 2130 i >= func_call_stack.top(); i--) 2131 { 2132 if(!strcmp(local_var_stack[i].var_name, 2133 vname)) 2134 { 2135 adaptive_assign_var(local_var_stack[i].value, value); 2136 return; 2137 } 2138 } 2139 2140 // Otherwise, try global vars. 2141 for(unsigned i = 0; i < global_vars.size(); i++) 2142 if(!strcmp(global_vars[i].var_name, vname)) 2143 { 2144 adaptive_assign_var(global_vars[i].value, value); 2145 //cout << value.float_value << " >>>" << endl; 2146 return; 2147 } 2148 //printf("jackiesteed\n"); 2149 throw InterpExc(NOT_VAR); // variable not found 2150 } 2151 2152 // Find the value of a variable, 这个不需要引用, 因为是拿来做中间变量做运算用的. 2153 anonymous_var find_var(char *vname) 2154 { 2155 anonymous_var* vp = NULL; 2156 if(get_member_var(vname, vp)) 2157 return *vp; 2158 // First, see if it's a local variable. 2159 if(!local_var_stack.empty()) 2160 for(int i = local_var_stack.size() - 1; 2161 i >= func_call_stack.top(); i--) 2162 { 2163 if(!strcmp(local_var_stack[i].var_name, vname)) 2164 return local_var_stack[i].value; 2165 } 2166 2167 // Otherwise, try global vars. 2168 for(unsigned i = 0; i < global_vars.size(); i++) 2169 if(!strcmp(global_vars[i].var_name, vname)) 2170 return global_vars[i].value; 2171 //printf("jackiesteed %s\n", token); 2172 throw InterpExc(NOT_VAR); // variable not found 2173 } 2174 2175 2176 //在处理if的时候也处理了else的模块 2177 // Execute an if statement. 2178 void exec_if() 2179 { 2180 anonymous_var cond; 2181 2182 eval_exp(cond); // get if expression. 2183 2184 if(get_bool_val(cond)) // if true, process target of IF 2185 { 2186 // Confirm start of block. 2187 2188 interp(); 2189 } 2190 else 2191 { 2192 // Otherwise skip around IF block and 2193 // process the ELSE, if present. 2194 2195 find_eob(); // find start of next line 2196 get_token(); 2197 2198 if(tok != ELSE) 2199 { 2200 // Restore token if no ELSE is present. 2201 putback(); 2202 return; 2203 } 2204 // Confirm start of block. 2205 get_token(); 2206 2207 if(tok == IF) 2208 { 2209 exec_if(); 2210 return; 2211 } 2212 putback(); 2213 interp(); 2214 } 2215 } 2216 2217 // Execute a switch statement. 2218 void exec_switch() 2219 { 2220 anonymous_var sval, cval; 2221 int brace; 2222 2223 eval_exp(sval); // Get switch expression. 2224 2225 // Check for start of block. 2226 if(*token != '{') 2227 throw InterpExc(BRACE_EXPECTED); 2228 2229 // Record new scope. 2230 nest_scope_stack.push(local_var_stack.size()); 2231 2232 // Now, check case statements. 2233 for(;;) 2234 { 2235 brace = 1; 2236 // Find a case statement. 2237 do 2238 { 2239 get_token(); 2240 if(*token == '{') brace++; 2241 else if(*token == '}') brace--; 2242 } 2243 while(tok != CASE && tok != END && brace && tok != DEFAULT); 2244 2245 // If no matching case found, then skip. 2246 if(!brace) break; 2247 2248 2249 if(tok == END) throw InterpExc(SYNTAX); 2250 if(tok == DEFAULT) 2251 { 2252 get_token(); 2253 if(*token != ':') 2254 throw InterpExc(COLON_EXPECTED); 2255 do 2256 { 2257 interp(); 2258 get_token(); 2259 if(*token == '}') 2260 { 2261 putback(); 2262 break; 2263 } 2264 putback(); 2265 //if(*token == '{') brace++; 2266 //else if(*token == '}') brace--; 2267 } 2268 while(!breakfound && tok != END); 2269 2270 brace = 1; 2271 2272 // Find end of switch statement. 2273 while(brace) 2274 { 2275 get_token(); 2276 if(*token == '{') brace++; 2277 else if(*token == '}') brace--; 2278 } 2279 breakfound = false; 2280 2281 break; 2282 2283 } 2284 2285 // Get value of the case statement. 2286 eval_exp(cval); 2287 2288 // Read and discard the : 2289 get_token(); 2290 2291 if(*token != ':') 2292 throw InterpExc(COLON_EXPECTED); 2293 2294 // If values match, then interpret. 2295 if(0 == cmp(cval, sval)) 2296 { 2297 2298 do 2299 { 2300 interp(); 2301 2302 get_token(); 2303 if(*token == '}') 2304 { 2305 putback(); 2306 break; 2307 } 2308 putback(); 2309 } 2310 while(!breakfound && tok != END && brace); 2311 2312 brace = 1; 2313 2314 // Find end of switch statement. 2315 while(brace) 2316 { 2317 get_token(); 2318 if(*token == '{') brace++; 2319 else if(*token == '}') brace--; 2320 } 2321 breakfound = false; 2322 2323 break; 2324 } 2325 } 2326 } 2327 2328 // Execute a while loop. 2329 //同下面的do while, 这个也会putback while 2330 void exec_while() 2331 { 2332 anonymous_var cond; 2333 char *temp; 2334 2335 putback(); // put back the while 2336 temp = prog; // save location of top of while loop 2337 2338 get_token(); 2339 eval_exp(cond); // check the conditional expression 2340 2341 if(get_bool_val(cond)) 2342 interp(); // if true, interpret 2343 else // otherwise, skip to end of loop 2344 { 2345 find_eob(); 2346 return; 2347 } 2348 continuefound = false; 2349 if(!breakfound) 2350 prog = temp; // loop back to top 2351 else 2352 { 2353 breakfound = false; 2354 return; 2355 } 2356 } 2357 2358 // Execute a do loop. 2359 2360 //解释: exec_do是在主函数读到了do的时候才会调用, 因此 2361 //在exec_do调用的时候, do这个token已经被读出来了, 2362 //而exec_do还想要在需要继续执行的时候是prog复位到do, 那么就得在程序开始putback一下. 2363 void exec_do() 2364 { 2365 anonymous_var cond; 2366 char *temp; 2367 2368 // Save location of top of do loop. 2369 putback(); // put back do 2370 temp = prog; 2371 2372 get_token(); // get start of loop block 2373 2374 // Confirm start of block. 2375 get_token(); 2376 if(*token != '{') 2377 throw InterpExc(BRACE_EXPECTED); 2378 putback(); 2379 2380 interp(); // interpret loop 2381 2382 // Check for break in loop. 2383 if(breakfound) 2384 { 2385 breakfound = false; 2386 get_token(); 2387 if(tok != WHILE) throw InterpExc(WHILE_EXPECTED); 2388 eval_exp(cond); // check the loop condition 2389 return; 2390 } 2391 if(continuefound) 2392 { 2393 continuefound = false; 2394 prog = temp; 2395 return; 2396 } 2397 2398 get_token(); 2399 if(tok != WHILE) throw InterpExc(WHILE_EXPECTED); 2400 2401 eval_exp(cond); // check the loop condition 2402 2403 // If true loop; otherwise, continue on. 2404 2405 if(get_bool_val(cond)) prog = temp; 2406 } 2407 2408 // Execute a for loop. 2409 //但是for就不能像while和do while那样, 在需要继续循环的时候复位prog指针了, 因为for 2410 //复位的话, 初始点也跟着复位了, 就是for(int i= 0; i< 12; i++)里面的i也会变成0 2411 void exec_for() 2412 { 2413 anonymous_var cond; 2414 char *temp, *temp2; 2415 int paren ; 2416 2417 //for_local用来标记是不是在for()内部定义了新变量, 如果是, 就会产生新的作用域 2418 bool for_local = false; 2419 2420 get_token(); // skip opening ( 2421 get_token(); 2422 2423 if(is_valid_simple_type(tok) || is_struct_type(token) || tok == STRUCT)//当前读入的token是个类型关键字, 这样就会触发一个局部作用域 2424 { 2425 if(tok != STRUCT)putback(); 2426 nest_scope_stack.push(local_var_stack.size()); 2427 for_local = true; 2428 decl_local(); 2429 } 2430 else 2431 { 2432 eval_exp(cond); // initialization expression 2433 } 2434 2435 //这个是decl_local和eval_exp最后读到的token, 已经被读出来了 2436 if(*token != ';') throw InterpExc(SEMI_EXPECTED); 2437 2438 prog++; // get past the ; 2439 temp = prog; 2440 2441 for(;;) 2442 { 2443 // Get the value of the conditional expression. 2444 eval_exp(cond); 2445 2446 if(*token != ';') throw InterpExc(SEMI_EXPECTED); 2447 prog++; // get past the ; 2448 temp2 = prog; 2449 2450 // Find start of for block. 2451 paren = 1; 2452 while(paren) 2453 { 2454 get_token(); 2455 if(*token == '(') paren++; 2456 if(*token == ')') paren--; 2457 } 2458 2459 2460 // If condition is true, interpret 2461 //现在从for()后面开始interpret 2462 // 2463 if(get_bool_val(cond)) 2464 { 2465 //continue只对interp里面的执行起作用, 不会对外面有影响. 2466 interp(); 2467 //cout << prog << endl; 2468 2469 } 2470 else // otherwise, skip to end of loop 2471 { 2472 find_eob(); 2473 if(for_local) 2474 { 2475 local_var_stack.resize(nest_scope_stack.top()); 2476 nest_scope_stack.pop(); 2477 } 2478 return; 2479 } 2480 if(breakfound) 2481 { 2482 breakfound = false; 2483 if(for_local) 2484 { 2485 local_var_stack.resize(nest_scope_stack.top()); 2486 nest_scope_stack.pop(); 2487 } 2488 return; 2489 } 2490 if(continuefound) 2491 { 2492 continuefound = false; 2493 } 2494 2495 2496 prog = temp2; // go to increment expression 2497 2498 // Check for break in loop. 2499 2500 2501 2502 // Evaluate the increment expression. 2503 eval_exp(cond); 2504 2505 prog = temp; // loop back to top 2506 } 2507 2508 } 2509 2510 // Execute a cout statement. 2511 void exec_cout() 2512 { 2513 anonymous_var val; 2514 2515 get_token(); 2516 if(*token != LS) throw InterpExc(SYNTAX); 2517 do 2518 { 2519 get_token(); 2520 2521 if(token_type == STRING) 2522 { 2523 // Output a string. 2524 cout << token; 2525 } 2526 else if(tok == ENDL) 2527 { 2528 cout << endl; 2529 } 2530 else 2531 { 2532 //cout << token << " :---" << endl; 2533 putback(); 2534 eval_exp(val); 2535 //cout << val.float_value << "<<<" << endl; 2536 cout_var(val); 2537 } 2538 2539 get_token(); 2540 } 2541 while(*token == LS); //<< 2542 2543 if(*token != ';') throw InterpExc(SEMI_EXPECTED); 2544 } 2545 2546 // Execute a cin statement. 2547 void exec_cin() 2548 { 2549 token_ireps vtype; 2550 2551 get_token(); 2552 if(*token != RS) throw InterpExc(SYNTAX); 2553 2554 do 2555 { 2556 get_token(); 2557 if(token_type != IDENTIFIER) 2558 throw InterpExc(NOT_VAR); 2559 2560 vtype = find_var_type(token); 2561 anonymous_var tmp; 2562 tmp.var_type = vtype; 2563 2564 cin_var(tmp); 2565 assign_var(token, tmp); 2566 get_token(); 2567 } 2568 while(*token == RS); //RS 是>> 2569 2570 if(*token != ';') throw InterpExc(SEMI_EXPECTED); 2571 } 2572 2573 2574 // Find the end of a block. 2575 //#这里find_eob在逻辑上做了一点修改, 由外部保证调用的正确 2576 //如果开始的是{, 那么就处理一个block, 否则就调用find_eol处理一个;语句. 2577 void find_eob() 2578 { 2579 int brace; 2580 2581 get_token(); 2582 //cout << token << " find_eob" <<endl; 2583 if(*token != '{') 2584 { 2585 putback(); 2586 find_eol(); 2587 return ; 2588 } 2589 2590 brace = 1; 2591 2592 do 2593 { 2594 get_token(); 2595 //cout << token << " find_eob" <<endl; 2596 if(*token == '{') brace++; 2597 else if(*token == '}') brace--; 2598 } 2599 while(brace && tok != END); 2600 2601 if(tok == END) throw InterpExc(UNBAL_BRACES); 2602 } 2603 2604 void find_eol() 2605 { 2606 do 2607 { 2608 get_token(); 2609 } 2610 while (*token != ';' && tok != END); 2611 2612 if(tok == END) throw InterpExc(SYNTAX); 2613 } 2614 2615 // Determine if an identifier is a variable. Return 2616 // true if variable is found; false otherwise. 2617 bool is_var(char *vname) 2618 { 2619 anonymous_var* vp; 2620 if(get_member_var(vname, vp)) return true; 2621 // See if vname a local variable. 2622 if(!local_var_stack.empty()) 2623 for(int i = local_var_stack.size() - 1; 2624 i >= func_call_stack.top(); i--) 2625 { 2626 if(!strcmp(local_var_stack[i].var_name, vname)) 2627 return true; 2628 } 2629 2630 // See if vname is a global variable. 2631 for(unsigned i = 0; i < global_vars.size(); i++) 2632 if(!strcmp(global_vars[i].var_name, vname)) 2633 return true; 2634 2635 return false; 2636 } 2637 2638 // Return the type of variable. 2639 token_ireps find_var_type(char *vname) 2640 { 2641 // First, see if it's a local variable. 2642 if(!local_var_stack.empty()) 2643 for(int i = local_var_stack.size() - 1; 2644 i >= func_call_stack.top(); i--) 2645 { 2646 if(!strcmp(local_var_stack[i].var_name, vname)) 2647 return local_var_stack[i].value.var_type; 2648 } 2649 2650 // Otherwise, try global vars. 2651 for(unsigned i = 0; i < global_vars.size(); i++) 2652 if(!strcmp(global_vars[i].var_name, vname)) 2653 return local_var_stack[i].value.var_type; 2654 2655 return UNDEFTOK; 2656 } 2657 2658 void decl_struct_type() 2659 { 2660 struct_type type; 2661 get_token(); 2662 if(strcmp(token, "struct") != 0) 2663 throw InterpExc(SYNTAX); 2664 get_token(); 2665 strcpy(type.type_name, token); 2666 2667 get_token(); 2668 2669 if(*token != '{') 2670 throw InterpExc(SYNTAX); 2671 2672 while(true) 2673 { 2674 get_token(); 2675 2676 if(strcmp(token, "}") == 0) break; 2677 var member_var; 2678 member_var.value.var_type = tok; 2679 2680 do 2681 { 2682 get_token(); 2683 strcpy(member_var.var_name, token); 2684 init_var(member_var.value); 2685 type.data.push_back(member_var); 2686 get_token(); 2687 }while(*token == ','); 2688 2689 if(*token != ';') throw InterpExc(SYNTAX); 2690 } 2691 get_token(); 2692 if(*token != ';') throw InterpExc(SYNTAX); 2693 struct_decls.push_back(type); 2694 2695 dump_struct_type(); 2696 } 2697 2698 void dump_struct_type() 2699 { 2700 char simple_type_names[7][8] = {"bool", "char", "short", "int", "long", "float", "double"}; 2701 int len = struct_decls.size(); 2702 for(int i = 0; i < len; i++) 2703 { 2704 printf("struct %s\n", struct_decls[i].type_name); 2705 printf("{\n"); 2706 struct_type& t = struct_decls[i]; 2707 int sz = t.data.size(); 2708 for(int j = 0; j < sz; j++) 2709 { 2710 printf("\t%s %s;\n", simple_type_names[t.data[j].value.var_type - BOOL], t.data[j].var_name); 2711 } 2712 printf("};\n"); 2713 } 2714 } 2715 2716 bool is_struct_type(char* type_name) 2717 { 2718 int sz = struct_decls.size(); 2719 for(int i = 0; i < sz; i++) if(0 == strcmp(type_name, struct_decls[i].type_name)) return true; 2720 return false; 2721 } 2722 2723 2724 bool get_member_var(char* vname, anonymous_var*& v) 2725 { 2726 bool b_contains_dots = false; 2727 char* p = vname; 2728 while(*p) 2729 { 2730 if(*p == '.') 2731 { 2732 b_contains_dots = true; 2733 break; 2734 } 2735 p++; 2736 } 2737 if(!b_contains_dots) return false; 2738 char struct_name[64]; 2739 char member_name[64];//这里没做太多假定, 所以你尽量别声明很长的变量名称.. 2740 strcpy(struct_name, vname); 2741 int len = strlen(struct_name); 2742 for(int i = 0; i < len; i++) 2743 { 2744 if(struct_name[i] == '.') 2745 { 2746 struct_name[i] = '\0'; 2747 break; 2748 } 2749 } 2750 for(int i = 0; i < len; i++) 2751 { 2752 if(vname[i] == '.') 2753 { 2754 strcpy(member_name, vname + i + 1); 2755 break; 2756 } 2757 } 2758 // See if vname a local variable. 2759 if(!local_var_stack.empty()) 2760 for(int i = local_var_stack.size() - 1; 2761 i >= func_call_stack.top(); i--) 2762 { 2763 if(local_var_stack[i].value.var_type == STRUCT && strcmp(struct_name, local_var_stack[i].var_name) == 0) 2764 { 2765 vector<var>& data= local_var_stack[i].value.struct_value.data; 2766 int len = data.size(); 2767 for(int j = 0; j < len; j++) 2768 { 2769 if(0 == strcmp(data[j].var_name, member_name)) 2770 { 2771 v = &(data[j].value); 2772 return true; 2773 } 2774 } 2775 } 2776 } 2777 2778 // See if vname is a global variable. 2779 unsigned sz = global_vars.size(); 2780 for(unsigned i = 0; i < sz; i++) 2781 { 2782 if(global_vars[i].value.var_type == STRUCT && strcmp(global_vars[i].var_name, struct_name) == 0) 2783 { 2784 vector<var>& data = global_vars[i].value.struct_value.data; 2785 int len = data.size(); 2786 for(int j = 0; j < len; j++) 2787 { 2788 if(0 == strcmp(data[j].var_name, member_name)) 2789 { 2790 v = &(data[j].value); 2791 return true; 2792 } 2793 } 2794 } 2795 } 2796 2797 return false; 2798 } 2799 void init_struct(char* struct_name, anonymous_var& value) 2800 { 2801 get_token(); 2802 if(*token != '{') throw InterpExc(SYNTAX); 2803 value.var_type = STRUCT; 2804 strcpy(value.struct_value.type_name, struct_name); 2805 var member_var; 2806 struct_type tp; 2807 get_struct_type_by_name(struct_name, tp); 2808 int sz = tp.data.size(); 2809 2810 int i = 0; 2811 do 2812 { 2813 2814 eval_exp(member_var.value); 2815 strcpy(member_var.var_name, tp.data[i].var_name); 2816 2817 //adaptive_assign_var(value.struct_value.data[i].value, member_var); 2818 value.struct_value.data.push_back(member_var); 2819 2820 get_token(); 2821 if(*token != ',') break; 2822 i++; 2823 if(i >= sz) 2824 throw InterpExc(MORE_MEMBER_THAN_EXPECTED); 2825 } while (true); 2826 if(*token != '}') throw InterpExc(SYNTAX); 2827 get_token(); 2828 if(*token != ';') throw InterpExc(SYNTAX); 2829 } 2830 2831 //通过名字来获得某个结构体的实体. 2832 bool get_struct_type_by_name(char* struct_name, struct_type& s_type) 2833 { 2834 int sz = struct_decls.size(); 2835 for(int i = 0; i < sz; i++) 2836 { 2837 if(0 == strcmp(struct_name, struct_decls[i].type_name)) 2838 { 2839 s_type = struct_decls[i]; 2840 return true; 2841 } 2842 } 2843 return false; 2844 } 2845 2846 2847 //这个函数目前只为结构体服务, 先不处理关于int, double等的内容... 2848 bool get_type_by_name(char* vname, char* type_name) 2849 { 2850 // See if vname a local variable. 2851 if(!local_var_stack.empty()) 2852 for(int i = local_var_stack.size() - 1; 2853 i >= func_call_stack.top(); i--) 2854 { 2855 if(!strcmp(local_var_stack[i].var_name, vname)) 2856 { 2857 strcpy(type_name, local_var_stack[i].value.struct_value.type_name); 2858 return true; 2859 } 2860 } 2861 2862 // See if vname is a global variable. 2863 for(unsigned i = 0; i < global_vars.size(); i++) 2864 if(!strcmp(global_vars[i].var_name, vname)) 2865 { 2866 strcpy(type_name, global_vars[i].value.struct_value.type_name); 2867 return true; 2868 } 2869 2870 return false; 2871 } 2872 2873 2874 //libcpp.cpp 2875 /*********************************************************************** 2876 libcpp.cpp, 主要是对库函数的封装 2877 ************************************************************************/ 2878 2879 // Add more of your own, here. 2880 2881 #include <iostream> 2882 #include <cstdlib> 2883 #include <cstdio> 2884 #include "mccommon.h" 2885 2886 using namespace std; 2887 2888 // Read a character from the console. 2889 // If your compiler supplies an unbuffered 2890 // character intput function, feel free to 2891 // substitute it for the call to cin.get(). 2892 anonymous_var call_getchar() 2893 { 2894 char ch; 2895 2896 ch = getchar(); 2897 2898 // Advance past () 2899 get_token(); 2900 if(*token != '(') 2901 throw InterpExc(PAREN_EXPECTED); 2902 2903 get_token(); 2904 if(*token != ')') 2905 throw InterpExc(PAREN_EXPECTED); 2906 anonymous_var val; 2907 val.var_type = CHAR; 2908 val.int_value = ch; 2909 return val; 2910 } 2911 2912 // Write a character to the display. 2913 anonymous_var call_putchar() 2914 { 2915 anonymous_var value; 2916 2917 eval_exp(value); 2918 2919 putchar(char(value.int_value)); 2920 2921 return value; 2922 } 2923 2924 // Return absolute value. 2925 anonymous_var call_abs() 2926 { 2927 anonymous_var val; 2928 2929 eval_exp(val); 2930 abs_var(val); 2931 return val; 2932 } 2933 2934 // Return a randome integer. 2935 anonymous_var call_rand() 2936 { 2937 2938 // Advance past () 2939 get_token(); 2940 if(*token != '(') 2941 throw InterpExc(PAREN_EXPECTED); 2942 2943 get_token(); 2944 if(*token != ')') 2945 throw InterpExc(PAREN_EXPECTED); 2946 2947 anonymous_var val; 2948 val.var_type = INT; 2949 val.int_value = rand(); 2950 return val; 2951 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能