"A or B or both" 的表达式组合

Expression-combination of "A or B or both"

这是我目前拥有的:

_filter_date_range = pp.Group(_keyword_date + pp.Group(
    pp.Group(_function_before + _argument_string) & pp.Group(_function_after + _argument_string)
))

由于我使用了Each(&),所以这两个表达式都是必需的。但我想允许:

如果我将两个组都设为 Optional,我也不会允许,这是我不希望的。那么有什么我可以用的吗?

以下是三种可能的解决方案:

from pyparsing import Literal, OneOrMore, Optional

A = Literal("A")
B = Literal("B")

language = OneOrMore( A | B )

assert language.matches("A")
assert language.matches("B")
assert language.matches("A B")
assert language.matches("B A")
assert language.matches("A A")
assert language.matches("B B")
assert language.matches("A B A B")
assert not language.matches("")

def EitherOrBoth(a, b):
    return (a + b) | (b + a) | a | b
language = EitherOrBoth(A, B)

assert language.matches("A")
assert language.matches("B")
assert language.matches("A B")
assert language.matches("B A")
assert not language.matches("A A")
assert not language.matches("B B")
assert not language.matches("A B A B")
assert not language.matches("")

def EitherOrBoth(a, b):
    return (a + Optional(b)) | (b + Optional(a))
language = EitherOrBoth(A, B)

assert language.matches("A")
assert language.matches("B")
assert language.matches("A B")
assert language.matches("B A")
assert not language.matches("A A")
assert not language.matches("B B")
assert not language.matches("A B A B")
assert not language.matches("")

@Rob 的第三个选项 EitherOrBoth 在这种情况下效果很好,我认为,但是当你必须处理 3 个或更多可能出现的表达式时,pyparsing 的 Each 真正发挥作用任意顺序:

from pyparsing import Literal, Each

A = Literal("A")
B = Literal("B")
C = Literal("C")

def noMoreThanOneOfEachAndAtLeastOne(exprs):
    ret = Each(map(Optional, exprs))
    ret.addCondition(bool)
    return ret
language = noMoreThanOneOfEachAndAtLeastOne([A,B,C])

assert language.matches("A")
assert language.matches("B")
assert language.matches("A C B")
assert language.matches("C A")
assert not language.matches("A A")
assert not language.matches("B B")
assert not language.matches("A B A B")
assert not language.matches("")

addCondition 是 pyparsing 的一个相当新的补充,addParseAction 的一个变体。 addCondition 接受一个可调用对象(具有与 addParseAction 相同的调用签名支持),它必须 return 一个布尔值。如果它 returns False,则该条件将导致引发 ParseException。 (这是使用解析操作作为验证器的用例的简化。)在这种情况下,我们所需要的只是 Python 内置 bool,因为 ParseResults 与所有 Python 一样本机序列,当为空时求值为 False,否则为 True。