Language agnostic 形式化构造控制流图

Language agnostic 形式化构造控制流图,language-agnostic,compiler-construction,scala,compiler-theory,Language Agnostic,Compiler Construction,Scala,Compiler Theory,我正在为大学项目编写一个编译器,我想把我的抽象语法树转换成一个控制流图(CFG) 我认为CFG中的节点(V)应该是来自AST的节点。我知道如何从算法上构造边集(G=(V,E)),但我很难把这个过程写得更正式一点 我创建了这个scala样式的模式匹配(伪): 应与AST结构匹配,如: ( IF(1, ASSIGN(x,1), // ia1 ASSIGN(x,2) // ia2 ) :: // i1 ASSIGN(y,2) :: // a1 ASSI

我正在为大学项目编写一个编译器,我想把我的抽象语法树转换成一个控制流图(CFG)

我认为CFG中的节点(
V
)应该是来自AST的节点。我知道如何从算法上构造边集(
G=(V,E)
),但我很难把这个过程写得更正式一点

我创建了这个scala样式的模式匹配(伪):

应与AST结构匹配,如:

( IF(1,
       ASSIGN(x,1), // ia1
       ASSIGN(x,2) // ia2
     ) ::  // i1
  ASSIGN(y,2) ::  // a1
  ASSIGN(z,ADD(x,y)) :: //a2 
  IF(z, 
       RET(z), //i2r1
         assign(z,0):: // i2a1
         ret(z) // i2r2
  ) :://i2
   Nil
)
并提供一个边缘集,如:

{ i1 -> ia1,
   i1 -> ia2,
   ia1 -> a1,
   ia2 -> a1,
   a1 -> a2,
   a2 -> i2,
   i2 -> i2r1
   i2-> i2a1
   i2a1 -> i2r2
   i2r2 -> _|_
   i2r1 -> _|_ 
}

有人得到了比scala“伪代码”更正式一点的提示吗

我的想法是归纳的:

e[[ IF(_,b1,b2) ]] = (if -> b1) + (if -> b2) \cup e[[ b1 ]] \cup e[[ b2 ]]
e[[ b1, b2 ]] = e[[b1]] \cup e[[b2]]
(上面只给出了一棵树,而不是一个图。例如,从then分支的边到下一个语句的边没有)

编辑:

我一直在阅读scala,我喜欢他们使用的“成功”和“跟随”方法。尽管如此,我还是很难将其归结为更正式的描述,主要是因为漂亮的
childAttr
s.next
隐藏了一些细节,当我试图正式指定它时,这些细节会变得丑陋

编辑2:

我读过《龙之书》和《ML中的现代编译器实现》以及其他一些材料,其中一些/大部分提到了数据流和控制流,但从未涉及过如何以任何形式创建CFG

编辑3:

通过作者,我收到了一些


据我所知,这些书中的“实现方法”是基于程序的“每条语句”而不是基于AST的,并且是基于基本块的。然而,伟大的投入

如果您的目的是简单地创建一些看起来更正式的内容,那么您可以使用。您应该用简化的单个步骤来表达它,而不是递归地表达,因为这样,只要继续应用这些规则就足够了,直到不能再应用这些规则为止

这就是说,这个定义本质上讲与scala代码完全相同。如果你真的想做任何“正式”的事情,你需要证明的属性是:

  • 您的CFG翻译算法始终终止
  • 对于给定的AST输入,您的CFG是否最小
  • 对于给定的AST输入,您的算法是否可以导出唯一的CFG(即,它生成的CFG不是不确定的)
我也不认为您的基本块方法(而不是每语句方法)一定是个坏主意。如果可以匹配一个基本块,那么就可以编写一条规则,根据此匹配的存在来断言集合成员资格,这似乎是完全合理的。看起来你开始绘制的归纳定义可以很好地工作


另一件有趣的事情可能是尝试(正式)与您的CFG构建联系起来。这方面可能已经有了一些工作,但我只是粗略地在谷歌上搜索了一下,并没有发现两者之间有任何明确的关系,但直觉上似乎应该存在一种关系。

实现了一种将AST for JavaScript转换为控制流图的方法。这个实现的想法来源于本文:。

我希望您不介意我在标签中添加了“scala”。@Randall一点也不:)我差点就这么做了,我自己啊!Kiama基于JastAdd,本文使用JastAdd。Kiama的数据流示例与本文中使用的方法密切相关。谢谢你的好意!关于操作语义(和推理规则),我最近经常想到它们,所以你提到它很有趣。
e[[ IF(_,b1,b2) ]] = (if -> b1) + (if -> b2) \cup e[[ b1 ]] \cup e[[ b2 ]]
e[[ b1, b2 ]] = e[[b1]] \cup e[[b2]]