2

我想知道 LR 属性解析器可以做什么以及它是如何实现的。

当属性的源是使用 $0、$-1 等规范语法位于左侧的同级时,yacc 生成的解析器允许继承属性。使用S -> A BB 将能够从 A 继承综合属性,但不能从 S 继承某些东西。我认为这是通过从堆栈中的 B 中向下查找 1 个元素来完成的,该元素将是 A。

现在 zyacc doc他们允许 LR 属性语法,我猜这与 yacc 允许的或多或少相同。只有 zyacc 的那些属性是用非终结符(如参数)指定的,而不仅仅是在语义操作中访问。是否还有其他区别,例如 LR 属性比 yacc 继承的属性更强大,或者 LR 属性的实现方式不同(不仅仅是向下查看堆栈)。

4

1 回答 1

1

LR 属性文法的要点是使在左侧上下文中看到的信息可用于右侧扩展。

想象一下你的语法有

      R -> X S Y;
      S -> A B;

您已经同意 S 可以看到从 X 合成的属性。事实上,这些属性可以在 X 的解析完成时使用。如果处理得当,这些属性应该对 A 和 B 可用,因为它们被解析,作为继承来自 S 的属性。

据我所知,YACC 没有实现任何这些,除非您想将 X 的解析树的存在算作解析 X 的“综合”属性。

你如何实现属性语法取决于你想要做什么。我公司的主要产品 DMS 大量使用属性语法,没有方向限制。我们只需构建完整的树并根据需要传播属性。

我们所做的是预先计算,对于每个节点类型,它可能继承的属性集[及其类型],以及它可能合成的集合,并为每个节点合成一个结构。在属性评估时,这些结构通过一个非常快速的访问哈希表与树节点相关联。对于每个节点类型,我们检查数据流(哪个孩子使用哪个继承的属性,哪些孩子使用来自其他孩子的综合属性)。从中我们计算执行顺序,以使所有属性以安全(在使用前生成)顺序计算,并为该节点类型生成一个过程来完成此操作,该过程称为子过程。然后,属性评估包括为语法根调用生成的过程。(实际上,我们实际上是生成了一个偏序用于评估孩子,并使用 DMS 的实现并行编程语言的功能生成部分顺序并行调用,确保在非常大的 AST 上使用多个内核进行快速评估)。

没有任何理由不能将此过程限制为 LR 属性。(有一天,我们会将与 LR 兼容的属性推入解析阶段,以允许它们在语义检查中使用)。

生成属性评估过程的设备本身就是一个对语法进行操作的属性评估器,这不足为奇。自举有点有趣。

于 2013-06-15T15:05:21.813 回答