Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PLY:解析错误。意外匹配空令牌集的规则_Python_Parsing_Yacc_Ply_Left Recursion - Fatal编程技术网

Python PLY:解析错误。意外匹配空令牌集的规则

Python PLY:解析错误。意外匹配空令牌集的规则,python,parsing,yacc,ply,left-recursion,Python,Parsing,Yacc,Ply,Left Recursion,所以我试图用PLY构建一个解析器,但它不起作用。它给了我一些我似乎无法解决的错误。为了测试的目的,我提取了解析器的一小部分放在另一个文件中:它也不工作 下面是一个我似乎无法解决的简化问题: 输入示例 #Trying to parse properties following the patter X1[some text]X2[other text] #Simplified input used GM[1]US[hello] 据我所知,解析器读取第一个属性(GM[1]),并在第二个属性上触发一

所以我试图用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])匹配规则属性,第二个匹配属性列表。但是我认为第一个规则匹配属性属性列表(作为属性列表中的空产品),这将减少到属性。然后,没有更多的规则可供读取第二个属性

以下是解析器的输出:

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
输入

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')))
结果

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')))
谢谢你的帮助


Loïc.

Ply解析器的结果包含在docstring中,docstring是函数开头的第一个字符串文字(如果有)

因此,
p\u property\u list
的文档字符串是
property\u list:
。(您可以通过查看
p\u属性列表来确认这一点.\uuuu文档\uuuu
),这就是Ply所看到的全部内容。如果要为单个函数提供多个产品,请使用单个多行字符串文字,这就是为什么您通常会将原始字符串文字视为docstring:

def p_属性_列表(self,p):
“”属性列表:
|属性列表属性
"""
# ...
然而,在这种情况下使用两个不同的函数是很常见的。见下文


除非必要,否则不要使用正确的递归。正确的语法是:

property_list: property
             | property_list property

property: PROPERTY_NAME single_property_content
如果愿意,可以调用第一个产品
属性
,但不需要两个不同的非终端。(您可能也不需要
单个属性内容
,但这取决于语法的其余部分。)

在帘布层中,无需将缩减功能与非端子对齐。对于减少操作不同的不同备选方案,使用不同的函数是很常见的,您通常可以为不同的非终端组合类似的产品。举个简单的例子:

#此函数可用作任何列表非终端的基本情况
#其语义值为列表(且其基本大小写不为空)
def p_列表_基础(自身,p):
“”属性\u列表:属性
函数列表:函数
"""
p[0]=[p[1]]
#此函数可用作任何非终端列表的递归
#其语义值为列表。
def p_列表再次出现(自身,p):
“”“属性列表:属性列表属性”
函数列表:函数列表函数
"""
p[1]。追加(p[2])
p[0]=p[1]

非常感谢。这很好用。但是,不需要文档字符串。如果第一次应用您的解决方案(带有文档字符串),它就成功了。但我已经看到了使用常规引号的示例,所以我删除了文档字符串,并用常规引号替换它们。它仍然有效。我更喜欢这种方式,因为与文档字符串相比,我的编辑器为常规字符串着色的方式。谢谢@loic:如果docstring是字符串文字,则它只是函数的第一条语句。不管它是什么类型的字符串文字或使用什么类型的引号。原始字符串(三重引号字符串文本)也只是普通字符串,但如果需要字符串跨越多行或包含许多特殊字符,则它们非常方便,这就是为什么它们经常用于正则表达式。我回答的要点是,您只能有一个docstring;您不正确的函数有两个。感谢您对doc字符串的澄清(我对python及其词汇表/概念不熟悉)。当我使用带有2个属性的玩具示例进行解析时,一切都正常,我认为这就结束了,但当我添加更多属性时,解析器再次生成错误。因为StackOverflow的目标是建立一个问答知识库,所以问题标题的主要目的是让其他人确定这个问题的答案是否对他们有帮助。这就是说,它不应该用来帮助人们决定他们是否可以帮助你——首先,它应该是为那些在未来对Ply有问题的人写的,以便他们快速决定你的问题的答案是否可能对他们有帮助;现在,它不能帮助任何人区分他们的特定解析错误是否就是这个问题的答案地址。比如说,Ply规则意外地匹配空的标记集会是一个准确的(更有用的特定)标题吗?嗨,Charles。我修改了标题,正如建议的那样。顺便说一句,有些东西仍然可以是没有三重引号的docstring。