疑似pyparsing最长匹配错误
Suspected pyparsing longest match error
我正在为 DOT 语言开发解析器,但遇到 "subgraph" 语句的问题。
我的 SUBGRAPH 解析表达式正常工作没有任何问题(请参阅下面的片段)但是当我将它添加为 STMT 中的替代项时它无法匹配。
简单测试:
test = '''subgraph cluster01 { n003 ; n004 ; }'''
FRAG_1 = SUBGRAPH + StringEnd()
FRAG_2 = STMT + StringEnd()
res1 = FRAG_1.parseString(test) # OK
res2 = FRAG_2.parseString(test) # ParseException -
错误:
subgraph cluster01 { n003 ; n004 ; }
^
ERROR: Expected end of text (at char 9), (line:1, col:10)
我 怀疑 问题涉及我的 STMT 表达式 - 它贪婪地将关键字 "subgraph" 作为 NODE_STMT 匹配,而不是作为 SUBGRAPH 匹配,但是我的预期是通过使用 "Or" 表达式 ("^"),最长匹配算法将选择 SUBGRAPH 而不是 NODE_STMT。或者它可能是别的东西。
我的部分语法如下:
语法片段:
LCURL = Literal("{").suppress()
RCURL = Literal("}").suppress()
STMTSEP = Literal(";").suppress()
ID = Word(alphas, alphanums + "_")
SUBGRAPH_KW = Keyword("subgraph", caseless=True)
SUBGRAPH = Forward("SUBGRAPH")
NODE_ID = ID("NODE_ID")
NODE_STMT = NODE_ID("NODE")
STMT = NODE_STMT("NODE") ^ SUBGRAPH("SUBGRAPH")
STMT_LIST = ZeroOrMore(STMT("STMT") + Optional(STMTSEP))
SUBGRAPH << Group(SUBGRAPH_KW + ID("SUBGRAPHNAME")) + Group(LCURL + STMT_LIST + RCURL)
这是因为您要在此行中创建 SUBGRAPH
对象的 copy:
STMT = NODE_STMT("NODE") ^ SUBGRAPH("SUBGRAPH")
调用 setResultsName()
,调用语法是 creates a copy of the ParserElement object.
的快捷方式
这是一个问题,因为 SUBGRAPH
是一个 Forward
对象,此时在代码中它还没有完全定义。
您真的不应该随时随地为所有内容设置名称!在实际需要的时间和地点执行此操作,并记住它会创建 ParserElement
个对象的副本。
一般来说,我建议在将表达式组装成更高级别的表达式之前不要分配结果名称,如下所示:
intnum = Word(nums).setParseAction(lambda t: int(t[0]))
realnum = Combine(Word(nums) + '.' + Word(nums)).setParseAction(lambda t: float(t[0]))
hostname = Word(alphas, alphanums+'-')
timestamp = Regex(r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d')
statslogentry = (timestamp('timestamp') + hostname('hostname') +
'CPU:' + realnum('cpu') +
'DISK_IO:' + intnum('disk_io') +
'NETWORK_IO:' + intnum('network_io'))
但是,当使用 Forward
时,这可能会对您不利,就像这里的情况一样。 OP 代码中的一个特定错误是
SUBGRAPH = Forward("SUBGRAPH")
我认为 OP 试图使用结果名称快捷方式,但实际上是在创建内容为 Literal("SUBGRAPH")
的 Forward
。将其更改为
SUBGRAPH = Forward()("SUBGRAPH")
并从 Or
表达式中删除结果名称将解决原始问题。但我仍然认为这有点属于 "gotcha" 类别。
我正在为 DOT 语言开发解析器,但遇到 "subgraph" 语句的问题。
我的 SUBGRAPH 解析表达式正常工作没有任何问题(请参阅下面的片段)但是当我将它添加为 STMT 中的替代项时它无法匹配。
简单测试:
test = '''subgraph cluster01 { n003 ; n004 ; }'''
FRAG_1 = SUBGRAPH + StringEnd()
FRAG_2 = STMT + StringEnd()
res1 = FRAG_1.parseString(test) # OK
res2 = FRAG_2.parseString(test) # ParseException -
错误:
subgraph cluster01 { n003 ; n004 ; }
^
ERROR: Expected end of text (at char 9), (line:1, col:10)
我 怀疑 问题涉及我的 STMT 表达式 - 它贪婪地将关键字 "subgraph" 作为 NODE_STMT 匹配,而不是作为 SUBGRAPH 匹配,但是我的预期是通过使用 "Or" 表达式 ("^"),最长匹配算法将选择 SUBGRAPH 而不是 NODE_STMT。或者它可能是别的东西。
我的部分语法如下:
语法片段:
LCURL = Literal("{").suppress()
RCURL = Literal("}").suppress()
STMTSEP = Literal(";").suppress()
ID = Word(alphas, alphanums + "_")
SUBGRAPH_KW = Keyword("subgraph", caseless=True)
SUBGRAPH = Forward("SUBGRAPH")
NODE_ID = ID("NODE_ID")
NODE_STMT = NODE_ID("NODE")
STMT = NODE_STMT("NODE") ^ SUBGRAPH("SUBGRAPH")
STMT_LIST = ZeroOrMore(STMT("STMT") + Optional(STMTSEP))
SUBGRAPH << Group(SUBGRAPH_KW + ID("SUBGRAPHNAME")) + Group(LCURL + STMT_LIST + RCURL)
这是因为您要在此行中创建 SUBGRAPH
对象的 copy:
STMT = NODE_STMT("NODE") ^ SUBGRAPH("SUBGRAPH")
调用 setResultsName()
,调用语法是 creates a copy of the ParserElement object.
这是一个问题,因为 SUBGRAPH
是一个 Forward
对象,此时在代码中它还没有完全定义。
您真的不应该随时随地为所有内容设置名称!在实际需要的时间和地点执行此操作,并记住它会创建 ParserElement
个对象的副本。
一般来说,我建议在将表达式组装成更高级别的表达式之前不要分配结果名称,如下所示:
intnum = Word(nums).setParseAction(lambda t: int(t[0]))
realnum = Combine(Word(nums) + '.' + Word(nums)).setParseAction(lambda t: float(t[0]))
hostname = Word(alphas, alphanums+'-')
timestamp = Regex(r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d')
statslogentry = (timestamp('timestamp') + hostname('hostname') +
'CPU:' + realnum('cpu') +
'DISK_IO:' + intnum('disk_io') +
'NETWORK_IO:' + intnum('network_io'))
但是,当使用 Forward
时,这可能会对您不利,就像这里的情况一样。 OP 代码中的一个特定错误是
SUBGRAPH = Forward("SUBGRAPH")
我认为 OP 试图使用结果名称快捷方式,但实际上是在创建内容为 Literal("SUBGRAPH")
的 Forward
。将其更改为
SUBGRAPH = Forward()("SUBGRAPH")
并从 Or
表达式中删除结果名称将解决原始问题。但我仍然认为这有点属于 "gotcha" 类别。