属性文法的概念
-
属性文法,也称为属性翻译文法
-
以上下文无关文法为基础
- 为每个文法符号(终结符或非终结符)配备若干相关的”值“(成为属性),代表与文法符号相关信息,如类型、值、代码序列、符号表内容等
举例:
- 对于文法的每个产生式都配备了一组属性的语义规则,对属性进行计算和传递
- 属性包括综合属性和继承属性
- 综合属性
- 自下而上传递信息
- 语法规则:根据右部候选式中的符号的属性计算左部被定义符号的综合属性
- 语法树:根据子结点的属性和父结点自身的属性计算父结点的综合属性
- 继承属性
- 自上而下传递信息
- 语法规则:根据右部候选式中的符号的属性和左部被定义符号的属性计算右部候选式中的符号的继承属性
- 语法树:根据父结点和兄弟结点的属性计算子节点的继承属性
- 综合属性
- 为每个文法符号(终结符或非终结符)配备若干相关的”值“(成为属性),代表与文法符号相关信息,如类型、值、代码序列、符号表内容等
-
属性依赖
- 对应于每个产生式A->α都有一套与之相关联的语义规则,每条规则的形式为(f是一个函数):b:=f(C1,C2,…,CK)
- 属性b依赖于属性C1,C2,…,CK
- b是A的一个综合属性并且C1,C2,…,CK是产生式右边文法符号的属性,
- 或者b是产生式右边某个文法符号的一个继承属性并且C1,C2,…,CK是A或产生式右边任何文法符号的属性
- 终结符只有综合属性,由词法分析器提供
- 非终结符既可有综合属性也可有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值
-
语义规则
- 对出现在产生式右边的继承属性和出现在产生式左边的综合属性都必须提供一个计算规则。属性计算规则中只能使用相应产生式中的文法符号的属性
- 出现在产生式左边的继承属性和出现在产生式右边的综合属性不由所给的产生式的属性计算规则进行计算,由其他产生式的属性规则计算或者由属性计算器的参数提供
- 语义规则所描述的工作可以包括属性计算,静态语义检查,符号表操作,代码生成等。
举例
属性计算
- 基于属性文法的处理方法
- 语义规则的计算
- 产生代码
- 再符号表中存放信息
- 给出错误信息
- 执行任何其他动作
- 对输入串的翻译就是根据语义规则进行计算
- 由源程序的语法结果后所驱动的处理办法就是语法制导翻译法
- 语义规则的计算
- 按照语义规则进行语法计算的三种方法
- 依赖图
- 树遍历
- 一边扫描
依赖图
-
在一颗语法树中的结点的继承属性和综合属性之间的相互依赖关系可以由依赖图(有向图)来描述
-
为每一个包含过程调用的语义规则引入一个虚综合属性b,这样把每一个语义规则都写称b:=f(C1,C2,…,CK)的形式。
-
依赖图中为每一个属性设置一个结点,如果属性b依赖于属性c,则从属性c的结点有一条有向边连到属性b的结点。
举例:
-
算法
-
依赖图的举例
先把终结符的属性写上去
注意接受addtype的值L的addtype属性是由id.entry和L.in进行确定的
-
良定义的属性文法
- 如果一属性文法不存在属性之间的循环依赖关系,则称该文法为良定义的
- 一个依赖图的任何拓扑排序都给出一个语法树中结点的语义规则计算的有效顺序
-
属性的计算次序
- 基础文法用于建立输入符号串的语法分析树
- 根据语义规则建立依赖图
- 根据依赖图的拓扑排序,得到计算语义规则的顺序
登记变量表的类别信息
树遍历的属性计算方法:
-
通过树遍历的方法计算属性的值
- 假设语法树已经建立,且树中已带有开始符号的继承属性和终结符的综合属性
- 以某种次序遍历语法树,直至计算出所有属性
- 深度优先,从左到右的遍历
-
算法:
-
示例
注意是深度优先遍历
开始时,遍历到x返回到X计算不出来,到y返回到Y计算不出来,再算z
算完继承属性再算综合属性
一遍扫描
-
一遍的处理方法:
- 在语法分析的同时计算属性值
- 所采用的语法分析方法
- 性的计算次序
- 所谓语法制导翻译法,直观上说就是为文法中每个产生式配上一组语义规则,并且在语法分析的同时执行这些语义规则
- 语义规则被计算的时机
- 自上而下分析,一个产生式匹配输入串成功时
- 自下而上分析,一个产生式被用于进行归约时
- 在语法分析的同时计算属性值
-
抽象语法树:在语法树中去掉那些对翻译不必要的信息,从而获得更有效的源程序中间表示
-
建立表达式的抽象语法树
-
建立抽象语法树的语义规则
Nptr指向子树的指针
举例:
从底向上,根据语法树建立结点(非终结符才有)
S-属性文法的自下而上计算
- 只含有综合属性
- 在自下而上的分析器分析输入符号串的同时计算综合属性
- 分析栈中保存语法符号和有关的综合属性值
- 每当进行归约时,新的语法符号的属性值就有栈中正在归约的产生式右边符号的属性值来计算
- 在分析栈中增加附加域存放综合属性值
- S-属性文法的自下而上计算
符号也要入栈
代码段是空,相当于是赋值,因为属性值一直不变 - S-属性文法的分析过程
L-属性文法
- 适合一边扫描的自上而下分析
- 按照深度优先遍历语法树,计算所有属性值
- 与LL(1)自上而下分析方法结合
- 深度优先建立语法树
- 按照语义规则计算属性
- 定义:
继承属性只能依赖左边符号的属性或者依赖于父节点的继承属性 - S-属性文法一定是L-属性文法
翻译模式
- 语义规则:给出了属性计算的定义,没有属性计算的次序等实现细节
- 翻译模式:给出使用语义规则进行计算的次序,把实现细节表示出来
- 在翻译模式中,和文法符号相关的属性和语义规则(也称语义动作),用花括号{}括起来,插入到产生式右部的合适位置上
举例:
-
设计翻译模式的原则
- 设计翻译模式时,必须保证当某个动作引用一个属性时它必须是有定义的
- L-属性文法本身就能确保每个动作不会引用尚未计算出来的属性
- 当只需要综合属性时:为每一个语义规则建立一个包含赋值的动作,并把这个动作放在相应的产生式右边的末尾
- 如果既有综合属性又有继承属性,在建立翻译模式时就必须保证:
- 产生式右边的符号的继承属性必须在这个符号以前的动作中计算出来
- 一个动作不能引用这个动作右边的符号的综合属性
- 产生式左边非终结符的综合属性只有在它所引用的所有属性都计算出来以后才能计算。计算这种属性的动作通常可放在产生式右端的末尾
- 产生式右边的符号的继承属性必须在这个符号以前的动作中计算出来
-
举例
-
数学格式语言EQN:
-
把所有的语义动作都放在产生式的末尾:
-
消除翻译模式中的左递归
-
消除翻译模式中的左递归(改造后)
改造前:只能从下向上
改造后:能从上向下
示例: