blob: 5432aaa324a8b0845af71e2a7ac10da8cfa8a52d [file] [log] [blame]
// Copyright (c) 2001-2007 Joel de Guzman
// Copyright (c) 2001-2009 Hartmut Kaiser
//
// 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_KARMA_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM)
#define BOOST_SPIRIT_KARMA_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once // MS compatible compilers support #pragma once
#endif
#include <boost/spirit/home/support/nonterminal/nonterminal.hpp>
#include <boost/spirit/home/support/nonterminal/detail/expand_arg.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/component.hpp>
#include <boost/spirit/home/support/attribute_transform.hpp>
#include <boost/spirit/home/support/detail/values.hpp>
#include <boost/fusion/include/transform.hpp>
#include <boost/fusion/include/join.hpp>
#include <boost/fusion/include/single_view.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/mpl/at.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
namespace boost { namespace spirit { namespace karma
{
struct nonterminal_director
{
// The attribute (parameter) of nonterminals is the type given to them
// as the return value of the function signature.
template <typename Component, typename Context, typename Unused>
struct attribute
{
typedef typename
result_of::subject<Component>::type
nonterminal_holder;
typedef typename
nonterminal_holder::nonterminal_type::attribute_type
type;
};
// the nonterminal_holder holds an actual nonterminal_object
template <
typename NonterminalContext, typename Nonterminal,
typename OutputIterator, typename Context, typename Delimiter,
typename Parameter>
static bool generate_nonterminal(
nonterminal_object<Nonterminal> const& x,
OutputIterator& sink, Context&, Delimiter const& delim,
Parameter const& param)
{
typedef typename Nonterminal::locals_type locals_type;
fusion::vector<Parameter const&> front(param);
NonterminalContext context(front, locals_type());
return x.obj.generate(sink, context, delim);
}
// the nonterminal_holder holds a pointer to a nonterminal
template <
typename NonterminalContext, typename Nonterminal,
typename OutputIterator, typename Context, typename Delimiter,
typename Parameter>
static bool generate_nonterminal(
Nonterminal const* ptr,
OutputIterator& sink, Context&, Delimiter const& delim,
Parameter const& param)
{
typedef typename Nonterminal::locals_type locals_type;
fusion::vector<Parameter const&> front(param);
NonterminalContext context(front, locals_type());
return ptr->generate(sink, context, delim);
}
// the nonterminal_holder holds a parameterized_nonterminal
template <
typename NonterminalContext, typename Nonterminal,
typename FSequence, typename OutputIterator,
typename Context, typename Delimiter, typename Parameter>
static bool generate_nonterminal(
parameterized_nonterminal<Nonterminal, FSequence> const& x,
OutputIterator& sink, Context& context_, Delimiter const& delim,
Parameter const& param)
{
typedef typename Nonterminal::locals_type locals_type;
fusion::single_view<Parameter const&> front(param);
NonterminalContext context(
fusion::join(
front,
fusion::transform(
x.fseq,
spirit::detail::expand_arg<Context>(context_)
)
),
locals_type()
);
return x.ptr->generate(sink, context, delim);
}
///////////////////////////////////////////////////////////////////////
// main entry point
///////////////////////////////////////////////////////////////////////
template <
typename Component, typename OutputIterator, typename Context,
typename Delimiter, typename Parameter>
static bool generate(
Component const& component, OutputIterator& sink,
Context& context, Delimiter const& delim, Parameter const& param)
{
typedef typename
result_of::subject<Component>::type
nonterminal_holder;
// The overall context_type consists of a tuple with:
// 1) a tuple of the attribute and parameters
// 2) the locals
// if no signature is specified the first tuple contains
// the attribute at position zero only.
typedef typename
nonterminal_holder::nonterminal_type::context_type
context_type;
return generate_nonterminal<context_type>(
subject(component).held, sink, context, delim, param);
}
template <typename Nonterminal>
static std::string what_nonterminal(nonterminal_object<Nonterminal> const& x)
{
// the nonterminal_holder holds an actual nonterminal_object
return x.obj.what();
}
template <typename Nonterminal>
static std::string what_nonterminal(Nonterminal const* ptr)
{
// the nonterminal_holder holds a pointer to a nonterminal
return ptr->what();
}
template <typename Nonterminal, typename FSequence>
static std::string what_nonterminal(
parameterized_nonterminal<Nonterminal, FSequence> const& x)
{
// the nonterminal_holder holds a parameterized_nonterminal
return x.ptr->what();
}
template <typename Component, typename Context>
static std::string what(Component const& component, Context const& ctx)
{
return what_nonterminal(subject(component).held);
}
};
}}}
#endif