我正在尝试创建一个解析器,以将“自定义”文件转换为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
}
其他令牌信息, 令牌类型可以是(具有可能的值)
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]
其他解析信息, 目前,我正在尝试将当前词典存储在路径数组中,以允许我将其插入词典和词典中的数组中。
非常感谢任何建议或解决方案,
谢谢。
答案 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]
。
如果您描述了所有规则,它将像这样工作。希望对您有所帮助。