2010-07-06 17 views
2

Est-il possible de donner à pyparsing une liste analysée et de lui renvoyer la chaîne d'origine?"Deparsing" une liste utilisant pyparsing

+1

Eventuellement - pourriez-vous éditer votre question pour inclure un exemple "avant" et "après"? – PaulMcG

+0

Il s'agit peut-être d'un fil de discussion connexe (http://pyparsing.wikispaces.com/message/view/home/19406599), qui décrit la fonctionnalité "bidirectionnelle" pour pyparsing. – PaulMcG

Répondre

6

Oui, vous pouvez si vous avez demandé à l'analyseur de ne pas supprimer d'entrée. Vous le faites avec le combinateur Combine.

Disons que votre entrée est:

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

Voici un analyseur qui saisit le texte exact de la liste:

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

Pour "Deparse":

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

qui donne vous l'entrée initiale de retour.

Mais cela a un coût: ayant tout ce que des espaces supplémentaires flottant autour des jetons est généralement pas pratique, et vous remarquerez que nous avons dû refuser explicitement sauter des espaces hors dans myList. Voici une version qui déshabille les espaces:

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

Notez que vous n'êtes pas obtenir l'entrée littérale revenir à ce point, mais cela peut être assez bon pour vous. Notez également que nous devions explicitement dire à Combine d'autoriser le saut d'espace. En réalité, cependant, dans la plupart des cas, vous ne vous souciez même pas des délimiteurs; vous voulez que l'analyseur se concentre sur les éléments eux-mêmes. Il y a une fonction appelée commaSeparatedList que les bandes commodément les délimiteurs et les espaces pour vous:

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

Dans ce cas, cependant, le « deparsing » étape n'a pas assez d'informations pour la chaîne reconstituée pour donner un sens:

>>> reconstitutedList = Combine(myList, adjacent=False) 
>>> reconstitutedList.parseString(s) 
(['abcdefghi'], {}) 
+0

Je dois dire pour une question si vague que vous avez vraiment pris celui-ci et a couru. Aimer! – jathanism

+1

Bonne réponse et merci d'avoir choisi le sujet de pyparsing! Jetez également un coup d'œil à la méthode d'assistance 'originalTextFor' récemment ajoutée pour des fonctionnalités similaires à celles que vous décrivez, mais qui peuvent préserver même les espaces intermédiaires. – PaulMcG

+0

Cool conseil, Paul! Je cherchais juste une telle chose mais ne l'ai pas trouvée parce que 1) le lien de documentation d'API sur la page de pyparsing est cassé, et 2) les docs en ligne d'UCSC que j'ai trouvés sont probablement datés. J'espère que nous pouvons mettre à jour l'un ou l'autre! Je vais jeter un oeil à la dernière source + doc. –