188 lines
6.3 KiB
C++
188 lines
6.3 KiB
C++
// Copyright (c) 2001-2011 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_AUTO_NOV_29_2009_0339PM)
|
|
#define BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0339PM
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma once
|
|
#endif
|
|
|
|
#include <boost/spirit/home/support/common_terminals.hpp>
|
|
#include <boost/spirit/home/support/info.hpp>
|
|
#include <boost/spirit/home/support/container.hpp>
|
|
#include <boost/spirit/home/support/assert_msg.hpp>
|
|
#include <boost/spirit/home/support/detail/hold_any.hpp>
|
|
#include <boost/spirit/home/karma/domain.hpp>
|
|
#include <boost/spirit/home/karma/meta_compiler.hpp>
|
|
#include <boost/spirit/home/karma/delimit_out.hpp>
|
|
#include <boost/spirit/home/karma/generator.hpp>
|
|
#include <boost/spirit/home/karma/auto/create_generator.hpp>
|
|
#include <boost/mpl/bool.hpp>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit
|
|
{
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Enablers
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct use_terminal<karma::domain, tag::auto_> // enables auto_
|
|
: mpl::true_ {};
|
|
|
|
template <typename A0>
|
|
struct use_terminal<karma::domain // enables auto_(...)
|
|
, terminal_ex<tag::auto_, fusion::vector1<A0> >
|
|
> : mpl::true_ {};
|
|
|
|
template <> // enables auto_(f)
|
|
struct use_lazy_terminal<
|
|
karma::domain, tag::auto_, 1 /*arity*/
|
|
> : mpl::true_ {};
|
|
|
|
}}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit { namespace karma
|
|
{
|
|
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
|
using spirit::auto_;
|
|
#endif
|
|
using spirit::auto_type;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename Modifiers>
|
|
struct auto_generator
|
|
: generator<auto_generator<Modifiers> >
|
|
{
|
|
typedef mpl::int_<generator_properties::all_properties> properties;
|
|
|
|
template <typename Context, typename Unused>
|
|
struct attribute
|
|
{
|
|
typedef spirit::basic_hold_any<char> type;
|
|
};
|
|
|
|
auto_generator(Modifiers const& modifiers)
|
|
: modifiers_(modifiers) {}
|
|
|
|
// auto_generator has an attached attribute
|
|
template <
|
|
typename OutputIterator, typename Context, typename Delimiter
|
|
, typename Attribute>
|
|
bool generate(OutputIterator& sink, Context& context
|
|
, Delimiter const& d, Attribute const& attr) const
|
|
{
|
|
return compile<karma::domain>(create_generator<Attribute>(), modifiers_)
|
|
.generate(sink, context, d, attr);
|
|
}
|
|
|
|
// this auto_generator has no attribute attached, it needs to have been
|
|
// initialized from a value/variable
|
|
template <typename OutputIterator, typename Context
|
|
, typename Delimiter>
|
|
static bool
|
|
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
|
|
{
|
|
// It is not possible (doesn't make sense) to use auto_ generators
|
|
// without providing any attribute, as the generator doesn't 'know'
|
|
// what to output. The following assertion fires if this situation
|
|
// is detected in your code.
|
|
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, auto_not_usable_without_attribute, ());
|
|
return false;
|
|
}
|
|
|
|
template <typename Context>
|
|
info what(Context& /*context*/) const
|
|
{
|
|
return info("auto_");
|
|
}
|
|
|
|
Modifiers modifiers_;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename T, typename Modifiers>
|
|
struct lit_auto_generator
|
|
: generator<lit_auto_generator<T, Modifiers> >
|
|
{
|
|
typedef mpl::int_<generator_properties::all_properties> properties;
|
|
|
|
template <typename Context, typename Unused>
|
|
struct attribute
|
|
{
|
|
typedef unused_type type;
|
|
};
|
|
|
|
lit_auto_generator(typename add_reference<T>::type t, Modifiers const& modifiers)
|
|
: t_(t)
|
|
, generator_(compile<karma::domain>(create_generator<T>(), modifiers))
|
|
{}
|
|
|
|
// auto_generator has an attached attribute
|
|
template <
|
|
typename OutputIterator, typename Context, typename Delimiter
|
|
, typename Attribute>
|
|
bool generate(OutputIterator& sink, Context& context
|
|
, Delimiter const& d, Attribute const&) const
|
|
{
|
|
return generator_.generate(sink, context, d, t_);
|
|
}
|
|
|
|
template <typename Context>
|
|
info what(Context& /*context*/) const
|
|
{
|
|
return info("auto_");
|
|
}
|
|
|
|
typedef typename spirit::result_of::create_generator<T>::type
|
|
generator_type;
|
|
|
|
typedef typename spirit::result_of::compile<
|
|
karma::domain, generator_type, Modifiers>::type generator_impl_type;
|
|
|
|
T t_;
|
|
generator_impl_type generator_;
|
|
|
|
// silence MSVC warning C4512: assignment operator could not be generated
|
|
BOOST_DELETED_FUNCTION(lit_auto_generator& operator= (lit_auto_generator const&))
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Generator generators: make_xxx function (objects)
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// auto_
|
|
template <typename Modifiers>
|
|
struct make_primitive<tag::auto_, Modifiers>
|
|
{
|
|
typedef auto_generator<Modifiers> result_type;
|
|
|
|
result_type operator()(unused_type, Modifiers const& modifiers) const
|
|
{
|
|
return result_type(modifiers);
|
|
}
|
|
};
|
|
|
|
// auto_(...)
|
|
template <typename Modifiers, typename A0>
|
|
struct make_primitive<
|
|
terminal_ex<tag::auto_, fusion::vector1<A0> >, Modifiers>
|
|
{
|
|
typedef typename add_const<A0>::type const_attribute;
|
|
|
|
typedef lit_auto_generator<const_attribute, Modifiers> result_type;
|
|
|
|
template <typename Terminal>
|
|
result_type operator()(Terminal const& term, Modifiers const& modifiers) const
|
|
{
|
|
return result_type(fusion::at_c<0>(term.args), modifiers);
|
|
}
|
|
};
|
|
|
|
}}}
|
|
|
|
#endif
|