关于Java:从抽象语法树获取控制流程图

关于Java:从抽象语法树获取控制流程图

Get Control flow graph from Abstract Syntax Tree

我有一个从ANTLR Parser Generator for Java派生的AST。 我想做的是以某种方式构造源代码的控制流程图,其中每个语句或表达式都是唯一的Node。 我知道此标识必须具有递归性,我想知道您建议的最佳选择是什么,以及ANTLR是否具有可以用于此工作的工具集。
干杯,
克里斯

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


通常,CFG是在较低级别的表示形式(例如JVM字节码)上计算的。几年前有人对这种事情做了论文。那里可能描述了一种有用的方法来获取该表示形式。

由于您的源语言和目标语言是相同的,因此没有代码生成步骤-您已经完成了!但是,现在您可以开始使用AST了。在AST的每个节点上,您都必须问自己:这是否是"跳跃"指令?方法调用和if语句是跳转指令的示例。循环构造(如forwhile)也是如此。诸如加法和乘法之类的指令是不可跳跃的。

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

  • 如果当前语句是一个方法调用,请找出该方法调用的相应主体的入口节点在哪里,并从当前语句指向该入口节点的边。如果该语句是方法返回,请枚举可能已调用它的位置,并在这些位置添加一条边。
  • 对于每个非跳转语句,在它与下一个语句之间取一个边。
  • 这将为您提供某种CFG。在第2步中,该过程有些繁琐,因为所调用的方法可以在库中声明,而不是在AST的其他地方声明-如果是这样,则不要在表示该条目的特殊节点上占优势或占优势库方法。

    这有意义吗?


    产生一个完全考虑所有语言的完整控制流程图
    问题比看起来难。您不仅需要识别什么
    似乎是"基本块",但是您必须确定函数调用
    (这很容易,但是确定目标可能会比较困难),
    诸如类初始化程序之类的幕后操作可能发生的地方。
    并担心可能发生异常的地方
    以及如果确实发生异常,控制权在哪里。

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

    也许您只想要控制流的抽象
    具有基本的块和条件。那是
    显然容易一些。

    无论哪种情况(简单CFG或完整CFG),您都需要使用AST,
    在每个点上都参考可能的控制流目标
    (例如,在大多数情况下,例如IF语句,有两个流目标:
    THEN和ELSE子句)。在每个节点上,将该节点链接到
    适当的控制流量目标,可能会替换流量目标
    (例如,遇到IF时)。

    对于Java(或C)的完整语言语义而言,做到这一点相当
    很多工作。您可能只想使用一种工具来计算
    现成的。
    参见http://www.semanticdesigns.com/Products/DMS/FlowAnalysis.html
    从我们的工具中获得真正的效果。


    根据一些评论,听起来OP确实想进行代码生成-将AST转换为基于基本块和跳转点的较低级指令序列。

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

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

    (如果需要进一步说明,请发表评论。)


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

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

    您要问的是最后一部分-如何进行语法树转换和解释AST在逻辑上的实际作用。当然,您需要为每种语言构建一个"编译器"。拥有正确的语法并不能告诉您程序的功能-只是从语法角度来看程序是正确的。

    Linter和语法突出显示器以及IDE都是基于这样的想法构建的,即试图使难题的最后一部分对人类来说变得更容易,更有效。


    过去完成此操作时,我使用了graphviz(尤其是点工具)来生成图形。我通过在编译时实际遍历控制流图来创建点输入文件。

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


    您是否尝试过ANTLR Studio?它不会生成孔AST图,但是对于回顾来说,它已经非常有用。


    推荐阅读

      抽像电脑图片|抽象电脑图片

      抽像电脑图片|抽象电脑图片,,抽象电脑图片计算思维是运用计算机科学的基础概念进行问题求解、系统设计、以及人类行为理解等涵盖计算机科

      java快捷键代码|java语句快捷键

      java快捷键代码|java语句快捷键,,java语句快捷键输入main + "提示(一般是ALT+/)"主方法是启动程序的开始,代码如下:public static void mai

      SQL IF 语句

      SQL IF 语句,语句,条件,本文目录SQL IF 语句sql语句中if判断条件怎么写SQL语言if语句sql的if语句怎么写SQL if语句SQL脚本里的IF语句怎么

      删除字段的sql语句是什么

      删除字段的sql语句是什么,字段,删除,字段名,表名,名称,编程,删除字段的sql语句是“ALTER TABLE”,具体语法格式为“ALTER TABLE <表名> DROP <字

      sql语句执行顺序是什么

      sql语句执行顺序是什么,语句,聚合函数,执行,限定,字段,排序,sql语句执行顺序:1、最先执行from tab;2、where语句是对条件加以限定;3、分组语句【gr

      抽象数据类型有哪些

      抽象数据类型有哪些,描述,数据,抽象数据类型,操作,抽象,对象,抽象数据类型是一种对“数据结构”的描述,这种描述是“抽象”的,描述内容有:1、数据

      javascript循环语句哪几种

      javascript循环语句哪几种,循环,语句,表达式,执行,条件,数组,循环语句有:1、for循环;2、“for...in”循环;3、while循环;4、“do…while”循环;5、fo

      javascript输出语句有哪些

      javascript输出语句有哪些,输出,元素,方法,语句,属性,调试,输出语句:1、“window.alert(内容)”;2、“document.write(内容)”;3、“document.getE

      sql查询语句有哪些

      sql查询语句有哪些,查询,子查询,语句,数据,部门,字符,sql查询语句:1、查看表结构【SQL>DESC emp】;2、查询所有列【SQL>SELECT * FROM emp】;3、查

      sql删除语句有哪些

      sql删除语句有哪些,删除,语句,删除表,释放,数据,空间,sql删除语句:1、delete语句用于删除表中的行;2、drop 【删除表】删除内容和定义,释放空间;3、

      sql插入语句是什么

      sql插入语句是什么,语句,字段名,执行,数据,插入数据,字段,sql插入语句是“INSERT INTO”,用于向表中插入新的数据行,有两种基本语法“INSERT INTO

      sql语句中创建表的语句是什么

      sql语句中创建表的语句是什么,选项,语句,类型,语法,数据库,表名,sql语句中创建表的语句是“CREATE TABLE”,具体语法格式为“CREATE TABLE 表名