LCC编译器的源程序分析(29)if条件语句

if语句是用来判定所给定的条件是否满足,根据判定的结果决定执行给出来的两种操作之一。if语句有下面三种形式:
1. if(表达式)语句
2. if(表达式)语句1 else 语句2
3. if(表达式1)语句1
else if(表达式2)语句2
else if(表达式3)语句3
else 语句4
那么LCC又是怎么样处理if语句的呢?LCC在函数statement调用ifstmt来处理的。下面就来查看ifstmt函数的源程序。
#001 static void ifstmt(int lab, int loop, Swtch swp, int lev)
#002 {
#003 t = gettok();
#004 expect('(');
#005 definept(NULL);
#006
第3行获取下一个记号,主要就是获取条件括号。
第4行是判断下一个记号是左括号开始。
第5行是定义了运行点。

#007 walk(conditional(')'), 0, lab);
#008
第7行是先调用函数conditional来处理条件表达式,然后再调用函数walk把条件表达式变成DAG森林。

#009 refinc /= 2.0;
#010 statement(loop, swp, lev);
#011
第9行是引用计数。由于条件语句分为两个分支,所以需要除2。
第10行是调用函数statement处理条件后面的第一个语句,这是递归调用处理。

#012 if (t == ELSE)
#013 {
#014 branch(lab + 1);
#015 t = gettok();
#016 definelab(lab);
#017 statement(loop, swp, lev);
#018 if (findlabel(lab + 1)->ref)
#019 definelab(lab + 1);
#020 }
#021 else
#022 definelab(lab);
#023 }
第12行是判断下一个记号是否有else关键字,如果有这个关键字说明它是第二、第三种if语句的形式,那么第13行到第20行就是处理else后面的语句。
第14行调用函数branch来生成跳转标号代码。
第15行是获取下一个记号。
第16行定义一个标号。
第17行是递归调用函数statement来处理else后面的语句。
第22行是生成标号1。

LCC会把if语句生成下面形式:
if 表达式 == 0 goto 标号1
语句1
goto 标号2
标号1:语句2
标号2:
上面的代码definelab(lab)是生成标号1,definelab(lab + 1)是生成标号2。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License