blob: b9cbeca6a457872a5b144655c22602367e7f4599 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
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_ARGUMENT_FEBRUARY_17_2007_0339PM)
#define BOOST_SPIRIT_ARGUMENT_FEBRUARY_17_2007_0339PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/argument.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp>
#if !defined(SPIRIT_ARGUMENTS_LIMIT)
# define SPIRIT_ARGUMENTS_LIMIT PHOENIX_LIMIT
#endif
#define SPIRIT_DECLARE_ARG(z, n, data) \
phoenix::actor<argument<n> > const \
BOOST_PP_CAT(_, BOOST_PP_INC(n)) = argument<n>();
#define SPIRIT_USING_ARGUMENT(z, n, data) using spirit::BOOST_PP_CAT(_, n);
namespace boost { namespace spirit
{
namespace result_of
{
template <typename Sequence, int N>
struct get_arg
{
typedef typename
fusion::result_of::size<Sequence>::type
sequence_size;
// report invalid argument not found (N is out of bounds)
BOOST_SPIRIT_ASSERT_MSG(
(N < sequence_size::value),
index_is_out_of_bounds, ());
typedef typename
fusion::result_of::at_c<Sequence, N>::type
type;
static type call(Sequence& seq)
{
return fusion::at_c<N>(seq);
}
};
template <typename Sequence, int N>
struct get_arg<Sequence&, N> : get_arg<Sequence, N>
{
};
}
template <int N, typename T>
typename result_of::get_arg<T, N>::type
get_arg(T& val)
{
return result_of::get_arg<T, N>::call(val);
}
struct attribute_context
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
// FIXME: is this remove_const really necessary?
typedef typename
remove_const<
typename mpl::at_c<typename Env::args_type, 0>::type
>::type
type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return fusion::at_c<0>(env.args());
}
};
template <int N>
struct argument
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef typename
mpl::at_c<typename Env::args_type, 0>::type
arg_type;
typedef typename result_of::get_arg<arg_type, N>::type type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return get_arg<N>(fusion::at_c<0>(env.args()));
}
};
// _0 refers to the whole attribute as generated by the lhs parser
phoenix::actor<attribute_context> const _0 = attribute_context();
// _1, _2, ... refer to the attributes of the single components the lhs
// parser is composed of
phoenix::actor<argument<0> > const _1 = argument<0>();
phoenix::actor<argument<1> > const _2 = argument<1>();
phoenix::actor<argument<2> > const _3 = argument<2>();
// '_pass' may be used to make a match fail in retrospective
phoenix::actor<phoenix::argument<2> > const _pass = phoenix::argument<2>();
// Bring in the rest of the arguments and attributes (_4 .. _N+1), using PP
BOOST_PP_REPEAT_FROM_TO(
3, SPIRIT_ARGUMENTS_LIMIT, SPIRIT_DECLARE_ARG, _)
// You can bring these in with the using directive
// without worrying about bringing in too much.
namespace labels
{
BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
}
}}
#undef SPIRIT_DECLARE_ARG
#endif