libclang:如何获取令牌语义

时间:2016-04-21 10:16:11

标签: c++ libclang

libclang只定义了5种类型的令牌:

  • CXToken_Punctuation
  • CXToken_Keyword
  • CXToken_Identifier
  • CXToken_Literal
  • CXToken_Comment

是否有可能获得有关令牌的更详细信息?例如,对于以下源代码:

struct Type;
void foo(Type param);

我希望输出如下:

  • struct - keyword
  • 类型 - 类型名称
  • ; - 标点符号
  • void - type / keyword
  • foo - 功能名称
  • ( - 标点符号
  • 类型 - 函数参数的类型
  • param - 函数参数名称
  • ) - 标点符号
  • ; - 标点符号

我还需要将这些实体映射到文件位置。

2 个答案:

答案 0 :(得分:7)

首先,您可能需要一些关于解析如何工作的背景知识。关于编译器的教科书将是一种有用的资源。首先,将文件转换为一系列令牌;它为您提供标识符,标点符号等。执行此操作的代码称为词法分析器。然后,解析器运行;这会将令牌列表转换为AST(结构化声明/表达式等)。

clang会跟踪声明和表达式的各个部分,但不会按照您描述的方式进行跟踪。对于给定的函数声明,它会跟踪诸如函数名称的位置和参数列表的开头之类的内容,但它会根据文件中的位置保留这些内容,而不是标记。

CXToken只是一个标记;除了您列出的五种类型之外,没有任何其他关联的语义信息。 (您可以使用clang_getTokenSpelling获取令牌的实际文本,并使用clang_getTokenExtentclang_annotateTokens的位置为您提供CXCursor,以便您查看相关声明。

请注意,libclang API未公开某些细节;如果您需要更多细节,可能需要使用clang的C ++ API。

答案 1 :(得分:2)

您正在寻找libclang公开的令牌spellinglocation属性。在C ++中,可以使用函数clang_getTokenLocationclang_getTokenSpelling来检索这些函数。最少使用这些函数(使用它们的python等价物将是:

s = '''
struct Type;
void foo(Type param);
'''

idx = clang.cindex.Index.create()
tu = idx.parse('tmp.cpp', args=['-std=c++11'],  unsaved_files=[('tmp.cpp', s)],  options=0)
for t in tu.get_tokens(extent=tu.cursor.extent):
    print t.kind, t.spelling, t.location

给出:

TokenKind.KEYWORD struct <SourceLocation file 'tmp.cpp', line 2, column 1>
TokenKind.IDENTIFIER Type <SourceLocation file 'tmp.cpp', line 2, column 8>
TokenKind.PUNCTUATION ; <SourceLocation file 'tmp.cpp', line 2, column 12>
TokenKind.KEYWORD void <SourceLocation file 'tmp.cpp', line 3, column 1>
TokenKind.IDENTIFIER foo <SourceLocation file 'tmp.cpp', line 3, column 6>
TokenKind.PUNCTUATION ( <SourceLocation file 'tmp.cpp', line 3, column 9>
TokenKind.IDENTIFIER Type <SourceLocation file 'tmp.cpp', line 3, column 10>
TokenKind.IDENTIFIER param <SourceLocation file 'tmp.cpp', line 3, column 15>
TokenKind.PUNCTUATION ) <SourceLocation file 'tmp.cpp', line 3, column 20>
TokenKind.PUNCTUATION ; <SourceLocation file 'tmp.cpp', line 3, column 21>