因此我需要能够使用注释解析一些相对简单的C ++文件,并从中生成其他源文件。
举个例子,我可能会有这样的事情:
//@ service
struct MyService
{
int getVal() const;
};
我需要找到// @ service注释,并获得它后面的结构的描述。
我正在考虑可能利用LLVM / Clang,因为它似乎支持在第三方应用程序中嵌入编译器/解析功能的库。但就解析源代码而言,我真的很无能,所以我不确定究竟需要查找什么,或者从哪里开始。
我知道AST是语言表示的核心,并且还有库支持从Clang中的源文件生成AST。但评论不会真正成为AST的一部分吗?那么找到一个遵循特定注释注释的结构表示的好方法是什么?
我并不太担心处理注释会出现在不适当位置的情况,因为它只会用于解析专门为此应用程序编写的C ++文件。但当然,我能做得越强大越好。
答案 0 :(得分:4)
我这样做的一种方法是注释标识符:
E.g:
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_);
这样的反射代码允许编写将任何对象类型序列化和反序列化为多种不同格式的仿函数。函数使用函数重载和/或类型推导来适当地处理不同的类型。
答案 1 :(得分:2)
解析C ++代码是一项极其复杂的任务。利用C ++编译器可能会有所帮助,但将自己局限于更具特定领域的功能不强的格式可能是有益的,即从更简单的表示形式生成源和其他C ++文件,如protobuf
原型文件或SOAP的WSDL甚至在您的特定情况下更简单。
答案 2 :(得分:1)
我最近做了一些非常类似的工作。我所做的研究表明,目前还没有任何开箱即用的解决方案,所以我最终手工制作了一个。
关于解析C ++代码,其他答案是无效的。我需要能够正确解析~90%的C ++代码的东西;我最终使用了srcML。此工具使用C ++或Java源代码并将其转换为XML文档,这使您可以更轻松地进行解析。它使评论保持一致。此外,如果您需要进行源代码转换,它会附带一个反向工具,它将获取XML文档并生成源代码。
它在90%的情况下都能正常工作,但它会在复杂的模板元编程和C ++解析的最黑暗角落上发生。幸运的是,我的输入源代码在设计上相当一致(不是很多C ++技巧),所以它对我们有用。
要查看的其他项目包括gcc-xml和reflex(实际上使用gcc-xml)。我不确定GCC-XML是否保留了注释,但它确实保留了GCC属性和编译指示。
最后一个要看的是关于编写GCC插件的blog,由CodeSynthesis ODB工具的作者编写。
祝你好运!