8

假设我有一个枚举定义,例如:

// myenum.h
enum MyEnum {
    First = 1,
    Second,
    Third,
    TwoAgain = Second
};

我想以编程方式从任何给定的枚举定义生成映射,其中键是枚举元素的名称,值是枚举元素的数值(例如myMap["TwoAgain"] == 2

到目前为止,我知道如何使用 遍历源文件clang_visitChildren(),并使用clang_tokenize(). 通过 AST 递归,我按以下顺序获取游标/标记:

  1. “我的枚举”(CXType_Enum)
    • “第一”(CXToken_Identifier)
    • "=" (CXToken_Punctuation)
    • "1" (CXToken_Literal)
  2. “无符号整数”(CXType_UInt)
    • "1" (CXToken_Literal)
  3. “我的枚举”(CXType_Enum)
    • “第二”(CXToken_Identifier)
  4. “我的枚举”(CXType_Enum)
    • “第三”(CXToken_Identifier)
  5. “我的枚举”(CXType_Enum)
    • "TwoAgain" (CXToken_Identifier)
    • "=" (CXToken_Punctuation)
    • “第二”(CXToken_Identifier)
  6. “无符号整数”(CXType_UInt)
    • “第二”(CXToken_Identifier)

我想我可以编写一个算法,使用这些信息来计算每个值。但是,我想知道是否有更简单的方法?我可以直接从 libclang API 获取数值吗?

4

3 回答 3

8

libclang 通过clang_getEnumConstantDeclValue和公开此信息clang_getEnumConstantDeclUnsignedValue。可以通过访问 a 的孩子来构建像您描述的地图CXCursor_EnumDecl

static enum CXChildVisitResult VisitCursor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
    if (cursor.kind == CXCursor_EnumConstantDecl) {
        CXString spelling = clang_getCursorSpelling(cursor);
        myMap[clang_getCString(spelling)] = clang_getEnumConstantDeclValue(cursor);
        clang_disposeString(spelling);
    }

    return CXChildVisit_Continue;
}
于 2015-03-28T15:30:15.230 回答
1

正如 id256 所说,我认为你不能用libclang. 但是,Clanglibtooling和插件接口允许您访问 AST 并直接对其进行操作。对于枚举,您需要查看EnumDecl该类,它允许您遍历内部 decl。那么这只是建立一个地图的例子:

for (auto declIterator = myEnumDecl.decls_begin();
     declIterator != myEnumDecl.decls_end();
     ++declIterator)
{
    myMap[declIterator->getNameAsString()] = declIterator->getInitVal;
}
于 2015-03-25T08:42:26.597 回答
0

您可以使用以下方式获取地图的名称和值。我正在使用clang 8。

bool VisitEnumDecl(EnumDecl *ED)
      {

        for (auto it = ED->enumerator_begin(); it != ED->enumerator_end(); it++)
        {


         std::cout <<it->getNameAsString()<<" "<<it->getInitVal().getSExtValue()<<std::endl;


        }
        return true;
      }
于 2019-11-16T16:59:03.993 回答