Как я могу анализировать макросы в коде C ++, используя CLANG в качестве синтаксического анализатора и Python в качестве языка сценариев?

Если у меня есть следующий макрос в коде C ++:

_Foo(arg1, arg2) 

Я хотел бы использовать Python, чтобы найти все экземпляры и экстенты этого макроса, используя привязки Clang и Python, снабженные cindex.py. Я не хочу использовать регулярное выражение из Python в коде напрямую, потому что это дает мне 99% пути, но не 100%. Мне кажется, что, чтобы добраться до 100%, вам нужно использовать настоящий парсер C ++, такой как Clang, для обработки всех случаев, когда люди делают глупые вещи, которые синтаксически правильны и компилируются, но не имеют смысла для регулярного выражения. Мне нужно обрабатывать 100% случаев, и поскольку мы используем Clang как один из наших компиляторов, имеет смысл использовать его в качестве анализатора для этой задачи.

Учитывая следующий код Python, я могу найти то, что представляется предопределенным типом, о котором знают привязки python Clang, но не макросы:

 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) 

То, что я думаю, что я ищу, – это способ разобрать исходный АСТ для имени моего макроса _FOO() , но я не уверен. Может ли кто-нибудь предоставить некоторый код, который позволит мне передать имя макроса и вернуть объем или данные от Clang?

2 Solutions collect form web for “Как я могу анализировать макросы в коде C ++, используя CLANG в качестве синтаксического анализатора и Python в качестве языка сценариев?”

Вам необходимо передать флаг соответствующих options Index.parse :

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

Остальная часть посетителя курсора может выглядеть так:

 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) 

Однажды я написал сценарий, чтобы отпечатать весь АСТ, который вы получаете от libclang, чтобы узнать, где найти какую информацию.

Вот он: https://gist.github.com/2503232

Python - лучший язык программирования в мире.