正在加载图片...
206 编译原理及实践 China-pub.Co 下载 正确的,但不能赋予任何值。因此,对于这些情况需要一个新的r值。另外,这个属性文法 必须能表示这样的事实,一个带有后缀o的数中包括数字8或9时将导致值为ror。最简单的方 法是在合适的属性等式函数中使用if.then-else表达式。例如,等式 num .val if digit.val=error or num,val=error then error else num,val*num,base +digit.val 对应于文法规则nm,一nm,digit,表示如果um,.val或digit.val为eor,那么num,-ral也必须为 error,除此之外只有一种情况:m,ra的值由公式um,ral*um,base+digit.val给出。 总结这个例子,再在一个语法树上表示属性计算。图6-4给出了数3450的语法树,同时根 据表64的属性文法计算出属性值。 6.1.2属性文法的简化和扩充 if-then-else表达式的使用扩充了表达式的种类,它们可以通过有用的途径出现在属性等式 中,在属性等式中,允许出现的表达式的集合称作属性文法的元语言(metalanguage)。通常我 们希塑元语言的内酒尽可能清晰,不致于引起其自身语义的混淆。我们还希望元语言接近于 种实际使用的编程语言,因为就像我们即将看到的一样,在语义分析程序中需要把属性等式转 换成执行代码。在本书中,我们使用的元语言局限于算术式、逻辑式以及一些其他种类的表达 式,再加上if-then-else表达式,偶尔还有case或switch表达式。 定义属性等式的另一个有用的特征是在元语言中加入了函数的使用,函数的定义可以在别 处给出。例如,在数的文法中,我们对g的每个选择都写出了属性等式。可以采用一个更简 洁的惯例来代替,为dig1写一个文法规则digi→D(这里D是数字中的一个),相应的属性等式是 digit.al=nval(D) 这里umyal是函数,必须在别处说明其作为属性文法的补充的定义。例如,我们可以用C代码 给出nmva的定义: int numval char D) return (int)D-(int)'0':】 在说明属性文法时更简化的有用方法是使用原始文法二义性的但简单的形式。事实上,因 为假定已经构造了分析程序,所有二义性在那个阶段都己经处理过了,属性文法可以自由地基 于二义性概念,而无须在结果属性中说明任何二义性,例如,例62的算术表达式文法有以下 简单的但二义性的形式: exp-exp+expl exp-exp l exp exp exp number 使用这个文法,属性a可以通过表6-5中的表定义(与表6-2相比较)。 表6-5使用二义性文法定义表达式的va属性 文法规则 语义规则 p,→p,+p exp val exp,val exp.val cxp,→ep-ep, exp,val-exp,val-exp,vat ep,一ep*cp, expval -exp,val*exp val exp.(ep) exp,val=exp,val cp number exp.val-number.val正确的,但不能赋予任何值。因此,对于这些情况需要一个新的 e rro r值。另外,这个属性文法 必须能表示这样的事实,一个带有后缀 o的数中包括数字8或9时将导致值为e rro r。最简单的方 法是在合适的属性等式函数中使用i f - t h e n - e l s e表达式。例如,等式 n u m1 .val = i f d i g i t . v a l = e rro r o r n u m2 .v a l = e rro r then e rro r e l s e n u m2 .v a l * n u m1 .b a s e + d i g i t . v a l 对应于文法规则n u m1 →n u m2 d i g i t,表示如果n u m2 .v a l或d i g i t . v a l为e rro r,那么n u m1 .v a l也必须为 e rro r,除此之外只有一种情况:n u m1 .v a l的值由公式n u m2 .val * n u m1 .base + d i g i t . v a l给出。 总结这个例子,再在一个语法树上表示属性计算。图 6 - 4给出了数3 4 5 o的语法树,同时根 据表6 - 4的属性文法计算出属性值。 6.1.2 属性文法的简化和扩充 i f - t h e n - e l s e表达式的使用扩充了表达式的种类,它们可以通过有用的途径出现在属性等式 中,在属性等式中,允许出现的表达式的集合称作属性文法的元语言 ( m e t a l a n g u a g e )。通常我 们希望元语言的内涵尽可能清晰,不致于引起其自身语义的混淆。我们还希望元语言接近于一 种实际使用的编程语言,因为就像我们即将看到的一样,在语义分析程序中需要把属性等式转 换成执行代码。在本书中,我们使用的元语言局限于算术式、逻辑式以及一些其他种类的表达 式,再加上i f - t h e n - e l s e表达式,偶尔还有c a s e或s w i t c h表达式。 定义属性等式的另一个有用的特征是在元语言中加入了函数的使用,函数的定义可以在别 处给出。例如,在数的文法中,我们对digit 的每个选择都写出了属性等式。可以采用一个更简 洁的惯例来代替,为digit 写一个文法规则d i g i t →D (这里D是数字中的一个),相应的属性等式是 d i g i t . v a l = numval (D) 这里n u m v a l是函数,必须在别处说明其作为属性文法的补充的定义。例如,我们可以用 C代码 给出n u m v a l的定义: int numval ( char D) { return (int)D-(int)'0';} 在说明属性文法时更简化的有用方法是使用原始文法二义性的但简单的形式。事实上,因 为假定已经构造了分析程序,所有二义性在那个阶段都已经处理过了,属性文法可以自由地基 于二义性概念,而无须在结果属性中说明任何二义性,例如,例 6 . 2的算术表达式文法有以下 简单的但二义性的形式: exp → exp + exp | exp - exp | exp * exp | ( exp ) | n u m b e r 使用这个文法,属性v a l可以通过表6 - 5中的表定义(与表6 - 2相比较)。 表6-5 使用二义性文法定义表达式的 v a l属性 文 法 规 则 语 义 规 则 e x p1 → e x p2 + e x p3 e x p1 .v a l = e x p2 .v a l + e x p3 .v a l e x p1 → e x p2 - e x p3 e x p1 .v a l = e x p2 .v a l - e x p3 .v a l e x p1 → e x p2 * e x p3 e x p1 .v a l = e x p2 .v a l * e x p3 .v a l e x p1 → ( e x p2 ) e x p1 .v a l = e x p2 .v a l exp → n u m b e r e x p.v a l = n u m b e r.val 2 0 6 编译原理及实践 下载
<<向上翻页向下翻页>>
©2008-现在 cucdc.com 高等教育资讯网 版权所有