N0v*_*ber 6 c++ clang abstract-syntax-tree
我在Windows上,使用MSVC来编译我的项目,但是我需要克服其整洁的AST解析器,这允许我编写一个小代码生成器.
问题是,clang无法解析MSVC头文件(一个众所周知且易于理解的问题).
我尝试了两种选择:
<string>包含类似的内容时都会导致完全失败并且解析得不多.我正在使用python绑定(libclang),但如果有解决方案,我会考虑切换到C/C++ API.
无论如何我可以改变这种行为并使clang继续解析,即使找不到某些标题?
使用 SetSuppressIncludeNotFoundError。我花了一个小时才找到!你可以想象我找到它是多么高兴!
https://clang.llvm.org/doxygen/classclang_1_1Preprocessor.html#ac7bafe67fc32e41460855b39d20ff6af
因此,您想要处理使用 MS 标头的 C++ 代码,并且想要访问 AST 以便生成代码。而且 Clang 不会处理 MS 标头。因此,除非 Clang 得到彻底的升级,否则它不可能成为答案。
您要求“任何可以使这项工作成功的解决方案”。
我们的DMS 软件再工程工具包及其C++14 前端可以做到这一点。
DMS 提供通用解析、AST 构造/检查/转换/生成以及逆向解析(将 AST 转换回可编译代码),并通过语言定义进行参数化。
C++ 前端提供完整的 C++14 解析器、预处理器处理、AST 构造以及全名和类型解析。已经使用GCC和MS VS 2013头文件进行了测试;我们现在正在使用 2015 头文件进行测试。(它也处理 MS VS 2013 语法)。
它可以完全处理棘手的解析情况,包括 C++ 著名的“最令人烦恼的解析”。您可以在从 c++ 代码获取人类可读的 AST中查看解析树。
DMS 不提供 Python 绑定,也不提供直接的 C++ 接口。相反,它是一个独立的工具,旨在支持自定义工具(例如,您的“小代码生成器”)的构建。它有自己非常广泛的内部 API 集,用类似于 LISP 的元编程语言 PARLANSE 编码。DMS 的其他方面是通过使用用于词法分析器、语法和转换的 DSL 来管理的。见下文。
需要注意的是:任何可以处理 C++ 的工具都注定是复杂的。DMS 相应地比较复杂,并且需要一段时间才能学会使用它,因此您不会立即得到答案。好消息是有些事情更容易做。您的代码生成问题可能是“读取框架文件,然后用问题特定的代码替换其中的关键条目”。如果是这种情况,具有以下代码(此处为了演示而简化)的 DMS 工具可能会解决问题:
...
(= myAST (Registry:ParseFile (. filename) (. `CppVisualStudio2013') ...)
(Registry:ApplyTransforms myAST (. `MyTransforms.rsl'))
(Registry:PrettyPrint myAST (concat filename `.modified'))
...
Run Code Online (Sandbox Code Playgroud)
具有包含概念形式的源到源表面语法(例如,C++语法)转换规则的转换文件MyTransforms.rsl
rule rulename if_you_see THIS then replace_by ("-->") THAT
Run Code Online (Sandbox Code Playgroud)
实际的 C++ 规则可能看起来像(这是因为我不知道你的实际代码生成目标而编造的)
rule replace_abstraction(s: STRING_LITERAL):
" abstraction_place_holder(\s) "
-> " my_DSL_library(\s,17); "
Run Code Online (Sandbox Code Playgroud)
上面的 ApplyTransforms 调用将应用此文件中的所有规则,直到不再适用为止。
编写表面语法转换(在您可以做到的地方)比调用破坏树的过程库(如 Clang,DMS 提供的)要容易得多。
您可以使用 PARLANSE 编写更复杂的元程序,在一个地方应用一些规则,在其他地方应用其他规则,并且如果需要,您可以将源到源转换与直接攻击树的过程转换混合在一起。
如果您想了解有关转换的更多详细信息,请询问,我将提供链接。