从抽象语法树获取控制流图

问题描述 投票:13回答:6

我有一个源自ANTLR Parser Generator for Java的AST。我想要做的是以某种方式构建源代码的控制流图,其中每个语句或表达式是唯一的节点。我知道必须有一些这种识别的递归,我想知道你会建议什么是最好的选择,如果ANTLR有一个工具集我可以用于这项工作。干杯,克里斯


编辑 - 我主要关心的是从AST获得控制流图(CFG)。这样我就可以获得源代码的树形表示。为了澄清,源代码和实现语言都是Java。

java parsing abstract-syntax-tree control-flow
6个回答
10
投票

通常,CFG是在较低级别的表示(例如JVM字节码)上计算的。几年前有人对a thesis做过这样的事情。可能有一种有用的方式描述如何获得该表示。

由于源语言和目标语言相同,因此没有代码生成步骤 - 您已经完成了!但是,现在你可以走AST了。在AST的每个节点,你必须问自己:这是一个“跳跃”指令吗?方法调用和if语句是跳转指令的示例。循环结构也是如此(例如forwhile)。加法和乘法等指令不跳转。

首先将每个java语句与CFG中的节点以及入口和出口节点相关联。作为第一个近似,走树和:

  1. 如果当前语句是方法调用,请确定该方法调用的相应主体的入口节点的位置,并使当前语句的边指向该入口节点。如果语句是方法返回,则枚举可以调用它的位置并为其添加边。
  2. 对于每个非跳转语句,在它与下一个语句之间建立一个优势。

这会给你一些CFG。在步骤2中,该过程略显毛茸茸,因为调用的方法可以在库中声明,而不是在AST中的其他地方声明 - 如果是这样,要么不为表示该条目的特殊节点创建边缘或边缘库方法。

这有意义吗?


5
投票

生成一个真正考虑到所有语言问题的完整控制流图表比看起来更难。你不仅必须确定看起来像“基本块”的东西,而且你必须识别函数调用(有点容易,但识别目标可能更难),其中幕后操作如类初始化器可以发生。并且担心可能发生异常的点以及如果发生异常则控制发生的地方。

如果仔细检查大多数语言,他们也会明确表达式中计算的评估顺序,如果你在表达式中有两个副作用,这就很重要;控制流应反映顺序(或非顺序,如果未定义)。

也许你只想要一个具有基本块和条件的控制流的抽象。这显然有点容易。

在任何一种情况下(简单的CFG或完整的CFG),您需要在每个点上都参与可能的控制流目标(例如,对于大多数情况,例如IF语句,有两个流目标:THEN和ELSE条款)。在每个节点处,将该节点链接到适当的控制流目标,可能替换流目标(例如,当您遇到IF时)。

为Java(或C)的完整语言语义执行此操作是相当多的工作。您可能只想使用一种计算现成的工具。从我们的工具中看出http://www.semanticdesigns.com/Products/DMS/FlowAnalysis.html的真实情况。


1
投票

根据一些评论,听起来OP真的想做code generation - 将AST转换为基于基本块和跳转点的低级指令序列。

代码生成是特定于语言的,并且已经在该主题中进行了大量工作。在进行代码生成之前,您需要了解目标语言 - 无论是汇编语言还是其他高级语言。一旦确定了这一点,您只需要遍历AST并生成一系列指令来实现AST中的代码。 (我说这很简单,但可能很难 - 很难概括,因为这里的注意事项非常适合特定语言。)

您为代码生成选择的表示将隐式或显式地包含控制流图。如果您的目标语言相当低级(接近汇编程序),那么控制流图应该相对容易提取。

(如果您想进一步澄清,请发表评论。)


-1
投票

你有没有试过ANTLR Studio?它不会生成孔AST图,但是对于审查,它已经非常有用。


-1
投票

当我在过去做过这个时,我使用graphviz,特别是点工具来生成图形。我通过在编译时实际遍历控制流图来创建点输入文件。

图形布局是一个难题,graphviz做得很好。它可以输出为ps,pdf和各种图像格式,布局通常非常直观。我强烈推荐它。


-1
投票

我不认为我能够以你可能正在寻找的方式回答你的问题,因为我不知道ANTLR中是否有任何方式可以生成有或没有AST的CFG。但是,简而言之,您将使用ANTLR生成的单独Java程序来生成CFG。您可以使用ANTLR生成的语法树作为输入,在您自己创建的单独Java程序中生成CFG。此时,您实际上是构建编译器。 “编译器”和JVM之间的区别在于输出是程序如何分支其各种执行路径的可视化表示(CFG),JVM / Java编译器生成用于在真实机器(CPU)上执行的代码。

一个类比是,如果有人坐下来写一本书(例如英文),句子中使用的单词是计算机语言的TOKENS,句子是以类似的方式形成的,上下文无关语法表达有效的计算机代码,段落整个小说以类似的方式讲述一个故事,语义分析/编译器/ CFG可能产生/代表逻辑上有效的程序,这些程序实际上做了一些有用的事情,或多或少地没有逻辑错误。换句话说,一旦你超越了有效语法(正确的句子结构)的问题,任何人都可以在页面上写一堆句子,但只有某些句子组合产生实际做某事的文本(讲故事)。

您要问的是最后一部分 - 如何采用语法树并转换或解释AST实际逻辑上的内容。当然,您需要为每个要执行此操作的语言构建“编译器”。拥有正确的语法并不能告诉你程序的作用 - 只是从语法的角度来看程序是正确的。

Linters和语法高亮显示器和IDE都围绕着试图使这个难题的最后一部分变得更容易和更有效的人类任务的想法。

© www.soinside.com 2019 - 2024. All rights reserved.