我能否在不使用编译器的情况下,通过clang获得C/C++代码的XML AST转储?

24

我成功地使用cmake和Visual Studio 10为Windows编译了clang。我想获得一个XML文件,作为源代码AST表示。有一个选项可以在Linux(Ubuntu)下使用clang与gcc提供结果,但在Windows上不起作用:

clang -cc1 -ast-print-xml source.c

然而,这会调用编译阶段(我想避免这种情况)。查看源代码目前对我来说没有帮助,因为我对clang还很陌生。我可以通过使用以下方式生成AST的二进制版本:

clang -emit-ast source.c

很遗憾,这种格式不能直接用于解析。有没有现成的方法可以直接生成XML树而不是二进制文件在clang中?

目标是在.NET环境中使用XML表示,在访问二进制AST之前需要对原生clang库进行一些包装。也许有第三种选择,如果有人已经为.NET编写了一些二进制clang AST解析器?

我可能错过了一些东西,比如clang前端生成的AST与编译阶段生成的AST不等价。


2
我的公司构建C++前端,我们可以发出AST的完整XML转储。我们将其作为复选框项,因为人们要求它。但实际上没有人使用它,因为真正的C++程序(包括所有头文件)的输出量非常大,这使得处理起来变得缓慢和笨重。真正的问题是,你为什么想要这样做?Clang很可能已经提供了大量机制来直接处理C++ AST(我们相应的工具也是如此);为什么要尝试复制所有这些工作呢?为什么不只是为您的目的使用Clang呢? - Ira Baxter
您可以在https://dev59.com/omQm5IYBdhLWcg3wug4u#17393852上查看C++树状结构转储。这不是XML,但该工具也可以生成完全相同内容的XML。 - Ira Baxter
3个回答

21

请注意,XML打印机已经在2.9版本中被Douglas Gregor(CLang FrontEnd的负责人)移除。

问题在于XML打印机的功能不足。一些AST节点从未在打印机中实现过,还有一些节点的属性也没有,这导致了源代码的不准确表示。

Douglas提出的另一个观点是,输出应该适用于外部工具而非仅仅是调试CLang本身(这就是-emit-ast的作用)。这要求输出稳定,不会因为版本的改变而发生变化。特别地,它不应该是CLang内部的1对1映射,而应该将源代码翻译成“标准化”的语言。

除非有志愿者进行大量的打印机工作(需要大量工作),否则它将不会被重新集成...


3
有趣的是,"-emit-ast" 会将类型漂亮地打印出来,而不是表示它们的结构,因此完全没有用。只有使用 XML 打印机才能调试和自动验证声明中的类型。 - SK-logic
@SK-logic:由于XML不再是一个选项,我们可能会看到-emit-ast行为的改进。 - Matthieu M.
感谢提供这么有趣的信息。我会查看旧的XML打印机,并尝试看看是否可以将其用于我的个人使用中。拥有一些通用/标准化的表示源代码的方式确实是一件好事,但是共同点意味着放弃某些功能,并且保留所有语言的特定内容使其过于复杂...一些可扩展的方法会很不错...目前非常感谢您的回答。 - jdehaan
1
当前版本(3.2)似乎在调试模式下有此功能,我能够从中提取xml。然而,对于我来说,2.9似乎无法做到这一点。 - Oeufcoque Penteano
1
@OeufcoquePenteano:怎么做?链接在哪里? - Janus Troelsen

3
我一直在研究从Clang的AST中提取XML的方法。我的代码使用libclang的Python绑定来遍历AST。
我的代码可以在https://github.com/BentleyJOakes/PCX找到。
编辑:我应该补充说明,就每个AST节点类型而言,它无法完全生成正确的源代码标记。不幸的是,这需要为每个AST节点类型编写代码。但是,该代码应该为任何想要进一步探索此问题的人提供基础。

1

使用自定义的ASTDumper可以完成任务,而无需编译任何源代码文件(在clang前端部分停止)。但是,您必须处理所有的llvm C和C++代码源文件才能完成这个任务。


在内部,clang 实现了一个 JSONNodeDumper 和一个 TextNodeDumper。我认为通过调用转换库以基于 JSONNodeDumper 的格式获取 XML 格式会更方便。 - Layne Liu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接