【发布时间】:2013-05-21 20:41:01
【问题描述】:
我刚刚开始通过 python 绑定使用libclang。我知道我可以使用 get_children 遍历整个语法树 (AST),但我无法找到 get_next_sibling()(或任何可能被调用的)函数,因此我可以跳过不感兴趣的子树.有这样的功能吗?
【问题讨论】:
标签: python clang traversal libclang
我刚刚开始通过 python 绑定使用libclang。我知道我可以使用 get_children 遍历整个语法树 (AST),但我无法找到 get_next_sibling()(或任何可能被调用的)函数,因此我可以跳过不感兴趣的子树.有这样的功能吗?
【问题讨论】:
标签: python clang traversal libclang
正如 francesco 指出的那样,可以跳过元素。 由于最新 cindex.py 修订版的更改,mentoined 代码示例不再起作用。
以下是从 AST 获取特定节点的最小示例。
example.cpp 文件:
int i;
char var[10];
double tmp;
int add (int a, int b)
{
int r;
r=a+b;
return (r);
}
示例python代码:
import sys
from clang.cindex import *
index = Index.create()
tu = index.parse('example.cpp')
root_node = tu.cursor
#for further working with children nodes i tend to save them in a seperate list
#wanted nodes in extra list "result"
wanted_nodes = ['var', 'tmp']
result = []
node_list= []
for i in node.get_children():
node_list.append(i)
for i in node_list:
if i.spelling in wanted_nodes:
result.append(i)
#now result contains the two nodes "var" and "add"
#print the name
for i in result:
print i.spelling
#print the type
for i in result:
print i.type.kind
######OUTPUT#######
>>> var
>>> add
>>> TypeKind.CONSTANTARRAY
>>> TypeKind.DOUBLE
如果你还想知道数组中每个元素的类型,你可以通过:
result[1].type.element_type.kind
#######OUTPUT######
>>> TypeKind.CHAR_S
由于模块cindex.py 有据可查,因此应该不难找到如何获取所需信息。
【讨论】:
我认为 Python API 中不存在 get_next_sibling 函数,但我也不明白您为什么需要它。
在 python API 中,AST 中的每个节点都知道它的所有子节点,因此只需在循环中跳过父节点的子节点即可轻松跳过不感兴趣的子树。重用Eli Bendersky's excellent blog post about the libclang Python API中的一个例子:
def find_typerefs(node, typename):
""" Find all references to the type named 'typename'
"""
if node.kind.is_reference():
ref_node = clang.cindex.Cursor_ref(node)
if ref_node.spelling == typename:
print 'Found %s [line=%s, col=%s]' % (
typename, node.location.line, node.location.column)
# Recurse for children of this node,
# skipping all nodes not beginning with "a"
for c in node.get_children():
if c.spelling.startswith ("a"):
find_typerefs(c, typename)
【讨论】:
clang-c 中枚举 CXChildVisitResult 有 3 个值,CXChildVisit_Continue 跳过访问孩子,所以访问者来到下一个兄弟。类似的东西也应该在 python 中。
【讨论】: