'|'Оператор создает выражение MatchFirst, в котором альтернативы оцениваются до первого совпадения.
Pyparsing работает исключительно слева направо, применяя выражения синтаксического анализатора к входной строке, насколько это возможно.Единственное, что делает pyparsing, - это то, что вы пишете в синтаксический анализатор.
В этом выражении:
a = Group( n | Group( n + OneOrMore( Suppress(",") + n )))
Скажем, n
- это просто буквальное "X".Если бы этому синтаксическому анализатору была задана входная строка «X», он, очевидно, соответствовал бы главному, одинокому n
выражению.Если задана строка «X, X, X», она все равно будет соответствовать только ведущему n
, потому что это первая альтернатива в синтаксическом анализаторе.
Если вы перевернете выражение на:
a = Group( Group( n + OneOrMore( Suppress(",") + n )) | n)
, затем для анализа "X" он сначала попытается сопоставить список, который потерпит неудачу, а затем сопоставить одиночному n
.Для разбора «X, X, X» первой альтернативой будет выражение списка, которое будет соответствовать.
Если вы хотите, чтобы самая длинная альтернатива соответствовала, используйте оператор «^», который дает выражение Or,Или оценит все заданные альтернативы, а затем выберет самое длинное совпадение.
a = Group( n ^ Group( n + OneOrMore( Suppress(",") + n )))
Вы также можете упростить это, используя вспомогательный метод pyparsing delimitedList
.Синтаксический анализ списков с одним и тем же выражением, разделенных запятыми, является обычным случаем, поэтому вместо того, чтобы видеть, что людям приходится изобретать expr + ZeroOrMore(Suppress(",") + expr)
снова и снова, я добавил delimitedList
в качестве стандартного помощника по синтаксическому анализу.delimitedList("X")
будет соответствовать как "X", так и "X, X, X".