我想知道LR归因解析器可以做什么以及如何实现它。
当属性的源是使用$ 0,$ -1等规范语法位于左侧的兄弟时,yacc生成的解析器允许继承的属性。使用S -> A B
B将能够从A继承合成属性,但无法从S继承某些内容。我认为这是通过向下查看堆栈中B的1个元素来完成的。
现在zyacc doc says他们允许LR属性语法,我猜这或多或少与yacc允许的相同。只有使用zyacc时,这些属性才会使用非终结符(如参数)指定,而不仅仅是在语义操作中访问。是否有任何其他差异,如LR属性比yacc继承的属性更强大,或者像LR属性以不同的方式实现(不只是向下看堆栈)。
答案 0 :(得分:1)
LR归因于语法的要点是使信息在左上下文中看到, 适用于正确的扩展名。
想象一下你的语法
R -> X S Y;
S -> A B;
你已经同意S可以看到从X合成的属性。实际上,这些属性可以在完成X的解析时可用。正确完成后,这些属性应该可用于A和B,因为它们被解析,作为S的继承属性。
根据我的知识,YACC没有实现任何这些,除非你想将X的解析树的存在计算为解析X的“合成”属性。
如何实现属性语法取决于您想要做什么。我公司的主要产品DMS使用属性语法,没有方向限制。我们只需构建完整的树并根据需要传播属性。
我们所做的是为每个节点类型预先计算它可以继承的属性集[及其类型],以及它可以合成的集合,并为每个节点合成一个结构。在属性评估时,这些结构通过非常快速的访问哈希表与树节点相关联。对于每个节点类型,我们检查数据流(哪个子节点使用哪个继承属性,哪些子节点使用其他子节点的合成属性)。由此我们计算执行顺序,使所有属性在安全(生成前消耗)顺序中计算,并为该节点类型生成一个过程来完成此操作,该类型调用子过程。然后,属性评估包括调用语法根的生成过程。 (实际上,我们实际上生成了一个用于评估子节点的部分顺序,并使用DMS的实现并行编程语言的功能生成部分顺序并行调用,确保在非常大的AST上使用多个内核进行快速评估)。
没有任何理由可以将此过程限制为LR属性。 (总有一天我们会将LR兼容的属性推入解析阶段,以允许它们用于语义检查)。
生成属性评估过程的设备本身就是一个对语法进行操作的属性评估器,这一点不应该让您感到惊讶。引导有点儿有趣。