![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
The RuleBoost , ,
Правилоявляется полиморфным парсером, который действует как названный держатель места, фиксирующий поведение назначенного ему выражения EBNF. Наименование выражения EBNF позволяет ссылаться на него позже. Правило— это класс шаблонов, параметризованный типом сканера (ScannerT).), контекст правилаи егоТэг. Параметры шаблона по умолчанию предоставляются, чтобы упростить использование правила.
Параметры шаблона по умолчанию поставляются для обработки наиболее распространенного случая.ScannerTпо умолчанию длясканера<>, простой ванильный сканер, который действует наитераторы char const*и не делает ничего особенного, кроме итерации через все загоны в нулевом завершенном входе символа за раз. Тег правилаTagT, обычно используемый сASTs, используется для идентификации правила; он объясняетсяздесь. В тривиальных случаях достаточно объявить правилоправилом<>. Вам не нужно беспокоиться о параметре шаблонаContextT, если вы не хотите настроить поведение правила на низком уровне. Подробная информация по шаблонному параметруContextTпредставленав другом месте. Order of parametersПо состоянию на v1.8.0,ScannerT,ContextTиTagTмогут быть указаны в любом порядке. Если параметр шаблона отсутствует, он будет предполагать по умолчанию. Примеры: rule<> rx1; rule<scanner<> > rx2; rule<parser_context Multiple scannersПри использовании v1.8.0 можно использовать один или несколько типов сканеров. Например, есть случаи, когда нам нужно правило, которое может работать на уровне фраз и символов. Несоответствие правил и сканеров было источником путаницы и является No 1FAQ. Для решения этой проблемы у нас теперь есть поддержка нескольких сканеров. Пример: typedef scanner_list<scanner<>, phrase_scanner_t> scanners; rule<scanners> r = +anychar_p; assert(parse("abcdefghijk", r).full); assert(parse("a b c d e f g h i j k", r, space_p).full); Обратите внимание на то, как правилоrиспользуется как во фразе, так и в уровнях символов. По умолчанию поддержка нескольких сканеров отключена. МакроBOOST_SPIRIT_RULE_SCANNERTYPE_LIMITдолжно быть определено максимальное количество сканеров, разрешенных в списке сканеров. Значение должно быть больше 1 для обеспечения работы нескольких сканеров. В приведенном выше примере для определения предела двух сканеров списка перед включением заголовков Spirit в исходный файл необходимо вставить следующую строку: #define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 2
Rule DeclarationsТиповое правило производства EBNF. Пример:
Тип и поведение выражения правой руки (rhs) EBNF, которое может быть произвольно сложным, закодировано в правиле под названием a_rule. a_rule теперь может упоминаться в другом месте грамматики:
a = int_p; b = a; c = int_p >> b; Copying RulesПравило является странным гражданином C++, в отличие от любого другого объекта C++. Он не имеет надлежащей семантики копирования и назначения и не может храниться и передаваться по стоимости. Если вам нужно скопировать правило, вы должны явно назвать его функцию участника: r.copy(); Тем не менее, следует предупредить, что копирование правила не будет глубоко копировать другие упомянутые правила копируемого правила источника. Это может привести к помехе ссылок. Опять же, клиент несет ответственность за то, чтобы все упомянутые правила оставались в сфере применения и не разрушались во время ссылки. Пещерный пылесос. Если вы скопируете правило, то вы захотите поместить его в хранилище где-нибудь. Проблема в том как? Хранение не может быть другим правилом:
Потому что правила странные и не имеют ожидаемого C++-конструктора и семантики назначения. Общее правило:Не вводите скопированное правило в другое!Вместо этого используйтесохраненное_правилодля этой цели. Forward declarationsПравиломожет быть объявлено до того, как будет определено, чтобы позволить циклические структуры, обычно встречающиеся в декларациях BNF. Пример:
RecursionПравая сторона правила может ссылаться на другие правила, включая его саму. Ограничение заключается в том, что прямое или косвенное левое повторение не допускается (это неконтролируемая ошибка времени выполнения, которая приводит к бесконечному циклу). Это типично для парсеров сверху вниз. Пример:
Undefined rulesНеопределенное правило не соответствует ничему и семантически эквивалентноnothing_p. RedeclarationsКак и любое другое задание C++, второе задание правилу является деструктивным и переопределит его. Старое определение утрачено. Правила динамичны. Правило может изменить свое определение в любое время:
Правилоrтеряет старое определение при выполнении второго задания. Как уже упоминалось, неопределенное правило не соответствует ничему и семантически эквивалентноnothing_p. Динамические парсерыХостинг декларативного EBNF в императивном C++ дает интересную смесь. У нас есть лучшее из обоих миров. У нас есть возможность удобно изменять грамматику во время выполнения с использованием императивных конструкций, таких как, если,и другиеутверждения. Пример:
Правила по существу являются динамическими парсерами. Динамический парсер характеризуется способностью изменять свое поведение во время выполнения. Первоначально неопределенное правило не соответствует ничему. В любое время правило может быть определено и переопределено, таким образом, динамически изменяя его поведение. No start ruleКак правило, парсеры имеют так называемый стартовый символ, выбранный как корень грамматики, где начинается парсинг. Система парсера Духа не имеет понятия о начальном символе. Любое правило может быть символом начала. Эта функция способствует поэтапному созданию парсеров. Мы можем создавать парсеры снизу вверх, полностью тестируя каждый уровень или модуль до тех пор, пока не достигнем самого верхнего уровня. Parser TagsПравила могут быть помечены для целей идентификации. Это необходимо, особенно при работе сразбором деревьев и AST, чтобы увидеть, какое правило создало конкретный узел дерева AST / разрез. Каждое правило имеет идентификатор типаparser_id. Этот идентификатор можно получить с помощью правилаid()Функция члена:
Классparser_idобъявляется: class parser_id parser_address_tagПараметр шаблона правилаTagTпредоставляет этот идентификатор. По умолчаниюparser_address_tag.parser_address_tagиспользует адрес правила в качестве своего идентификатора. Это часто не самое удобное, так как не всегда можно получить адрес правила для сравнения. parser_tagМожно иметь конкретные постоянные целые числа для определения правила. Для этого мы можем использоватьparser_tag
dynamic_parser_tagparser_tag
Если функцияset_id()не называется, идентификатор парсера по умолчанию указывает на адрес правила в качестве своего идентификатора, как и параметр шаблонаparser_address_tag.
Copyright © 1998-2003 Joel de Guzman Статья The Rule раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
||||||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |