123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*=============================================================================
- 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
- #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/core/ignore_unused.hpp>
- #include <boost/assert.hpp>
- #include <string>
- #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
- #include <typeinfo>
- #endif
- namespace boost { namespace spirit { namespace x3
- {
- 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;
- constexpr Derived const& derived() const
- {
- return *static_cast<Derived const*>(this);
- }
- template <typename Action>
- constexpr action<Derived, Action> operator[](Action f) const
- {
- return { this->derived(), f };
- }
- template <typename Handler>
- constexpr guard<Derived, Handler> on_error(Handler f) const
- {
- return { 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;
- constexpr unary_parser(Subject const& 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;
- constexpr binary_parser(Left const& left, Right const& 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 constexpr 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 constexpr type call(Derived const& p)
- {
- return p;
- }
- };
- template <typename Derived>
- struct as_parser<parser<Derived>>
- {
- typedef Derived const& type;
- typedef Derived value_type;
- static constexpr type call(parser<Derived> const& p)
- {
- return p.derived();
- }
- };
- }
- template <typename T>
- constexpr typename extension::as_parser<T>::type
- as_parser(T const& x)
- {
- return extension::as_parser<T>::call(x);
- }
- template <typename Derived>
- constexpr 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
|