Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Parser Semantic Actions

Boost , Spirit 2.5.2 , Tutorials

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Пример в предыдущем разделе был очень упрощенным. Он распознавал только данные, но ничего с ними не делал. Он ответил на вопрос: «Соответствовал ли входной сигнал?» Теперь мы хотим извлечь информацию из того, что было разобрано. Например, мы хотели бы сохранить парсинговый номер после успешного матча. Для этого вам потребуетсясемантических действий..

Семантические действия могут быть прикреплены к любой точке грамматической спецификации. Эти действия являются функциями C++ или функциональными объектами, которые называются всякий раз, когда часть парсера успешно распознает часть ввода. Предположим, у вас есть парсер<P>и функция C++<F>. Вы можете сделать парсерный вызов<F>всякий раз, когда он соответствует входу, прикрепив<F>:

P[F]

Выражение выше связывает<F>с парсером<P>.

Подпись функции/функции объекта зависит от типа парсера, к которому он прикреплен. При этом<double_>число падает. Таким образом, если бы мы прикрепили функцию<F>к<double_>, мы должны были бы объявить<F>:

void F(double n);

На самом деле, есть еще 2 аргумента (контекст парсера и ссылка на фулевый параметр «удар»). На данный момент они нам не нужны, но мы увидим больше других аргументов позже. Дух. Ци позволяет нам связать одну функцию аргумента, как выше. Остальные аргументы просто игнорируются.

Examples of Semantic Actions

Представлены различные способы прикрепления семантических действий:

  • Использование функции Simple Pointer
  • Использование простого функционального объекта
  • Boost.Bindс простой функцией
  • ИспользованиеBoost.Bindс функцией участника
  • ИспользованиеBoost.Lambda

Учитывая:

namespace client
{
    namespace qi = boost::spirit::qi;
    // A plain function
    void print(int const& i)
    {
        std::cout << i << std::endl;
    }
    // A member function
    struct writer
    {
        void print(int const& i) const
        {
            std::cout << i << std::endl;
        }
    };
    // A function object
    struct print_action
    {
        void operator()(int const& i, qi::unused_type, qi::unused_type) const
        {
            std::cout << i << std::endl;
        }
    };
}

Обратите внимание, что с функциональными объектами нам нужно иметь<operator()>с 3 аргументами. Поскольку мы не заботимся о двух других, мы можем использовать<unused_type>для них. Мы увидим больше<unused_type>в другом месте.<unused_type>— класс поддержки, обеспеченный Духом.

Все примеры анализируют входы формы:

"{integer}"

Целое число внутри кудрявых брекетов.

Первый пример показывает, как прикрепить простую функцию:

parse(first, last, '{' >> int_[&print] >> '}');

Что нового?<int_>является родным братом<double_>. Уверен, вы догадаетесь, что делает этот парсер.

Следующий пример показывает, как прикрепить простой функциональный объект:

parse(first, last, '{' >> int_[print_action()] >> '}');

Мы можем использоватьBoost.Bindдля связывания функций членов:

writer w;
parse(first, last, '{' >> int_[boost::bind(&writer::print, &w, _1)] >> '}');

Также мы можем использоватьBoost.Bindдля связывания простых функций:

parse(first, last, '{' >> int_[boost::bind(&print, _1)] >> '}');

Да, мы также можем использоватьBoost.Lambda:

parse(first, last, '{' >> int_[std::cout << _1 << '\n'] >> '}');

Существует больше способов связывания семантических функций действия, но примеры выше являются наиболее распространенными. Привязка семантических действий является первым препятствием, которое нужно преодолеть, когда вы начинаете разбираться с Духом. Ознакомьтесь с этой задачей и свяжитесь с инструментами, стоящими за ней, такими какBoost.BindиBoost.Lambda.

The examples above can be found here: ../../example/qi/actions.cpp

Phoenix

Феникс, библиотека-компаньон в комплекте с Духом, специально подходит для связывания смысловых действий. Это какBoost.Lambdaна стероидах, с особыми пользовательскими функциями, которые позволяют легко интегрировать семантические действия с Духом. Если ваши требования выходят за рамки простого и умеренного анализа, рекомендуется использовать эту библиотеку. Все следующие примеры в этом руководстве будут использоватьФениксдля семантических действий.

[Important]Important

Существуют различные способы написания семантических действий дляSpirit.Qi: с использованием простых функций,Boost.Bind,Boost.LambdaилиPhoenix. Последние три позволяют использовать специальные заполнители для управления размещением параметров<_1>,<_2>и т.д. Каждая из этих библиотек имеет свою собственную реализацию заполнителей, все в разных пространствах имен. Вы должны убедиться, что не смешиваете заполнители с библиотекой, к которой они не принадлежат, и не используете разные библиотеки при написании семантического действия.

Как правило, дляBoost.Bind, использовать<::_1>,<::_2>и т. Д. (Да, эти заполнители определены в глобальном пространстве имен).

ДляBoost.Lambdaиспользуйте заполнители, определенные в пространстве имен<boost::lambda>.

Для семантических действий, написанных с использованиемФеникса, используйте заполнители, определенные в пространстве имен<boost::spirit>. Обратите внимание, что все существующие держатели для вашего удобства также доступны из пространства имен<boost::spirit::qi>.


PrevUpHomeNext

Статья Parser Semantic Actions раздела Spirit 2.5.2 Tutorials может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Tutorials ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 13:55:06/0.0046398639678955/0