blob: 588d8b967b4c54b66f47be769c4caab7aafd5243 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2007 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_NONTERMINAL_FEB_19_2007_0236PM)
#define BOOST_SPIRIT_NONTERMINAL_FEB_19_2007_0236PM
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
#include <boost/spirit/home/support/nonterminal/locals.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/proto/core.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/is_function.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/joint_view.hpp>
#include <boost/fusion/include/single_view.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/preprocessor/enum_params.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost { namespace spirit { namespace qi
{
template <typename Derived, typename Sig, typename Locals>
struct nonterminal
: proto::extends<
typename make_nonterminal_holder<
Derived const*, Derived
>::type
, Derived
>
{
typedef Sig sig_type;
typedef typename function_types::result_type<sig_type>::type attr_type_;
// This is the nonterminal return type
typedef typename
mpl::if_<
is_same<attr_type_, void>
, unused_type
, attr_type_
>::type
attr_type;
typedef typename add_reference<attr_type>::type attr_reference_type;
// param_types is a sequence of types passed as parameters to the nonterminal
typedef typename function_types::parameter_types<sig_type>::type param_types;
// locals_type is a sequence of types to be used as local variables
typedef typename fusion::result_of::as_vector<Locals>::type locals_type;
// The overall context_type consist of a tuple with:
// 1) a tuple of the return value and parameters
// 2) the locals
typedef fusion::vector<
typename fusion::result_of::as_vector<
fusion::joint_view<
fusion::single_view<attr_reference_type>
, param_types
>
>::type
, typename fusion::result_of::as_vector<locals_type>::type
>
context_type;
typedef nonterminal<Derived, Sig, Locals> self_type;
typedef nonterminal_holder<Derived const*, Derived> nonterminal_holder_;
typedef typename proto::terminal<nonterminal_holder_>::type nonterminal_tag;
typedef proto::extends<nonterminal_tag, Derived> base_type;
explicit nonterminal()
: base_type(make_tag())
{
}
// bring in the operator() overloads
#include <boost/spirit/home/support/nonterminal/detail/nonterminal_fcall.hpp>
private:
nonterminal_tag make_tag() const
{
nonterminal_tag xpr = {{static_cast<Derived const*>(this)}};
return xpr;
}
};
template <typename Derived, typename T0, typename T1, typename T2>
struct make_nonterminal
{
typedef mpl::vector<T0, T1, T2> types;
typedef function_types::is_function<mpl::_> is_function;
typedef spirit::detail::is_locals<mpl::_> is_locals;
typedef spirit::traits::is_component<qi::domain, mpl::_> is_skipper;
typedef typename mpl::find_if<types, is_function>::type sig_;
typedef typename mpl::find_if<types, is_locals>::type locals_;
typedef typename mpl::find_if<types, is_skipper>::type skipper_;
typedef typename
mpl::eval_if<
is_same<sig_, typename mpl::end<types>::type>
, mpl::identity<unused_type()>
, mpl::deref<sig_>
>::type
sig_type;
typedef typename
mpl::eval_if<
is_same<locals_, typename mpl::end<types>::type>
, mpl::identity<locals<> >
, mpl::deref<locals_>
>::type
locals_type;
typedef typename
mpl::eval_if<
is_same<skipper_, typename mpl::end<types>::type>
, mpl::identity<unused_type>
, mpl::deref<skipper_>
>::type
skipper_type;
typedef nonterminal<Derived, sig_type, locals_type> type;
};
}}}
#endif