Разбор списка с помощью pyparsing

Можно ли дать pyparsing проанализированный список и вернуть исходную строку?


person adinsa    schedule 06.07.2010    source источник
comment
Возможно - не могли бы вы отредактировать свой вопрос, включив в него примеры до и после?   -  person PaulMcG    schedule 06.07.2010
comment
Это может быть связанная ветка обсуждения (pyparsing.wikispaces.com/message/view/home/ 19406599), обсуждая возможность двунаправленного анализа для pyparsing.   -  person PaulMcG    schedule 13.07.2010


Ответы (1)


Да, можете, если вы дали парсеру указание не отбрасывать ввод. Вы делаете это с помощью комбинатора Combine.

Допустим, ваш ввод:

>>> s = 'abc,def,  ghi'

Вот синтаксический анализатор, который получает точный текст списка:

>>> from pyparsing import *
>>> myList = Word(alphas) + ZeroOrMore(',' + Optional(White()) + Word(alphas))
>>> myList.leaveWhitespace()
>>> myList.parseString(s)
(['abc', ',', 'def', ',', '  ', 'ghi'], {})

Чтобы «разобрать»:

>>> reconstitutedList = Combine(myList)
>>> reconstitutedList.parseString(s)
(['abc,def,  ghi'], {})

который возвращает вам исходный ввод.

Но за это приходится платить: все эти лишние пробелы, плавающие в виде токенов, обычно неудобны, и вы заметите, что нам пришлось явно отключить пропуск пробелов отключить в myList. Вот версия, которая удаляет пробелы:

>>> myList = Word(alphas) + ZeroOrMore(',' + Word(alphas))
>>> myList.parseString(s)
(['abc', ',', 'def', ',', 'ghi'], {})
>>> reconstitutedList = Combine(myList, adjacent=False)
>>> reconstitutedList.parseString(s)
(['abc,def,ghi'], {})

Обратите внимание, что на данный момент вы не получаете буквальный ввод обратно, но этого может быть достаточно для вас. Также обратите внимание, что мы должны были явно указать Combine разрешить пропуск пробелов.

Однако на самом деле во многих случаях вы даже не заботитесь о разделителях; вы хотите, чтобы синтаксический анализатор сосредоточился на самих элементах. Есть функция commaSeparatedList, которая удобно удаляет как разделители, так и пробелы:

>>> myList = commaSeparatedList
>>> myList.parseString(s)
(['abc', 'def', 'ghi'], {})

В этом случае, однако, шаг «депарсинга» не имеет достаточно информации, чтобы восстановленная строка имела смысл:

>>> reconstitutedList = Combine(myList, adjacent=False)
>>> reconstitutedList.parseString(s)
(['abcdefghi'], {})
person Owen S.    schedule 08.07.2010
comment
Я должен сказать, что для такого расплывчатого вопроса вы действительно взяли его и убежали. Любить это! - person jathanism; 08.07.2010
comment
Отличный ответ и спасибо за участие в теме pyparsing! Также проверьте недавно добавленный вспомогательный метод originalTextFor для некоторых возможностей, подобных описанным вами, но которые могут сохранять даже промежуточные пробелы. - person PaulMcG; 13.07.2010
comment
Классный совет, Павел! Я искал именно такую ​​вещь, но не нашел ее, потому что 1) ссылка на документацию API на странице pyparsing не работает, и 2) онлайн-документы UCSC, которые я нашел, вероятно, устарели. Надеюсь, мы сможем обновить один или другой! Я посмотрю последний источник + документ. - person Owen S.; 13.07.2010