A semantic search engine for source code https://bitshift.benkurtovic.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

107 lines
2.9 KiB

  1. from pycparser import c_parser, c_ast
  2. class _TreeCutter(c_ast.NodeVisitor):
  3. """
  4. Local node visitor for c abstract syntax trees.
  5. :ivar accum: (dict) Information on variables, functions, and structs
  6. accumulated from an abstract syntax tree.
  7. :ivar cache: (dict or None) Information stored about parent nodes. Added
  8. to accum when node reaches the lowest possible level.
  9. .. todo::
  10. Add visit function for c_ast.ID to record all uses of a variable.
  11. Use self.cache to store extra information about variables.
  12. """
  13. def __init__(self):
  14. """
  15. Create a _TreeCutter instance.
  16. """
  17. self.accum = {'vars': {}, 'functions': {}, 'structs': {}}
  18. self.cache = None
  19. def start_n_end(self, node):
  20. pass
  21. def visit_FuncDecl(self, node):
  22. """
  23. Visits FuncDecl nodes in a tree. Adds relevant data about them to accum
  24. after visiting all of its children as well.
  25. :param node: The current node.
  26. :type node: c_ast.FuncDecl
  27. .. todo::
  28. Add other relevant information about functions like parameters and
  29. return type.
  30. """
  31. self.cache['group'] = 'functions'
  32. self.cache['meta']['end_ln'] = node.coord.line
  33. self.cache['meta']['end_col'] = node.coord.column
  34. self.generic_visit(node)
  35. def visit_Struct(self, node):
  36. """
  37. Visits Struct nodes in a tree. Adds relevant data about them to accum
  38. after visiting all of its children as well.
  39. :param node: The current node.
  40. :type node: c_ast.Struct
  41. .. todo::
  42. Find other relevant information to add about structs.
  43. """
  44. self.cache['group'] = 'structs'
  45. self.cache['meta']['end_ln'] = node.coord.line
  46. self.cache['meta']['end_col'] = node.coord.column
  47. self.generic_visit(node)
  48. def visit_Decl(self, node):
  49. """
  50. Visits Decl nodes in a tree. Adds relevant data about them to accum
  51. after visiting all of its children as well.
  52. :param node: The current node.
  53. :type node: c_ast.Decl
  54. """
  55. self.cache = {'group': 'vars', 'meta': {}}
  56. self.cache['meta']['start_ln'] = node.coord.line
  57. self.cache['meta']['start_col'] = node.coord.column
  58. self.cache['meta']['end_ln'] = node.coord.line
  59. self.cache['meta']['end_col'] = node.coord.column
  60. self.generic_visit(node)
  61. self.accum[self.cache['group']][node.name] = self.cache['meta']
  62. self.cache = None
  63. def parse_c(codelet):
  64. """
  65. Adds 'symbols' field to the codelet after parsing the c code.
  66. :param codelet: The codelet object to parsed.
  67. :type code: Codelet
  68. .. todo::
  69. Preprocess c code so that no ParseErrors are thrown.
  70. """
  71. tree = c_parser.CParser().parse(codelet.code)
  72. cutter = _TreeCutter()
  73. cutter.visit(tree)
  74. codelet.symbols = cutter.accum