blob: bc63a7438b74d5ed0bc9278804f53bf8f055c0de [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2014 Joel de Guzman
Copyright (c) 2013 Agustin Berge
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_X3_PARSER_OCTOBER_16_2008_0254PM)
#define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/spirit/home/x3/support/context.hpp>
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
#include <string>
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
#include <typeinfo>
#endif
namespace boost { namespace spirit { namespace x3
{
using x3::unused_type;
using x3::unused;
using x3::get;
template <typename Subject, typename Action>
struct action;
template <typename Subject, typename Handler>
struct guard;
struct parser_base {};
struct parser_id;
template <typename Derived>
struct parser : parser_base
{
typedef Derived derived_type;
static bool const handles_container = false;
static bool const is_pass_through_unary = false;
static bool const has_action = false;
Derived const& derived() const
{
return *static_cast<Derived const*>(this);
}
template <typename Action>
action<Derived, Action>
operator[](Action f) const
{
return action<Derived, Action>(this->derived(), f);
}
template <typename Handler>
guard<Derived, Handler>
on_error(Handler f) const
{
return guard<Derived, Handler>(this->derived(), f);
}
};
struct unary_category;
struct binary_category;
template <typename Subject, typename Derived>
struct unary_parser : parser<Derived>
{
typedef unary_category category;
typedef Subject subject_type;
static bool const has_action = Subject::has_action;
unary_parser(Subject subject)
: subject(subject) {}
unary_parser const& get_unary() const { return *this; }
Subject subject;
};
template <typename Left, typename Right, typename Derived>
struct binary_parser : parser<Derived>
{
typedef binary_category category;
typedef Left left_type;
typedef Right right_type;
static bool const has_action =
left_type::has_action || right_type::has_action;
binary_parser(Left left, Right right)
: left(left), right(right) {}
binary_parser const& get_binary() const { return *this; }
Left left;
Right right;
};
///////////////////////////////////////////////////////////////////////////
// as_parser: convert a type, T, into a parser.
///////////////////////////////////////////////////////////////////////////
namespace extension
{
namespace detail
{
namespace as_parser_guard
{
void as_spirit_parser(...);
template<typename T, typename R =
decltype(as_spirit_parser(boost::declval<T const&>()))>
struct deduce_as_parser
{
typedef R type;
typedef typename
boost::remove_cv<
typename boost::remove_reference<R>::type
>::type
value_type;
static type call(T const& v)
{
return as_spirit_parser(v);
}
};
template<typename T>
struct deduce_as_parser<T, void>
{};
}
using as_parser_guard::deduce_as_parser;
}
template <typename T, typename Enable = void>
struct as_parser : detail::deduce_as_parser<T> {};
template <>
struct as_parser<unused_type>
{
typedef unused_type type;
typedef unused_type value_type;
static type call(unused_type)
{
return unused;
}
};
template <typename Derived>
struct as_parser<Derived
, typename enable_if<is_base_of<parser_base, Derived>>::type>
{
typedef Derived const& type;
typedef Derived value_type;
static type call(Derived const& p)
{
return p;
}
};
template <typename Derived>
struct as_parser<parser<Derived>>
{
typedef Derived const& type;
typedef Derived value_type;
static type call(parser<Derived> const& p)
{
return p.derived();
}
};
}
template <typename T>
inline typename extension::as_parser<T>::type
as_parser(T const& x)
{
return extension::as_parser<T>::call(x);
}
template <typename Derived>
inline Derived const&
as_parser(parser<Derived> const& p)
{
return p.derived();
}
///////////////////////////////////////////////////////////////////////////
// The main what function
//
// Note: unlike Spirit2, spirit parsers are no longer required to have a
// "what" member function. In X3, we specialize the get_info struct
// below where needed. If a specialization is not provided, the default
// below will be used. The default "what" result will be the typeid
// name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
// "undefined"
///////////////////////////////////////////////////////////////////////////
template <typename Parser, typename Enable = void>
struct get_info
{
typedef std::string result_type;
std::string operator()(Parser const&) const
{
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
return typeid(Parser).name();
#else
return "undefined";
#endif
}
};
template <typename Parser>
std::string what(Parser const& p)
{
return get_info<Parser>()(p);
}
}}}
namespace boost { namespace spirit { namespace x3 { namespace traits
{
template <typename Subject, typename Derived, typename Context>
struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
: has_attribute<Subject, Context> {};
template <typename Left, typename Right, typename Derived, typename Context>
struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
: mpl::bool_<has_attribute<Left, Context>::value ||
has_attribute<Right, Context>::value> {};
}}}}
#endif