我有许多不同格式的 .h
文件。它们包括函数定义、变量定义等。我的目标是提取所有函数名称及其各自的注释并映射它们。 我正在寻找一种使用 Python 来完成此操作的工作方法。 我尝试了以下方法:
https://github.com/eliben/pycparser
我阅读了以下关于我的问题的博客文章,但我无法让它工作: https://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers
使用下面的代码我得到以下错误:
pycparser.plyparser.ParseError: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h:100:27: before: __darwin_va_list
import sys
from pycparser import parse_file
sys.path.extend(['.', '..'])
if __name__ == "__main__":
filename = "<pathToHeader>/file.h"
ast = parse_file(filename, use_cpp=True,
cpp_path='gcc',
cpp_args=['-E', r'<pathToPycparser>/utils/fake_libc_include'])
ast.show()
https://pyclibrary.readthedocs.io/en/latest/
这实际上运行没有错误,但是它没有在示例文件中找到任何函数。
from pyclibrary import CParser
parser = CParser(["<pathToHeader>/file.h")])
print(parser)
https://pygccxml.readthedocs.io/en/master/index.html
运行下面的代码,我得到了很多错误,例如unknown type name 'NSString
并且脚本在 20 个错误后停止,因为发出了太多错误。
from pygccxml import utils
from pygccxml import declarations
from pygccxml import parser
generator_path, generator_name = utils.find_xml_generator()
xml_generator_config = parser.xml_generator_configuration_t(
xml_generator_path=generator_path,
xml_generator=generator_name)
filename = "<pathToHeader>/file.h"
decls = parser.parse([filename], xml_generator_config)
global_namespace = declarations.get_global_namespace(decls)
ns = global_namespace.namespace("ns")
https://www.doxygen.nl/index.html
尽管 Doxygen 本身不是一个解析器,而是一个代码文档工具,但我用它得到了最好的结果。它创建一个包含所有函数名称(甚至正确解析)以及注释的 xml 输出。评论被标记为评论,甚至用行号注明。但是,函数并没有标注行号,所以将正确的注释匹配到正确的函数基本上是不可能的。
我自己创建了一个简单的解析器,它以某种方式工作,但我不能确定我涵盖了这些文件中使用的所有可能的 C 语法,因为文件中使用了不同的语法,我无法手动检查所有文件的语法因为太多了。
functionComments = {}
inComment = False
comment = []
function = None
for i in range(0, len(lines)):
line = lines[i].strip()
if line.startswith("/*"):
inComment = True
elif line.endswith("*/"):
inComment = False
comment.append(line[:-2].strip())
if len(lines) > i+1 and lines[i+1].startswith("- ("):
functionName = lines[i+1]
counter = 2
while len(lines) > i+counter and lines[i+counter] != "\n":
functionName += " " + lines[i+counter].lstrip().split(" API_")[0]
counter += 1
if ":" in functionName:
functionNameParts = functionName.split(":")
functionNamePartsSplitBySpace = []
function = ""
for j in range(0, len(functionNameParts)-1):
functionNamePartsSplitBySpace.append(functionNameParts[j].split(" "))
for k in range(0, len(functionNamePartsSplitBySpace)):
function += functionNamePartsSplitBySpace[k][-1].split(")")[-1] + ":"
else:
function = lines[i+1].split(" NS_AVAILABLE")[0].split(")")[-1]
functionComments[function] = "\n".join(comment)
comment = []
function = None
else:
function = None
comment = []
elif inComment:
if line.startswith("* "):
comment.append(line[2:].strip())
else:
comment.append(line)