1 第四章 语义分析 前面章节介绍的词法分析和语法分析主要用来解决单词和语言成分的识别及词法和语法结构的检查。语法结构可以形式化地用一组产生式来描述。对于给定的一组产生式,我们能够比较容易地将其分析程序构造出来。但是仅仅完成这两部分还是不够的,因为程序不但要在词法和语法结构上满足要求,它的语义也必须正确。也就是说,源程序和编译后的目标程序可以在语法结构上不同,但是它们所要表达的语义必须是一致的,它们所产生的结果必须一样,否则编译过程就失去了意义。 紧接在词法分析和语法分析之后,编译程序要做的工作是进行语义分析。其任务是对语法分析所识别出的各类语法范畴,分析其含义,并进行初步翻译。包括两个方面的工作:首先是对各种语法范畴进行静态语义检查,例如,变量是否定义、类型是否正确等等。如果语义正确,则进行中间代码的翻译。 在该阶段需要识别出什么时候同一单词的多个出现引用的是同一个程序实体,并且要保证这些使用的相容性。在大部分的语言里,语义分析器需要跟踪标识符和表达式的类型,这既是为了验证使用的相容性,也用于知道后面阶段中的代码生成。 利用符号表,语义分析器就能贯彻执行许多分析规则,这些规则是上下文无关文法和语法分析树无法表示的。举例说,它需要检查并确定以下内容: 每个标识符在使用之前都已有定义; 没有标识符被用在不合适的上下文中; 为子程序调用提供的是数目和类型都正确的实际参数; 每个函数里至少包含了一个刻画返回值的语句; 语义分析需要结合程序的上下文来进行,在这个过程中,要对变量,表达式进行类型检查,查看类型是否匹配。同时还要检查变量是否重复定义,以及是否没有定义就使用等。与语义分析过程联系紧密的一个环节就是对符号表的操作。 本章将集中讨论类型检查和中间表示的生成,有关符号表的设计和实现我们将放到下一章中去描述。正如上面的例子所指出的,大部分静态检查都是一些简单的工作。例如,当我们将名字信息填入符号表时,即可对该名字的惟一性进行检查。对于更复杂的结构,将类型检查作为语法分析和中间代码生成(中间代码生成我们将在稍后介绍)之间单独的一遍会更方便一些,如下图 4.1 所示: 类型检查器将验证结构的类型是否与上下文所期望的类型相匹配。例如,Pascal内置的算术运算符 mod 要求整型操作数,所以类型检查器必须检查 mod 的操作数是否为整型。同样地,类型检查器必须能够验证指针地址访问只作用于指...