我用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是一个不错的起点。我将尝试以这种方式进行操作,直到出现新的更具体的问题为止。谢谢大家。
答案 0 :(得分:0)
我找到了既快速又可以接受的解决方案。 LLVM-8包含一个选项,可通过从中生成点格式文件来可视化控制流图(CFG)。基本上,只要您专门研究llvm::GraphTraits
和llvm::DOTGraphTraits
模板(稍作解决),llvm::WriteGraph()
就会为您服务。这是没有太多微调的结果:
给出了类似C的代码段:
const int IntConstant = 1;
int Array[2];
void main() {
Printf("hello");
}
此语言是C的简化,不区分大小写。 Printf()
由Write
语句表示为映像中的节点。 ConstDecl
表示常量声明。 VarDecl
表示变量声明,FuncDef
表示函数定义。其他事情非常简单。
在解释魔术之前,我想向您指出这些文档,这些文档确实有助于使用所涉及的llvm APT。
WriteGraph
对您的代码有什么要求。GraphTraits
现在有了这个知识库,您只需要将它们放在一起。实际上,请按照以下步骤操作:
nodes_iterator
实现。ChildIteratorType
实现。getNodeLabel()
中的getNodeDescription()
和DOTGraphTraits
。NodeRef
类型的GraphTraits
必须!事先知道这一点可以节省您的一天。对于最新版本,这是正确的。也许将来他们会取消限制。我当前的实现只包含节点的类名称作为其标签,并包含一个不言自明的字符串作为其描述,而无需进行任何微调。如果您想要更多效果,例如颜色,形状等,可以在DOTGraphTraits
中进行。