boost/spirit/home/karma/char/char_generator.hpp
// Copyright (c) 2001-2011 Hartmut Kaiser
// 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_CHAR_GENERATOR_SEP_07_2009_0417PM)
#define BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/container.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::complement> // enables ~
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace traits // classification
{
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(char_generator_id)
}
template <typename T>
struct is_char_generator : detail::has_char_generator_id<T> {};
}}}
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// The base char_parser
///////////////////////////////////////////////////////////////////////////
template <typename Derived, typename CharEncoding, typename Tag
, typename Char = typename CharEncoding::char_type, typename Attr = Char>
struct char_generator : primitive_generator<Derived>
{
typedef CharEncoding char_encoding;
typedef Tag tag;
typedef Char char_type;
struct char_generator_id;
// if Attr is unused_type, Derived must supply its own attribute
// metafunction
template <typename Context, typename Unused>
struct attribute
{
typedef Attr type;
};
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr) const
{
if (!traits::has_optional_value(attr))
return false;
Attr ch = Attr();
if (!this->derived().test(traits::extract_from<Attr>(attr, context), ch, context))
return false;
return karma::detail::generate_to(sink, ch, char_encoding(), tag()) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// Requirement: g.test(attr, ch, context) -> bool
//
// attr: associated attribute
// ch: character to be generated (set by test())
// context: enclosing rule context
};
///////////////////////////////////////////////////////////////////////////
// negated_char_generator handles ~cg expressions (cg is a char_generator)
///////////////////////////////////////////////////////////////////////////
template <typename Positive>
struct negated_char_generator
: char_generator<negated_char_generator<Positive>
, typename Positive::char_encoding, typename Positive::tag>
{
negated_char_generator(Positive const& positive)
: positive(positive) {}
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context& context) const
{
return !positive.test(attr, ch, context);
}
template <typename Context>
info what(Context& context) const
{
return info("not", positive.what(context));
}
Positive positive;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Positive>
struct make_negated_char_generator
{
typedef negated_char_generator<Positive> result_type;
result_type operator()(Positive const& positive) const
{
return result_type(positive);
}
};
template <typename Positive>
struct make_negated_char_generator<negated_char_generator<Positive> >
{
typedef Positive result_type;
result_type operator()(negated_char_generator<Positive> const& ncg) const
{
return ncg.positive;
}
};
}
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::complement, Elements, Modifiers>
{
typedef typename
fusion::result_of::value_at_c<Elements, 0>::type
subject;
BOOST_SPIRIT_ASSERT_MSG((
traits::is_char_generator<subject>::value
), subject_is_not_negatable, (subject));
typedef typename
detail::make_negated_char_generator<subject>::result_type
result_type;
result_type operator()(Elements const& elements, unused_type) const
{
return detail::make_negated_char_generator<subject>()(
fusion::at_c<0>(elements));
}
};
}}}
#endif