LCC编译器的源程序分析(39)goto语句

在现代设计的程序里,很少再用到 goto 语句了。虽然使用 goto 语句是比较高效,但它使程序也会得非常难懂,非常难维护,比较容易出错,所以很少使用 goto 语句的。 goto 语句为无条件跳转语句,它的一般形式为:
 goto 标号 ;
LCC 里的是用下面的代码来处理:
#001 case GOTO:   
#002         walk(NULL, 0, 0);
#003         definept(NULL);
#004         t = gettok();
#005         if (t == ID)
#006         {
#007               Symbol p = lookup(token, stmtlabs);
#008 
#009               if (p == NULL)
#010               {
#011                    p = install(token, &stmtlabs, 0, FUNC);
#012                    p->scope = LABELS;
#013                    p->u.l.label = genlabel(1);
#014                    p->src = src;
#015               }
#016               use(p, src);
#017               branch(p->u.l.label);
#018               t = gettok();
#019         }
#020         else
#021               error("missing label in goto/n"); expect(';');
#022         break;
2 行复位所有分配的内存。
3 行定义执行点。
4 行获取下一个记号。
5 行判断 goto 语句后面是否标号变量。如果是标号变量,就跳到第 6 行到第 19 行里处理。否则就在第 21 行里提示出错。
7 行里查找标号是否已经定义。
9 行是当标号还没有定义时,就把这个标号安装到符号表里。这是在第 9 行到第 15 行里处理。
17 行是生成跳转到标号的代码。
 
下面再来分析标号语句是怎么样定义的,如下:
#001 case ID:    
#002         if (getchr() == ':')
#003         {
#004               stmtlabel();
#005               statement(loop, swp, lev);
#006               break;
#007         }
2 行就判断一个 ID 标识符是否标号变量,如果在一个 ID 后面紧跟着一个冒号,就是表示声明了一个标号变量,所以在第 4 行里调用函数 stmtlabel 来处理标号。
5 行是处理标号后面的语句。
 
下面来分析函数 stmtlabel
#001 static void stmtlabel(void)
#002 {
#003  Symbol p = lookup(token, stmtlabs);
#004 
#005  if (p == NULL)
#006  {
#007         p = install(token, &stmtlabs, 0, FUNC);
#008         p->scope = LABELS;
#009         p->u.l.label = genlabel(1);
#010         p->src = src;
#011  }
#012 
#013  if (p->defined)
#014         error("redefinition of label `%s' previously defined at %w/n", p->name, &p->src);
#015 
#016  p->defined = 1;
#017  definelab(p->u.l.label);
#018  t = gettok();
#019  expect(':');
#020 }
3 行是查找这个标号是否定义。
5 行判断这个标号是否定义,如果没有定义就添加到符号表。
7 行是保存到符号表。
8 行到第 10 行都是设置标号的属性。
13 行当重复定义标号时,提示出错。
16 行设置这个标号已经定义。
17 行定义一个标号。
18 行获取下一个记号。
19 行检查标号后是否冒号。
 
这样就可以处理 goto 语句和标号语句了,到这里就把所有基本的语句分析完成了。
 

你可能感兴趣的:(null,token,编译器,branch)