pyparsing 异常说明:需要有关错误位置的更精确信息

pyparsing exception explaination: need more precise information on error location

这是一段产生异常的代码:

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}\d\w{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,因此要捕获它们,您需要执行 except ParseBaseException.

在您的解析器中,尝试将 ELM 替换为:

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

基本上是在说“一旦你看到 TYPE_1 和“-”,后面最好有一个有效的 ELM,如果不是,那就是语法错误。”不过不要太过分,只需将每个“+”替换为“-”——只需在您希望解析器承诺解析该表达式的其余部分或只是放弃异常的地方执行此操作。