AFAIK,ANTLR在构建控制流图时没有提供任何具体帮助.
您可以通过遍历AST自己构建一个,并收集操作(无条件语句)和条件(表达式节点控制条件)的知识,并根据该信息组合图形.请注意,switch语句是一种复合条件,需要作为一组决策或特殊的N路条件处理.
异常处理可能会改变您所认为的“无条件行为”;每个方法调用都有可能将控制流重定向到异常处理程序(或函数的退出),您需要决定是否要在控制流图中包含这些.如果您想了解程序的功能(特别是数据流),您需要对这些进行建模.
您将需要创建控制流节点(只是一种类),它可以引用AST的各个部分(“这是动作”)和其他两个控制流节点(以处理if-then-else);这些出口中的这些出口为“真正退出”和“错误退出”,或者“继续”和“陷阱”出口.这个子类将代表纯计算,IF语句,TRY块等.
Java是一个纯粹的“结构化”语言,这意味着您可以“自下而上”构建控制流图;您可以在向上遍历叶子时构建控制流图的位,并在爬树时组合来自子项的控制流图.您需要做的是将一个如此远的组装控制流图(最初在叶子处为空)传递到树上,并引用该图中要将控制传递给异常处理程序的控制流节点列表.然后在爬树时,扩展控制流图.
大多数工作都是在条件下进行的,例如IF-THEN-ELSE节点;在这种情况下,将两个具有两组异常的控制流子图传递给该节点.然后创建一个控制流节点来表示条件,将其动作设置为指向条件表达式,将其两个子节点设置为指向传入的两个子图,并将其异常集设置为异常集的并集.
子例程调用获取流动节点,其动作是方法调用,退出到以下语句/子表达式,另一个退出(未填充)最终将指向catch子句.将子例程调用节点添加到传递的异常列表中.
尽管他们没有“下一步”行动,但同样对待THROW法则.
遇到TRY构造时,生成一个条件节点,其动作指向try主体,一个退出指向try的结束或者指向finally子例程调用.最后,修补例外列表中的所有控制流节点以指向catch子句.
您需要将catch子句链接在一起作为if语句的序列.
您必须将“finally”视为从try子句调用的子例程调用以及各种catch子句.