在分析源代码之前,笔者先简单介绍一下各语义子程序的功能,以便读者理解。
semantic068:1、判断表达式结果是否为布尔类型。
2、生成JNT语句,目标标号就是假分支标号。
semantic069:1、生成JMP语句,目标标号就是出口标号。
2、生成假分支的入口LABEL语句,即翻译方案中的第一个LABEL语句。
semantic070:1、生成if语句的出口LABEL语句,即翻译方案中的第二个LABEL语句。
下面,就来看看if语句相关的语义子程序。
程序5-4 semantic.cpp
第3行:OpData栈就是表达式翻译时使用的辅助栈结构。if语句中的条件表达式的运算结果就是OpData的栈顶元素。因此,程序必须判断OpData是否为空。
第10行:这个条件语句判断OpData栈顶元素是否为BOOLEAN类型。在Pascal中,if语句的条件表达式类型必须为BOOLEAN类型,这里的类型检查是非常严格的。
第17行:声明一个Statement实例。
第21行:在翻译if语句时,m_blsElse是非常有用的。当然,m_blsElse的缺省值应该是false,仅当编译器分析到相应的else子句时,才将该属性重置为true。
第22-~26行:生成一个临时标号,并将其设置为当前if语句的假分支标号。实际上,在任何编译器中,临时标号都是静态的且全局有效的,并不是临时存在的,称其为“临时标号”仅因为它是编译过程中由编译器自动产生的而已。Neo Pascal调用了SymbolTbl的静态方法GetTmpLabel生成一个临时标号,其返回值即为该临时标号在标号信息表中的位序号。GetTmpLabel方法的源程序列表稍后给出。
第27行:m_Labels是TmpS对象的标号集合,主要用于存储当前语句相关的标号信息。m_Labels集合中的标号不存在先后顺序。(www.daowen.com)
第28~33行:主要的工作是生成出口标号,其过程与假分支标号处理基本类似。
第35--36行:生成JNT指令,并将其加入IR列表。通常,JNT指令需要提供两个操作数,即条件变量(常量)及跳转标号,程序调用EmitlR函数统一生成IR指令。
程序5-5 semantic.cpp
第3行:有效性判断。实际上,语法分析完全有能力保证else子句位置有效性,因此。这个判断是可以省略的。
第9行:设置m_bIsElse属性的目的就是便于semantic070生成适合的出口标号。仔细分析后,不难发现,semantic070可能遇到两种情景,即if-then和if-then-else结构。针对这两种结构,semantic070生成的出口标号是不同的,所以需要明确地标识输入语句结构是if-then还是if-then-else。
第11~12行:生成JMP语句。这个JMP语句的目标标号就是if结构的出口标号。
第13,-14行:生成LABEL语句。这个LABEL语句的标号就是if结构的假分支标号,即对应翻译方案中的第一个LABEL语句的“ Ll”。
程序5-6 semantic.cpp
第3行:有效性判断。
第10行:判断当前正在分析的语句是否含有else子句。如果是if.then-else结构,标志是由semantic069设置的。
第11、12行:生成LABEL语句。当输入语句为if-then-else结构时,则LABEL语句的标号即为if语句的出口标号。
第14、15行:生成LABEL语句。当输入语句为if-then结构时,则LABEL语句的标号即为if语句的假分支标号。
第16行:当前if语句分析完毕,将CurrentStatement栈顶元素弹出,这个步骤是非常重要的。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。