理论教育 编译器设计之路:break、continue语句的翻译

编译器设计之路:break、continue语句的翻译

时间:2023-11-04 理论教育 版权反馈
【摘要】:ISO/IEC 7185-1990标准并没有提供关于break、continue语句的任何描述。因此,笔者参考了C语言及Delphi的实现,将break、continue作为Neo Pascal的标准语句。Neo Pascal的break、continue语法、语义与C语言完全一致,这里就不多作解释了。在程序设计语言中,类似于break、continue的语句结构并不少见,例如,Ruby语言的next、redo、retry等等。当然,除了break、continue之外,有些高级语言还提供了exit、quit之类的过程(函数)的出口语句。

编译器设计之路:break、continue语句的翻译

ISO/IEC 7185-1990标准(Pascal语言标准)并没有提供关于break、continue语句的任何描述。不过,由于这两种语句结构确实为编程带来了极大的便利,所以得到了程序员的广泛支持。因此,笔者参考了C语言及Delphi的实现,将break、continue作为Neo Pascal的标准语句。Neo Pascal的break、continue语法、语义与C语言完全一致,这里就不多作解释了。

在程序设计语言中,类似于break、continue的语句结构并不少见,例如,Ruby语言的next、redo、retry等等。通过使用这类语句,程序员可以方便地改变循环控制结构的执行流程。当然,除了break、continue之外,有些高级语言还提供了exit、quit之类的过程(函数)的出口语句。这类语句的文法结构比较简单,所以翻译过程也并不复杂,关键是明确跳转的目标标号。

实际上,了解C语言break、continue语句的读者应该都明白这两个结构的本质就是一次无条件跳转,只是跳转的目标不同而己。根据C语言的语义,break语句的跳转目标是最内层循环的出口标号,而continue语句的跳转目标是最内层循环的入口标号。当然,这并不是绝对的,例如,Ada语言的循环终止语句exit就允许程序员定义欲跳出的循环名(缺省情况为最内层循环)。处理这类特殊应用时,编译器设计者不得不跟踪输入程序循环的嵌套情况,并记录一些必要的信息。在Neo Pascal中,笔者使用CurrentStatement栈详细记录了各语句分析的状况信息,因此,即使Pascal存在类似于Ada语言的exit结构,也可以比较方便地分析与处理。

下面就来看看break、continue语句的具体实现。

程序5-21 semantic.cpp

第5~13行:遍历CurrentStatement栈,检索最内层循环。注意,最内层循环并不一定是CurrentStatement的栈顶元素,所以不能依此判断。在Pascal语言中,标准的循环结构有三种:for、while、repeat。(www.daowen.com)

第14行:判断是否检索到最内层循环,如果检索失败(即i<0),表示break语句没有出现在任何循环体内,编译器必须报错。

第20~21行:生成JMP语句,目标标号就是最内层循环的出口标号。

程序5-22 semantic.cpp

continue语句的处理与break语句类似,主要差别就在于continue语句的目标标号。对于for语句而言,continue语句的目标标号是TrueLabel。然而,对于repeat、while语句而言,continue语句的目标标号是EntryLabel。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈