Skip to content

Syntax-Direted Translation Handout

这篇文章文章总结的是龙书的语法制导翻译的章节,个人认为制导这个词加深了我对这个过程的误解,根据直译,我觉得应该翻译成“语法指导”的翻译过程,即文法-语法树为翻译过程提供了启发、提供了基础更加的合适。

这个过程按照书上的来说,是把一些属性附加到代表语言构造的文法符号上,从而把信息和一个语言构造联系起来。简单而言就是将需要的信息附加到书上,对树遍历产生信息,再对信息使用总结产生翻译的结果。

语法制导定义 属性的概念

语法制导的定义(Syntax-Directed Definition, SDD) 是一个上下文无关文法属性和规则的集合,简单而言 SDD 就是文法加上属性。

对于非终结符号而言,有两种属性:

  • 综合属性:顾名思义是从其他子节点综合各种属性得到的属性,用图的观点来看,综合属性依赖于子节点,综合属性往往通过访问子节点的各种属性得到,方向是从子节点到父节点。
  • 继承属性:顾名思义是从父节点或者兄弟节点得到的属性,用图的观点来看,继承属性依赖于父节点与各个兄弟节点的属性,方向是从父节点或者兄弟节点到当前的节点。

看到这个的时候很容易简单的想象,综合属性的获取是对子节点的递归完成之后进行计算的属性,而继承属性是对子节点进行之前应该赋值得到的属性。终结符被定义为只有继承属性,属性值直接在词法分析的时候就被指定了。

S 属性的 SDD

对于一个只包含综合属性的 SDD 称之为 S 属性的 SDD。根据对综合属性的概念理解,很简单的就可以想到 S 属性的 SDD 可以很好的和 LR 分析器进行配合,毕竟这两个都是自底向上的。有时候在计算属性的时候可能会调用一些函数,这些函数有或者没有产生副作用。对没有副作用的 SDD 称之为属性文法。一个属性文法的规则仅仅通过其他属性值和常量值来定义属性值。

在语法分析树的节点上对 SDD 求值

一个显示了各个属性值的语法分析树被称为 注释语法分析树。对于这种树上的求值过程一般只要不要产生依赖,就是可以求出来的。但是不能保证一个 SDD 不会产生循环的依赖。因此不是对于每个 SDD 都有一个求值的方案,我们只对一类特殊的子集有求值方案,但是这类子集足以覆盖掉编程语言的大多数场景。

SDD 的求值顺序

无论是什么属性的 SDD,对于这种求属性的计算而言,只要不产生循环的依赖,就有办法通过一定顺序将数据求出来。

S 属性 SDD 的定义

对于 SDD 中每个节点的属性都是综合属性的,称为 S 属性的 SDD,显而易见的,对于这种 SDD 的顺序是要自底向上的,因此这种 SDD 肯定是能和 LR 分析器的移入规约进行配合的。

L 属性 SDD 的定义

对于 SDD 中的每个节点,属性都是综合的,或者使用的继承属性只能来自自己左边的节点,称之为 L 属性的 SDD 定义,显而易见的,对于这种 SDD 的顺序是要自顶向下的,从顶得到继承属性计算,向顶返回综合属性供顶使用。这个过程可以和 LL 分析器配合使用,但是令人惊奇的是,和 LR 分析器也能配合使用。

语法制导翻译的应用

即对于节点附加属性之后,我们能用这种附加属性节点做到什么事。

抽象语法树的构造

抽象语法树不同于之前的语法分析书。这两个本质上应该是一个东西,语法分析书更加侧重于对于语法解析的全过程的解析,抽象分析树更加侧重于对属性的利用。实际上在编译的过程中不会真正的生成一棵树,这棵树只是放在心里作为翻译的指导而已。

对于类型的构造

利用语法指导的翻译,附加了属性之后能够获得更多的上下文信息。比如说一个数组的元素大小,可以通过子节点的综合属性进行推算。

语法制导的翻译方案

语法制导的翻译方案(syntax-directed translation scheme, SDT)是在产生式体中嵌入了程序片段的上下文无关文法,简单的来说就是利用 SDD 中的各种属性,加入点 print 生成代码。

对于 S 属性的 SDD,其 SDT 能够和移入规约配合,使用后缀翻译方案实现。

L 属性的 SDD 的实现

  • 直接在递归下降中实现,即接受继承属性作为参数,向上级返回综合属性,这个过程涉及字符串的拼接,是效率低的
  • 边扫描边生成代码,和上面差不多,只是不回传字符串了,直接打印
  • 和 LL 分析器配合
  • 和 LR 分析器配合