pyparsing异常解释:需要更精确的错误位置信息



下面是一段产生异常的代码:

from pyparsing import *
strg = 'ab3jh-lokdk-12345-lopf9$ab3jh-lokdk-12345-lopfr'
# strg = 'ab3jh-lokdk-12345-lopf9$ab3jh-lokdk-12345-lopf9'
D = Suppress('-')
TYPE_1 = Regex('w{2}dw{2}').setName('tp1')
TYPE_2 = Regex('w{5}').setName('tp2')
TYPE_3 = Regex('d{5}').setName('tp3')
TYPE_4 = Regex('w{4}d').setName('tp4')
ELM = Group(TYPE_1 + D + TYPE_2 + D + TYPE_3 + D + TYPE_4).setName('elm')
ALL = ELM + (Literal('$')+ELM)[...]
try:
result = ALL.parseString(strg,parseAll=True)
except ParseException as parse_err:
print(parse_err.explain())

打印的异常解释如下:

ab3jh-lokdk-12345-lopf9$ab3jh-lokdk-12345-lopfr
^
ParseException: Expected end of text, found '$'  (at char 23), (line:1, col:24)
pyparsing.core.StringEnd - StringEnd

可以看到,错误显示在美元符号上,而实际上是在最后一个字符上。是否有一种方法可以让pyparsing指示错误实际在哪里(意思是第二组的最后一个字符)?

是的,pyparsing有时会冒泡异常。您可以使用"-"操作符,而不是"+"作为一种说法,"如果在这里之后有解析不匹配,不要备份并尝试其他东西"。它会触发ParseSyntaxException而不是ParseException,因此要捕获它们,您需要执行除ParseBaseException之外的操作。

在解析器中,尝试用:

替换ELM
ELM = Group(TYPE_1 + D - TYPE_2 + D + TYPE_3 + D + TYPE_4).setName('elm')

它基本上是说"一旦你看到TYPE_1和"-",之后最好有一个有效的ELM,如果没有,这是一个语法错误。"不过也不要太过火,只是替换掉每一个"+"与"产生绯闻;-只在那些你希望解析器提交解析表达式的其余部分或只是放弃异常的地方执行。