【问题标题】:Syntax directed translation语法定向翻译
【发布时间】:2015-04-25 14:00:07
【问题描述】:

我正在尝试编写语义规则,用于将给定 cfg 之后的表达式的语法定向翻译成 3 个代码表示。

考虑一下,

这里,为什么是||需要操作员? gen() 似乎是唯一需要的东西,因为它完成了所需的操作。

【问题讨论】:

  • 对我来说,|| 在这种情况下似乎起到了语句分隔符的作用(而不是作为运算符)。
  • @500-InternalServerError 为什么还要放 E.code。 ||看起来像串联。
  • @500-InternalServerError: 它不是语句分隔符。阅读我的答案。

标签: compiler-construction abstract-syntax-tree context-free-grammar semantic-analysis


【解决方案1】:

这组规则描述了一个属性语法,一个计算方案 树的属性。这样的方案几乎总是纯粹的功能性(没有副作用)。它在每个规则/树节点上计算属性,在它们使用的符号中命名为 X.Y,其中 X 代表规则/树(例如,具有变体 E1 和 E2 的 S 和 E。Y 代表计算的属性(在这种情况下,有“code”和“place”属性。

每个规则对应一个子树,E = E1 + E2 对应于 S 表达式表示法中的树 (E+ E1 E2)。 “E.code:=...”表示计算“...”并将结果分配给“E(+)”树根的属性“code”(“综合”属性); “E1.code:=...”表示计算“...”并分配给“E1”叶(“继承属性”)。 “X.Y”不在赋值左侧,意思是“获取节点 X 上属性 Y 的值”。

使用的计算是“newtemp”(实际上应该是“newtemp()” 因为它不是一个变量,而是一个函数)、“gen( ... )”和“||”。 “gen”显然是在做制造个别指令的关键工作。 但它的结果是什么?一个简单的答案是“一个字符串”;更复杂的答案可能是生成指令的二进制表示。

“||”的目的将代码生成步骤的结果组装成生成代码的;如果生成结果是一个字符串,“||”可以是一个字符串连接,如果结果是一个二进制记录,它将二进制记录的列表连接成一个列表。

您可能会因为认为“gen”只是产生结果并将它们写入未提及的输出流而感到困惑。这将违反不允许这样的属性语法的精神。 “||”需要运算符来计算向上传递的函数结果。

您可能会扭曲属性语法,因此 gen 确实 写入隐藏流。在那种情况下,所有的“||”运算符消失了,之前计算的结果(例如“E1.code”)的提及也消失了。如果您的属性树评估是从左到右的,您可以进行这项工作,(很大),当严格左完成时,生成的子树组合以产生结果流的顺序是正确的对。如果属性语法说“E.code = E2.code || E1.code || gen(...)”,即对生成的代码进行重新排序,那么隐藏输出流的技巧就不起作用了。

换个角度看:假设您想在大型程序上快速评估此属性语法。如果您坚持纯函数语法,那么您可以并行评估所有属性!您使用递归过程为每个孩子分叉 helper grain。 [听起来很疯狂?不是,我有一个属性评估系统(请参阅我的简历),它完全按照这个原则工作]。在这种情况下,隐藏的输出流也不起作用,因为并行性可能会导致以任何顺序访问子级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多