如何使用python绑定为libclang跳过AST遍历中的子树

时间:2013-05-27 02:22:24

标签: python clang traversal libclang

我刚开始通过python绑定使用libclang。我理解我可以使用get_children遍历整个语法树(AST),但是我无法找到get_next_sibling()(或者它可能被称为)的任何功能,因此我可以跳过子树不感兴趣。这样的功能是否存在?

3 个答案:

答案 0 :(得分:3)

正如弗朗西斯科指出的那样,可以跳过元素。 由于最新的cindex.py修订版本的更改,精神错误的代码示例不再起作用。

以下是从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已有详细记录,因此很难找到如何获取所需信息。

答案 1 :(得分:2)

我不认为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)

答案 2 :(得分:-1)

就clang-c而言,枚举CXChildVisitResult有3个值,而CXChildVisit_Continue会跳过访问的孩子,所以访问者来到下一个兄弟。这样的东西也应该在python中。