使用Python遍历Clang抽象语法树

4
我正在使用clang绑定的Python来遍历C/C++代码并生成AST结构,如何获得基于树形结构的AST结构?
在这方面开始的指针、教程或任何相关信息都将非常有帮助!
我发现了一份非常有用的工作(如果您想查看,请访问以下链接:https://www.chess.com/blog/lockijazz/using-python-to-traverse-and-modify-clang-s-ast-tree),并尝试了他的代码,但不幸的是我没有得到有用的输出。
function_calls = []           
function_declarations = []     
def traverse(node):

    for child in node.get_children():
        traverse(child)

    if node.type == clang.cindex.CursorKind.CALL_EXPR:
        function_calls.append(node)

    if node.type == clang.cindex.CursorKind.FUNCTION_DECL:
        function_declarations.append(node)


    print 'Found %s [line=%s, col=%s]' % (node.displayname, node.location.line, node.location.column)

clang.cindex.Config.set_library_path("/Users/tomgong/Desktop/build/lib")
index = clang.cindex.Index.create()

tu = index.parse(sys.argv[1])

root = tu.cursor        
traverse(root)
3个回答

1

我一直在使用pycparser来获取C/C++源代码的AST,并使用Python进行探索。

您可以在存储库中的example中找到用于探索AST的API。


1

如果你仍然遇到问题,我发现你应该使用kind而不是type

你可以运行clang.cindex.CursorKind.get_all_kinds()来检索所有种类,并且会发现在使用node.type时没有出现在任何一种中。

function_calls = []           
function_declarations = []     
def traverse(node):

    for child in node.get_children():
        traverse(child)

    if node.kind == clang.cindex.CursorKind.CALL_EXPR:
        function_calls.append(node)

    if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
        function_declarations.append(node)


    print 'Found %s [line=%s, col=%s]' % (node.displayname, node.location.line, node.location.column)

clang.cindex.Config.set_library_path("/Users/tomgong/Desktop/build/lib")
index = clang.cindex.Index.create()

tu = index.parse(sys.argv[1])

root = tu.cursor        
traverse(root)

0
如何获取基于树的AST结构?
翻译单元对象的光标(tu.cursor)实际上是AST的起始节点。您可能想使用clang工具来可视化分析树。也许这会为您提供启示,并让您了解如何处理树。
clang++ -cc1 -ast-dump test.cpp 但基本上,它归结为获取主节点(tu.cursor)的子节点,并递归遍历它们,并到达您感兴趣的节点。
您可能还想查看Eli Benderski的一篇文章,介绍如何开始使用Python绑定: https://eli.thegreenplace.net/2011/07/03/parsing-c-in-python-with-clang#id9 不幸的是,我没有得到有用的输出。

如果在解析文件时没有向libclang模块提供包含路径,可能会遇到不完整或错误的解析。例如,如果要解析的源文件使用了一些QT包含文件,则需要在parse()调用中指定相关的包含路径,就像这里的示例一样:

index = clang.cindex.Index.create()
tu = index.parse(src_file, args = [
     '-I/usr/include/x86_64-linux-gnu/qt5/',
     '-I/usr/include/x86_64-linux-gnu/qt5/QtCore'])

同时在libclang.cindex的Python模块中寻找一些注释,它们可以帮助你。例如,我通过阅读那些注释找到了上面的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接