Sorry für die ausführliche Frage, aber ich kann keine andere Möglichkeit, um es klar zu sehen. Ich schreibe ein Werkzeug, um C++ - Header-Dateien in SWIG-Interface-Dateien als Starter für die weitere Feinabstimmung zu transformieren.Parsing Namespaces mit Clang: AST Unterschiede in, wenn Sie einen Header in einer anderen Quelldatei oder Parsing es direkt
In diesem Prozess habe ich ein seltsames Verhalten von Clang bemerkt (v3.0). Wenn ich die Headerdatei analysiere, erhalte ich eine wesentlich andere AST als wenn ich eine Quelldatei analysiere, die den Header enthält.
Zum Zwecke der Darstellung, sind hier einige Beispieldateien,:
Quelldatei:
// example.cpp: Test case for nsbug.py
//
#include "example.h"
Rubrik:
// 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
ich folgende Python-Code verwendet haben, um es zu analysieren und die AST entladen:
# 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)
Wenn ich laufe dies auf example.cpp ich (richtig glaube ich):
<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()"
}
}
}
Aber wenn ich es auf der Header-Datei zusammen mit python nsbug.py example.py
versuchen erhalte ich nur:
<CursorKind.TRANSLATION_UNIT>
"example.h"
{
(deleted lots of clang-generated definitions such as __VERSION__)
Geom <CursorKind.VAR_DECL>
"Geom"
}
Warum ist der Geom
Namensraum im AST als VAR_DECL? Ich hätte keinen Unterschied erwartet, außer in den Präprozessorcursors.
Die Umgehung ist offensichtlich - machen Sie einfach eine temporäre Datei im Speicher, die die Kopfzeile enthält - aber das ist nicht sehr befriedigend. Kann mich jemand aufklären?
Der Gremlins Mann. Sie sind überall. –