![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Storable RulesBoost , ,
Правило является странным гражданином C++, в отличие от любого другого объекта C++. Он не имеет надлежащей копии и семантики уступки и не может быть сохранен и передан по стоимости. Вы не можете хранить правила в контейнерах STL (вектор, стек и т.д.) для последующего использования, и вы не можете передавать и возвращать правила к функциям и от них по стоимости. EBNF в основном декларативный. Как и в функциональном программировании, грамматика EBNF является статичным рецептом, и нет понятия, что делать это тогда. Тем не менее, в Spirit нам удалось коаксировать императив C++, чтобы принять в декларативном EBNF. Ха! Забавно... Мы сделали это, маскируя оператора назначения C++ для имитации EBNF ::=. Для этого мы дали оператору присвоения класса правил и конструктору копий другой смысл и семантику. Недостатком является то, что это сделало правило не похожим на любой другой объект C++. Ты не можешь это копировать. Ты не можешь его назначить. Мы хотим иметь динамическую природу C++ в наших интересах. Мы видели динамичный Дух в действии здесь и там. Действительно, есть несколько интересных применений динамических парсеров, использующих Дух. Тем не менее, мы не будем полностью использовать силу динамического парсинга, если у нас нет правила, которое ведет себя как любой другой хороший объект C++. С таким зверем мы можем писать полные парсеры, которые определены во время бега, в отличие от времени компиляции. Теперь у нас есть динамические правила: stored_правила. В основном это правила с идеальной семантикой назначения C++/копии-конструктора. Это означает, что stored_правила могут храниться в контейнерах и/или динамически создаваться в режиме ожидания.
Интерфейс точно такой же, как и с классом правил (более подробную информацию о API см. в разделе ). Единственное отличие - это семантика копирования и уступки. Теперь, с stored_правило, мы можем динамически и алгоритмически определять наши правила. Вот несколько образцов... Скажем, я хочу динамически создать правило для: start = *(a | b | c); Я могу писать его динамически шаг за шагом: stored_rule<> start; start = a; start = start.copy() | b; start = start.copy() | c; start = *(start.copy()); Позже я передумала и хочу переосмыслить его (динамически) как: start = (a | b) >> (start | b); Я пишу: start = b; start = a | start.copy(); start = start.copy() >> (start | b); Обратите внимание на заявление: start = start.copy() | b; Почему требуется start.copy()? Ну, потому что, как и правила, сохраненные правила все еще встроены по ссылкам, когда они найдены в RHS (одна из причин избежать циклических-совместных указателей). Если мы пишем: start = start | b; У нас есть левый рекурс! Копирование копии начала позволяет избежать самоссылки. То, что мы делаем, это делаем копию начала, ИЛИ ее с помощью b, а затем деструктивно присваивая результат обратно, чтобы начать.
Copyright © 1998-2003 Joel de Guzman Статья Storable Rules раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
|||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |