博客 > 硬件&操作系统&网络&DevOps > 编译原理
# 语法制导翻译-语法制导翻译方案(SDT) ![4a08e1aa5260b46352d04a4f64148688.png](/resources/1433f1e9c0354669af1be9ca179ace31) 存在一套SDD定义时,可以将其细化为SDT方案。针对典型的两种SDD(S-SDD、L-SDD),有以下几种典型的SDT。 ## S-SDD转换为SDT ![155cb9db7947d0692ab40d51370bea5f.png](/resources/4acb347dd1b54c56b4d4d1f14e06759d) 对于LR文法,可以将SDT植入LR分析过程实现语法制导翻译 - 除了符号栈和状态栈,再引入另一个平行的**属性栈,存储符号对应的综合属性**(可以以元组作为元素,存储多个综合属性) - **在归约时,执行产生式对应的语义规则,计算其综合属性,然后将结果放入与归约后的非终结符平行的属性栈位置** - SDT执行动作的具体代码中,可能涉及到引用不同符号的各种属性,这些符号的属性数据可由归约时栈顶的相对位置确定 ![0dcc5ca5d14af8c7b5ad301fc1a5a6e6.png](/resources/0d940cbb6c284049b90e714f993d1df8) ## L-SDD转换为SDT ![5a6a1dd91b9266ef2977d2b29d1ccc97.png](/resources/0f30880e546947f7b6c6465850d9fb64) ![63dc5902d61969987673a8675e8e6cca.png](/resources/e60409367f8442feb6713377b03634b2) ### 植入LL分析过程 #### 非递归实现 对于非递归(手动栈)的LL分析,对栈的结构进行扩展: - 每一个栈元素都附带一个元组结构,用来存储一些属性 - 每一个动作都视为一个单独的栈元素 - 在每一个非终结符入栈之前,都先入栈一个该非终结符对应的syn节点,syn节点和原节点将分别存储该非终结符的综合属性和继承属性 如下图,为分析栈从(T)展开至(F{a1}T'{a2})时的状态: ![42a8f136b7c1efdc69be92ec6da6b5db.png](/resources/38d103a6f811425cb88e3d9b922e5c93) 这是不够的,在出栈时,对应元素的属性可能需要保留,需要按如下两条规则在出栈时进行转移: ![5bb460905f55059b726637e42895bd20.png](/resources/e1d36222d54a4dab99f160841f8eff54) #### 递归实现 递归实现相对简单,仅需对每个非终结符的展开过程添加参数和返回值来表示一些属性,再在过程中动作对应的位置使用这些参数做计算即可。 ![8b29e55095dd176b3cd73bcf23049726.png](/resources/0b6b280277664af6854e25455742d7f2) ### 植入LR分析过程 将L-SDD稍作修改: - 将计算继承属性的动作替换为一个“标记非终结符”,即一个只有空产生式的非终结符 - 在标记非终结符的空产生式归约时计算原动作,且视为紧邻的下一个非终结符的继承属性 - 以此处理,L-SDD将回退为一个类似S-SDD的结构,便于植入LR分析中进行语法制导翻译 ![b1e0dd6f9332d71d58c52e47cf96ef58.png](/resources/aa7ee4296ffb4678b85fa2d9d9c7040c) 这实际上是一种很hacky的技术: - ①标记非终结符的综合属性与紧邻的下一个非终结符的继承属性并不等价,需要补充规则 - ②标记非终结符将使用其产生式右部中没有的文法符号的属性进行计��,需要补充规则 因此它不是使用简单的S-SDD处理方案,相对而言设计出执行动作的具体代码会更困难。 ![73b5d4da0190c538521c6b88c4414103.png](/resources/c4584ad6541d43b7a0fd06d359dddc9d)