libclang:如何获取令牌语义
libclang: how to get token semantics
libclang 只定义了 5 种类型的标记:
- CXToken_Punctuation
- CXToken_Keyword
- CXToken_Identifier
- CXToken_Literal
- CXToken_Comment
是否可以获得有关令牌的更详细信息?例如,对于以下源代码:
struct Type;
void foo(Type param);
我希望输出如下:
- 结构-关键字
- 类型 - 类型名称
- ; - 标点符号
- 无效 - type/keyword
- foo - 函数名
- ( - 标点符号
- Type - 函数参数的类型
- param - 函数参数名
- ) - 标点
- ; - 标点符号
我还需要将这些实体映射到文件位置。
首先,您可能需要了解一些有关解析工作原理的背景知识。关于编译器的教科书将是一个有用的资源。首先,文件被转换成一系列的令牌;为您提供标识符、标点符号等。执行此操作的代码称为词法分析器。然后,解析器运行;这会将标记列表转换为 AST(结构化 declarations/expressions/etc..
clang 确实跟踪声明和表达式的各个部分,但不是以您描述的方式。对于给定的函数声明,它会跟踪函数名称的位置和参数列表的开头等内容,但它会根据文件中的位置而不是标记来保留这些内容。
一个CXToken
只是一个token;除了您列出的五种类型之外,没有任何其他关联的语义信息。 (您可以使用 clang_getTokenSpelling
获取令牌的实际文本,使用 clang_getTokenExtent
获取位置。)clang_annotateTokens
为您提供 CXCursor
s,让您检查相关声明。
请注意,libclang 没有公开一些细节 API;如果您需要更多详细信息,您可能需要改用 clang 的 C++ API。
您正在查找 libclang 公开的令牌 spelling
和 location
属性。在 C++ 中,这些可以使用函数 clang_getTokenLocation and clang_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>
libclang 只定义了 5 种类型的标记:
- CXToken_Punctuation
- CXToken_Keyword
- CXToken_Identifier
- CXToken_Literal
- CXToken_Comment
是否可以获得有关令牌的更详细信息?例如,对于以下源代码:
struct Type;
void foo(Type param);
我希望输出如下:
- 结构-关键字
- 类型 - 类型名称
- ; - 标点符号
- 无效 - type/keyword
- foo - 函数名
- ( - 标点符号
- Type - 函数参数的类型
- param - 函数参数名
- ) - 标点
- ; - 标点符号
我还需要将这些实体映射到文件位置。
首先,您可能需要了解一些有关解析工作原理的背景知识。关于编译器的教科书将是一个有用的资源。首先,文件被转换成一系列的令牌;为您提供标识符、标点符号等。执行此操作的代码称为词法分析器。然后,解析器运行;这会将标记列表转换为 AST(结构化 declarations/expressions/etc..
clang 确实跟踪声明和表达式的各个部分,但不是以您描述的方式。对于给定的函数声明,它会跟踪函数名称的位置和参数列表的开头等内容,但它会根据文件中的位置而不是标记来保留这些内容。
一个CXToken
只是一个token;除了您列出的五种类型之外,没有任何其他关联的语义信息。 (您可以使用 clang_getTokenSpelling
获取令牌的实际文本,使用 clang_getTokenExtent
获取位置。)clang_annotateTokens
为您提供 CXCursor
s,让您检查相关声明。
请注意,libclang 没有公开一些细节 API;如果您需要更多详细信息,您可能需要改用 clang 的 C++ API。
您正在查找 libclang 公开的令牌 spelling
和 location
属性。在 C++ 中,这些可以使用函数 clang_getTokenLocation and clang_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>