Мэтт -
Добро пожаловать на pyparsing!Вы попали в одну из самых распространенных ловушек в работе с pyparsing, и это то, что люди умнее компьютеров.Когда вы смотрите на введенный текст, вы можете легко увидеть, какой текст может быть заголовком, а какой - нет.К сожалению, pyparsing не так интуитивно понятен, поэтому вы должны сказать , что именно может и не может быть текстом.
Когда вы смотрите на образец текста, вы не принятие только любой строки текста в качестве возможного текста в заголовке раздела.Откуда вы знаете, что «какой-то другой заголовок:» недействителен как текст?Потому что вы знаете, что эта строка соответствует одной из известных строк заголовка.Но в своем текущем коде вы сказали pyparsing, что любая коллекция Word(printables)
является допустимым текстом, , даже если эта коллекция является действительным заголовком раздела .
Чтобы исправить это, вы должныдобавьте некоторый явный взгляд на ваш парсер.Pyparsing предлагает две конструкции, NotAny и FollowedBy.NotAny может быть сокращено с помощью оператора '~', поэтому мы можем записать это выражение псевдокода для текста:
text = ~any_section_header + everything_up_to_the_end_of_the_line
Вот полный анализатор, использующий отрицательный взгляд, чтобы убедиться, что вы читаете каждый раздел, разбивая заголовки разделов:
from pyparsing import ParserElement, LineEnd, Literal, restOfLine, ZeroOrMore, Group, StringEnd
test = """
section header 1:
some words can be anything
more words could be anything at all
etc etc lala
some other header:
as before could be anything
hey isnt this fun
"""
ParserElement.defaultWhitespaceChars=(" \t")
NL = LineEnd().suppress()
END = StringEnd()
header_1=Literal('section header 1:')
header_2=Literal('some other header:')
any_header = (header_1 | header_2)
# text isn't just anything! don't accept header line, and stop at the end of the input string
text=Group(~any_header + ~END + restOfLine)
overall_structure = ZeroOrMore(Group(any_header +
Group(ZeroOrMore(text))))
overall_structure.ignore(NL)
from pprint import pprint
print(overall_structure.parseString(test).asList())
В моей первой попытке я забыл также искать конец строки, поэтому мое выражение restOfLine зациклилось навсегда.Добавив второй запрос конца строки, моя программа успешно завершается.Упражнение, оставленное для вас: вместо перечисления всех возможных заголовков определите строку заголовка как любую строку, заканчивающуюся символом ':'.
Удачи в ваших усилиях по переносу, - Пол