blob: cb4919778a4ccde06d9634f2959533e534cc6c5a [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2001-2011 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
#if defined(_MSC_VER)
#pragma once
#endif
#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>
#include <boost/spirit/home/support/attributes.hpp>
#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
namespace detail
{
template <typename FunctionType, typename Iterator, typename Context
, typename IdType>
struct wrap_action
{
// plain functions with 5 arguments and function objects are not
// touched at all
template <typename F>
static FunctionType call(F const& f)
{
return f;
}
// wrap phoenix actor
struct phoenix_action
{
template <typename F, typename T1, typename T2, typename T3
, typename T4, typename T5>
struct result { typedef void type; };
template <typename Eval>
void operator()(phoenix::actor<Eval> const& f, Iterator& start
, Iterator& end, BOOST_SCOPED_ENUM(pass_flags)& pass
, IdType& id, Context& ctx) const
{
f (start, end, pass, id, 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;
using phoenix::arg_names::_5;
return phoenix::bind(phoenix_action(), phoenix::lambda[f],
_1, _2, _3, _4, _5);
}
// semantic actions with 4 arguments
template <typename F>
static void arg4_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)& pass, IdType& id
, Context const&)
{
f(start, end, pass, id);
}
template <typename A0, typename A1, typename A2, typename A3>
static FunctionType call(void (*f)(A0, A1, A2, A3))
{
void (*pf)(void(*)(A0, A1, A2, A3)
, Iterator&, Iterator&, BOOST_SCOPED_ENUM(pass_flags)&
, IdType&, Context const&) = &wrap_action::arg4_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// semantic actions with 3 arguments
template <typename F>
static void arg3_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)& pass, IdType
, Context const&)
{
f(start, end, pass);
}
template <typename A0, typename A1, typename A2>
static FunctionType call(void (*f)(A0, A1, A2))
{
void (*pf)(void(*)(A0, A1, A2), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, IdType
, Context const&) = &wrap_action::arg3_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// semantic actions with 2 arguments
template <typename F>
static void arg2_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
{
f (start, end);
}
template <typename A0, typename A1>
static FunctionType call(void (*f)(A0, A1))
{
void (*pf)(void(*)(A0, A1), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&
, IdType, Context const&) = &wrap_action::arg2_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// we assume that either both iterators are to be passed to the
// semantic action or none iterator at all (i.e. it's not possible
// to have a lexer semantic action function taking one arguments).
// semantic actions with 0 argument
template <typename F>
static void arg0_action(F* f, Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
{
f();
}
static FunctionType call(void (*f)())
{
void (*pf)(void(*)(), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&
, IdType, Context const&) = &arg0_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
};
// specialization allowing to skip wrapping for lexer types not
// supporting semantic actions
template <typename Iterator, typename Context, typename Idtype>
struct wrap_action<unused_type, Iterator, Context, Idtype>
{
// plain function objects are not touched at all
template <typename F>
static F const& call(F const& f)
{
return f;
}
};
}
}}}}
#endif