【发布时间】:2011-04-06 17:27:33
【问题描述】:
我正在为大学项目编写编译器,我想将我的抽象语法树转换为控制流图 (CFG)。
我认为 CFG 中的节点(V)应该是来自 AST 的节点。我在算法上知道如何构造边缘集 (G=(V,E)),但我很难更正式地编写过程
我已经创建了这个 scala 样式模式匹配(伪):
def edges(n:Node)(nestedin_next: Node) : List[(Node,Node)] =
n match {
case (c_1 :: c_2::tl) => (c1,c2) :: edges(c2::tl)(nestedin_next)++
edges(c_1)(c_2)//recurse
case c_1 :: Nil => (c_1,nestedin_next)::Nil
case i@ IF(_,c1,c2) => (i,c1)::(i,c2)::edges(c1)(nestedin_next)++
edges(c2)(nestedin_next)
case _ => Nil
}
应该匹配 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]]
(虽然上面只给出一棵树而不是一个图。例如,从分支的边缘到下一条语句没有边缘)
编辑:
我一直在阅读 kiama and dataflows 上的 scala,我喜欢他们使用的“succ”和“following”方法。不过,我很难将其归结为更正式的描述,主要是因为漂亮的childAttr、s.next 隐藏了一些在我尝试正式指定时变得丑陋的细节。
编辑2:
我已经阅读了 Dragon Book 和“ML 中的现代编译器实现”以及来自 Learning to write a compiler 的一些其他材料,其中一些/大部分提到了数据流和控制流,但从未过多地涉及如何创建任何正式的 CFG。
EDIT3:
通过Kiama作者,Associate Professor Dr. Tony Sloane我收到了一些additional book references to look up。
据我所知,这些书籍的“实现方式”是基于程序的“每个语句”而不是 AST,并且基于基本块。尽管如此,伟大的投入!
【问题讨论】:
-
我希望你不介意我在标签中添加了“scala”。
-
@Randall 一点也不 :) 我差点就这么做了
标签: language-agnostic compiler-construction scala compiler-theory