[转载]LCC编译器的源程序分析(27)基本语句

来源:互联网 发布:极域电子教室网络锁屏 编辑:程序博客网 时间:2024/05/19 04:02
由前面的例子可以知道,C函数里包含数据定义部分和执行部分,执行部分就是由语句组成。计算机最基本的动作就是具备条件判断,这也是计算机具有这么大魔力的原因。而这些条件判断是通过语句来实现的。基本的语句有下面几种:
1.     控制语句:
if else
for 
while
do while
continue
break
switch
goto
return
2.     函数调用语句
max(a,b);
3.     表达式语句
nPos = 10;
4.     空语句
;
最后面一种在LCC里会提示警告的。
在这节和后面跟着的节就是分析这些基本语句是怎么样处理,以及会生成什么样的代码。在compound函数里是这样调用语句分析函数的:
#052  while (kind[t] == IF || kind[t] == ID)
#053  {
#054         statement(loop, swp, lev);
#055  }   
#056  
因此要去分析函数statement是怎么样分析处理上面出现的语句。
 
下面就是statement的代码:
#001 //所有基本语句处理函数。
#002 //蔡军生 2007/06/02
#003 void statement(int loop, Swtch swp, int lev)
#004 {
#005  float ref = refinc;
#006 
#007  if (Aflag >= 2 && lev == 15)
#008          warning("more than 15 levels of nested statements/n");
#009 
5行是保存引用计数。
7行是判断递归调用超过15层。
 
#010  switch (t)
#011  {
#012  case IF:      
#013         ifstmt(genlabel(2), loop, swp, lev + 1);
#014         break;
13行是调函数ifstmt来处理if语句。
 
#015  case WHILE:   
#016         whilestmt(genlabel(3), swp, lev + 1);
#017         break;
16行是调用函数whilestmt来处理while语句。
 
#018  case DO:      
#019         dostmt(genlabel(3), swp, lev + 1);
#020         expect(';');
#021         break;
#022 
19行是调用函数dostmt来处理do while语句。
20行是处理do while语句后需要分号。
 
 
#023  case FOR:     
#024         forstmt(genlabel(4), swp, lev + 1);
#025         break;
24行是调用函数forstmt来处理for语句。
 
 
#026  case BREAK:   
#027         walk(NULL, 0, 0);
#028         definept(NULL);
#029 
#030         if (swp && swp->lab > loop)
#031               branch(swp->lab + 1);
#032         else if (loop)
#033               branch(loop + 2);
#034         else
#035               error("illegal break statement/n");
#036 
#037         t = gettok();
#038         expect(';');
#039         break;
#040 
31,33行是调用函数branch来处理break语句。
 
 
#041  case CONTINUE:
#042         walk(NULL, 0, 0);
#043         definept(NULL);
#044 
#045         if (loop)
#046               branch(loop + 1);
#047         else
#048               error("illegal continue statement/n");
#049 
#050         t = gettok();
#051         expect(';');
#052         break;
#053 
46行是调用函数branch来处理continue语句。
 
 
#054  case SWITCH:  
#055         swstmt(loop, genlabel(2), lev + 1);
#056         break;
55行是调用函数swstmt来处理switch语句。
 
 
#057  case CASE:    
#058         {
#059               int lab = genlabel(1);
#060               if (swp == NULL)
#061                    error("illegal case label/n");
#062 
#063               definelab(lab);
#064               while (t == CASE)
#065               {
#066                    static char stop[] = { IF, ID, 0 };
#067                    Tree p;
#068                    t = gettok();
#069                    p = constexpr(0);
#070                    if (generic(p->op) == CNST && isint(p->type))
#071                    {
#072                          if (swp)
#073                          {
#074                               needconst++;
#075                               p = cast(p, swp->sym->type);
#076                               if (p->type->op == UNSIGNED)
#077                                     p->u.v.i = extend(p->u.v.u, p->type);
#078                               needconst--;
#079                               caselabel(swp, p->u.v.i, lab);
#080                          }
#081                    }
#082                    else
#083                          error("case label must be a constant integer expression/n");
#084 
#085                    test(':', stop);
#086               }
#087               statement(loop, swp, lev);
#088         }
#089         break;
59行是调用函数genlabel生成标号。
64行是处理所有case语句。
69行是处理case语句后面的常量表达式,调用函数constexpr来处理。
70行到第81行是作类型转换的工作,如果不能处理常量类型,就会在第83行里提示出错。
87行是递归调用函数statement处理case语句里语句。
 
 
#090  case DEFAULT: 
#091         if (swp == NULL)
#092               error("illegal default label/n");
#093         else if (swp->deflab)
#094               error("extra default label/n");
#095         else
#096         {
#097               swp->deflab = findlabel(swp->lab);
#098               definelab(swp->deflab->u.l.label);
#099         }
#100         t = gettok();
#101         expect(':');
#102         statement(loop, swp, lev);
#103         break;
97行是查找default语句生成的标号。
98行是定义这个标号。
102行是调用函数statement递归处理所有后面语句。
 
#104  case RETURN: 
#105         {
#106               Type rty = freturn(cfunc->type);
#107               t = gettok();
#108               definept(NULL);
#109               if (t != ';')
#110                    if (rty == voidtype)
#111                    {
#112                          error("extraneous return value/n");
#113                          expr(0);
#114                          retcode(NULL);
#115                    }
#116                    else
#117                          retcode(expr(0));
#118               else
#119               {
#120                    if (rty != voidtype)
#121                    {
#122                          warning("missing return value/n");
#123                          retcode(cnsttree(inttype, 0L));
#124                    }
#125                    else
#126                          retcode(NULL);
#127               }
#128               branch(cfunc->u.f.label);
#129         }
#130         expect(';');
#131         break;
#132 
106行是取得函数返回的类型。
109行是判断返回语句是否有返回值,如果有返回值,但函数定义类型没有返回值就提示出错,这是在第110行里处理。如果函数定义有返回值,并且return语句也有返回值就调用第117行里的retcode(expr(0))来处理返回表达式的值。
如果return语句后面没有返回值,但函数需要返回值,这样是出错的,是在第120行里处理。如果真的没有返回值,就是返回空值,在第126行里处理。
128行跳转到函数调用之后标号执行。
 
#133  case '{':    
#134         compound(loop, swp, lev + 1);
#135         break;
当是大括号开始时,又是复合语句,所以要递归调用函数compound来处理。
 
 
#136  case ';':    
#137         definept(NULL);
#138         t = gettok();
#139         break;
上面是空行语句的处理。
 
#140  case GOTO:   
#141         walk(NULL, 0, 0);
#142         definept(NULL);
#143         t = gettok();
#144         if (t == ID)
#145         {
#146               Symbol p = lookup(token, stmtlabs);
#147 
#148               if (p == NULL)
#149               {
#150                    p = install(token, &stmtlabs, 0, FUNC);
#151                    p->scope = LABELS;
#152                    p->u.l.label = genlabel(1);
#153                    p->src = src;
#154               }
#155               use(p, src);
#156                branch(p->u.l.label);
#157               t = gettok();
#158         }
#159         else
#160               error("missing label in goto/n"); expect(';');
#161         break;
#162 
上面是goto语句的处理。
144行先判断goto语句后面是否标号ID,如果是就运行146行的代码来查找已经定义的标号。如果没有找到就生成一个新的标号。最后在第156行里跳到标号的位置运行后面的代码。
 
 
#163  case ID:    
#164         if (getchr() == ':')
#165         {
#166               stmtlabel();
#167               statement(loop, swp, lev);
#168               break;
#169         }
上面处理标号语句。
166行调用函数stmtlabel来处理标号语句,最后调用函数statement处理其它跟着的语句。
 
#170  default:    
#171         definept(NULL);
#172          if (kind[t] != ID)
#173         {
#174               error("unrecognized statement/n");
#175               t = gettok();
#176         }
#177         else
#178         {
#179               Tree e = expr0(0);
#180               listnodes(e, 0, 0);
#181               if (nodecount == 0 || nodecount > 200)
#182                    walk(NULL, 0, 0);
#183               else if (glevel) walk(NULL, 0, 0);
#184               deallocate(STMT);
#185         }
#186         expect(';');
#187         break;
#188 
#189  }
#190 
#191  if (kind[t] != IF && kind[t] != ID
#192         && t != '}' && t != EOI)
#193  {
#194         static char stop[] = { IF, ID, '}', 0 };
#195         error("illegal statement termination/n");
#196         skipto(0, stop);
#197  }
#198  refinc = ref;
#199 }
#200 
如果一个ID后面没有跟着冒号,那么它是一个表达式语句。
比如像例子里的语句:
nTest3 = nTest1 + nTest2;
这就是ID开始的表达式语句。它会调用前面介绍的表达式处理函数expr0来分析的。
172行到175行处理不是ID的出错。
179行是处理右边的表达式。
180行是调用函数listnodes来遍历整个语句树,主要的目的是生成中间的树表示,删除公共的表达式节点,起到优化代码的作用,为后面生成代码作好准备工作。
181行是当中间表示的树节点多于200个就进行代码生成。
191行是出错的符号,并进入第195行到第196行的错误处理。
 
到这里就把基本语句函数分析完成,接着后面就需要专门地分析具体语句的处理函数。
 
  <script type="text/javascript"><!--google_ad_client = "pub-0904655026211899";google_ad_width = 468;google_ad_height = 60;google_ad_format = "468x60_as";google_ad_type = "text_image";google_ad_channel = "";google_color_border = "336699";google_color_bg = "FFFFFF";google_color_link = "0000FF";google_color_text = "000000";google_color_url = "008000";//--></script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大学交学费的卡丢了怎么办 交学费的银行卡丢了怎么办 学校补助卡丢了怎么办 学校交学费的卡丢了怎么办 采购零星材料无发票怎么办 租房合同弄丢了怎么办 买房的合同丢了怎么办 押金的收据丢了怎么办 房东的合同掉了怎么办 个人档案里单位没有放合同怎么办 签的合同掉了怎么办 一方合同弄丢了怎么办 合同丢了怎么办如何补 签了定金合同对方违约怎么办 医学出生证明丢了怎么办 易通行出站未刷怎么办 炭烧酸奶过期了怎么办 西安建行etc坏了怎么办 电机在设备壳体中拔不出来怎么办 公司变更股东不能亲临现场怎么办? 公司股东变更老股东不签字怎么办 公司变更地址股东不签字怎么办 公司变更股份股东不签字怎么办 公司股东离职股东没变更过来怎么办 河南省宋基投资公司欠钱怎么办 曲江楼观2O18怎么办 华旭金卡身份证扫描不了怎么办 水表里有钱没水怎么办? ff14过图速度慢怎么办 想让电表跑的慢怎么办 家里电表突然没有电了怎么办 电表不识别电卡怎么办 家里水表不转了怎么办 车管所体检色弱怎么办 煤气押金单没了怎么办 中国建设银行登录密码忘了怎么办 中国建设银行登录密码忘记了怎么办 公司车辆怎么办换新能源牌 杭州新能源汽车牌照外地人怎么办 建行登录密码忘了怎么办 新捷达epc灯亮怎么办