Трудно сделать простой анализ в pyparsing - PullRequest
3 голосов
/ 23 ноября 2011

У меня есть некоторые основные проблемы с использованием pyparsing. Ниже приведена тестовая программа и вывод прогона.

aaron-mac:sql aaron$ more s.py

from pyparsing import *

n = Word(alphanums)
a = Group( n | Group( n + OneOrMore( Suppress(",") + n )))
p = Group( a + Suppress(".") )
print a.parseString("first")
print a.parseString("first,second")
print p.parseString("first.")
print p.parseString("first,second.")


aaron-mac:sql aaron$ python s.py
[['first']]
[['first']]
[[['first']]]
Traceback (most recent call last):
 File "s.py", line 15, in <module>
   print p.parseString("first,second.")
 File "/Library/Python/2.6/site-packages/pyparsing.py", line 1032, in parseString
   raise exc
pyparsing.ParseException: Expected "." (at char 5), (line:1, col:6)
aaron-mac:sql aaron$ 

Как изменить грамматику в тестовой программе, чтобы проанализировать список разделенных запятыми имен, оканчивающихся точкой? Я просмотрел документы и попытался найти живой список поддержки, но решил, что, скорее всего, получу ответ здесь.

Ответы [ 2 ]

5 голосов
/ 23 ноября 2011

'|'Оператор создает выражение 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".

2 голосов
/ 23 ноября 2011

Если вы просто хотите охватить случай списка имен через запятую, оканчивающегося на точку, вы можете использовать следующее:

from pyparsing import *
p = Word(alphanums)+ZeroOrMore(Suppress(",")+Word(alphanums))+Suppress(".")

При этом вы получите следующие результаты:

>>> print p.parseString("first.")
['first']
>>> print p.parseString("first,second.")
['first', 'second']

Другие примеры в вашем вопросе терпят неудачу, потому что они не заканчиваются точкой.

...