2012-04-11 10 views
12

Se ho la seguente macro in qualche codice C++:Come posso analizzare le macro in codice C++, usando CLANG come parser e Python come linguaggio di scripting?

_Foo(arg1, arg2) 

Vorrei usare Python per trovare me tutte le istanze e le estensioni di quella macro usando Clang ei binding Python forniti con cindex.py. Non voglio usare un'espressione regolare da Python sul codice direttamente perché questo mi dà il 99% del modo in cui ci sono, ma non al 100%. Mi sembra che per arrivare al 100%, è necessario utilizzare un parser C++ reale come Clang per gestire tutti i casi in cui le persone fanno cose stupide che sono sintatticamente corrette e compilabili, ma non hanno senso per un'espressione regolare. Ho bisogno di gestire il 100% dei casi e poiché utilizziamo Clang come uno dei nostri compilatori, ha senso utilizzarlo come parser per questo compito.

Dato il seguente codice Python sono in grado di trovare quelli che sembrano essere i tipi predefiniti che le associazioni Clang pitone conoscono, ma non le macro:

def find_typerefs(node): 
    ref_node = clang.cindex.Cursor_ref(node) 
    if ref_node: 
     print 'Found %s Type %s DATA %s Extent %s [line=%s, col=%s]' % (
      ref_node.spelling, ref_node.kind, node.data, node.extent, node.location.line, node.location.column) 

# Recurse for children of this node 
for c in node.get_children(): 
    find_typerefs(c) 

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

Quello che penso che sto cercando è un modo per analizzare il raw AST per il nome della mia macro _FOO(), ma non sono sicuro. Qualcuno può fornire un codice che mi consenta di passare il nome di una macro e recuperare l'estensione oi dati da Clang?

+1

's/CLANG/Clang/g' –

+4

Non ho usato Clang ma non penso che troverai la tua macro in AST. Se si guardano le fasi della compilazione C++ (http://stackoverflow.com/questions/8833524/what-are-the-stages-of-compilation-of-ac-program) le macro "spariscono" nella parte di pre-elaborazione che è completato prima della compilazione e viene generato l'AST. A questo punto la tua macro non esiste perché è stata sostituita interamente dal contenuto della macro. Vorrei esaminare la porzione di pre-elaborazione di Clang e vedere cosa si può ottenere da quello. – uesp

+4

@uesp Bene, Clang non è solo un compilatore. È un * grande * compilatore che si impegna a fornire * ottima * diagnostica. Ecco perché le macro * sono * tenute traccia di in Clang (controlla la [class list] (http://clang.llvm.org/doxygen/annotated.html) per le occorrenze di "macro"), in una certa misura. Sarei molto sorpreso se questo catturasse anche le più sporche macro che sfidano la sintassi, ma penso che sia molto possibile per macro come quelle di OP. – delnan

risposta

8

è necessario passare la options flag appropriato per Index.parse:

tu = index.parse(sys.argv[1], options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD) 

Il resto del visitatore del cursore potrebbe assomigliare a questo:

def visit(node): 
    if node.kind in (clang.cindex.CursorKind.MACRO_INSTANTIATION, clang.cindex.CursorKind.MACRO_DEFINITION): 
     print 'Found %s Type %s DATA %s Extent %s [line=%s, col=%s]' % (node.displayname, node.kind, node.data, node.extent, node.location.line, node.location.column) 
    for c in node.get_children(): 
     visit(c) 
Problemi correlati