анализиране на вложени групи (низове в кавички) с pyparsing (латекс)

Искам да анализирам евентуално вложени групи в LaTeX файл: нещо подобно:

import pyparsing as pp
qs = pp.QuotedString(quoteChar='{', endQuoteChar='}')
s = r'''{ This is a \textbf{\texttt{example}} of \textit{some $\mb{y}$ text} to parse.}'''
print qs.parseString(s)

Но това не може да е правилно (спира на първата затваряща скоба). Резултатът е:

([' This is a \\textbf{\\texttt{example'], {})

Как мога да получа резултат, който мога да повторя, мисля за връщане като това, ако всичко, което исках, бяха групите:

{ This is a \textbf{\texttt{example}} of \textit{some $\mb{y}$ text} to parse.}
{\texttt{example}}
{example}
{some $\mb{y}$ text}
{y}

Случаят на използване е да се тества изходен файл на LaTeX за често срещани грешки при маркиране.


person Tim    schedule 20.09.2013    source източник
comment
Вижте дали nestedExpr на pyparsing може да е по-добър избор от QuotedString.   -  person PaulMcG    schedule 21.09.2013


Отговори (1)


Ключът тук е, че вложените скоби трябва да бъдат правилно съпоставени със затварящата им скоба. Граматиката, както сте я написали, наистина ще спре до първата затваряща скоба, а не до съответстващата затваряща скоба. Решението е да се дефинира граматика, така че новите отварящи скоби да се съпоставят като друг раздел.

import pyparsing as pp

allSections = []
def rememberSection(m):
    allSections.append(''.join(m))
other = pp.Word(pp.printables.replace('{','').replace('}','') + ' \t\r\n')
section = pp.Forward()
section << ('{' + pp.OneOrMore(other | section) + '}').setParseAction(rememberSection)

s = r'''{ This is a \textbf{\texttt{example}} of \textit{some $\mb{y}$ text} to parse.}'''
print section.parseString(s)
print allSections

Това определя какво е позволено да бъде вътре в раздел като всичко с изключение на скобите или друг раздел. След това всяка скоба се съпоставя със съответната затваряща скоба. Ако скобите не съвпадат, ще бъде повдигнато pyparsing.ParseException.

Обикновено всички токени ще бъдат върнати като списък с токени, всеки от които съвпада с „{“, „}“ или поредица от други знаци без скоби. Тъй като искаме всеки израз в скоби да бъде запомнен, parseAction тук ги добавя към външен списък. Не съм сигурен за някакъв по-чист начин да се справя, но това ще създаде списъка allSections, който съдържа групите, както искате.

person Eldritch Cheese    schedule 20.09.2013
comment
Добро използване на Forward за дефиниране на израз за рекурсивен анализ. Последните издания на pyparsing имат добавен аргумент към Word за опростяване на правенето на всички печатни файлове с изключение на x - Word(printables, excludeChars="{}"). - person PaulMcG; 21.09.2013