Я только начал использовать libclang через привязки python. Я понимаю, что я могу пересечь все дерево синтаксиса (AST), используя get_children
, но мне не удалось найти функцию get_next_sibling()
(или что бы ее там ни называли), чтобы я мог пропускать поддеревья, которые не представляют интереса. Существует ли такая функция?Как пропустить поддеревья в обход AST с использованием привязок python для libclang
ответ
С точки зрения clang-c, перечисление CXChildVisitResult имеет 3 значения, а CXChildVisit_Continue пропускает посещение детей, поэтому посетитель приходит к следующему брату. Нечто подобное должно быть и в питоне.
Я не думаю, что в Python API существует функция get_next_sibling
, но я также не понимаю, зачем вам это нужно.
В API-интерфейсе python каждый узел в 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)
Как Франческо отметил, что можно пропустить элементы. Пример с учетом кода, хотя он больше не работает из-за изменений в последней версии cindex.py.
Ниже приведен минимальный пример получения определенных узлов из АСТ.
example.cpp файл:
int i;
char var[10];
double tmp;
int add (int a, int b)
{
int r;
r=a+b;
return (r);
}
пример питон код:
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
, если вы хотите, кроме того, тип каждого элемента массива U получить его через:
result[1].type.element_type.kind
#######OUTPUT######
>>> TypeKind.CHAR_S
, так как модуль cindex.py хорошо документирован, его не должно быть трудно найти, как получить необходимую вам информацию.