实验目的
这次实验的实验目的其实很明确——对源码进行语义分析,输出语义分析结果,并要求有适当的错误处理机制。可是指导书上实验目的要求自己分析,我的分析结果:本次实验要求自己定义上次实验的语法分析的文法的SDD,然后编写程序在上次语法分析的基础上完成语义分析,生成测试程序的中间代码(三地址码)。
基本概念
本次实验离不开一些概念:语法制导定义(syntax-directed definition ( SDD ),我觉得这个翻译略显生硬,“制导”?导弹制导系统?),语法制导翻译(Syntax-Directed Translation(SDT),同上),以及中间代码生成(Intermediate-Code Generation,个人认为把它翻译成“中介”更好一些)。刚开始可能课上听课程度不够,对这些概念不是很了解,导致做实验时有很大的障碍。
下面说说我的理解:
SDD是一个偏理论上的概念,龙书第二版这样说:
A syntax-directed definition ( SDD ) is a context-free grammar together with attributes and rules. Attributes are associated with grammar symbols and rules are associated with productions(“rules” is “semantic rules”,笔者加).
也就是说,为了理解语言的含义,我们要把语言符号和语言符号所代表的信息联系起来,我们要为文法的每个grammar symbol(s)附加一些属性。而附加到Production的语义规则则告知这些属性是怎么得来的以及文法符号属性之间的关系是怎样的。我们可以把SDD理解为对单纯的Grammar Symbols和Productions的扩展。SDD让文法的Grammar Symbols和Productions变得“活”了,变得有意义了。
SDT是一种技术(老师的讲义上把它理解为SDD的一种便于书写的形式)。这种翻译技术可以被应用到语义翻译过程中的类型检查和中间代码生成上,也可以被应用到一些某些具有特定任务的轻量级的语言中。可以这么理解,SDT是根据SDD所定义的那些规则和计算顺序对语言进行语义翻译的技术。通过SDT,我们理解了源语言到底要表达个什么意思,为后续的编译工作打下了基础。
中间代码生成,是一个生成一种独立于源语言也独立于目标语言(我们叫它中间代码)的代码过程,中间代码有很多形式,生成中间代码有很多好处,这里不再赘述。中间代码的生成工作要用到SDT技术。
总之,它们都没有什么明确的定义,意会这些就好。
引子:Python实现递归和非递归遍历树
不一定要把SDT作为一个单独的过程去完成它,可能在句法分析的过程中(句法分析当然也有可多方法,LL、LR等)就调用相应的语义子程序完成了SDT的工作。此外,这次实验我最大的收获:LL(1)语法分析的过程本质上就是一个对语法分析树进行先根遍历的过程。
所以,先写一个简单的脚本实现非递归先根顺序遍历树,来模拟LL(1)的过程,以加深对其的理解。
下面上代码,其中非递归遍历树的过程就是LL(1)执行时遍历语法分析树的过程,读者可以画一下树的结构,并对着输出看一下遍历顺序,会对LL分析过程中分析栈的变化的认识有帮助。
树是这样被录入程序的(tree.txt):
Root:A
A -> B C
B -> D E F
C -> G H
E -> I J
J -> K L M
H -> N O
下面是脚本:
Tree = {}
Root = None
def read_tree(tree_file_path):
'''Read the Tree from the file, bu