2012-05-12 10 views
8

वर्बोज़ प्रश्न के लिए खेद है, लेकिन मुझे इसे स्पष्ट करने के लिए कोई और तरीका नहीं दिख रहा है। मैं सी ++ हेडर फ़ाइलों को SWIG इंटरफ़ेस फ़ाइलों में बदलने के लिए एक टूल लिख रहा हूं ताकि आगे बढ़ने के लिए स्टार्टर के रूप में।क्लैंग के साथ नामांकन पार्सिंग: एएसटी अंतर जब किसी अन्य स्रोत फ़ाइल में हेडर समेत या सीधे इसे पार्सिंग

ऐसा करने की प्रक्रिया में, मैंने क्लैंग (v3.0) द्वारा कुछ अजीब व्यवहार देखा है। यदि मैं हेडर फ़ाइल को पार्स करता हूं तो मुझे एक अलग फ़ाइल एएसटी मिलती है, अगर मैं एक स्रोत फ़ाइल को पार्स करता हूं जिसमें हेडर शामिल है।

चित्रांकन के लिए, यहाँ कुछ नमूना स्रोत फ़ाइलें हैं:

स्रोत फ़ाइल:

// example.cpp: Test case for nsbug.py 
// 
#include "example.h" 

हैडर:

// example.h: Test case for nsbug.py 
// 
namespace Geom { 

struct Location 
{ 
    double x, y; 
}; 

class Shape 
{ 
public: 
    Shape(); 

    void set_location(const Location &where) 
    { 
     m_pos = where; 
    }; 

    const Location &get_location() const 

    // Draw it... 
    virtual void draw() const = 0; 

protected: 
    Location m_pos; 
}; 

class Circle : public Shape 
{ 
    Circle(); 

    virtual void draw() const; 
}; 
} // namespace Geom 

मैं निम्नलिखित पायथन कोड का उपयोग किया है यह पार्स करने के लिए और एएसटी डंप करें:

# Usage: python nsbug.py <file> 

import sys 
import clang.cindex 

def indent(level): 
    """ Indentation string for pretty-printing 
    """ 
    return ' '*level 

def output_cursor(cursor, level): 
    """ Low level cursor output 
    """ 
    spelling = '' 
    displayname = '' 

    if cursor.spelling: 
     spelling = cursor.spelling 
    if cursor.displayname: 
     displayname = cursor.displayname 
    kind = cursor.kind; 

    print indent(level) + spelling, '<' + str(kind) + '>' 
    print indent(level+1) + '"' + displayname + '"' 

def output_cursor_and_children(cursor, level=0): 
    """ Output this cursor and its children with minimal formatting. 
    """ 
    output_cursor(cursor, level) 
    if cursor.kind.is_reference(): 
     print indent(level) + 'reference to:' 
     output_cursor(clang.cindex.Cursor_ref(cursor), level+1) 

    # Recurse for children of this cursor 
    has_children = False; 
    for c in cursor.get_children(): 
     if not has_children: 
      print indent(level) + '{' 
      has_children = True 
     output_cursor_and_children(c, level+1) 

    if has_children: 
     print indent(level) + '}' 

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

output_cursor_and_children(tu.cursor) 

जब मैं example.cpp मैं (सही ढंग से मुझे लगता है कि) पर इस चलाएँ:

<CursorKind.TRANSLATION_UNIT> 
    "example.cpp" 
{ 

    (Deleted lots of clang-generated declarations such as __VERSION__) 

    Geom <CursorKind.NAMESPACE> 
    "Geom" 
    { 
    Location <CursorKind.STRUCT_DECL> 
     "Location" 
    { 
     x <CursorKind.FIELD_DECL> 
     "x" 
     y <CursorKind.FIELD_DECL> 
     "y" 
    } 
    Shape <CursorKind.CLASS_DECL> 
     "Shape" 
    { 
     <CursorKind.CXX_ACCESS_SPEC_DECL> 
     "" 
     <CursorKind.CXX_ACCESS_SPEC_DECL> 
     "" 
     Shape <CursorKind.CONSTRUCTOR> 
     "Shape()" 
     set_location <CursorKind.CXX_METHOD> 
     "set_location(const Geom::Location &)" 
     { 
     where <CursorKind.PARM_DECL> 
      "where" 
     { 
      <CursorKind.TYPE_REF> 
      "struct Geom::Location" 
      reference to: 
      Location <CursorKind.STRUCT_DECL> 
       "Location" 
     } 
     <CursorKind.COMPOUND_STMT> 
      "" 
     { 
      <CursorKind.CALL_EXPR> 
      "operator=" 
      { 
      <CursorKind.MEMBER_REF_EXPR> 
       "m_pos" 
      <CursorKind.UNEXPOSED_EXPR> 
       "operator=" 
      { 
       <CursorKind.DECL_REF_EXPR> 
       "operator=" 
      } 
      <CursorKind.DECL_REF_EXPR> 
       "where" 
      } 
     } 
     } 
     get_location <CursorKind.CXX_METHOD> 
     "get_location()" 
     { 
     <CursorKind.TYPE_REF> 
      "struct Geom::Location" 
     reference to: 
      Location <CursorKind.STRUCT_DECL> 
      "Location" 
     } 
     <CursorKind.CXX_ACCESS_SPEC_DECL> 
     "" 
     <CursorKind.CXX_ACCESS_SPEC_DECL> 
     "" 
     m_pos <CursorKind.FIELD_DECL> 
     "m_pos" 
     { 
     <CursorKind.TYPE_REF> 
      "struct Geom::Location" 
     reference to: 
      Location <CursorKind.STRUCT_DECL> 
      "Location" 
     } 
    } 
    Circle <CursorKind.CLASS_DECL> 
     "Circle" 
    { 
     <CursorKind.CXX_BASE_SPECIFIER> 
     "class Geom::Shape" 
     reference to: 
     Shape <CursorKind.CLASS_DECL> 
      "Shape" 
     { 
     <CursorKind.TYPE_REF> 
      "class Geom::Shape" 
     reference to: 
      Shape <CursorKind.CLASS_DECL> 
      "Shape" 
     } 
     Circle <CursorKind.CONSTRUCTOR> 
     "Circle()" 
     draw <CursorKind.CXX_METHOD> 
     "draw()" 
    } 
    } 
} 

लेकिन जब मैं python nsbug.py example.py के साथ हेडर फाइल पर यह कोशिश मैं सिर्फ मिलती है:

<CursorKind.TRANSLATION_UNIT> 
    "example.h" 
{ 

    (deleted lots of clang-generated definitions such as __VERSION__) 

    Geom <CursorKind.VAR_DECL> 
    "Geom" 
} 

एएसटी में Geom नाम स्थान VAR_DECL के रूप में क्यों है? प्रीप्रोसेसर कर्सर को छोड़कर, मुझे कोई फर्क नहीं पड़ता।

कार्य-आसपास स्पष्ट है - बस मेमोरी में एक अस्थायी फ़ाइल बनाएं जिसमें हेडर शामिल है - लेकिन यह बहुत संतोषजनक नहीं है। क्या कोई मुझे प्रबुद्ध कर सकता है?

+3

gremlins आदमी। वे हर जगह हैं। –

उत्तर

10

चूंकि आप स्पष्ट रूप से एक भाषा निर्दिष्ट नहीं कर रहे हैं, क्लैंग फ़ाइल एक्सटेंशन से भाषा निर्धारित करता है, जिसके परिणामस्वरूप "example.h" सी के रूप में पार्स किया जा रहा है, सी ++ नहीं। इस प्रकार फ़ाइल काफी हद तक खराब है, और सूचकांक ठीक वसूली करने की कोशिश करता है। namespace Geom को अज्ञात प्रकार namespace के साथ Geom के लिए एक परिवर्तनीय घोषणा के रूप में माना जा रहा है, और निम्न अप्रत्याशित { ... } ब्लॉक छोड़ दिया गया है।

प्रयास करें:

tu = index.parse(sys.argv[1], args=['-x', 'c++']) 
+1

यह काम किया, धन्यवाद! अजीब है कि यह एक त्रुटि उत्पन्न नहीं किया है। –

4

जबकि रिचर्ड का जवाब इस मामले में काम करता है, मैं एक ही समस्या का सामना करना और यह मेरे लिए काम नहीं किया जा सकता है। यह पता चला कि पाइथन क्लैंग बाइंडिंग त्रुटि संदेश छुपा रहे थे। यदि आप निम्न चलाते हैं:

clang -Xclang -ast-dump -fsyntax-only yourfile.cpp 

यह एएसटी जानकारी प्रिंट करेगा। मेरे मामले में, यह हेडर फ़ाइल नहीं मिला क्योंकि यह एक अलग निर्देशिका में था। इसलिए, मुझे -I जोड़ना पड़ा और args में अतिरिक्त पथ शामिल हो गया और यह काम किया।