Language agnostic 形式化构造控制流图
我正在为大学项目编写一个编译器,我想把我的抽象语法树转换成一个控制流图(CFG) 我认为CFG中的节点(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
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]]