blob: b7314cd629cffe85f527d28aa4f7361685faf3cb [file] [log] [blame]
/*=============================================================================
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_META_GRAMMAR_FEB_05_2007_0951AM)
#define BOOST_SPIRIT_META_GRAMMAR_FEB_05_2007_0951AM
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/support/placeholders.hpp>
#include <boost/spirit/home/support/meta_grammar.hpp>
#include <boost/spirit/home/qi/numeric/real_policies.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost { namespace spirit
{
namespace qi
{
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct int_tag;
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct uint_tag;
template <typename T, typename RealPolicies>
struct real_tag;
}
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct is_int_tag<qi::int_tag<T, Radix, MinDigits, MaxDigits>, qi::domain>
: mpl::true_ {};
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct is_int_tag<qi::uint_tag<T, Radix, MinDigits, MaxDigits>, qi::domain>
: mpl::true_ {};
template <typename T, typename RealPolicies>
struct is_real_tag<qi::real_tag<T, RealPolicies>, qi::domain>
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
///////////////////////////////////////////////////////////////////////////
// forwards
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct int_parser;
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct uint_parser;
template <typename T, typename RealPolicies>
struct real_parser;
template <typename Expr, typename Enable>
struct is_valid_expr;
template <typename Expr, typename Enable>
struct expr_transform;
///////////////////////////////////////////////////////////////////////////
// numeric tags
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct int_tag
{
};
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct uint_tag
{
};
template <typename T, typename RealPolicies>
struct real_tag
{
RealPolicies policies;
};
///////////////////////////////////////////////////////////////////////////
// numeric specs
///////////////////////////////////////////////////////////////////////////
template <
typename T = int
, unsigned Radix = 10
, unsigned MinDigits = 1
, int MaxDigits = -1
>
struct int_spec
: proto::terminal<
int_tag<T, Radix, MinDigits, MaxDigits>
>::type
{
};
template <
typename T = int
, unsigned Radix = 10
, unsigned MinDigits = 1
, int MaxDigits = -1
>
struct uint_spec
: proto::terminal<
uint_tag<T, Radix, MinDigits, MaxDigits>
>::type
{
};
///////////////////////////////////////////////////////////////////////////
template <
typename T = double,
typename RealPolicies = real_policies<T>
>
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; }
};
}
///////////////////////////////////////////////////////////////////////////
// get the director of an int tag
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct extract_int_director;
template <>
struct extract_int_director<tag::bin>
{
typedef uint_parser<unsigned, 2, 1, -1> type;
};
template <>
struct extract_int_director<tag::oct>
{
typedef uint_parser<unsigned, 8, 1, -1> type;
};
template <>
struct extract_int_director<tag::hex>
{
typedef uint_parser<unsigned, 16, 1, -1> type;
};
template <>
struct extract_int_director<tag::ushort>
{
typedef uint_parser<unsigned short, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::ulong>
{
typedef uint_parser<unsigned long, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::uint>
{
typedef uint_parser<unsigned int, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::short_>
{
typedef int_parser<short, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::long_>
{
typedef int_parser<long, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::int_>
{
typedef int_parser<int, 10, 1, -1> type;
};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct extract_int_director<tag::ulong_long>
{
typedef uint_parser<unsigned long long, 10, 1, -1> type;
};
template <>
struct extract_int_director<tag::long_long>
{
typedef int_parser<long long, 10, 1, -1> type;
};
#endif
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct extract_int_director<int_tag<T, Radix, MinDigits, MaxDigits> >
{
typedef int_parser<T, Radix, MinDigits, MaxDigits> type;
};
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct extract_int_director<uint_tag<T, Radix, MinDigits, MaxDigits> >
{
typedef uint_parser<T, Radix, MinDigits, MaxDigits> type;
};
///////////////////////////////////////////////////////////////////////////
// get the director of a real tag
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct extract_real_director;
template <>
struct extract_real_director<tag::float_>
{
typedef real_parser<float, real_policies<float> > type;
};
template <>
struct extract_real_director<tag::double_>
{
typedef real_parser<double, real_policies<double> > type;
};
template <>
struct extract_real_director<tag::long_double>
{
typedef real_parser<long double, real_policies<long double> > type;
};
template <typename T, typename RealPolicies>
struct extract_real_director<real_tag<T, RealPolicies> >
{
typedef real_parser<T, RealPolicies> type;
};
///////////////////////////////////////////////////////////////////////////
// numeric parser meta-grammar
///////////////////////////////////////////////////////////////////////////
struct int_meta_grammar
: meta_grammar::compose_empty<
proto::if_<is_int_tag<proto::_child, qi::domain>()>
, qi::domain
, mpl::identity<extract_int_director<mpl::_> >
>
{};
struct real_meta_grammar
: meta_grammar::compose_single<
proto::if_<is_real_tag<proto::_child, qi::domain>()>
, qi::domain
, mpl::identity<extract_real_director<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