编译原理 Switch语句的分析

来源:互联网 发布:开源 学校网站 php 编辑:程序博客网 时间:2024/06/10 18:45
今天我的编译系统中所有类型的语句分析都完成了——但没有做优化——包括Switch语句,因为我的系统地语法是类似C++语言的所以实现的方式也类似于C++。在"C++、Pascal =(赋值),for,case语句,函数,变量空间的区别"中我已介绍过C++的switch和Pascal的case语句的区别。在这里复制一下其中的switch语句与if-goto语句的转换实例:
switch 语句
switch(a){
case 1:
a += 2;
default:
a += 16;
case 2:
a += 4;
break;
case 3:
a += 8;
}
等价的if-goto语句
if(a == 1)
goto a1;
if(a == 2)
goto a2;
if(a == 3)
goto a3;
goto df;
a1:
a += 2;
df:
a += 16;
a2:
a += 4;
goto end;
a3:
a += 8;
end:
这儿有一个重要的转变就是将case 语句都集中在一起并提前到switch语句的开头。要在编译时就做到这样是有点困难的,他必须要收集所有的case条件语句,然后建立一张跳转表格。C++编译其肯定是做到了,并且case语句达到一定数量时他还会在这些条件和跳转的目标之间建立一个合适的hash函数,而不是一个一个的if判断,从而使得switch语句更高效。(题外话:在pascal的case语句的条件值好像不能多于256个,不知道是出于什么目的,可能也是为了优化吧!)
在我做的编译系统中没有做任何的优化,但是和上面的在语义上是完全等价的,先将上面switch语句对应的四元式列举在下面,并作一定的解释:
0: JNE 5 a 1 // if(a!=1) goto 5 如果不等于1跳转到下一个判断
1: + a a 2 // a += 2
2: JMP 3 // goto 3 跳转到下 default 的内部
3: + a a 16 // a += 16
4: JMP 6 // goto 6 跳转到下一个case 的内部
5: JNE 9 a 2 // if(a!=2) goto 9 如果不等于2跳转到下一个判断
6: + a a 4 // a += 16
7: JMP 13 // goto 13 跳转到结束 对应break
8: JMP 10 // goto 10 跳转到下一个case 的内部
9: JNE 12 a 3 // if(a!=2) goto 12 如果不等于3跳转到下一个判断
10: + a a 8 // a += 16
11: JMP 13 // goto 13 跳转到结束
12: JMP 3 // goto 3 如果没有匹配的 跳转到 default
13: END // 结束

这样的编译其实有很多是可以做优化的,比如第2句是没有意义的,第8句是永远也运行不到的。当然能够像C++编译其那样优化才是最好的,等我什么时候有大片的时间再做这个优化吧。更希望看到这个文章并对这个感兴趣的人能够帮我做这个优化,如果您感兴趣请和我联系我会为你提供现在所有的源代码和我的设计思想。我期待作您!

原文地址:http://blog.sina.com.cn/s/blog_5526d40f0100orrc.html