China-pub.Com 下载 第6章语义分析 本章要点 ·属性和属性文法 ·数据类型和类型检查 ·属性计算算法 ·TNY语言的语义分析 ·符号表 本章要研究的编译程序阶段是计算编译过程所需的附加信息。这个阶段称作语义分析, 因为它包括计算上下文无关文法和标准分析算法以外的信息,因此,它不被看成是语法⊙。信 息的计算也与被翻译过程的最终含义或语义密切相关。因为编译器完成的分析是静态(它在执 行之前发生)定义的,这样,语义分析也可称作静态语义分析(static semantic analysis)。在 个典型的静态类型的语言(如℃语言)中,语义分析包括构造符号表、记录声明中建立的名字的 含义、在表达式和语句中进行类型推断和类型检查以及在语言的类型规则作用域内判断它们 的正确性。 语义分析可以分为两类。第1类是程序的分析,要求根据编程语言的规则建立其正确性, 并保证其正确执行。对于不同的语言来说,语言定义所要求的这一类分析的总量变化很大。在 LISP和Smalltalki这类动态制导的语言中,可能完全没有静态语义分析:而在Ada这类语言中就 有很强的需求,程序必须提交执行。其他的语言介于这两种极端情况之间(例如Pascal语言,不 像Ada和C对静态语义分析的要求那样严格,也不像LISP那样完全设有要求)。 语义分析的第2类是由编译程序执行的分析,用以提高翻译程序执行的效率。这一类分析 通常包括对“最优化”或代码改进技术的讨论。第8章“代码生成”中将研究一些这样的方法, 而本章则集中讨论语言定义对正确性要求的一般分析。读者应该注意到,这里研究的技术对两 类情况都适用。这两类分析也不是相互排斥的,因为与没有正确性要求的语言相比,如静态类 型检查这样的正确性要求能使编译程序产生更加有效的代码。另外,值得注意的是,这里讨论 的正确性要求永远不能建立程序的完全正确性,正确性仅仅是部分的。但这样的要求仍然是有 用的,可以给编程人员提供一些信息,提高程序的安全性和有效性。 静态语义分析包括执行分析的描述(description)和使用合适的算法对分析的实现 (implementation)。在这里,它和词法及语法分析相类似。例如,在语法分析中,我们使用 Backus-.Naus范式(BNF)中的上下文无关文法描述语法结构,并用各种自顶向下和自底向上的分 析算法实现语法结构。在语义分析中,情形不是那么清晰,其部分原因是没有用标准的方法 (如BNF)来说明语言的静态语义:另一个原因是对于各种语言,静态语义分析的种类和总量的 变化范围很大。编译程序编写者过去常用的且实现得很好的一种描述语义分析方法是:确定语 言实体的属性(attribute))或特性,它们必须进行计算并写成属性等式(attribute equation)或语义规 则(semantic rule),并描述这些属性的计算如何与语言的文法规则相关。这样的一组属性和等 式称作属性文法(attribute grammar)。属性文法对遵循语法制导语义(syntax--directed semantic)原 日这一点在第3章的3.6.3节进行了较为详细的时论
下载 第6章 语 义 分 析 本章要点 • 属性和属性文法 • 数据类型和类型检查 • 属性计算算法 • TINY语言的语义分析 • 符号表 本章要研究的编译程序阶段是计算编译过程所需的附加信息。这个阶段称作语义分析, 因为它包括计算上下文无关文法和标准分析算法以外的信息,因此,它不被看成是语法 。信 息的计算也与被翻译过程的最终含义或语义密切相关。因为编译器完成的分析是静态 (它在执 行之前发生)定义的,这样,语义分析也可称作静态语义分析 (static semantic analysis)。在一 个典型的静态类型的语言 (如C语言)中,语义分析包括构造符号表、记录声明中建立的名字的 含义、在表达式和语句中进行类型推断和类型检查以及在语言的类型规则作用域内判断它们 的正确性。 语义分析可以分为两类。第 1类是程序的分析,要求根据编程语言的规则建立其正确性, 并保证其正确执行。对于不同的语言来说,语言定义所要求的这一类分析的总量变化很大。在 L I S P和S m a l l t a l k这类动态制导的语言中,可能完全没有静态语义分析;而在 A d a这类语言中就 有很强的需求,程序必须提交执行。其他的语言介于这两种极端情况之间 (例如P a s c a l语言,不 像A d a和C对静态语义分析的要求那样严格,也不像L I S P那样完全没有要求)。 语义分析的第2类是由编译程序执行的分析,用以提高翻译程序执行的效率。这一类分析 通常包括对“最优化”或代码改进技术的讨论。第 8章“代码生成”中将研究一些这样的方法, 而本章则集中讨论语言定义对正确性要求的一般分析。读者应该注意到,这里研究的技术对两 类情况都适用。这两类分析也不是相互排斥的,因为与没有正确性要求的语言相比,如静态类 型检查这样的正确性要求能使编译程序产生更加有效的代码。另外,值得注意的是,这里讨论 的正确性要求永远不能建立程序的完全正确性,正确性仅仅是部分的。但这样的要求仍然是有 用的,可以给编程人员提供一些信息,提高程序的安全性和有效性。 静态语义分析包括执行分析的描述 ( d e s c r i p t i o n )和使用合适的算法对分析的实现 ( i m p l e m e n t a t i o n )。在这里,它和词法及语法分析相类似。例如,在语法分析中,我们使用 B a c k u s - N a u s范式( B N F )中的上下文无关文法描述语法结构,并用各种自顶向下和自底向上的分 析算法实现语法结构。在语义分析中,情形不是那么清晰,其部分原因是没有用标准的方法 (如B N F )来说明语言的静态语义;另一个原因是对于各种语言,静态语义分析的种类和总量的 变化范围很大。编译程序编写者过去常用的且实现得很好的一种描述语义分析方法是:确定语 言实体的属性( a t t r i b u t e )或特性,它们必须进行计算并写成属性等式(attribute equation)或语义规 则(semantic rule),并描述这些属性的计算如何与语言的文法规则相关。这样的一组属性和等 式称作属性文法(attribute grammar)。属性文法对遵循语法制导语义(syntax-directed semantic)原 这一点在第3章的3 . 6 . 3节进行了较为详细的讨论
China-pub.com 第6章语义分析 199 下载 理的语言最有用,它表明程序的语义内容与它的语法密切相关。所有的现代语言都有这个特性。 然而,编译程序的编写者通常必须根据语言手册手工构造属性文法,因为语言设计者很少为之 提供。更糟糕的是,由于坚持语言清晰的语法结构,属性文法的构造会有不必要的复杂性。语 义计算表达式的一种更好标准是抽象语法,就像抽象语法树表示的那样。但是抽象语法树的说 明通常也由语言设计者留给了编译程序编写者。 语义分析实现的算法也不像语法分析算法那样能洁晰地表达。这部分原因也是因为在考虑 语义分析说明时,出现了刚刚提及的同样的问题。还有另外一个问题,它是由编译过程中分析 的时间选择引起的。如果语义分析可以推迟到所有的语法分析(以及抽象语法树的构造)完成之 后进行,那么实现语义分析的任务就相当容易,其本质上由指定对语法树遍历的一个顺序组成, 同时在遍历中每次遇到节点时进行计算。这就意味着编译程序必须是多遍的。另 一方面,如乐 必须要求绵译程序在一遍中完成所有的操作(包括代码生成),那么语义分析的实现就更加会变 成寻找计算语义信息的正确顺序和方法的特别的过程(假定这样的顺序实际存在)。当然,现代 的惯例越来越允许编译程序编写者使用多遍扫描简化语义分析和代码生成的过程。 尽管有点扰乱语义分析的状态,研究属性文法和规范发布仍是特别有用的,因为这能从写 出更加清晰、简练、不易出错的语义分析代码中得到补偿,同时代码也更加易懂 因此,本章从研究属性和属性文法开始。接下来是通过属性文法说明实现计算的技术,包 括推断与树的遍历相连的计算顺序。随后的两节集中于语义分析的两个主要方面:符号表和类 型检查。最后一节讲述前一章介绍的TNY编程语言的语义分析程序。 与第5章不同,本章没有包含对语义分析程序生成器(semantic analyzer generator)或构造语 义分析程序的通用工具的描述。尽管已经构造了许多这样的工具,但没有 个能得到广泛的使 用且能用于Lex或Yacc。在本章最后的“注意与参考”一节中,我们提及了几个这样的工具, 并为感兴趣的读者提供了参考文款。 6.1属性和属性文法 届性(attribute)是编程语言结构的任意特性。属性在其包含的信息和复杂性等方面变化很大, 特别是当它们能确定时翻译/执行过程的时间。属性的典型例子有: ·变量的数据类型。 ·表达式的值。 ·存储器中变量的位置 ·程序的目标代码。 ·数的有效位数。 可以在复杂的处理(甚至编译程序的构造)之前确定属性。例如,一个数的有效位数可以根 据语言的定义确定(或者至少给出一个最小值)。属性也可以在程序执行期间才确定,如(非常 数)表达式的值,或者动态分配的数据结构的位置。属性的计算及将计算值与正在讨论的语言 结构联系的过程称作属性的联编(binding)。联编属性发生时编译/快行过程的时间称作联编时间 (binding time)。不同的属性变化,甚至不同语言的相同属性都可能有完全不同的联编时间。在 执行之前联编的属性称作静态的(static),而只在执行期间联编的属性是动态的(dynamic)。对于 编译程序编写者而言,当然对那些在翻译时联编的动态属性感兴趣。 考虑先前给出的属性表的示例。我们时论表中每个属性在编译时的联编时间和重要性 ·在如C或Pascali这样的静态类型的语言中,变量或表达式的数据类型是一个重要的编译时 属性。类型检查器(type checker)是一个语义分析程序,它计算定义数据类型的所有语言
理的语言最有用,它表明程序的语义内容与它的语法密切相关。所有的现代语言都有这个特性。 然而,编译程序的编写者通常必须根据语言手册手工构造属性文法,因为语言设计者很少为之 提供。更糟糕的是,由于坚持语言清晰的语法结构,属性文法的构造会有不必要的复杂性。语 义计算表达式的一种更好标准是抽象语法,就像抽象语法树表示的那样。但是抽象语法树的说 明通常也由语言设计者留给了编译程序编写者。 语义分析实现的算法也不像语法分析算法那样能清晰地表达。这部分原因也是因为在考虑 语义分析说明时,出现了刚刚提及的同样的问题。还有另外一个问题,它是由编译过程中分析 的时间选择引起的。如果语义分析可以推迟到所有的语法分析 (以及抽象语法树的构造)完成之 后进行,那么实现语义分析的任务就相当容易,其本质上由指定对语法树遍历的一个顺序组成, 同时在遍历中每次遇到节点时进行计算。这就意味着编译程序必须是多遍的。另一方面,如果 必须要求编译程序在一遍中完成所有的操作 (包括代码生成),那么语义分析的实现就更加会变 成寻找计算语义信息的正确顺序和方法的特别的过程 (假定这样的顺序实际存在 )。当然,现代 的惯例越来越允许编译程序编写者使用多遍扫描简化语义分析和代码生成的过程。 尽管有点扰乱语义分析的状态,研究属性文法和规范发布仍是特别有用的,因为这能从写 出更加清晰、简练、不易出错的语义分析代码中得到补偿,同时代码也更加易懂。 因此,本章从研究属性和属性文法开始。接下来是通过属性文法说明实现计算的技术,包 括推断与树的遍历相连的计算顺序。随后的两节集中于语义分析的两个主要方面:符号表和类 型检查。最后一节讲述前一章介绍的T I N Y编程语言的语义分析程序。 与第5章不同,本章没有包含对语义分析程序生成器 (semantic analyzer generator)或构造语 义分析程序的通用工具的描述。尽管已经构造了许多这样的工具,但没有一个能得到广泛的使 用且能用于L e x或Ya c c。在本章最后的“注意与参考”一节中,我们提及了几个这样的工具, 并为感兴趣的读者提供了参考文献。 6.1 属性和属性文法 属性( a t t r i b u t e )是编程语言结构的任意特性。属性在其包含的信息和复杂性等方面变化很大, 特别是当它们能确定时翻译/执行过程的时间。属性的典型例子有: • 变量的数据类型。 • 表达式的值。 • 存储器中变量的位置。 • 程序的目标代码。 • 数的有效位数。 可以在复杂的处理(甚至编译程序的构造)之前确定属性。例如,一个数的有效位数可以根 据语言的定义确定 (或者至少给出一个最小值 )。属性也可以在程序执行期间才确定,如 (非常 数)表达式的值,或者动态分配的数据结构的位置。属性的计算及将计算值与正在讨论的语言 结构联系的过程称作属性的联编( b i n d i n g )。联编属性发生时编译/执行过程的时间称作联编时间 (binding time)。不同的属性变化,甚至不同语言的相同属性都可能有完全不同的联编时间。在 执行之前联编的属性称作静态的( s t a t i c ),而只在执行期间联编的属性是动态的( d y n a m i c )。对于 编译程序编写者而言,当然对那些在翻译时联编的动态属性感兴趣。 考虑先前给出的属性表的示例。我们讨论表中每个属性在编译时的联编时间和重要性。 • 在如C或P a s c a l这样的静态类型的语言中,变量或表达式的数据类型是一个重要的编译时 属性。类型检查器(type checker)是一个语义分析程序,它计算定义数据类型的所有语言 第 6章 语 义 分 析 1 9 9 下载
200 编译原理及实践 China-pub.co 下载 实体的数据类型属性,并验证这些类型符合语言的类型规则。在如C或Pascali这样的语言 中,类型检查是语义分析的一个重要部分。而在LISP这样的语言中,数据类型是动态的, LSP编译程序必须生成代码来计算类型,并在程序执行期间完成类型检查。 ·表达式的值通常是动态的,编译程序要在执行时生成代码来计算这些值。然而事实上 一些表达式可能是常量(例如3+4*5),语义分析程序可以选择在编译时求出它们的值(这 FORTRAN77中所有的变量都是静态分配的,而在LISP中所有的变量是动态分配的。C和 Pascali语言混合了静态和动态的两种变量分配。因为编译程序与变量分配联系的计算依 赖于运行时环境,有时还依赖于具体的目标机器,所以这些计算会一直推迟到代码生成 (第7章将更详细地探讨这一问题)。 ·程序的目标代码无疑是一个静态属性。编译程序的代码生成器专门用于这个属性的计算。 ·数的有效位数在编译期间是一个不被明确探讨的属性。编译程序编写者实现值的表示是 不言而喻的,这通常被视为运行时环境的一部分,这将在第7章中讨论。 然而,甚至扫描 器也需要知道允许的有效位数并判断是否正确转换了常量。 正如从这些例子中看到的,届性计算变化极大。当它们在绵译程序中显式出现时,可能在 编译过程的任意时刻发生:即使语义分析阶段与属性计算的联系最紧密,扫描器和语法分析程 序也都需要对它们有用的属性信息,在语法分析的同时也需要进行一些语义分析。在本章中, 我们集中讨论在代码生成前及语法分析后的典型计算(语法分析期间的语义分析信息见6.2.5 节)。直接应用于代码生成的属性分析在第8章中讨论。 6.1.1属性文法 在语法制导语义(syntax--directed semantics))中,属性直接与语言的文法符号相联系(终结符 号或非终结符号)⊙。如果X是一个文法符号,a是X的一个属性,那么我们把与X关联的的值 记作X.a。这个记号让人回忆起Pascali语言的记录字段表示符或(等价于)C语言中的结构成员操 作符。实际上,实现属性计算的一种典型方法是使用记录字段(或结构成员)将属性值放到语法 树的节点中去。下一节将更详细地讨论这一点。 若有一个性的集合a ,,语法制导语义的原理应用于每个文法规则X。一XX (这里X是一个非终结符号,其他的X都是任意符号),每个文法符号X的属性X.口的值与规则 中其他符号的属性值有关。如果同一个符号X在文法规则中出现不止一次,那么每次必须用合 适的下标与在其他地方出现的符号区分开来。每个关系用属性等式()或语义规 则(semantics rule)e表示,形式如下 Xa=f(X。a,,X。ayXa,,Xa,,Xa,,Xa) 这里的f是一个数学函数。属性a,,,a,的属性文法(attribute grammar)是对语言的所有文法 规则的所有这类等式的集合。 在这个一般性情况中,属性文法显得相当复杂。在实际情况下,函数通常非常简单。属 性也很少依赖于大量的其他属性,因此可以将相互依赖的属性分割为较小的独立属性集,并对 语法制导酒义可以简单地称作语义制导语法(semantics-direeted syntax)),因为在大多数语言中语法是用已经 在头脑中建立的(最终)语义设 。后面我们将看到语义规则比属性等式更加通用一些。这里读者可以先把它们看成是等效的
实体的数据类型属性,并验证这些类型符合语言的类型规则。在如 C或P a s c a l这样的语言 中,类型检查是语义分析的一个重要部分。而在 L I S P这样的语言中,数据类型是动态的, L I S P编译程序必须生成代码来计算类型,并在程序执行期间完成类型检查。 • 表达式的值通常是动态的,编译程序要在执行时生成代码来计算这些值。然而事实上, 一些表达式可能是常量 (例如3 + 4 * 5 ),语义分析程序可以选择在编译时求出它们的值 (这 个过程称作常量合并(constant folding))。 • 变量的分配可以是静态的也可以是动态的,这依赖于语言和变量自身的特性。例如,在 F O RT R A N 7 7中所有的变量都是静态分配的,而在 L I S P中所有的变量是动态分配的。C和 P a s c a l语言混合了静态和动态的两种变量分配。因为编译程序与变量分配联系的计算依 赖于运行时环境,有时还依赖于具体的目标机器,所以这些计算会一直推迟到代码生成 (第7章将更详细地探讨这一问题)。 • 程序的目标代码无疑是一个静态属性。编译程序的代码生成器专门用于这个属性的计算。 • 数的有效位数在编译期间是一个不被明确探讨的属性。编译程序编写者实现值的表示是 不言而喻的,这通常被视为运行时环境的一部分,这将在第 7章中讨论。然而,甚至扫描 器也需要知道允许的有效位数并判断是否正确转换了常量。 正如从这些例子中看到的,属性计算变化极大。当它们在编译程序中显式出现时,可能在 编译过程的任意时刻发生:即使语义分析阶段与属性计算的联系最紧密,扫描器和语法分析程 序也都需要对它们有用的属性信息,在语法分析的同时也需要进行一些语义分析。在本章中, 我们集中讨论在代码生成前及语法分析后的典型计算 (语法分析期间的语义分析信息见 6 . 2 . 5 节)。直接应用于代码生成的属性分析在第8章中讨论。 6.1.1 属性文法 在语法制导语义(syntax-directed semantics)中,属性直接与语言的文法符号相联系 (终结符 号或非终结符号) 。如果X是一个文法符号,a 是X的一个属性,那么我们把与 X关联的a的值 记作X.a。这个记号让人回忆起 P a s c a l语言的记录字段表示符或 (等价于) C语言中的结构成员操 作符。实际上,实现属性计算的一种典型方法是使用记录字段 (或结构成员)将属性值放到语法 树的节点中去。下一节将更详细地讨论这一点。 若有一个属性的集合a1 , . . . , ak ,语法制导语义的原理应用于每个文法规则X0→X1 X2 . . . X n (这里X0 是一个非终结符号,其他的Xi 都是任意符号),每个文法符号Xi 的属性Xi .aj 的值与规则 中其他符号的属性值有关。如果同一个符号 Xi 在文法规则中出现不止一次,那么每次必须用合 适的下标与在其他地方出现的符号区分开来。每个关系用属性等式 (attribute equation)或语义规 则(semantics rule) 表示,形式如下 Xi .aj = f i j (X0 .a1 , . . . , X0 .ak ,X1 .a1 , . . . , X1 .ak , . . . , Xn .a1 , . . . , Xn .ak ) 这里的f i j 是一个数学函数。属性a1 , . . . , ak 的属性文法(attribute grammar)是对语言的所有文法 规则的所有这类等式的集合。 在这个一般性情况中,属性文法显得相当复杂。在实际情况下,函数 f i j 通常非常简单。属 性也很少依赖于大量的其他属性,因此可以将相互依赖的属性分割为较小的独立属性集,并对 2 0 0 编译原理及实践 下载 语法制导语义可以简单地称作语义制导语法 (semantics-directed syntax),因为在大多数语言中语法是用已经 在头脑中建立的(最终)语义设计的。 后面我们将看到语义规则比属性等式更加通用一些。这里读者可以先把它们看成是等效的
China-pub.com 下载 第6章语义分析 201 每个属性集单独写出一个属性文法。 一般地,将属性文法写成表格形式,每个文法规则用属性等式的集合或者相应规则的语义 规则列出,如下所示⊙ 文法规则 语义规则 规则1 相关的属性等式 规则n 相关的属性等式 接下来继续看几个例子。 例6.1考虑下面简单的无符号数文法 number-number digit digit digt→0111213141516171819 一个数最重要的属性是它的值,我们将其命名为vl。每个数字都有一个值,可以用它表示的 实际数直接计算。因此,例如,文法规则dg1一0表明在这个情况下dgt的值为0。这可以用 属性等式digit.val=0表示,我们将这个等式和规则digi一0联系在一起。此外,每个数都有 个基于它所包含的数字的值。如果一个数使用了下面的规则推导 mber→digit 那么这个数就只包含了一个数字,其值就是这个数字的值。用属性等式表示为 number.val =digit.val 如果一个数包含的数字多于1个,可以使用下列文法规则推导 mumber→number digit 我们必须表示出这个文法规则左边符号的值和右边符号的值之间的关系。请读者注意,在这个 文法规则中对number的两次出现必须进行区分,因为右边的number和左边的numbere的值不相 同。我们使用下标进行区分,将这个文法写成如下形式: number,→umber,digit 现在考虑一个数,如34。这个数的(最左)推导如下:mumber一number digit→digit digit→3 digit一34。考虑在这个推导的第一步文法规则number,→number:digit的使用。非终结符号 mumber,对应于数字3,digit对应于数字4。每个符号的值分别是3和4。为了获得number的值 (它为34),必须用nmbe,的值乘以10,再加上dg的值:34=3*10+4.换句话说,是把3左 移一个十进制位再加上4。相应的属性等式是 number,val number,val*10+digit.val 完整的ral属性文法在表6-1中给出。 使用字符串的语法树可以形象化地表示特殊字符串的属性等式的意义。例如,图6-1给出 了数345的语法树。在这个图中相应合适的属性等式的计算显示在每个内部节点的下面。在语 日这些表中通常用表头“语义规则”代替“属性等式”,以便后面对语义规则进行更通用的解释
每个属性集单独写出一个属性文法。 一般地,将属性文法写成表格形式,每个文法规则用属性等式的集合或者相应规则的语义 规则列出,如下所示 : 文 法 规 则 语 义 规 则 规则1 相关的属性等式 . . . . . . 规则n 相关的属性等式 接下来继续看几个例子。 例6.1 考虑下面简单的无符号数文法: number → number digit | d i g i t digit →0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 一个数最重要的属性是它的值,我们将其命名为 v a l。每个数字都有一个值,可以用它表示的 实际数直接计算。因此,例如,文法规则 d i g i t→0 表明在这个情况下digit 的值为0。这可以用 属性等式digit.val = 0 表示,我们将这个等式和规则d i g i t→0 联系在一起。此外,每个数都有一 个基于它所包含的数字的值。如果一个数使用了下面的规则推导 number → d i g i t 那么这个数就只包含了一个数字,其值就是这个数字的值。用属性等式表示为 n u m b e r.val = d i g i t . v a l 如果一个数包含的数字多于1个,可以使用下列文法规则推导 number → number digit 我们必须表示出这个文法规则左边符号的值和右边符号的值之间的关系。请读者注意,在这个 文法规则中对number 的两次出现必须进行区分,因为右边的 number 和左边的n u m b e r的值不相 同。我们使用下标进行区分,将这个文法写成如下形式: n u m b e r1 →n u m b e r2 d i g i t 现在考虑一个数,如3 4。这个数的(最左)推导如下:number Þ number digit Þ digit digit Þ 3 digit Þ 3 4。考虑在这个推导的第一步文法规则 n u m b e r 1 →n u m b e r 2 digit 的使用。非终结符号 n u m b e r2 对应于数字3,digit 对应于数字4。每个符号的值分别是3和4。为了获得n u m b e r1 的值 (它为3 4 ),必须用n u m b e r2 的值乘以1 0,再加上digit 的值:34 = 3*10+4。换句话说,是把3左 移一个十进制位再加上4。相应的属性等式是 n u m b e r1 .val = n u m b e r2 .v a l * 10 + d i g i t . v a l 完整的val 属性文法在表6 - 1中给出。 使用字符串的语法树可以形象化地表示特殊字符串的属性等式的意义。例如,图 6 - 1给出 了数3 4 5的语法树。在这个图中相应合适的属性等式的计算显示在每个内部节点的下面。在语 第 6章 语 义 分 析 2 0 1 下载 这些表中通常用表头“语义规则”代替“属性等式”,以便后面对语义规则进行更通用的解释
202 编译原理及实践 China-pub.co 下载 法树中计算时观察属性等式对于计算属性值的算法是重要的,就像在下一节将看到的那样⊙。 在表6-1和图6-1中,通过使用不同的字体,我们强调了数字和值的语法表示或者数字语义 内容之间的不同。例如在文法规则dig1一0中,数字0是一个记号或特性,而digit.val=0的含 义是数字的数值为0。 表6-1例6.1的属性文法 文法规则 语义规则 Number,→number,digit number..val numberval 10+digit.val Number-一digit numberval digit.val -0 digit.val-0 digit -2 digit.val =2 digit-3 digit.val =3 dhgi→4 digit.val =4 digit.val -5 -6 digit.val-6 digit.val -7 igr→8 digit.val =8 gt→g digit.val=9 0a1-3407095=345 0al-30r4=30 (val =5) (l 3) ( (val =3) 图6-1显示例6.1中属性计算的语法树 例6.2考虑下列简单的整数算术表达式文法: exp exp term exp -term term term-term factor|factor factor→(ep number 这个文法对第5章广泛讨论的简单表达式文法稍微作了一些改动。 exp(或iem或factor)的基本属 性是它的数字值,写作ral。val属性的届性等式在表6-2中给出。 日事实上,扫描器通常认为数是标记,它们的数值也很容易计算。在此期间,扫指器很可能隐含地使用这里定 义的属性等式
法树中计算时观察属性等式对于计算属性值的算法是重要的,就像在下一节将看到的那样 。 在表6 - 1和图6 - 1中,通过使用不同的字体,我们强调了数字和值的语法表示或者数字语义 内容之间的不同。例如在文法规则 d i g i t→0 中,数字0是一个记号或特性,而d i g i t . v a l = 0的含 义是数字的数值为0。 表6-1 例6 . 1的属性文法 文 法 规 则 语 义 规 则 N u m b e r1 → n u m b e r2 d i g i t n u m b e r1 .val = n u m b e r 2 .val * 10 + d i g i t.v a l Number → d i g i t n u m b e r.val = d i g i t . v a l digit → 0 digit.val = 0 digit → 1 digit.val = 1 digit → 2 digit.val = 2 digit → 3 digit.val = 3 digit → 4 digit.val = 4 digit → 5 digit.val = 5 digit → 6 digit.val = 6 digit → 7 digit.val = 7 digit → 8 digit.val = 8 digit → 9 digit.val = 9 图6-1 显示例6 . 1中属性计算的语法树 例6.2 考虑下列简单的整数算术表达式文法: exp → exp + t e r m | exp - t e r m | t e r m t e r m → t e r m * f a c t o r | f a c t o r f a c t o r →(e x p)| n u m b e r 这个文法对第5章广泛讨论的简单表达式文法稍微作了一些改动。 e x p(或t e r m或f a c t o r)的基本属 性是它的数字值,写作v a l。val 属性的属性等式在表6 - 2中给出。 2 0 2 编译原理及实践 下载 事实上,扫描器通常认为数是标记,它们的数值也很容易计算。在此期间,扫描器很可能隐含地使用这里定 义的属性等式