我有一个C头文件,其中包含一系列类,并且我正在尝试编写一个将这些类转换为python dict的函数。该文件的示例位于底部。

格式将类似于

class CFGFunctions {
  class ABC {
    class AA {
      file = "abc/aa/functions"
      class myFuncName{ recompile = 1; };
    };
    class BB
    {
      file = "abc/bb/functions"
      class funcName{
        recompile=1;
      }
    }
  };
};


我希望把它变成像

{CFGFunctions:{ABC:{AA:"myFuncName"}, BB:...}}
# Or
{CFGFunctions:{ABC:{AA:{myFuncName:"string or list or something"}, BB:...}}}


最后,我的目标是获取文件路径字符串(实际上是文件夹的路径...,但无论如何),并且类名称与文件/文件夹路径在同一类中。

我看过SO,Google等,但是我发现的大多数事情都是关于将行拆分为dict,而不是n深度的“块”

我知道我将不得不遍历该文件,但是,我不确定将其转换为dict的最有效方法。
我在想我需要抓住外部类及其相关的括号,然后对保留在内部的文本进行相同的处理。

如果这些都没有道理,那是因为我自己对这个过程还不太了解哈哈

如果需要更多信息,我们很乐意提供。

以下代码是我正在思考的快速模型...
它很可能已损坏,可能无法正常工作。但是我正在考虑的过程

def get_data():
    fh = open('CFGFunctions.h', 'r')
    data = {}    # will contain final data model

    # would probably refactor some of this into a function to allow better looping
    start = ""   # starting class name
    brackets = 0 # number of brackets
    text= ""     # temp storage for lines inside block while looping
    for line in fh:
        # find the class (start
        mt = re.match(r'Class ([\w_]+) {', line)
        if mt:
            if start == "":
                start = mt.group(1)
            else:
                # once we have the first class, find all other open brackets
                mt = re.match(r'{', line)
                if mt:
                    # and inc our counter
                    brackets += 1
                mt2 = re.match(r'}', line)
                if mt2:
                    # find the close, and decrement
                    brackets -= 1
                    # if we are back to the initial block, break out of the loop
                    if brackets == 0:
                        break
                text += line
    data[start] = {'tempText': text}


====

样本文件

class CfgFunctions {
    class ABC {
        class Control {
            file = "abc\abc_sys_1\Modules\functions";
            class assignTracker {
                description = "";
                recompile = 1;
            };

            class modulePlaceMarker {
                description = "";
                recompile = 1;
            };
        };

        class Devices
        {
            file = "abc\abc_sys_1\devices\functions";
            class registerDevice { recompile = 1; };
            class getDeviceSettings { recompile = 1; };
            class openDevice { recompile = 1; };
        };
    };
};


编辑:
如果可能的话,如果我必须使用一个程序包,我希望将其放在程序目录中,而不是常规的python libs目录中。

最佳答案

正如您检测到的那样,解析是进行转换所必需的。看一下PyParsing包,它是一个非常易于使用的库,可以在您的Python程序中实现解析。

编辑:这是识别非常简单的语法的方式的非常象征性的版本-有点像问题顶部的示例。它不会起作用,但是可能会为您提供正确的方向:

from pyparsing import ZeroOrMore, OneOrMore, \
                      Keyword, Literal


test_code = """
class CFGFunctions {
  class ABC {
    class AA {
      file = "abc/aa/functions"
      class myFuncName{ recompile = 1; };
    };
    class BB
    {
      file = "abc/bb/functions"
      class funcName{
        recompile=1;
      }
    }
  };
};
"""

class_tkn       = Keyword('class')
lbrace_tkn      = Literal('{')
rbrace_tkn      = Literal('}')
semicolon_tkn   = Keyword(';')
assign_tkn      = Keyword(';')

class_block     = ( class_tkn + identifier + lbrace_tkn + \
                    OneOrMore(class_block | ZeroOrMore(assignment)) + \
                    rbrace_tkn + semicolon_tkn \
                  )

def test_parser(test):
    try:
        results = class_block.parseString(test)
        print test, ' -> ', results
    except ParseException, s:
        print "Syntax error:", s


def main():
    test_parser(test_code)

    return 0

if __name__ == '__main__':
    main()


另外,此代码只是解析器-它不会生成任何输出。如您在PyParsing文档中所见,您以后可以添加所需的操作。但是第一步是要识别您想要翻译的内容。

最后一点:不要低估解析代码的复杂性……即使使用像PyParsing这样的库来处理很多工作,也有很多方法可以陷入无限循环和其他解析功能中。逐步实施!

编辑:有关PyParsing信息的一些来源是:

http://werc.engr.uaf.edu/~ken/doc/python-pyparsing/HowToUsePyparsing.html

http://pyparsing.wikispaces.com/

(特别有趣的是http://pyparsing.wikispaces.com/Publications,其中包含一长篇文章-其中一些是介绍性的-关于PyParsing)

http://pypi.python.org/pypi/pyparsing_helper是用于调试解析器的GUI

在stackoverflow上还有一个“标记” Pyparsing,Paul McGuire(PyParsing的作者)似乎经常来此。

* 注意: *
来自PaulMcG的以下评论:Pyparsing不再托管在wikispaces.com上。转到github.com/pyparsing/pyparsing

关于python - Python将C头文件转换为字典,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25026932/

10-14 14:07