blob: 313ec6c88275c90989cf2cd1102c8040b5c1d9dd [file] [log] [blame]
// Copyright (c) 2001-2009 Hartmut Kaiser
// 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_KARMA_META_GRAMMAR_FEB_23_2007_0505PM)
#define BOOST_SPIRIT_KARMA_META_GRAMMAR_FEB_23_2007_0505PM
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once // MS compatible compilers support #pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/numeric_fwd.hpp>
#include <boost/spirit/home/support/placeholders.hpp>
#include <boost/spirit/home/support/meta_grammar.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit { namespace karma
{
template <typename Expr, typename Enable>
struct is_valid_expr;
template <typename Expr, typename Enable>
struct expr_transform;
///////////////////////////////////////////////////////////////////////////
// numeric tags
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, bool ForceSign>
struct int_tag
{};
template <typename T, unsigned Radix, bool ForceSign>
struct uint_tag
{};
template <typename T, typename RealPolicies>
struct real_tag
{
RealPolicies policies;
};
///////////////////////////////////////////////////////////////////////////
// numeric specs
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, bool ForceSign>
struct int_spec
: proto::terminal<int_tag<T, Radix, ForceSign> >::type
{};
template <typename T, unsigned Radix, bool ForceSign>
struct uint_spec
: proto::terminal<uint_tag<T, Radix, ForceSign> >::type
{};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename RealPolicies>
struct real_spec
: proto::terminal<real_tag<T, RealPolicies> >::type
{
private:
typedef typename
proto::terminal<real_tag<T, RealPolicies> >::type
base_type;
base_type make_tag(RealPolicies const& p) const
{
base_type xpr = {{p}};
return xpr;
}
public:
real_spec(RealPolicies const& p = RealPolicies())
: base_type(make_tag(p))
{}
};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename RealPolicies>
struct real_policy
{
template <typename Tag>
static RealPolicies get(Tag) { return RealPolicies(); }
template <typename T>
static RealPolicies const& get(real_tag<T, RealPolicies> const& p)
{ return p.policies; }
};
}
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// test if a tag is an int tag (the basic specializations are defined in
// the file support/placeholders.hpp)
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, bool ForceSign>
struct is_int_tag<karma::int_tag<T, Radix, ForceSign>, karma::domain> :
mpl::true_ {};
template <typename T, unsigned Radix, bool ForceSign>
struct is_int_tag<karma::uint_tag<T, Radix, ForceSign>, karma::domain> :
mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// test if a tag is a real tag (the basic specializations are defined in
// the file support/placeholders.hpp)
///////////////////////////////////////////////////////////////////////////
template <typename T, typename RealPolicies>
struct is_real_tag<karma::real_tag<T, RealPolicies>, karma::domain> :
mpl::true_ {};
}} // namespace boost::spirit
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// get the director of an int tag
///////////////////////////////////////////////////////////////////////////
template <typename T, bool IsLiteral>
struct extract_int_director;
template <bool IsLiteral>
struct extract_int_director<tag::bin, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned, 2, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::oct, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned, 8, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::hex, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned, 16, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::ushort, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned short, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::ulong, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned long, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::uint, IsLiteral>
{
typedef uint_generator<IsLiteral, unsigned int, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::short_, IsLiteral>
{
typedef int_generator<IsLiteral, short, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::long_, IsLiteral>
{
typedef int_generator<IsLiteral, long, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::int_, IsLiteral>
{
typedef int_generator<IsLiteral, int, 10, false> type;
};
#ifdef BOOST_HAS_LONG_LONG
template <bool IsLiteral>
struct extract_int_director<tag::ulong_long, IsLiteral>
{
typedef uint_generator<IsLiteral, boost::ulong_long_type, 10, false> type;
};
template <bool IsLiteral>
struct extract_int_director<tag::long_long, IsLiteral>
{
typedef int_generator<IsLiteral, boost::long_long_type, 10, false> type;
};
#endif
template <typename T, unsigned Radix, bool ForceSign, bool IsLiteral>
struct extract_int_director<int_tag<T, Radix, ForceSign>, IsLiteral>
{
typedef int_generator<IsLiteral, T, Radix, ForceSign> type;
};
template <typename T, unsigned Radix, bool ForceSign, bool IsLiteral>
struct extract_int_director<uint_tag<T, Radix, ForceSign>, IsLiteral>
{
typedef uint_generator<IsLiteral, T, Radix, ForceSign> type;
};
template <typename T, typename Unused>
struct extract_int_director_lit
: extract_int_director<T, true> {};
template <typename T>
struct extract_int_director_plain
: extract_int_director<T, false> {};
///////////////////////////////////////////////////////////////////////////
// get the director of a floating point literal type
///////////////////////////////////////////////////////////////////////////
template <typename Tag>
struct extract_literal_real_director;
template <>
struct extract_literal_real_director<float>
{
typedef
real_generator<true, float, real_generator_policies<float> >
type;
};
template <>
struct extract_literal_real_director<double>
{
typedef
real_generator<true, double, real_generator_policies<double> >
type;
};
template <>
struct extract_literal_real_director<long double>
{
typedef
real_generator<
true, long double, real_generator_policies<long double>
>
type;
};
///////////////////////////////////////////////////////////////////////////
// get the director of a floating point tag
///////////////////////////////////////////////////////////////////////////
template <typename Tag, bool IsLiteral>
struct extract_real_director;
template <bool IsLiteral>
struct extract_real_director<tag::float_, IsLiteral>
{
typedef
real_generator<IsLiteral, float, real_generator_policies<float> >
type;
};
template <bool IsLiteral>
struct extract_real_director<tag::double_, IsLiteral>
{
typedef
real_generator<IsLiteral, double, real_generator_policies<double> >
type;
};
template <bool IsLiteral>
struct extract_real_director<tag::long_double, IsLiteral>
{
typedef
real_generator<
IsLiteral, long double, real_generator_policies<long double>
>
type;
};
template <typename T, typename RealPolicies, bool IsLiteral>
struct extract_real_director<real_tag<T, RealPolicies>, IsLiteral>
{
typedef real_generator<IsLiteral, T, RealPolicies> type;
};
///////////////////////////////////////////////////////////////////////////
template <typename Tag, typename Unused>
struct extract_real_director_lit
: extract_real_director<Tag, true> {};
template <typename Tag>
struct extract_real_director_plain
: extract_real_director<Tag, false> {};
///////////////////////////////////////////////////////////////////////////
// get the director of an integer literal type
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct extract_literal_int_director;
template <>
struct extract_literal_int_director<short>
{
typedef int_generator<true, short, 10, false> type;
};
template <>
struct extract_literal_int_director<unsigned short>
{
typedef uint_generator<true, unsigned short, 10, false> type;
};
template <>
struct extract_literal_int_director<int>
{
typedef int_generator<true, int, 10, false> type;
};
template <>
struct extract_literal_int_director<unsigned int>
{
typedef uint_generator<true, unsigned int, 10, false> type;
};
template <>
struct extract_literal_int_director<long>
{
typedef int_generator<true, long, 10, false> type;
};
template <>
struct extract_literal_int_director<unsigned long>
{
typedef uint_generator<true, unsigned long, 10, false> type;
};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct extract_literal_int_director<boost::ulong_long_type>
{
typedef int_generator<true, boost::ulong_long_type, 10, false> type;
};
template <>
struct extract_literal_int_director<boost::long_long_type>
{
typedef uint_generator<true, boost::long_long_type, 10, false> type;
};
#endif
///////////////////////////////////////////////////////////////////////////
// numeric parser meta-grammar
///////////////////////////////////////////////////////////////////////////
// literals: 10, 10L, 10LL
struct int_literal_meta_grammar
: meta_grammar::compose_empty<
proto::if_<
is_int_lit_tag<proto::_child, karma::domain>()
>,
karma::domain,
mpl::identity<extract_literal_int_director<mpl::_> >
>
{};
// all the different integer's as int_, uint, bin, oct, dec, hex, etc.
// and the corresponding int_(10), uint(10), etc.
struct int_meta_grammar
: proto::or_<
meta_grammar::compose_empty<
proto::if_<
is_int_tag<proto::_child, karma::domain>()
>,
karma::domain,
mpl::identity<extract_int_director_plain<mpl::_> >
>,
meta_grammar::compose_function1_eval<
proto::function<
proto::if_<
is_int_tag<proto::_child, karma::domain>()
>,
int_literal_meta_grammar
>,
karma::domain,
mpl::identity<extract_int_director_lit<mpl::_, mpl::_> >
>
>
{};
// floating point literals: 1.0, 1.0f, 10.1e2 etc.
struct real_literal_meta_grammar
: meta_grammar::compose_empty<
proto::if_<
is_real_lit_tag<proto::_child, karma::domain>()
>,
karma::domain,
mpl::identity<extract_literal_real_director<mpl::_> >
>
{};
struct real_meta_grammar
: proto::or_<
meta_grammar::compose_single<
proto::if_<
is_real_tag<proto::_child, karma::domain>()
>,
karma::domain,
mpl::identity<extract_real_director_plain<mpl::_> >
>,
meta_grammar::compose_function1_full<
proto::function<
proto::if_<
is_real_tag<proto::_child, karma::domain>()
>,
real_literal_meta_grammar
>,
karma::domain,
mpl::identity<extract_real_director_lit<mpl::_, mpl::_> >
>
>
{};
///////////////////////////////////////////////////////////////////////////
struct numeric_meta_grammar
: proto::or_<
int_meta_grammar,
real_meta_grammar
>
{};
///////////////////////////////////////////////////////////////////////////
// These specializations non-intrusively hooks into the RD meta-grammar.
// (see qi/meta_grammar.hpp)
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct is_valid_expr<Expr
, typename enable_if<proto::matches<Expr, numeric_meta_grammar> >::type>
: mpl::true_
{};
template <typename Expr>
struct expr_transform<Expr
, typename enable_if<proto::matches<Expr, numeric_meta_grammar> >::type>
: mpl::identity<numeric_meta_grammar>
{};
}}}
#endif