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

Transforming the Expression Tree

Boost , Chapter 1. Phoenix 3.2.0 , Advanced Examples

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

Этот пример покажет, как писатьДействия, преобразующие АСТ Феникса.

"Макросы Lisp трансформируют саму структуру программы, используя весь язык для выражения таких преобразований.".

Википедия

Мы хотим перевернуть некоторые арифметические операторы, т. е. плюс будет преобразован в минус, минус в плюс, умножение на деление и деление на умножение.

Давайте начнем с определения наших действий по умолчанию:

struct invert_actions
{
    template <typename Rule>
    struct when
        : proto::_ // the default is proto::_
    {};
};

По умолчанию мы не хотим ничего делать, ну, не совсем ничего, а просто возвращаем выражение. Это делаетсяпрото::, которая, будучи преобразованной, просто передает текущее выражение. Сделайте это действие преобразованием идентичности.

Итак, после того, как основы установлены, мы можем начать с написания преобразований, которые мы хотим иметь на нашем дереве:

// Transform plus to minus
template <>
struct invert_actions::when<phoenix::rule::plus>
    : proto::call<
        proto::functional::make_expr<proto::tag::minus>(
            phoenix::evaluator(proto::_left, phoenix::_context)
          , phoenix::evaluator(proto::_right, phoenix::_context)
        )
    >
{};

Вау, это выглядит сложно! Конечно, вам нужно знать немного оBoost.Proto(Для хорошего введения прочитайте сериюExpressive C++).

Что делается, так это следующее:

  • Левое выражение передается оценщику (с текущим контекстом, который содержит наши инвертные действия).
  • Правильное выражение передается оценщику (с текущим контекстом, который содержит наши инвертные действия).
  • Результат этих двухПротопревращенийпередается<proto::functional::make_expr>, который возвращает вновь созданное выражение.

После того, как вы знаете, что происходит, может быть, все остальное уже не так страшно:

// Transform minus to plus
template <>
struct invert_actions::when<phoenix::rule::minus>
    : proto::call<
        proto::functional::make_expr<proto::tag::plus>(
            phoenix::evaluator(proto::_left, phoenix::_context)
          , phoenix::evaluator(proto::_right, phoenix::_context)
        )
    >
{};
// Transform multiplies to divides
template <>
struct invert_actions::when<phoenix::rule::multiplies>
    : proto::call<
        proto::functional::make_expr<proto::tag::divides>(
            phoenix::evaluator(proto::_left, phoenix::_context)
          , phoenix::evaluator(proto::_right, phoenix::_context)
        )
    >
{};
// Transform divides to multiplies
template <>
struct invert_actions::when<phoenix::rule::divides>
    : proto::call<
        proto::functional::make_expr<proto::tag::multiplies>(
            phoenix::evaluator(proto::_left, phoenix::_context)
          , phoenix::evaluator(proto::_right, phoenix::_context)
        )
    >
{};

Вот так! Теперь, когда мы определили наши действия, мы хотим оценить некоторые из наших выражений с ними:

template <typename Expr>
// Calculate the result type: our transformed AST
typename boost::result_of<
    phoenix::evaluator(
        Expr const&
      , phoenix::result_of::context<int, invert_actions>::type
    )
>::type
invert(Expr const & expr)
{
    return
        // Evaluate it with our actions
        phoenix::eval(
            expr
          , phoenix::context(
                int()
              , invert_actions()
            )
        );
}

Проведите несколько тестов, чтобы увидеть, работает ли он:

invert(_1);                    // --> _1
invert(_1 + _2);               // --> _1 - _2
invert(_1 + _2 - _3);          // --> _1 - _2 + _3
invert(_1 * _2);               // --> _1 / _2
invert(_1 * _2 / _3);          // --> _1 / _2 * _3
invert(_1 * _2 + _3);          // --> _1 / _2 - _3
invert(_1 * _2 - _3);          // --> _1 / _2 + _2
invert(if_(_1 * _4)[_2 - _3]); // --> if_(_1 / _4)[_2 + _3]
_1 * invert(_2 - _3));         // --> _1 * _2 + _3

Полный пример можно найти здесь:example/invert.cpp

Довольно просто...


PrevUpHomeNext

Статья Transforming the Expression Tree раздела Chapter 1. Phoenix 3.2.0 Advanced Examples может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Advanced Examples ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-07-05 07:09:12/0.0040669441223145/0