joxeankoret

Dump AST Python script

Aug 12th, 2018
574
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.38 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import sys
  4. import clang
  5. import popen2
  6.  
  7. from clang.cindex import Diagnostic, CursorKind, TokenKind
  8.  
  9. #-------------------------------------------------------------------------------
  10. def severity2text(severity):
  11.   if severity == Diagnostic.Ignored:
  12.     return ""
  13.   elif severity == Diagnostic.Note:
  14.     return "note"
  15.   elif severity == Diagnostic.Warning:
  16.     return "warning"
  17.   elif severity == Diagnostic.Error:
  18.     return "error"
  19.   elif severity == Diagnostic.Fatal:
  20.     return "fatal"
  21.   else:
  22.     return "unknown"
  23.  
  24. #-------------------------------------------------------------------------------
  25. INLINE_NAMES = ["inline", "__inline", "__inline__", "__forceinline", "always_inline"]
  26. def is_inline(cursor):
  27.   if cursor.kind != CursorKind.FUNCTION_DECL:
  28.     return False
  29.  
  30.   for token in cursor.get_tokens():
  31.     tkn = token.spelling
  32.     if tkn in INLINE_NAMES:
  33.       return True
  34.     if tkn == "{":
  35.       break
  36.   return False
  37.  
  38. #-------------------------------------------------------------------------------
  39. def is_static(cursor):
  40.   if cursor.kind != CursorKind.FUNCTION_DECL:
  41.     return False
  42.   token = next(cursor.get_tokens(), None)
  43.   return token.spelling == "static"
  44.  
  45. #-------------------------------------------------------------------------------
  46. def dump_ast(filename, cursor, level = 0):
  47.   fileobj = cursor.location.file
  48.   if fileobj is not None and fileobj.name != filename:
  49.     return
  50.  
  51.   prototype = None
  52.   if cursor.kind == CursorKind.FUNCTION_DECL:
  53.     try:
  54.       args = []
  55.       for arg in cursor.get_arguments():
  56.         args.append("%s %s" % (arg.type.spelling, arg.spelling))
  57.  
  58.       #prototype = "%s %s" % (cursor.get_definition().result_type.spelling, cursor.get_definition().displayname)
  59.       definition = cursor.get_definition()
  60.       if definition is not None:
  61.         prototype = "%s %s(%s)" % (cursor.get_definition().result_type.spelling, cursor.spelling, ", ".join(args))
  62.     except:
  63.       pass
  64.  
  65.     inlined = is_inline(cursor)
  66.  
  67.   token = next(cursor.get_tokens(), None)
  68.   if token is not None:
  69.     token = token.spelling
  70.  
  71.   if prototype is not None:
  72.     print "  "*level, cursor.kind, "INLINED?", inlined, repr(prototype), repr(token), cursor.location
  73.   else:
  74.     print "  "*level, cursor.kind, repr(cursor.spelling), repr(token), cursor.location
  75.  
  76.   for children in cursor.get_children():
  77.     dump_ast(filename, children, level+1)
  78.  
  79. #-------------------------------------------------------------------------------
  80. def resolve_clang_includes():
  81.   cmd = "clang -print-file-name=include"
  82.   rfd, wfd = popen2.popen2(cmd)
  83.   return rfd.read().strip("\n")
  84.  
  85. #-------------------------------------------------------------------------------
  86. def usage():
  87.   print "Usage: %s <source file> <arguments>" % sys.argv[0]
  88.  
  89. #-------------------------------------------------------------------------------
  90. def main(src, args):
  91.   clang_includes = resolve_clang_includes()
  92.   args.append("-I%s" % clang_includes)
  93.   index = clang.cindex.Index.create()
  94.   tu = index.parse(path=src, args=args)
  95.   diags = tu.diagnostics
  96.  
  97.   for diag in diags:
  98.     print("%s:%d,%d: %s: %s" % (diag.location.file, diag.location.line,
  99.           diag.location.column, severity2text(diag.severity), diag.spelling))
  100.  
  101.   dump_ast(src, tu.cursor)
  102.  
  103. if __name__ == "__main__":
  104.   args = []
  105.   if len(sys.argv) != 3:
  106.     usage()
  107.   else:
  108.     main(sys.argv[1], sys.argv[2:])
Add Comment
Please, Sign In to add comment