|
@@ -1,3 +1,106 @@ |
|
|
|
|
|
from pycparser import c_parser, c_ast |
|
|
|
|
|
|
|
|
def parse_c(): |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
class CTreeCutter(c_ast.NodeVisitor): |
|
|
|
|
|
""" |
|
|
|
|
|
Local node visitor for c abstract syntax trees. |
|
|
|
|
|
|
|
|
|
|
|
:ivar accum: (dict) Information on variables, functions, and structs |
|
|
|
|
|
accumulated from an abstract syntax tree. |
|
|
|
|
|
|
|
|
|
|
|
:ivar cache: (dict or None) Information stored about parent nodes. Added |
|
|
|
|
|
to accum when node reaches the lowest possible level. |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: |
|
|
|
|
|
Add visit function for c_ast.ID to record all uses of a variable. |
|
|
|
|
|
|
|
|
|
|
|
Use self.cache to store extra information about variables. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
|
""" |
|
|
|
|
|
Create a CTreeCutter instance. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
self.accum = {'vars': {}, 'functions': {}, 'structs': {}} |
|
|
|
|
|
self.cache = None |
|
|
|
|
|
|
|
|
|
|
|
def start_n_end(self, node): |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def visit_FuncDecl(self, node): |
|
|
|
|
|
""" |
|
|
|
|
|
Visits FuncDecl nodes in a tree. Adds relevant data about them to accum |
|
|
|
|
|
after visiting all of its children as well. |
|
|
|
|
|
|
|
|
|
|
|
:param node: The current node. |
|
|
|
|
|
|
|
|
|
|
|
:type node: c_ast.FuncDecl |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: |
|
|
|
|
|
Add other relevant information about functions like parameters and |
|
|
|
|
|
return type. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
self.cache['group'] = 'functions' |
|
|
|
|
|
self.cache['meta']['end_ln'] = node.coord.line |
|
|
|
|
|
self.cache['meta']['end_col'] = node.coord.column |
|
|
|
|
|
|
|
|
|
|
|
self.generic_visit(node) |
|
|
|
|
|
|
|
|
|
|
|
def visit_Struct(self, node): |
|
|
|
|
|
""" |
|
|
|
|
|
Visits Struct nodes in a tree. Adds relevant data about them to accum |
|
|
|
|
|
after visiting all of its children as well. |
|
|
|
|
|
|
|
|
|
|
|
:param node: The current node. |
|
|
|
|
|
|
|
|
|
|
|
:type node: c_ast.Struct |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: |
|
|
|
|
|
Find other relevant information to add about structs. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
self.cache['group'] = 'structs' |
|
|
|
|
|
self.cache['meta']['end_ln'] = node.coord.line |
|
|
|
|
|
self.cache['meta']['end_col'] = node.coord.column |
|
|
|
|
|
|
|
|
|
|
|
self.generic_visit(node) |
|
|
|
|
|
|
|
|
|
|
|
def visit_Decl(self, node): |
|
|
|
|
|
""" |
|
|
|
|
|
Visits Decl nodes in a tree. Adds relevant data about them to accum |
|
|
|
|
|
after visiting all of its children as well. |
|
|
|
|
|
|
|
|
|
|
|
:param node: The current node. |
|
|
|
|
|
|
|
|
|
|
|
:type node: c_ast.Decl |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
self.cache = {'group': 'vars', 'meta': {}} |
|
|
|
|
|
|
|
|
|
|
|
self.cache['meta']['start_ln'] = node.coord.line |
|
|
|
|
|
self.cache['meta']['start_col'] = node.coord.column |
|
|
|
|
|
self.cache['meta']['end_ln'] = node.coord.line |
|
|
|
|
|
self.cache['meta']['end_col'] = node.coord.column |
|
|
|
|
|
|
|
|
|
|
|
self.generic_visit(node) |
|
|
|
|
|
|
|
|
|
|
|
self.accum[self.cache['group']][node.name] = self.cache['meta'] |
|
|
|
|
|
self.cache = None |
|
|
|
|
|
|
|
|
|
|
|
def parse_c(codelet): |
|
|
|
|
|
""" |
|
|
|
|
|
Adds 'symbols' field to the codelet after parsing the c code. |
|
|
|
|
|
|
|
|
|
|
|
:param codelet: The codelet object to parsed. |
|
|
|
|
|
|
|
|
|
|
|
:type code: Codelet |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: |
|
|
|
|
|
Preprocess c code so that no ParseErrors are thrown. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
tree = c_parser.CParser().parse(codelet.code) |
|
|
|
|
|
cutter = CTreeCutter() |
|
|
|
|
|
cutter.visit(tree) |
|
|
|
|
|
codelet.symbols = cutter.accum |