翻译模式
- 属性文法的语义规则:总是放在产生式的尾部
- 翻译模式:把语义规则(也称为语义动作),用花括号{}括起来,插入到产生式右部的合适位置上。进一步细化了语义计算的时机。
S-翻译模式
- 只涉及到综合属性,语义动作集置于产生式右端的 末尾;
- 常采用LR的自底向上的分析法,和S-属性文法类似
L-翻译模式
-
包含综合属性,也可以包含继承属性
-
必须满足以下条件:
- 产生式右部符号的继承属性,其语义计算必须位于该符号前,且语义动作不访问右边符号的属性
- 产生式左部符号的综合属性只有在它所引用的所有属性都计算出来之后才可以计算。计算这种属性的动作通常放在产生式的末尾;
- 前者 { C . i = B . v + 1 } \{C.i=B.v+1\} {C.i=B.v+1}中i为继承属性,需要位于该符号前
- 后者 { A . v = B . v + C . v } \{A.v=B.v+C.v\} {A.v=B.v+C.v}中v为综合属性,需要位于产生式末尾
A → B { C . i = B . v + 1 } C { A . v = B . v + C . v } , B → . . , C → . . A →B\{C.i=B.v+1\}C\{A.v=B.v+C.v\},B→.., C →.. A→B{C.i=B.v+1}C{A.v=B.v+C.v},B→..,C→..
- 继承属性只能依赖于兄长的属性、父亲的继承属性、自身的属性
- 属性间的依赖图不能形成环路
S-翻译模式和L-翻译模式的举例
基于S-翻译模式的语义计算
和S-属性文法类似:
- 基础文法:LL(1):自顶向下计算
- 基础文法:LR系:自底向上计算
基于L-翻译模式的自顶向下计算
递归下降L-翻译模式
- 分析程序由一组递归子程序(函数)组成,每个非终结符对应一个子程序
- 如果非终结符有多个产生式,根据当前符号和SELECT集决定使用哪个产生式
- 从左到右分析符号串,遇到终结符就匹配,遇到非终结符就调用相应的分析子程序
- 要求基础文法是LL(1)
我的理解:
- 有明确的语义计算时机
- 将语义动作也看成类似于一个符号作为一个节点,根据select集合构造出语法树之后,以前序遍历的顺序执行
翻译步骤:
- 检查基础文法是否为LL(1)文法
- 构造LL(1)分析子程序
非递归下降的L-翻译模式
- 在LL(1)分析法基础上,增加属性列表栈
- 从文法起始符号最左推导,根据下一符号和select集选择产生式
- 产生式右部和语义动作 逆序进栈
- 综合属性计算得出结果后出栈
我的笔记:
- 继承属性的计算是自顶向下的,因此自顶向下的L-翻译模式先计算出来的是继承属性
- 综合属性是最后“压箱底”最后才慢慢弹出栈计算出来
https://www.bilibili.com/video/BV13B4y197wo?t=1403.2
精准定位!From这个视频中的老师讲解的非常透彻!
基于L-翻译模式的自底向上计算
有以下三种方法:(不保证文法可以被翻译出来)
- 从翻译模式中删除嵌入在产生式中间的语义动作
- 继承属性的求值结果以综合属性存放在语义栈中,继承属性由综合属性来计算出来时,对继承属性的访问变成对语义栈某个综合属性的访问
- 模拟继承属性的计算
第一种:删除嵌入在产生式中的语义动作,即对翻译模式进行转换:
- 把嵌入在产生式中的每个语义动作用不同的非终结符(比如M,N,…)代替
- 加入新的产生式M → ε \varepsilon ε
- 再把原来的语义动作放在产生式M → ε \varepsilon ε的末尾
例:将L-属性文法变成了S-属性文法翻译模式(自底向上和自顶向下都可以)
第二种:继承属性的求值结果以综合属性存放在语义栈中,对继承属性的访问变成对语义栈中某个综合属性的访问
- 对LR栈进行扩充,添加entry存标识符,type为type属性值
- 第一行产生式不用扩充,因为L.in一定在T.type后一位
- 最后两个产生式中的in值来自type,在栈中相差固定的位置
- 做规约的时候,将标识符和类型存入符号表的操作是根据综合属性和继承属性在栈中相差固定位数的规律
没有固定规律的L-翻译模式
解决方法:
- 添加M后,使C.i的继承属性来自的位置是固定的,都是向前一个位置
第三种:模拟继承属性的计算(继承属性不是复写值,通过运算得来)
- 引入一个新的非终结符
- 给这个新加入的非终结符,添加综合属性原先的继承属性的值的计算值
- 让继承属性拷贝该综合属性,并把这个继承属性以形参的函数的时候,将其改成综合属性
举个例子,理理思路:
- 第一步:改写翻译模式,使继承属性仅含有复写规则
- 第二步:将语义规则转换成为栈操作
- 第三步:根据基础文法,构造LR自动机
- 第四步:根据LR自动机,构造LR分析表
- 第五步:根据LR分析表,以及栈操作指令,分析目标符号串