-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest_ast_clang.py
63 lines (54 loc) · 2.38 KB
/
test_ast_clang.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# inspired by http://eli.thegreenplace.net/2011/07/03/parsing-c-in-python-with-clang/
import sys
import clang.cindex
the_location = ""
def verbose(*args, **kwargs):
'''filter predicate for show_ast: show all'''
return True
def no_system_includes(cursor, level):
'''filter predicate for show_ast: filter out verbose stuff from system include files'''
return (level!= 1) or (cursor.location.file is not None and not cursor.location.file.name.startswith('/usr/include'))
# A function show(level, *args) would have been simpler but less fun
# and you'd need a separate parameter for the AST walkers if you want it to be exchangeable.
class Level(int):
'''represent currently visited level of a tree'''
def show(self, *args):
'''pretty print an indented line'''
print '\t'*self + ' '.join(map(str, args))
def __add__(self, inc):
'''increase level'''
return Level(super(Level, self).__add__(inc))
def is_valid_type(t):
'''used to check if a cursor has a type'''
return t.kind != clang.cindex.TypeKind.INVALID
def qualifiers(t):
'''set of qualifiers of a type'''
q = set()
if t.is_const_qualified(): q.add('const')
if t.is_volatile_qualified(): q.add('volatile')
if t.is_restrict_qualified(): q.add('restrict')
return q
def show_type(t, level, title):
'''pretty print type AST'''
level.show(title, str(t.kind), ' '.join(qualifiers(t)))
if is_valid_type(t.get_pointee()):
show_type(t.get_pointee(), level+1, 'points to:')
def show_ast(cursor, filter_pred=verbose, level=Level()):
'''pretty print cursor AST'''
if filter_pred(cursor, level):
#if(cursor.location.file.name == the_location):
#level.show(cursor.kind, cursor.spelling, cursor.displayname, cursor.location)
#if is_valid_type(cursor.type):
#show_type(cursor.type, level+1, 'type:')
#show_type(cursor.type.get_canonical(), level+1, 'canonical type:')
print cursor.location.file.name
for c in cursor.get_children():
show_ast(c, filter_pred, level+1)
if __name__ == '__main__':
index = clang.cindex.Index.create()
tu = index.parse(sys.argv[1])
the_location = sys.argv[1]
print 'Translation unit:', tu.spelling
#for f in tu.get_includes():
# print '\t'*f.depth, f.include.name
show_ast(tu.cursor, no_system_includes)