/*============================================================================= 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 #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(BOOST_SPIRIT_X3_NO_RTTI) #include #endif namespace boost { namespace spirit { namespace x3 { template struct action; template struct guard; struct parser_base {}; struct parser_id; template 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(this); } template action operator[](Action f) const { return action(this->derived(), f); } template guard on_error(Handler f) const { return guard(this->derived(), f); } }; namespace detail { template static void assert_initialized_rule(Parser const& p) { boost::ignore_unused(p); // Assert that we are not copying an unitialized static rule. If // the static is in another TU, it may be initialized after we copy // it. If so, its name member will be nullptr. // // Rather than hardcoding behaviour for rule-type subject parsers, // we simply allow get_info<> to do the check in debug builds. #ifndef NDEBUG what(p); // note: allows get_info<> to diagnose the issue #endif } } struct unary_category; struct binary_category; template struct unary_parser : parser { typedef unary_category category; typedef Subject subject_type; static bool const has_action = Subject::has_action; unary_parser(Subject const& subject) : subject(subject) { detail::assert_initialized_rule(subject); } unary_parser const& get_unary() const { return *this; } Subject subject; }; template struct binary_parser : parser { 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 const& left, Right const& right) : left(left), right(right) { detail::assert_initialized_rule(left); detail::assert_initialized_rule(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()))> struct deduce_as_parser { typedef R type; typedef typename boost::remove_cv< typename boost::remove_reference::type >::type value_type; static type call(T const& v) { return as_spirit_parser(v); } }; template struct deduce_as_parser {}; } using as_parser_guard::deduce_as_parser; } template struct as_parser : detail::deduce_as_parser {}; template <> struct as_parser { typedef unused_type type; typedef unused_type value_type; static type call(unused_type) { return unused; } }; template struct as_parser>::type> { typedef Derived const& type; typedef Derived value_type; static type call(Derived const& p) { return p; } }; template struct as_parser> { typedef Derived const& type; typedef Derived value_type; static type call(parser const& p) { return p.derived(); } }; } template inline typename extension::as_parser::type as_parser(T const& x) { return extension::as_parser::call(x); } template inline Derived const& as_parser(parser 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 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 std::string what(Parser const& p) { return get_info()(p); } }}} namespace boost { namespace spirit { namespace x3 { namespace traits { template struct has_attribute, Context> : has_attribute {}; template struct has_attribute, Context> : mpl::bool_::value || has_attribute::value> {}; }}}} #endif