" A或B或两者的表达组合"

时间:2016-06-23 16:28:57

标签: python pyparsing

以下是我目前的情况:

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

由于我使用Each&),因此两个表达式都是必需的。但我想允许:

  • A或B
  • 或两者
  • 但至少有一个
  • 以任何顺序

如果我同时制作两个组Optional,我也不会允许,我不想要。那么我可以使用它吗?

2 个答案:

答案 0 :(得分:3)

@ 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相同的调用签名支持)。如果返回False,则该条件将导致引发ParseException。 (这是使用解析操作作为验证器的用例的简化。)在这种情况下,我们需要的只是Python内置bool,因为ParseResults与所有Python本机序列一样,在空时评估为False否则就是真的。

答案 1 :(得分:2)

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

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("")