Обычно, когда я вижу «в любом порядке» как часть грамматики, моей первой мыслью является использование Each
, которое вы можете создать с помощью оператора &
:
undelimited_foo_bar_baz = foo & bar & baz
Это Парсер будет анализировать foo
, bar
и baz
в любом порядке. Если вы хотите, чтобы они были необязательными, просто заключите их в необязательные значения:
undelimited_foo_bar_baz = Optional(foo) & Optional(bar) & Optional(baz)
Но запятые в вашем входе делают этот вид грязным, поэтому в качестве запасного варианта вы можете придерживаться delimitedList
(который уберет запятые) добавьте действие разбора условия для запуска после анализа списка, чтобы убедиться, что присутствовал только один из каждого соответствующего элемента:
from collections import Counter
def no_more_than_one_of_any(t):
return all(freq == 1 for freq in Counter(t.asList()).values())
foobarbaz.addCondition(no_more_than_one_of_any, message="duplicate item found in list")
if __name__ == "__main__":
tests = '''\
"foo"
"bar"
"baz"
"foo", "baz"
"foo", "bar", "baz"
"foo", "bar", "baz", "foo"
'''
foobarbaz.runTests(tests)
Печать:
"foo"
['foo']
"bar"
['bar']
"baz"
['baz']
"foo", "baz"
['foo', 'baz']
"foo", "bar", "baz"
['foo', 'bar', 'baz']
"foo", "bar", "baz", "foo"
^
FAIL: duplicate item found in list, found '"' (at char 0), (line:1, col:1)