编译原理—翻译方案、属性栈代码

系列文章戳这里👇

  1. 什么是上下文无关文法、最左推导和最右推导
  2. 如何判断二义文法及消除文法二义性
  3. 何时需要消除左递归
  4. 什么是句柄、什么是自上而下、自下而上分析
  5. 什么是LL(1)、LR(0)、LR(1)文法、LR分析表
  6. LR(0)、SLR(1)、LR(1)、LALR(1)文法之间的关系
  7. 编译原理第三章习题
  8. 词法分析、构建DFA、上下文无关文法、LL(1)分析、提取正规式
  9. 证明LL(1)、SLR(1)、LALR(1)文法
  10. 翻译方案、属性栈代码
  11. 【运行时环境】什么是活动记录、 活动记录与汇编代码的关系


文法如下:
S → ( L ) ∣ a L → L , S ∣ S S → (L) | a\\ L → L, S | S S(L)aLL,SS
(a) 写一个翻译方案,它输出每个 a 的嵌套深度。例如,对于句子 (a, (a, a)),输出的结果是 1 2 2。
文法符号S,L继承属性depth表示嵌套深度,则翻译方案如下:
S ′ → { S . d e p t h = 0 } S S → ( { L . d e p t h = S . d e p t h } L ) S → a { p r i n t ( S . d e p t h ) } L → { L 1 . d e p t h = L . d e p t h , S . d e p t h = L . d e p t h } L 1 , S L → { S . d e p t h = L . d e p t h } S \begin{aligned} S'&→\{S.depth=0\}S\\ S&→(\{L.depth = S.depth\}L)\\ S&→a\{print(S.depth)\}\\ L&→\{L_1.depth=L.depth,S.depth=L.depth\}L_1,S\\ L&→\{S.depth=L.depth\}S \end{aligned} SSSLL{S.depth=0}S({L.depth=S.depth}L)a{print(S.depth)}{L1.depth=L.depth,S.depth=L.depth}L1,S{S.depth=L.depth}S
属性栈代码,由于 属性栈上仅能存放综合属性(后文有详细介绍),所以需要引入标记非终结符P、Q、R,及其综合属性s,继承属性i,模拟继承属性的计算,则栈代码如下:
S ′ → { S . d e p t h = P . s } P S P → ϵ { P . s = 0 }                         S t a c k [ n t o p ] = 0 S → ( { Q . i = S . d e p t h , L . d e p t h = Q . s } Q L ) Q → ϵ { Q . s = Q . i + 1 }              S t a c k [ n t o p ] = S t a c k [ t o p − 1 ] + 1 S → a { p r i n t ( S . d e p t h ) }            p r i n t ( S t a c k [ t o p − 1 ] ) L → { L 1 . d e p t h = L . d e p t h , R . i = L . d e p t h , S . d e p t h = R . s } L 1 , R S R → ϵ { R . s = R . i }                     S t a c k [ n t o p ] = S t a c k [ t o p − 2 ] L → { S . d e p t h = L . d e p t h } S \begin{aligned} S'&→\{S.depth=P.s\}PS\\ P&→\epsilon\{P.s=0\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop]=0\\ S&→(\{Q.i=S.depth,L.depth = Q.s\}QL)\\ Q&→\epsilon\{Q.s=Q.i+1\}\ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop]= Stack[top-1]+1\\ S&→a\{print(S.depth)\}\ \ \ \ \ \ \ \ \ \ print(Stack[top-1])\\ L&→\{L_1.depth=L.depth,R.i=L.depth,S.depth=R.s\}L_1,RS\\ R&→\epsilon\{R.s=R.i\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop] = Stack[top-2]\\ L&→\{S.depth=L.depth\}S \end{aligned} SPSQSLRL{S.depth=P.s}PSϵ{P.s=0}                       Stack[ntop]=0({Q.i=S.depth,L.depth=Q.s}QL)ϵ{Q.s=Q.i+1}            Stack[ntop]=Stack[top1]+1a{print(S.depth)}          print(Stack[top1]){L1.depth=L.depth,R.i=L.depth,S.depth=R.s}L1,RSϵ{R.s=R.i}                   Stack[ntop]=Stack[top2]{S.depth=L.depth}S

(b) 写一个翻译方案,它打印出每个 a 在句子中是第几个字符。例如,当句子是 (a, (a, (a, a),(a)))时,打印的结果是 2 5 8 10 14。
使用综合属性out表示当前文法符号推出的字符总数,基础属性before表示该文法符号前有多少个字符,则翻译方案如下:
S ′ → { S . b e f o r e = 0 } S S → { L . b e f o r e = S . b e f o r e }             ( L )             { S . o u t = L . o u t + 2 } S → a { S . o u t = 1 ; p r i n t ( S . b e f o r e + 1 ) } L → { L 1 . b e f o r e = L . b e f o r e ,             S . b e f o r e = L . b e f o r e + L 1 . o u t + 1 }             L 1 , S             { L . o u t = L 1 . o u t + S . o u t + 1 } L → { S . b e f o r e = L . b e f o r e } S { L . o u t = S . o u t } \begin{aligned} S'&→\{S.before=0\}S\\ S&→\{L.before = S.before\} \\&\ \ \ \ \ \ \ \ \ \ \ (L) \\&\ \ \ \ \ \ \ \ \ \ \ \{S.out=L.out+2\}\\ S&→a\{S.out=1;print(S.before+1)\}\\ L&→\{L_1.before=L.before, \\&\ \ \ \ \ \ \ \ \ \ \ S.before=L.before+L_1.out+1\} \\&\ \ \ \ \ \ \ \ \ \ \ L_1,S \\&\ \ \ \ \ \ \ \ \ \ \ \{L.out=L_1.out+S.out+1\}\\ L&→\{S.before=L.before\}S\{L.out=S.out\} \end{aligned} SSSLL{S.before=0}S{L.before=S.before}           (L)           {S.out=L.out+2}a{S.out=1;print(S.before+1)}{L1.before=L.before,           S.before=L.before+L1.out+1}           L1,S           {L.out=L1.out+S.out+1}{S.before=L.before}S{L.out=S.out}
同理,引入标记非终结符P、Q、R,及其综合属性s,继承属性i,模拟继承属性的计算,上述翻译方案栈代码如下:
S ′ → { S . b e f o r e = P . s } P S P → ϵ { P . s = 0 }                                                S t a c k [ n t o p ] = 0 S → ( { Q . i = S . b e f o r e , L . b e f o r e = Q . s }             Q L )             { S . o u t = L . o u t + 2 } Q → ϵ { Q . s = Q . i + 1 }                                     S t a c k [ n t o p ] = S t a c k [ t o p − 1 ] + 1 S → a { p r i n t ( S . b e f o r e ) }                                 p r i n t ( S t a c k [ t o p − 1 ] ) L → { L 1 . b e f o r e = L . b e f o r e ,             R . i = L . b e f o r e + L 1 . o u t + 1 ,             S . b e f o r e = R . s }             L 1 , R S             { L . o u t = L 1 . o u t + S . o u t + 1 }           S t a c k [ n t o p ] = S t a c k [ t o p − 3 ] + S t a c k [ t o p ] + 1 R → ϵ { R . s = R . i }                                            S t a c k [ n t o p ] = S t a c k [ t o p − 2 ] + S t a c k [ t o p − 1 ] + 1 L → { S . b e f o r e = L . b e f o r e } S         { L . o u t = S . o u t }                                     S t a c k [ n t o p ] = S t a c k [ t o p ] \begin{aligned} S'&→\{S.before=P.s\}PS\\ P&→\epsilon\{P.s=0\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop]=0\\ S&→(\{Q.i = S.before,L.before = Q.s\} \\&\ \ \ \ \ \ \ \ \ \ \ QL) \\&\ \ \ \ \ \ \ \ \ \ \ \{S.out=L.out+2\} \\ Q&→\epsilon\{Q.s=Q.i+1\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop]= Stack[top-1]+1\\ S&→a\{print(S.before)\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ print(Stack[top-1])\\ L&→\{L_1.before=L.before, \\&\ \ \ \ \ \ \ \ \ \ \ R.i=L.before+L_1.out+1, \\&\ \ \ \ \ \ \ \ \ \ \ S.before=R.s\} \\&\ \ \ \ \ \ \ \ \ \ \ L_1,RS \\&\ \ \ \ \ \ \ \ \ \ \ \{L.out=L_1.out+S.out+1\} \ \ \ \ \ \ \ \ \ Stack[ntop]=Stack[top-3]+Stack[top]+1 \\ R&→\epsilon\{R.s=R.i\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop] = Stack[top-2]+Stack[top-1]+1\\ L&→\{S.before=L.before\}S \\& \ \ \ \ \ \ \ \{L.out=S.out\} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Stack[ntop]=Stack[top] \end{aligned} SPSQSLRL{S.before=P.s}PSϵ{P.s=0}                                              Stack[ntop]=0({Q.i=S.before,L.before=Q.s}           QL)           {S.out=L.out+2}ϵ{Q.s=Q.i+1}                                   Stack[ntop]=Stack[top1]+1a{print(S.before)}                               print(Stack[top1]){L1.before=L.before,           R.i=L.before+L1.out+1,           S.before=R.s}           L1,RS           {L.out=L1.out+S.out+1}         Stack[ntop]=Stack[top3]+Stack[top]+1ϵ{R.s=R.i}                                          Stack[ntop]=Stack[top2]+Stack[top1]+1{S.before=L.before}S       {L.out=S.out}                                   Stack[ntop]=Stack[top]

针对以下文法
E → E ’ > ’ E            ∣ E ’ < ’ E            ∣ n u m b e r E → E ’>’ E\\ \ \ \ \ \ \ \ \ \ \ | E ’<’ E\\ \ \ \ \ \ \ \ \ \ \ | number EE>E          E<E          number
(c)设计语法制导定义,使之能计算诸如 1 < 2 < 3 的表达式值为 True;而计算表达式 1 < 5 >
3 的值也为 True。

用综合属性 lef t 和 right 表示 E 推出的字符序列中最左和最右的数字,综合属性 bool 表
示 E 推出的表达式的布尔值,语法制导的定义如下:

在这里插入图片描述
(d) 给出生成如下 C 风格for语句中间代码的翻译方案;假定代码生成的顺序不变。
S → f o r ( E 1 ; E 2 ; E 3 ) S 1 S → for(E1; E2; E3) S1 Sfor(E1;E2;E3)S1
首先给出中间代码的结构
在这里插入图片描述
据此给出一个翻译方案如下
在这里插入图片描述

属性栈代码:

  • 如何在自底向上分析中计算继承属性?
    • 属性栈上仅能存放综合属性
    • 分析栈中符号的继承属性
      • 属性copy规则
        如果, A → X Y A→XY AXY,有语义规则 Y . i : = X . s Y.i := X.s Y.i:=X.s
        翻译方案可写为:
        A → X { Y . i : = X . s } Y A → X \{ Y.i := X.s \} Y AX{Y.i:=X.s}Y
    • 从句柄下面取继承属性! 在这里插入图片描述

举个栗子

有如下文法与翻译方案

 D→T { L.in := T.type }  L 			
   T→int { T.type := integer }
   T→real	{ T.type := real }
   L→ { L1.in := L.in }
		  L1 , id {addtype(id.entry, L.in) }
   	L→id { addtype(id.entry, L.in) }

对于输入串:int p,q,r 分析过程如下:

![在这里插入图片描述](https://img-blog.csdnimg.cn/c10261d903ac4b72a199dc6df3755419.png

在这里插入图片描述

引入标记非终结符模拟继承属性的计算

在这里插入图片描述
在这里插入图片描述

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,我们需要构造文法G[E`]的LR(0)自动机。LR(0)自动机是一种有限状态机,可以根据输入的符号序列决定是否接受该序列。 下面是文法G[E`]的LR(0)自动机: ![LR(0)自动机](https://i.imgur.com/GzXhY9x.png) 接下来,我们需要构造该自动机的SLR分析表。SLR分析表包括以下几个部分:ACTION表、GOTO表、状态集合和项集簇。 1. 状态集合 状态集合包括所有的状态(节点)和它们的编号。在这个例子中,状态集合为{0, 1, 2, 3, 4, 5, 6, 7}。 2. 项集簇 项集簇表示在每个状态下可能出现的所有项。在这个例子中,我们可以得到以下项集簇: I0: E' -> .E E -> .L E -> .a L -> .(S) S -> .SS S -> .E I1: E' -> E. I2: L -> (.S) S -> .SS S -> .E I3: S -> S.S S -> .SS S -> .E I4: E -> L. I5: L -> (S.) I6: S -> SS. I7: E -> E.L 3. ACTION表 ACTION表用于处理终结符的移入和规约操作。在这个例子中,ACTION表如下: | 状态 | ( | ) | a | L | E | $ | | --- | --- | --- | --- | --- | --- | --- | | 0 | S4 | | S5 | S2 | S1 | | | 1 | | | | | | acc | | 2 | S4 | R3 | S5 | S2 | S8 | R3 | | 3 | S4 | | S5 | S2 | S7 | | | 4 | | R2 | | | | R2 | | 5 | S4 | R5 | S5 | S2 | | R5 | | 6 | | R1 | | | | R1 | | 7 | | R4 | | | | R4 | 其中,S表示移入,R表示规约,acc表示接受。例如,ACTION[0, a] = S5 表示在状态0遇到终结符a时要移入到状态5。 4. GOTO表 GOTO表用于处理非终结符的移入操作。在这个例子中,GOTO表如下: | 状态 | L | S | E | | --- | --- | --- | --- | | 0 | 2 | 3 | 6 | | 2 | 2 | 3 | 7 | | 3 | | | | | 4 | | | | | 5 | | | | | 7 | | | | 例如,GOTO[0, L] = 2 表示在状态0遇到非终结符L时要移入到状态2。 通过SLR分析表,我们可以进行语法分析并检查输入序列是否符合文法G[E`]的规则。由于题目要求列表链接运算为右结合运算,我们需要对文法进行修改,使得规约时能够将右结合的运算符合并成一个符号。修改后的文法如下: ``` E' -> E E -> L | a L -> (S) S -> SS | E S -> S , E ``` 其中,逗号表示列表的连接操作。 最后,我们使用构造好的SLR分析表对输入序列进行分析,如果能够成功地匹配到终结符,就说明输入序列符合文法G[E`]的规则,并且列表链接运算为右结合运算。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

之墨_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值