parser.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import sys
  2. import os
  3. from threading import Thread
  4. import clang.cindex
  5. import itertools
  6. from mako.template import Template
  7. def get_annotations(node):
  8. return [c.displayname for c in node.get_children()
  9. if c.kind == clang.cindex.CursorKind.ANNOTATE_ATTR]
  10. class Function(object):
  11. def __init__(self, cursor):
  12. self.name = cursor.spelling
  13. self.annotations = get_annotations(cursor)
  14. self.access = cursor.access_specifier
  15. # template_pars = [c.extent for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER]
  16. # parameter_dec = [c for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.PARM_DECL]
  17. # print(parameter_dec, template_pars)
  18. # print(cursor.get_num_template_arguments(), cursor.get_template_argument_type(0), cursor.get_template_argument_value(0), template_pars, parameter_dec)
  19. self.parameters = []
  20. self.parnames = []
  21. self.documentation = cursor.raw_comment
  22. class Enum(object):
  23. def __init__(self, cursor):
  24. self.name = cursor.spelling
  25. self.annotations = get_annotations(cursor)
  26. self.access = cursor.access_specifier
  27. # template_pars = [c.extent for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER]
  28. # parameter_dec = [c for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.PARM_DECL]
  29. # print(parameter_dec, template_pars)
  30. # print(cursor.get_num_template_arguments(), cursor.get_template_argument_type(0), cursor.get_template_argument_value(0), template_pars, parameter_dec)
  31. self.parameters = []
  32. self.parnames = []
  33. self.documentation = cursor.raw_comment
  34. # class Class(object):
  35. # def __init__(self, cursor):
  36. # self.name = cursor.spelling
  37. # self.functions = []
  38. # self.annotations = get_annotations(cursor)
  39. # for c in cursor.get_children():
  40. # if (c.kind == clang.cindex.CursorKind.CXX_METHOD and
  41. # c.access_specifier == clang.cindex.AccessSpecifier.PUBLIC):
  42. # f = Function(c)
  43. # self.functions.append(f)
  44. def find_namespace_node(c):
  45. if (c.kind == clang.cindex.CursorKind.NAMESPACE and c.spelling == "igl"):
  46. return c
  47. else:
  48. for child_node in c.get_children():
  49. return find_namespace_node(child_node)
  50. def traverse(c, path, objects):
  51. if c.location.file and not c.location.file.name.endswith(path):
  52. return
  53. # print(c.kind, c.spelling)
  54. if c.kind == clang.cindex.CursorKind.TRANSLATION_UNIT or c.kind == clang.cindex.CursorKind.UNEXPOSED_DECL:
  55. # Ignore other cursor kinds
  56. pass
  57. elif c.kind == clang.cindex.CursorKind.NAMESPACE:
  58. objects["namespaces"].append(c.spelling)
  59. # print("Namespace", c.spelling, c.get_children())
  60. pass
  61. elif c.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE:
  62. # print("Function Template", c.spelling, c.raw_comment)
  63. objects["functions"].append(Function(c))
  64. return
  65. elif c.kind == clang.cindex.CursorKind.FUNCTION_DECL:
  66. # print("FUNCTION_DECL", c.spelling, c.raw_comment)
  67. objects["functions"].append(Function(c))
  68. return
  69. elif c.kind == clang.cindex.CursorKind.ENUM_DECL:
  70. # print("ENUM_DECL", c.spelling, c.raw_comment)
  71. objects["enums"].append(Enum(c))
  72. return
  73. else:
  74. # print("Unknown", c.kind, c.spelling)
  75. pass
  76. for child_node in c.get_children():
  77. traverse(child_node, path, objects)
  78. def parse(path):
  79. index = clang.cindex.Index.create()
  80. tu = index.parse(path, ['-x', 'c++', '-std=c++11', '-fparse-all-comments', '-DIGL_STATIC_LIBRARY'])
  81. # Clang can't parse files with missing definitions, add static library definition
  82. objects = {"functions": [], "enums": [], "namespaces": [], "classes": []}
  83. traverse(tu.cursor, path, objects)
  84. # tpl = Template(filename='bind.mako')
  85. # rendered = tpl.render(functions=functions)
  86. # OUTPUT_DIR = 'generated'
  87. # if not os.path.isdir(OUTPUT_DIR): os.mkdir(OUTPUT_DIR)
  88. # with open("generated/{}.bind.cc".format(sys.argv[1]), "w") as f:
  89. # f.write(rendered)
  90. return objects
  91. if __name__ == '__main__':
  92. if len(sys.argv) != 2:
  93. print("Usage: python3 parser.py <headerfile_path>")
  94. exit(-1)
  95. parse(sys.argv[1])