How to skip subtrees in AST traversal using python bindings for libclang
我刚刚开始通过 python 绑定使用 libclang。我知道我可以使用
正如弗朗西斯科指出的那样,可以跳过元素。
由于最新的 cindex.py 修订版的变化,所提到的代码示例不再工作了。
以下是从 AST 获取特定节点的最小示例。
example.cpp 文件:
1 2 3 4 5 6 7 8 9 10 | int i; char var[10]; double tmp; int add (int a, int b) { int r; r=a+b; return (r); } |
示例python代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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 |
如果你还想知道数组中每个元素的类型,你可以通过:
1 2 3 4 | result[1].type.element_type.kind #######OUTPUT###### >>> TypeKind.CHAR_S |
因为模块 cindex.py 有很好的文档记录,所以不难找到如何获取您需要的信息。
我认为 Python API 中不存在
在 Python API 中,AST 中的每个节点都知道其所有子节点,因此只需在父节点的循环中跳过它们,就可以轻松跳过无趣的子树。重用 Eli Bendersky 关于 libclang Python API 的优秀博客文章中的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 中。