10

libclang defines only 5 types of tokens:

  • CXToken_Punctuation
  • CXToken_Keyword
  • CXToken_Identifier
  • CXToken_Literal
  • CXToken_Comment

Is it possible to get a more detailed information about tokens? For example, for the following source code:

struct Type;
void foo(Type param);

I would expect the output to be like:

  • struct - keyword
  • Type - type name
  • ; - punctuation
  • void - type/keyword
  • foo - function name
  • ( - punctuation
  • Type - type of the function parameter
  • param - function parameter name
  • ) - punctuation
  • ; - punctuation

I also need to map those entities to file locations.

4

2 回答 2

7

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

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

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

请注意,libclang API 没有公开一些细节;如果您需要更多详细信息,您可能需要改用 clang 的 C++ API。

于 2016-04-23T21:40:35.227 回答
2

您正在寻找libclang 公开的令牌spelling和属性。location在 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>
于 2016-04-24T10:52:07.473 回答