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

Posted 之墨_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理—翻译方案属性栈代码相关的知识,希望对你有一定的参考价值。

系列文章戳这里👇

  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. 翻译方案、属性栈代码

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


文法如下:
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 \\beginaligned 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 \\endaligned SSSLLS.depth=0S(L.depth=S.depthL)aprint(S.depth)L1.depth=L.depth,S.depth=L.depthL1,SS.depth=L.depthS
属性栈代码,由于 属性栈上仅能存放综合属性(后文有详细介绍),所以需要引入标记非终结符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 \\beginaligned 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 \\endaligned SPSQSLRLS.depth=P.sPSϵP.s=0                       Stack[ntop]=0(Q.i=S.depth,L.depth=Q.sQL)ϵQ.s=Q.i+1            Stack[ntop]=Stack[top1]+1aprint(S.depth)          print(Stack[top1])L1.depth=L.depth,R.i=L.depth,S.depth=R.sL1,RSϵR.s=R.i                   Stack[ntop]=Stack[top2]S.depth=L.depthS

(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 \\beginaligned 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\\ \\endaligned SSSLLS.before=0SL.before=S.before           (L)          

以上是关于编译原理—翻译方案属性栈代码的主要内容,如果未能解决你的问题,请参考以下文章

编译原理—中间代码生成布尔表达式翻译短路计算控制流语句翻译条件语句循环语句

三万五千字长文!让你懂透编译原理——第六章 属性文法和语法制导翻译

编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译

编译原理—语法制导翻译S属性L属性自上而下自下而上计算

编译原理123

编译原理初感悟