类似于json python的文件的自定义解析器

时间:2018-11-13 00:38:52

标签: python json algorithm parsing lexical-analysis

我正在尝试创建一个解析器,以将“自定义”文件转换为JSON,以便我可以更轻松地操纵其内容(出于参数的考虑,将“自定义”格式称为.qwerty)。

我已经创建了一个Lexer,它将文件分解为单个词素(令牌),其结构为[token_type,token_value]。现在,我正在努力将词素解析为其正确的字典,因为Keys并不是恒定的,因此很难将数据插入到子子字典中。以及将数据插入存储在字典中的数组中。

应注意,我正在尝试将标记顺序解析为实际的python json对象,然后转储json对象。

下面可以看到文件的示例,以及最终结果的相似之处。

文件:ABC.querty

Dict_abc_1{

    Dict_abc_2{
        HeaderGUID="";
        Version_TPI="999";
        EncryptionType="0";
    }

    Dict_abc_3{
        FamilyName="John Doe";
    }

    Dict_abc_4{
        Array_abc{
            {TimeStamp="2018-11-07 01:00:00"; otherinfo="";}
            {TimeStamp="2018-11-07 01:00:00"; otherinfo="";}
            {TimeStamp="2018-11-07 01:00:00"; otherinfo="";}
            {TimeStamp="2018-11-07 02:53:57"; otherinfo="";}
            {TimeStamp="2018-11-07 02:53:57"; otherinfo="";}
        }

        Dict_abc_5{
            LastContact="2018-11-08 01:00:00";
            BatteryStatus=99;
            BUStatus=PowerOn;
            LastCallTime="2018-11-08 01:12:46";
            LastSuccessPoll="2018-11-08 01:12:46";
            CallResult=Successful;
        }
    }
}
Code=999999;

文件:ABC.json

{  
    "Dict_abc_1":{
        "Dict_abc_2":{
            "HeaderGUID":"",
            "Version_TPI":"999",
            "EncryptionType":"0"
        },

        "Dict_abc_3":{
            "FamilyName":"John Doe"
        },

        "Dict_abc_4":{
            "Array_abc":[
                {"TimeStamp":"2018-11-07 01:00:00", "otherinfo":""},
                {"TimeStamp":"2018-11-07 01:00:00", "otherinfo":""},
                {"TimeStamp":"2018-11-07 01:00:00", "otherinfo":""},
                {"TimeStamp":"2018-11-07 02:53:57", "otherinfo":""},
                {"TimeStamp":"2018-11-07 02:53:57", "otherinfo":""}
            ],

            "Dict_abc_5":{
                "LastContact":"2018-11-08 01:00:00",
                "BatteryStatus":99,
                "BUStatus":"PowerOn",
                "LastCallTime":"2018-11-08 01:12:46",
                "LastSuccessPoll":"2018-11-08 01:12:46",
                "CallResult":"Successful"
            }
        }
    },
    "Code":999999
}

其他令牌信息, 令牌类型可以是(具有可能的值)

  • IDENTIFIER 包含变量标识符的名称
  • 变量包含属于父IDENTIFIER的实际数据
  • 操作员等于“ =”
  • OPEN_BRACKET 等于“ {”
  • CLOSE_BRACKET 等于“}”

ABC.querty的词素的一个例子可以看到HERE

main.py

的基本逻辑摘录
def main():
    content = open_file(file_name) ## read file

    lexer = Lexer(content) ## create lexer class
    tokens = lexer.tokenize() ## create lexems as seen in pastebin

    parser = Parser(tokens).parse() ## create parser class given tokens 

    print(json.dumps(parser, sort_keys=True,indent=4, separators=(',', ': ')))

parser.py

import re

class Parser(object):
    def __init__(self, tokens):
        self.tokens = tokens
        self.token_index = 0
        self.json_object = {}
        self.current_object = {}
        self.path = [self.json_object]

    def parse(self):
        while self.token_index < len(self.tokens):

            token = self.getToken()
            token_type = token[0]
            token_value = token[1]

            print("%s \t %s" % (token_type, token_value))

            if token_type in "IDENTIFIER":
                self.increment()
                identifier_type = self.getToken()
                if identifier_type[0] in "OPEN_BRACKET":
                    identifier_two_type = self.getToken(1)
                    if identifier_two_type[0] in ["OPERATOR","IDENTIFIER"]:
                        ## make dict in current dict 
                        pass

                    elif identifier_two_type[0] in "OPEN_BRACKET":
                        ## make array in current dict 
                        pass

                elif identifier_type[0] in "OPERATOR":
                    ## insert data into current dict
                    pass


            if token_type in "CLOSE_BRACKET":
                identifier_type = self.getToken()
                if "OPEN_BRACKET" in identifier_type[0]:
                    #still in array of current dict
                    pass
                elif "IDENTIFIER" in identifier_type[0]:
                    self.changeDirectory()

                else:
                    #end script
                    pass

            self.increment()
        print(self.path)
        return self.json_object


    def changeDirectory(self):
        if len(self.path) > 0:
            self.path = self.path.pop()
            self.current_object = -1

    def increment(self):
        if self.token_index < len(self.tokens):
            self.token_index+=1

    def getToken(self, x=0):
        return self.tokens[self.token_index+x]

其他解析信息, 目前,我正在尝试将当前词典存储在路径数组中,以允许我将其插入词典和词典中的数组中。

非常感谢任何建议或解决方案,

谢谢。

1 个答案:

答案 0 :(得分:1)

上次我解决了这个问题,发现有限状态机非常有帮助。在您拥有令牌后,我想推荐这种方式,但是我不知道它是怎么用英语称呼的。原理是:您遍历令牌并在堆栈中一一添加。在堆栈上添加之后,您正在检查堆栈中的一些规则。就像您将原始标记组合到表达式中一样,这些表达式可能是更复杂的表达式的一部分。

例如"FamilyName":"John Doe"。令牌为"FamilyName":"John Doe"

您在堆栈上添加了第一个令牌。 stack = ["FamilyName"]。 规则1:str_obj -> E。因此,您创建了Expression(type='str', value="FamilyName"),现在堆栈为stack = [Expression]

然后添加下一个令牌。 stack = [Expression, ':']':'没有规则。接下来。

stack = [Expression, ':', "FamilyName"]。我们再次符合规则1。因此堆栈变为stack = [Expression, ':', Expression]。然后我们看到另一个规则。规则2:E:E -> E。像Expression(type='kv_pair, value=(Expression, Expression))一样使用它。堆栈变成stack=[Expression]

如果您描述了所有规则,它将像这样工作。希望对您有所帮助。