![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
List ParsersBoost , ,
Парсеры списка генерируются специальным предопределенным объектом генератора парсера list_p, который генерирует парсеры, распознающие структуры списка типа item >> *(delimiter >> item) >> !end где item является выражением, делимитер является делимитером, а конец является необязательным выражением закрытия. Как видите, сгенерированный парсер list_p не распознает пустые списки, т.е. парсер должен найти хотя бы один элемент во входном потоке, чтобы вернуть успешное совпадение. Если вы также хотите сопоставить пустой список, вы можете сделать свой список_p необязательным с оператором! Примером полезного парсера утилиты является разбор запятых, разделенных строками C/C++, которые могут быть легко сформулированы как: rule<> list_of_c_strings_rule = list_p(confix_p('\"', *c_escape_char_p, '\"'), ',') ; Генераторы парсера confix_p и c_escape_char_p описаны here и here. Объект парсерного генератора list_p может использоваться для генерации следующих различных типов парсеров списка:
Все параметры list_p могут быть отдельными символами, строками или, если требуется более сложная логика разбора, вспомогательными парсерами, каждый из которых автоматически преобразуется в соответствующий тип парсера, необходимый для успешного разбора. Если парсер item является типом action_parser_category (парсер с прилагаемым семантическим действием), мы должны сделать что-то особенное. Это происходит, если пользователь написал что-то вроде: list_p(item[func], delim) где item является парсером, соответствующим одному элементу последовательности списка, и func является функтором, который должен быть вызван после сопоставления одного элемента. Если мы ничего не будем делать, полученный код разберет последовательность следующим образом: (item[func] - delim) >> *(delim >> (item[func] - delim)) в большинстве случаев это не то, что ожидает пользователь. (Если это , то, пожалуйста, используйте одну из функций генератора list_p direct(), которая будет препятствовать рефакторингу парсера item). Чтобы сделать список парсера вести себя как ожидалось: (item - delim)[func] >> *(delim >> (item - delim)[func]) актер, прикрепленный к парсеру элемента, должен быть повторно прикреплен к конструкции парсера (пункт - делим) , которая заставит результирующий парсер списка «делать правильные вещи». Рефакторинг осуществляется с помощью парсеров Refactoring. Кроме того, следует соблюдать особую осторожность, если парсер является unary_parser_category Тип парсера, например: list_p(*anychar_p, ',') которые без какого-либо рефакторинга привели бы к (*anychar_p - ch_p(',')) >> *( ch_p(',') >> (*anychar_p - ch_p(',')) ) и не даст ожидаемого результата (первый *anychar_p съест весь вход до конца входного потока). Поэтому мы должны реорганизовать это в: *(anychar_p - ch_p(',')) >> *( ch_p(',') >> *(anychar_p - ch_p(',')) ) что даст правильный результат. Случай, когда парсер является комбинацией двух упомянутых проблем (т.е. парсер является унарным парсером с прилагаемым действием), обрабатывается соответственно: list_p((*anychar_p)[func], ',') будут разобраны, как и ожидалось: (*(anychar_p - ch_p(',')))[func] >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[func] ) Необходимый рефакторинг реализуется с помощью Рефакторинг Парсеров.
Это часть духовного распределения.
Copyright © 2001-2003 Hartmut Kaiser Статья List Parsers раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
|||||||||||||||||||||||||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |