blob: 7b787c2969e546bc24e546e959a17b68da8df9cd [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2008 Joel de Guzman
Copyright (c) 2001-2008 Hartmut Kaiser
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM)
#define BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM
#include <boost/spirit/home/support/detail/values.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/argument.hpp>
#include <boost/spirit/home/phoenix/bind.hpp>
#include <boost/spirit/home/phoenix/scope.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex { namespace detail
{
template <typename FunctionType, typename Attribute, typename Context>
struct wrap_action
{
// plain functions with 4 arguments and function objects are not
// touched at all
template <typename F>
static FunctionType call(F const& f)
{
return f;
}
// wrap phoenix actor, make sure first argument is a fusion sequence
struct phoenix_action
{
template <typename F, typename T1, typename T2, typename T3, typename T4>
struct result { typedef void type; };
template <typename Eval>
void
operator()(phoenix::actor<Eval> const& f, Attribute const& attr,
std::size_t id, bool& pass, Context& ctx) const
{
f (spirit::detail::pass_value<Attribute const>::call(attr),
id, pass, ctx);
}
};
template <typename Eval>
static FunctionType call(phoenix::actor<Eval> const& f)
{
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
return phoenix::bind(phoenix_action(), phoenix::lambda[f],
_1, _2, _3, _4);
}
// semantic actions with 3 arguments
template <typename F>
static void arg3_action(F* f, Attribute const& attr,
std::size_t id, bool& pass, Context&)
{
f(attr, id, pass);
}
template <typename A0, typename A1, typename A2>
static FunctionType call(void(*f)(A0, A1, A2))
{
void (*pf)(void(*)(A0, A1, A2), Attribute const&, std::size_t,
bool&, Context&) = &wrap_action::arg3_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
return phoenix::bind(pf, f, _1, _2, _3);
}
// semantic actions with 2 arguments
template <typename F>
static void arg2_action(F* f, Attribute const& attr,
std::size_t id, bool&, Context&)
{
f(attr, id);
}
template <typename A0, typename A1>
static FunctionType call(void(*f)(A0, A1))
{
void (*pf)(void(*)(A0, A1), Attribute const&, std::size_t,
bool&, Context&) = &wrap_action::arg2_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
return phoenix::bind(pf, f, _1, _2);
}
// semantic actions with 1 argument
template <typename F>
static void arg1_action(F* f, Attribute const& attr,
std::size_t, bool&, Context&)
{
f(attr);
}
template <typename A0>
static FunctionType call(void(*f)(A0))
{
void (*pf)(void(*)(A0), Attribute const&, std::size_t,
bool&, Context&) = &arg1_action;
using phoenix::arg_names::_1;
return phoenix::bind(pf, f, _1);
}
// semantic actions with 0 argument
template <typename F>
static void arg0_action(F* f, Attribute const&,
std::size_t, bool&, Context&)
{
f();
}
static FunctionType call(void(*f)())
{
void (*pf)(void(*)(), Attribute const&, std::size_t,
bool&, Context&) = &arg0_action;
using phoenix::arg_names::_1;
return phoenix::bind(pf, f, _1);
}
};
// specialization allowing to skip wrapping for lexer types not supporting
// semantic actions
template <typename Attribute, typename Context>
struct wrap_action<unused_type, Attribute, Context>
{
// plain functors are not touched at all
template <typename F>
static F const& call(F const& f)
{
return f;
}
};
}}}}
#endif