blob: efe04b2dafc0364df5b6bda3e99208ad91eb688a [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_RULE_MAR_05_2007_0455PM)
#define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once // MS compatible compilers support #pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/nonterminal/nonterminal.hpp>
#include <boost/spirit/home/karma/nonterminal/grammar_fwd.hpp>
#include <boost/spirit/home/karma/nonterminal/detail/rule.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
#endif
namespace boost { namespace spirit { namespace karma
{
template <typename OutputIterator, typename T0 = unused_type,
typename T1 = unused_type, typename T2 = unused_type>
struct rule
: make_nonterminal<rule<OutputIterator, T0, T1, T2>, T0, T1, T2>::type
{
typedef
make_nonterminal<rule<OutputIterator, T0, T1, T2>, T0, T1, T2>
make_nonterminal_;
typedef typename make_nonterminal_::delimiter_type delimiter_type;
typedef typename make_nonterminal_::type base_type;
typedef detail::output_iterator<OutputIterator> iterator_type;
typedef rule<OutputIterator, T0, T1, T2> self_type;
typedef
detail::virtual_component_base<
iterator_type,
typename base_type::context_type,
delimiter_type
>
virtual_component;
typedef intrusive_ptr<virtual_component> pointer_type;
rule() {}
~rule() {}
rule(rule const& rhs)
: ptr(rhs.ptr)
{
}
rule& operator=(rule const& rhs)
{
ptr = rhs.ptr;
return *this;
}
template <typename Expr>
rule& operator=(Expr const& xpr)
{
typedef
spirit::traits::is_component<karma::domain, Expr>
is_component;
// report invalid expression error as early as possible
// BOOST_MPL_ASSERT_MSG(
// is_component::value,
// xpr_is_not_convertible_to_a_generator, ());
// temp workaround for mpl problem
BOOST_STATIC_ASSERT(is_component::value);
define(xpr, mpl::false_());
return *this;
}
template <typename Expr>
friend rule& operator%=(rule& r, Expr const& xpr)
{
typedef
spirit::traits::is_component<karma::domain, Expr>
is_component;
// report invalid expression error as early as possible
// BOOST_MPL_ASSERT_MSG(
// is_component::value,
// xpr_is_not_convertible_to_a_generator, ());
// temp workaround for mpl problem
BOOST_STATIC_ASSERT(is_component::value);
r.define(xpr, mpl::true_());
return r;
}
self_type alias() const
{
self_type result;
result.define(*this, mpl::false_());
return result;
}
typename
make_nonterminal_holder<
nonterminal_object<self_type>
, self_type
>::type
copy() const
{
typename
make_nonterminal_holder<
nonterminal_object<self_type>
, self_type
>::type
result = {{*this}};
return result;
}
std::string name() const
{
return name_;
}
void name(std::string const& str)
{
name_ = str;
}
private:
template <typename Iterator_, typename T0_, typename T1_, typename T2_>
friend struct grammar;
template <typename Expr, typename Auto>
void define(Expr const& xpr, Auto)
{
typedef typename
result_of::as_component<karma::domain, Expr>::type
component;
typedef
detail::virtual_component<
iterator_type,
component,
typename base_type::context_type,
delimiter_type,
Auto
>
virtual_component;
ptr = new virtual_component(spirit::as_component(karma::domain(), xpr));
}
template <typename OutputIterator_, typename Context, typename Delimiter>
bool generate(
OutputIterator_& sink, Context& context, Delimiter const& delim) const
{
// If the following line produces a compilation error stating the
// 3rd parameter is not convertible to the expected type, then you
// are probably trying to use this rule instance with a delimiter
// which is not compatible with the delimiter type used while
// defining the type of this rule instance.
return ptr->generate(sink, context, delim);
}
std::string what() const
{
if (name_.empty())
{
if (ptr)
{
return "unnamed-rule";
}
else
{
return "empty-rule";
}
}
else
{
return name_;
}
}
friend struct nonterminal_director;
pointer_type ptr;
std::string name_;
};
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif