LCC编译器的源程序分析(35)switch语句

switch语句是多分支选择语句,主要方便多个选择的情况使用,当然也可以使用if语句来实现,但嵌套的if语句过多会使用程序的可读性降低。
switch(表达式)
{
 case 常量表达式1
       语句1;
 case 常量表达式2
       语句2;
 …
 case 常量表达式n
       语句n;
 default:
       语句n+1
}
上面就是switch的语法和语义,现在来分析LCC的源程序是怎么样处理这个语句的,先通过下面的函数代码调用:
#054  case SWITCH:  
#055         swstmt(loop, genlabel(2), lev + 1);
#056         break;
55行是调用函数swstmt来处理switch语句。第一个参数是循环次数,第二个参数是标号的起始大小,最后一个参数是调用嵌套层数。
 
然后在swstmt分析处理这个语句,如下:
#001  static void swstmt(int loop, int lab, int lev)
#002 {
#003  Tree e;
#004  struct swtch sw;
#005  Code head, tail;
#006 
#007  t = gettok();
#008  expect('(');
#009  definept(NULL);
7行是获取下一个记号。
8行是检测下一个记号是左括号开始。
9行是定义了执行点。
 
#010  e = expr(')');
#011  if (!isint(e->type))
#012  {
#013          error("illegal type `%t' in switch expression/n",
#014               e->type);
#015         e = retype(e, inttype);
#016  }
#017 
#018  e = cast(e, promote(e->type));
#019  if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op)
#020         && e->kids[0]->u.sym->type == e->type
#021         && !isvolatile(e->kids[0]->u.sym->type))
#022  {
#023         sw.sym = e->kids[0]->u.sym;
#024         walk(NULL, 0, 0);
#025  }
#026  else
#027  {
#028         sw.sym = genident(REGISTER, e->type, level);
#029         addlocal(sw.sym);
#030         walk(asgn(sw.sym, e), 0, 0);
#031  }
#032 
10行是处理switch后面括号里的表达式,它是调用函数expr来处理的。
11行判断这个表达式返回值是否整数类型,如果不是就会在第13行里提示出错,在第15行里转换为整型类型。
18行是转换表达式的值。
19行到21行是判断类型是否可以分配为寄存器变量,如果不可以就在第23行和第24行里处理;如果可以就在第28行到第30行里处理。
 
#033  head = code(Switch);
#034  sw.lab = lab;
#035  sw.deflab = NULL;
#036  sw.ncases = 0;
#037  sw.size = SWSIZE;
#038  sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC);
#039  sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC);
#040  refinc /= 10.0;
#041 
33行生成switch的块代码开始。
34行到第39行是设置switch的属性结构。
 
#042  statement(loop, &sw, lev);
#043  if (sw.deflab == NULL)
#044  {
#045         sw.deflab = findlabel(lab);
#046         definelab(lab);
#047         if (sw.ncases == 0)
#048               warning("switch statement with no cases/n");
#049  }
#050 
42行是处理复合语句。
43行是判断这个switch语句的复合语句里是否有分支语句,如果没有就在第47行到第48行里给出警告。
 
#051  if (findlabel(lab + 1)->ref)
#052         definelab(lab + 1);
#053 
#054  tail = codelist;
#055  codelist = head->prev;
#056  codelist->next = head->prev = NULL;
#057 
#058  if (sw.ncases > 0)
#059         swgen(&sw);
#060 
#061  branch(lab);
#062  head->next->prev = codelist;
#063  codelist->next = head->next;
#064  codelist = tail;
#065 }
51行是找到最后的标号,并且在第52里生成这个标号。
54行是保存代码表。
59行生成跳转代码。
61行是生成标号。
62行到第64行都是设置代码表。
 
通过上面函数的分析,了解LCC是怎么样处理switch语句的。
 
posted @ 2007-06-13 19:04  ajuanabc  阅读(362)  评论(0)    收藏  举报