2016-10-27 11 views
1

C++ 코드 파일을 구문 분석하고 정규화 된 이름으로 모든 함수 호출을 찾아야합니다. 나는 libclang의 Python 바인딩을 사용하고 있습니다. 왜냐하면 문서가 희박하더라도 내 자신의 C++ 파서를 작성하는 것보다 쉽기 때문입니다.libclang으로 정규화 된 함수 이름을 검색하려면 어떻게해야합니까?

예 C++ 코드 :

namespace a { 
    namespace b { 
    class Thing { 
    public: 
     Thing(); 
     void DoSomething(); 
     int DoAnotherThing(); 
    private: 
     int thisThing; 
    }; 
    } 
} 

int main() 
{ 
    a::b::Thing *thing = new a::b::Thing(); 
    thing->DoSomething(); 
    return 0; 
} 

파이썬 스크립트 :

a::b::Thing::Thing 
a::b::Thing::DoSomething 
:

import clang.cindex 
import sys 

def find_function_calls(node): 
    if node.kind == clang.cindex.CursorKind.CALL_EXPR: 
    # What do I do here? 
    pass 
    for child in node.get_children(): 
    find_function_calls(child) 

index = clang.cindex.Index.create() 
tu = index.parse(sys.argv[1]) 
find_function_calls(tu.cursor) 

내가 찾고 출력은 호출 된 함수의 완전한 이름의 목록입니다

node.spelling을 사용하여 함수의 "짧은"이름을 가져올 수 있지만 어떻게 찾을 수 있을지 모르겠다. 클래스/네임 스페이스가 속합니다.

답변

2

정규화를 구축하는 당신은 정의에 대한 핸들을 얻기 위해 커서 referenced 속성을 사용할 수 있으며, 다음 (루트 또는 커서 종류가 번역 단위에서 중지)를 semantic_parent 특성을 통해 AST를 재귀 수 있습니다 이름.

import clang.cindex 
from clang.cindex import CursorKind 

def fully_qualified(c): 
    if c is None: 
     return '' 
    elif c.kind == CursorKind.TRANSLATION_UNIT: 
     return '' 
    else: 
     res = fully_qualified(c.semantic_parent) 
     if res != '': 
      return res + '::' + c.spelling 
    return c.spelling 

idx = clang.cindex.Index.create() 
tu = idx.parse('tmp.cpp', args='-xc++ --std=c++11'.split()) 
for c in tu.cursor.walk_preorder(): 
    if c.kind == CursorKind.CALL_EXPR: 
     print fully_qualified(c.referenced) 

생산 어떤 :

a::b::Thing::Thing 
a::b::Thing::DoSomething