属性文法——S属性文法、L属性文法/语法制导定义SDD

属性文法是在上下文无关文法的基础上为每个文法符号(终结符或非终结符)配备若干个相关的“值”(称为属性)。这些属性代表与文法符号相关的信息,例如它的类型、值、代码序列 、符号表内容等等。属性和变量一样,可以进行计算和传递。

属性一般分为两类:

  • 综合属性:用于“自下而上”传递信息。在语法树中,一个结点的综合属性的值由其子结点或其自身的某些属性值确定。
  • 继承属性:用于“自上而下”传递信息。在语法树中,一个结点的继承属性值由该结点的父结点、兄弟结点和其自身的某些属性值确定。

注意:

  1. 终结符只有综合属性,由词法分析器提供
  2. 非终结符既可以有综合属性也可以有继承属性
  3. 文法开始符号的所有继承属性作为属性计算前的初始值

属性传递和计算的过程即是语义处理的过程,其相应的规则就称为语义规则。

语法制导定义(Syntax-Directed Definition, SDD):

  • 每个文法符号和一个属性(attribute)集合相关联
  • 每个产生式和一组语义规则(semantic rules)相关联,这些规则用于计算与该产生式中符号相关联的属性值

翻译方案(Translation Scheme):根据语义处理的先后顺序,把语义动作(程序片段)嵌入到产生式右部的合适位置。

  • 属性的类型(综合/继承)表达了语义信息传递的方向
  • 语义动作的位置表达了语义信息传递的时机(先后顺序)

树遍历的属性计算方法

以某种次序遍历语法树,直至计算出所有的属性。这种方法最简单,适应面最广。

缺点:

  • 必须在语法树建立之后才能使用
  • 效率不高
  • 对每个非终结符号:多次重复计算所有能够计算的继承属性,最后计算所有能够计算的综合属性

一遍扫描的处理方法

在语法分析的同时计算属性值,处理完一个语法单位就执行与之相关的语义处理。

一遍扫描的语法制导翻译:为文法中每个产生式配上一组语义规则,在语法分析的同时执行这些语义规则。

计算语义规则,完成有关语义分析和代码生成动作的时机

  • 自上而下分析中一个产生式匹配输入串成功时
  • 自下而上分析中一个产生式被用于进行归约时

S-属性文法

只含有综合属性的属性文法。

L-属性文法

在这里插入图片描述
L-属性文法支持从上到下、从下到上、从左到右的边。

例题

在这里插入图片描述
首先用S-属性文法处理的结果:

在这里插入图片描述

然后用L-属性文法处理的结果:

在这里插入图片描述

  • 9
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
L属性定义的自上而下计算方法是一种基于语法分析树的计算方法。它的原理是将表达式转换为语法分析树,然后按照 L属性文法定义,从根节点开始递归地计算属性值,最终得到整个表达式的值。 步骤如下: 1. 定义 L属性文法,其中每个非终结符都有一个属性(通常是值或类型),并按照计算顺序将属性计算为子节点属性的函数形式表示。 2. 将表达式转换为语法分析树,其中每个节点是一个操作符或操作数,每个叶子节点都是一个操作数。 3. 从根节点开始递归地计算属性值,按照 L属性文法中每个非终结符的定义计算属性值。计算属性值时,需要先计算子节点的属性值,然后根据函数形式计算当前节点的属性值。 4. 最终得到整个表达式的值,即根节点的属性值。 具体来说,以表达式 "2+3*4" 为例,其语法分析树如下所示: ``` + / \ 2 * / \ 3 4 ``` 根据 L属性文法定义,可以定义如下属性计算函数: - 对于叶子节点,其属性值为节点的值。 - 对于加号节点,其属性值为左子节点的属性值加上右子节点的属性值。 - 对于乘号节点,其属性值为左子节点的属性值乘以右子节点的属性值。 按照上述步骤,我们可以实现 L属性定义的自上而下计算方法的计算器。实现过程中,需要先将表达式转换为语法分析树,然后从根节点开始递归地计算属性值。具体实现可以参考下面的代码: ```python class Node: def __init__(self, value, left=None, right=None): self.value = value self.left = left self.right = right class Calculator: def __init__(self): pass def calculate(self, expression): root = self.build_tree(expression) return self.calculate_property(root) def build_tree(self, expression): # 将表达式转换为语法分析树 # ... return root def calculate_property(self, node): if node.left is None and node.right is None: # 对于叶子节点,其属性值为节点的值 return int(node.value) elif node.value == '+': # 对于加号节点,其属性值为左子节点的属性值加上右子节点的属性值 return self.calculate_property(node.left) + self.calculate_property(node.right) elif node.value == '*': # 对于乘号节点,其属性值为左子节点的属性值乘以右子节点的属性值 return self.calculate_property(node.left) * self.calculate_property(node.right) ``` 在实现过程中,需要注意如何将表达式转换为语法分析树,以及如何递归地计算属性值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花无凋零之时

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值