解析/处理 C++ 文件的选项
Posted
技术标签:
【中文标题】解析/处理 C++ 文件的选项【英文标题】:Options for parsing/processing C++ files 【发布时间】:2012-02-07 10:36:37 【问题描述】:所以我需要能够解析一些带有注释的相对简单的 C++ 文件,并从中生成额外的源文件。
例如,我可能有这样的事情:
//@ service
struct MyService
int getVal() const;
;
我需要找到 //@ 服务注解,并获得它后面结构的描述。
我正在考虑可能利用 LLVM/Clang,因为它似乎支持在第三方应用程序中嵌入编译器/解析功能的库。但就解析源代码而言,我真的很无知,所以我不确定我到底需要寻找什么,或者从哪里开始。
我了解 AST 是语言表示的核心,并且库支持从 Clang 中的源文件生成 AST。但是 cmets 不会真正成为 AST 的一部分,对吧?那么,找到遵循特定注释注释的结构表示的好方法是什么?
我不太担心注释会出现在不适当的位置的情况,因为它只会用于解析专门为此应用程序编写的 C++ 文件。但当然,我能做得越健壮越好。
【问题讨论】:
您是否只处理一个子集,其中遵循注释的唯一合法事物是具有简单成员的struct
?因为你在解析 C++,所以它很快就会变得非常复杂。
修改文档生成器是最简单的。
@Dervall 最初,是的。一旦达到这一点,我可能会考虑更进一步,但最初的要求是针对具有简单成员的简单结构。我永远不需要处理模板、虚函数或重载运算符。
你需要解析结构/类的内容,还是只是找出它的名字?您是否设置了注释,或者基于预处理器的注释是否可以替代?
@Jan Hudec 我需要解析结构的接口,尽管我不需要解析结构成员函数中的任何代码。我现在什么都没有。您所说的基于预处理器的注释是什么意思?
【参考方案1】:
我一直在这样做的一种方法是注释标识符:
类 基类 班级成员 枚举 枚举器例如:
class /* @ann-class */ MyClass
: /* @ann-base-class */ MyBaseClass
int /* @ann-member */ member_;
;
这样的注释可以很容易地编写一个python或perl脚本,逐行读取标题并提取注释和相关的标识符。
注解和相关标识符使得以函数模板的形式生成 C++ 反射成为可能,该模板遍历将基类和成员传递给函子的对象,例如:
template<class Functor>
void reflect(MyClass& obj, Functor f)
f.on_object_start(obj);
f.on_base_subobject(static_cast<MyBaseClass&>(obj));
f.on_member(obj.member_);
f.on_object_end(obj);
为每个基类和成员生成数字 ID(枚举)并将其传递给函子也很方便,例如:
f.on_base_subobject(static_cast<MyBaseClass&>(obj), BaseClassIndex<MyClass>::MyBaseClass);
f.on_member(obj.member_, MemberIndex<MyClass>::member_);
这样的反射代码允许编写函子,将任何对象类型序列化和反序列化到/从多种不同格式。函子使用函数重载和/或类型推导来适当地处理不同的类型。
【讨论】:
【参考方案2】:解析 C++ 代码是一项极其复杂的任务。利用 C++ 编译器可能会有所帮助,但将自己限制为更特定于域的功能更弱的格式可能是有益的,即从更简单的表示形式生成源文件和其他 C++ 文件,例如 protobuf
s proto 文件或 SOAP 的 WSDL 或在您的特定情况下甚至更简单。
【讨论】:
是的,我现在实际上正在使用 protobuf。我只是在研究一些替代方案,以简化只使用 C++ 且无需担心语言之间编组的项目的工作流程。【参考方案3】:我最近做了一些非常相似的工作。我所做的研究表明,目前还没有任何开箱即用的解决方案,所以我最终选择了一个。
其他答案是关于解析 C++ 代码的。我需要能够正确解析约 90% 的 C++ 代码的东西;我最终使用了srcML。该工具采用 C++ 或 Java 源代码并将其转换为 XML 文档,这使您更容易解析。它使 cmets 保持完好。此外,如果您需要进行源代码转换,它还带有一个反向工具,可以获取 XML 文档并生成源代码。
它在 90% 的情况下都能正常工作,但它会遇到复杂的模板元编程和 C++ 解析的最黑暗角落。幸运的是,我的输入源代码在设计上相当一致(没有很多 C++ 技巧),所以它对我们有用。
其他要查看的项目包括 gcc-xml 和 reflex(实际上使用 gcc-xml)。我不确定 GCC-XML 是否保留 cmets,但它确实保留了 GCC 属性和 pragma。
最后要查看的内容是 blog 关于编写 GCC 插件,由 CodeSynthesis ODB 工具的作者编写。
祝你好运!
【讨论】:
以上是关于解析/处理 C++ 文件的选项的主要内容,如果未能解决你的问题,请参考以下文章