我正在研究一个围绕使用文本字符串指定有线协议格式的问题。基本思想是你只在线上放二进制,因为它是一个低带宽环境。但为了做到这一点,双方必须提前达成一致意味着什么才能使他们能够正确地从电线中提取价值。
为了协调"什么意味着"使用配置文件。它的核心是每个数据包主体都有定义。以下是一些例子:
ABC:16
ABC:15:P
ABC:15:P; def:14:ecc
你指定一个三个或四个字母的标识符,后跟一个颜色,然后是位数(通常是4的倍数,但这不是保证),也可以选择另一个冒号后跟一个" p"意思是有点专门用于平价或者" ecc"这意味着有两个专门用于ecc。
因此,将此翻译为pyparsing就是我所拥有的:
from pyparsing import *
abbr = Word(alphas)
internal_separator = Literal(":")
bits = Word(nums, min=1, max=2)
parity = Or([CaselessLiteral("P"), CaselessLiteral("ECC")])
separator = Literal(";")
parity_part = internal_separator + parity
statement = Group(abbr + internal_separator + bits + Optional(parity_part))
#statement_list = delimitedList(statement, delim=";")
statement_list = statement + ZeroOrMore(separator + statement)
tests = (
"abc:16",
"abc:15:p",
"abc:15:p; def:14:ecc",
"abc:17:p; def:q; ghi:21:", #this one should fail!
)
for t in tests:
try:
print t, "->", statement_list.parseString(t)
except Exception as e:
print e
当我运行时,这是我得到的:
abc:16 -> [['abc', ':', '16']]
abc:15:p -> [['abc', ':', '15', ':', 'P']]
abc:15:p; def:14:ecc -> [['abc', ':', '15', ':', 'P'], ';', ['def', ':', '14', ':', 'ECC']]
abc:17:p; def:q; ghi:21: -> [['abc', ':', '17', ':', 'P']]
我无法理解为什么pyparsing只是在最后一次测试中截断输出。对我来说,它似乎应该失败,因为它无效。我也试过了delimitedList,我得到了同样的行为。
我也尝试过" abbr"最小值为3,最大值为4,因此它可以确定":q"是无效的,但没有改变任何东西。
似乎错误已经被某种方式吞没了,我不知道为什么,也不知道如何让这个错误传播起来以便我能抓住它。
我发现这个问题(Trouble doing simple parse in pyparsing)似乎很相关,但并没有给我答案。
答案 0 :(得分:2)
我可以告诉你为什么会这样,但是这是预期的pyparsing。您必须在语法中添加一个明确的StringEnd()
:
statement_list = statement + ZeroOrMore(separator + statement) + StringEnd()