【发布时间】:2017-09-12 10:21:56
【问题描述】:
所以我正在尝试使用 PLY 构建解析器,但它不起作用。它给了我似乎无法解决的错误。我提取了我放入另一个文件的解析器的一小部分,用于测试目的:它也不起作用。
这是我似乎无法解决的简化问题:
输入示例
#Trying to parse properties following the patter X1[some text]X2[other text]
#Simplified input used
GM[1]US[hello]
据我了解,解析器读取第一个属性 (GM[1]) 并在第二个属性上触发错误。他正在采取尽可能短的减少(我的规则确实允许)并读取单个属性。然后,第二个规则就没有规则可循了,这会触发错误。
所以问题是:你能帮我正确地写下我的规则吗?
parser.py
#For simplicity, i only give you the rules, and removed operations on the tree.
def p_properties(self,p):
"properties : property property_list"
def p_property_list(self,p):
"property_list : "
" | properties"
def p_property(self,p):
"property : PROPERTY_NAME single_property_content"
def p_single_property_content(self,p):
"single_property_content : OBRACKET TEXT CBRACKET"
起始规则是“属性”。我希望输入属性 (GM[1]) 匹配规则 property,第二个匹配 match property_list。但我认为第一条规则匹配property AND property_list(作为property_list 中的空产生式),这简化为properties。那么,就没有更多的规则可供读取第二个属性了。
这是解析器的输出:
State : 0
Stack : . LexToken(PROPERTY_NAME,'GM',1,0)
Action : Shift and goto state 2
State : 2
Stack : PROPERTY_NAME . LexToken(OBRACKET,'[',1,2)
Action : Shift and goto state 4
State : 4
Stack : PROPERTY_NAME OBRACKET . LexToken(TEXT,'1',1,3)
Action : Shift and goto state 7
State : 7
Stack : PROPERTY_NAME OBRACKET TEXT . LexToken(CBRACKET,']',1,4)
Action : Shift and goto state 8
State : 8
Defaulted state 8: Reduce using 4
Stack : PROPERTY_NAME OBRACKET TEXT CBRACKET . None
Action : Reduce rule [single_property_content -> OBRACKET TEXT CBRACKET] with ['[','1',']'] and goto state 5
Result : <tuple @ 0x7fea37eb4588> (('single_property_content', '1'))
State : 5
Defaulted state 5: Reduce using 3
Stack : PROPERTY_NAME single_property_content . None
Action : Reduce rule [property -> PROPERTY_NAME single_property_content] with ['GM',<tuple @ 0x7fea37eb4588>] and goto state 3
Result : <tuple @ 0x7fea3964f798> (('property', 'GM', ('single_property_con ...)
State : 3
Defaulted state 3: Reduce using 2
Stack : property . None
Action : Reduce rule [property_list -> <empty>] with [] and goto state 6
Result : <NoneType @ 0xa3f020> (None)
State : 6
Defaulted state 6: Reduce using 1
Stack : property property_list . None
Action : Reduce rule [properties -> property property_list] with [<tuple @ 0x7fea3964f798>,None] and goto state 1
Result : <tuple @ 0x7fea3964f678> (('properties', ('property', 'GM', ('sing ...)
State : 1
Stack : properties . LexToken(PROPERTY_NAME,'US',1,5)
ERROR: Error : properties . LexToken(PROPERTY_NAME,'US',1,5)
Error while parsing : LexToken(PROPERTY_NAME,'US',1,5)
State : 1
Stack : properties . error
ERROR: Error : properties . error
State : 0
Stack : . error
ERROR: Error : . error
State : 0
Stack : . LexToken(OBRACKET,'[',1,7)
ERROR: Error : . LexToken(OBRACKET,'[',1,7)
State : 0
Stack : . LexToken(TEXT,'hello',1,8)
ERROR: Error : . LexToken(TEXT,'hello',1,8)
State : 0
Stack : . LexToken(CBRACKET,']',1,13)
ERROR: Error : . LexToken(CBRACKET,']',1,13)
State : 0
Stack : . $end
ERROR: Error : . $end
None
我以 15 种不同的方式(右递归、左递归)修改了这些规则,但均无济于事。你们能告诉我我做错了什么吗?
编辑 在实施解决方案时遇到了一些麻烦(仅在我解析 2 个元素但解析更多创建的错误时才有效),感谢@rici 的帮助,我设法使其工作。
解决方案
def p_properties(self,p):
"""
properties : property_list property
"""
p[0] = ('properties',p[1], p[2])
def p_property_list(self,p):
"""
property_list : property_list property
|
"""
if(len(p)==3):
p[0] = ('property_list',p[1],p[2])
def p_property(self,p):
"""
property : PROPERTY_NAME property_content_list
"""
p[0] = ('property', p[1], p[2])
输入
GM[1]AP[hello]AW[world]C[1.this is a comment]C[2.this is a comment]C[3.this is a comment]
TM[50]WR[alalala]GM[will it fail?]GM[should succeed]
结果
('properties', ('property_list', ('property_list', ('property_list',
('property_list', ('property_list', ('property_list',
('property_list',('property_list', ('property_list', None,
('property', 'GM', ('property_content', '1'))),
('property', 'AP', ('property_content','hello'))),
('property', 'AW', ('property_content', 'world'))),
('property', 'C', ('property_content', '1.this is a comment'))),
('property', 'C', ('property_content', '2.this is a comment'))),
('property', 'C', ('property_content', '3.this is a comment'))),
('property', 'TM', ('property_content', '50'))), ('property', 'WR',
('property_content', 'alalala'))), ('property', 'GM',
('property_content','will it fail?'))),
('property', 'GM', ('property_content', 'should succeed')))
感谢您的帮助。
洛伊克。
【问题讨论】:
-
由于 StackOverflow 的目标是建立一个问答知识库,问题标题的主要目的是让其他人确定该问题的答案是否会对他们有所帮助。也就是说,它不应该是为了帮助人们决定他们是否可以帮助你——首先,它应该是为了将来对 Ply 有问题的人来快速决定你的问题的答案是否可能对他们有所帮助。
-
我很确定“Ply:解析错误(简单问题)”可以为此改进;现在它不能帮助任何人区分他们的具体解析错误是否是这个问题的答案地址。
-
比方说,Ply 规则意外匹配空的标记集会是一个准确(并且更具体)的标题吗?
-
你好,查尔斯。我按照建议修改了标题。
-
顺便说一句,有些东西仍然可以是没有三引号的文档字符串。
标签: python parsing yacc ply left-recursion