При использовании setResultsName с listAllMatches true некоторые совпадающие элементы являются вложенными

#python #pyparsing

#python #pyparsing

Вопрос:

Основываясь на этой грамматике:

 from pyparsing import *

g = quotedString.setParseAction( removeQuotes )
eg = Suppress('-')   quotedString.setParseAction( removeQuotes )
choice = Or( [ g.setResultsName("out",listAllMatches=True),     
              eg.setResultsName("in",listAllMatches=True) ] )
grammar = ZeroOrMore( choice )   Suppress(restOfLine)

a = world.parseString( ' "ali"  -"baba"  "holy cow"   -"smoking beaute"  ' )
print a.dump()
  

Я обнаружил, что токены, которые удовлетворяют eg нетерминальному параметру, всегда помещаются в дополнительный список. Единственное отличие от g заключается в том, что у него есть ведущее `Suppress(‘-‘)’.

 ['ali', 'baba', 'holy cow', 'smoking beaute']
- in: [['baba'], ['smoking beaute']]
- out: ['ali', 'holy cow']
  

Как заставить их вести себя одинаково? Я хочу добиться результата, приведенного ниже:

 ['ali', 'baba', 'holy cow', 'smoking beaute']
- in: ['baba', 'smoking beaute']
- out: ['ali', 'holy cow']
  

Комментарии:

1. Здесь нет причин для использования Or, первое совпадение является однозначным и лучше справляется с коротким замыканием. Мне также жаль видеть, что синтаксис оператора вам не по вкусу, я думаю, это действительно улучшает читаемость грамматик — но каждому свое.

2. Следующий выпуск pyparsing позволит вам задавать имена результатов с помощью listAllMatches=True, используя форму: choice = Or( [ g("out*"),eg("in*")] ) Действительно ли это предпочтительнее choice = g("out*") | eg("in*") ? Ну, это ваш код…

Ответ №1:

Прошло некоторое время с тех пор, как я рассматривал эту проблему — проблема в том, что И всегда возвращают свои токены в виде списков, даже если содержат только одно значение.

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

 ungroup = lambda expr : TokenConverter(expr).setParseAction(lambda t:t[0])
eg = ungroup(Suppress('-')   quotedString.setParseAction( removeQuotes ))
  

С вашим тестовым кодом я теперь получаю эти результаты:

 ['ali', 'baba', 'holy cow', 'smoking beaute']
- in: ['baba', 'smoking beaute']
- out: ['ali', 'holy cow']
  

Комментарии:

1. Мне удалось устранить проблему, добавив выражение Combine to quoteString. Но помощник по разгруппировке действительно выглядит полезным.