如何以图形方式可视化抽象语法树?

时间:2018-12-02 08:29:34

标签: c++ abstract-syntax-tree graph-visualization

我用C ++写了一个简单的编译器,想可视化它产生的抽象语法树。目前,我将AST转储为超长字符串,类似于以下内容:

Program(decls=[ConstDecl(type=BasicTypeKind::Int, value=Num(n=1, loc=Location(1, 21)), name=positive, loc=Location(1, 10)), ConstDecl(type=BasicTypeKind::Int, value=Num(n=-1, loc=Location(2, 21)), name=negative, loc=Location(2, 10)), ConstDecl(type=BasicTypeKind::Int, value=Num(n=100, loc=Location(3, 26)), name=max_heap_size, loc=Location(3, 10)), ConstDecl(type=BasicTypeKind::Character, value=Char(c=99, loc=Location(4, 23)), name=...

如您所见,此转储在可视化方面不是很人性化。人们不能自然地将 tree 概念与如此长的字符串相关联。我尝试了漂亮地打印AST的方法,并发现了astpretty,它适用于Python。它的目标是进行调试,但是如果我想举例说明AST,该怎么办?图形格式肯定更适合。

实际上,我对我期望的输出情况有所了解。 Graphviz在这一领域做得很好,而C ++文档工具Doxygen生成的各种图形在概念上与我的目的非常接近。

将这些内容放在一起,我想一种将C ++对象中内存中的AST转换为合适的图形输出的方法(静态的是可以的)。有什么好的起点吗?

编辑:正如评论所说,以Graphviz格式转储AST是一个不错的起点。我将尝试以这种方式进行操作,直到出现新的更具体的问题为止。谢谢大家。

1 个答案:

答案 0 :(得分:0)

我找到了既快速又可以接受的解决方案。 LLVM-8包含一个选项,可通过从中生成点格式文件来可视化控制流图(CFG)。基本上,只要您专门研究llvm::GraphTraitsllvm::DOTGraphTraits模板(稍作解决),llvm::WriteGraph()就会为您服务。这是没有太多微调的结果:

enter image description here

给出了类似C的代码段:

const int IntConstant = 1;
int Array[2];

void main() {
  Printf("hello");
}

此语言是C的简化,不区分大小写。 Printf()Write语句表示为映像中的节点。 ConstDecl表示常量声明VarDecl表示变量声明FuncDef表示函数定义。其他事情非常简单。

在解释魔术之前,我想向您指出这些文档,这些文档确实有助于使用所涉及的llvm APT。

现在有了这个知识库,您只需要将它们放在一起。实际上,请按照以下步骤操作:

  1. 考虑如何遍历AST中的每个节点并专门化nodes_iterator实现。
  2. 考虑如何遍历给定节点的所有子节点并专门实现ChildIteratorType实现。
  3. 考虑如何从节点中提取有用的信息,并专门化getNodeLabel()中的getNodeDescription()DOTGraphTraits
  4. 注意我的:NodeRef类型的GraphTraits 必须!事先知道这一点可以节省您的一天。对于最新版本,这是正确的。也许将来他们会取消限制。

我当前的实现只包含节点的类名称作为其标签,并包含一个不言自明的字符串作为其描述,而无需进行任何微调。如果您想要更多效果,例如颜色,形状等,可以在DOTGraphTraits中进行。