解析/处理C++文件的选项

4

我需要能够解析一些带有注释的相对简单的C++文件,并从中生成额外的源文件。

例如,我可能会有这样的代码:

//@ service
struct MyService
{
   int getVal() const;
};

我需要找到//@ service注释,并获取其后面的结构描述。
我考虑使用LLVM/Clang,因为它似乎支持在第三方应用程序中嵌入编译器/解析功能的库。但是,对于解析源代码,我真的很无知,所以我不确定我需要寻找什么,或者从哪里开始。
我了解AST是语言表示的核心,并且在Clang中有生成AST的库支持。但是,注释实际上不会成为AST的一部分,对吗?那么,如何找到特定注释标记后面结构的表示方式呢?
我不太担心处理注释出现在不适当位置的情况,因为它只用于解析专门为此应用程序编写的C++文件。但是,如果我能使其更加健壮,那就更好了。

修改文档生成器是最容易的。 - Pubby
@Dervall 首先是的。一旦我达到那个点,我可能会考虑进一步,但最初的要求是简单结构体和简单成员。我永远不需要处理模板、虚函数或重载运算符。 - Gerald
@Jan Hudec - 你是指像 #pragma 这样的东西吗?那绝对是一个有效的选项,我之前还没有想到过。实际上,这可能是更好的选择。 - Gerald
不,我不是指像#pragma那样的东西,因为那是编译器内置的。我指的是一个宏,它可以扩展为空或者编译中的某个关键字,但是将用于轻松查找以下标识符。所以#define serviceservice struct MyService#define service structservice MyService。Qt扩展就是这样工作的。 - Jan Hudec
我发现一个快速的技巧是,我可以在Clang编译器中注册一个AST消费者,它会在类型声明时触发回调。然后当结构体被声明时,我可以获取行号并查找前面一行或几行的注释。注释必须在自己的一行上,但这对于快速验证概念来说可能已经足够了。我相信在花更多时间研究之后,我可以想出更好的方法:p - Gerald
显示剩余5条评论
3个回答

4

我一直在做的一种方法是对以下内容进行标识:

  • 基类
  • 类成员
  • 枚举
  • 枚举值

例如:

class /* @ann-class */ MyClass 
    : /* @ann-base-class */ MyBaseClass
{
    int /* @ann-member */ member_;
};

这样的注释使得编写读取头部行并提取注释和相关标识符的python或perl脚本变得容易。

注释和相关标识符使得能够生成以函数模板形式遍历对象传递基类和成员到一个函数器(functor)中的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++编译器可能有所帮助,但更有益的做法是限制自己使用更具领域特定性、功率较小的格式,例如从更简单的表示形式(如protobuf的proto文件或SOAP的WSDL)生成源代码和其他C++文件,在您的特定情况下甚至可以更简单。

是的,我现在实际上正在使用protobuf。我只是在研究替代方案,以简化仅使用C++且不需要担心语言间编组的项目工作流程。 - Gerald

1

我最近做了一些非常类似的工作。我的研究表明,目前没有现成的解决方案可用,所以我最终手动编写了一个。

其他答案都很准确,关于解析C++代码。我需要的是一个能够正确解析约90% C++ 代码的工具,最终我使用了srcML。这个工具可以将C++或Java源代码转换为XML文档,使您更容易解析。它保留注释。此外,如果您需要进行源代码转换,它还带有一个反向工具,可以将XML文档转换为源代码。

它在90%的情况下可以正常工作,但在复杂的模板元编程和C++解析的最黑暗的角落中会出现问题。幸运的是,我的输入源代码在设计上相当一致(不会使用很多C++技巧),所以它对我们有用。

其它需要注意的项目包括gcc-xmlreflex(实际上是使用gcc-xml)。我不确定GCC-XML是否会保留注释,但它确实会保留GCC属性和编译指示。

最后一个需要查看的项目是博客,讲述了编写GCC插件的方法,这篇文章是CodeSynthesis ODB工具的作者所写。

祝你好运!


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