1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2013 Agustin Berge
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM)
9 #define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
11 #include <boost/mpl/bool.hpp>
12 #include <boost/type_traits/is_base_of.hpp>
13 #include <boost/type_traits/remove_cv.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <boost/utility/declval.hpp>
16 #include <boost/utility/enable_if.hpp>
17 #include <boost/spirit/home/x3/support/unused.hpp>
18 #include <boost/spirit/home/x3/support/context.hpp>
19 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
20 #include <boost/spirit/home/x3/support/utility/sfinae.hpp>
21 #include <boost/core/ignore_unused.hpp>
22 #include <boost/assert.hpp>
25 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
29 namespace boost { namespace spirit { namespace x3
31 template <typename Subject, typename Action>
34 template <typename Subject, typename Handler>
37 struct parser_base {};
40 template <typename Derived>
41 struct parser : parser_base
43 typedef Derived derived_type;
44 static bool const handles_container = false;
45 static bool const is_pass_through_unary = false;
46 static bool const has_action = false;
48 Derived const& derived() const
50 return *static_cast<Derived const*>(this);
53 template <typename Action>
54 action<Derived, Action> operator[](Action f) const
56 return { this->derived(), f };
59 template <typename Handler>
60 guard<Derived, Handler> on_error(Handler f) const
62 return { this->derived(), f };
67 template <typename Parser>
68 static void assert_initialized_rule(Parser const& p) {
69 boost::ignore_unused(p);
71 // Assert that we are not copying an unitialized static rule. If
72 // the static is in another TU, it may be initialized after we copy
73 // it. If so, its name member will be nullptr.
75 // Rather than hardcoding behaviour for rule-type subject parsers,
76 // we simply allow get_info<> to do the check in debug builds.
78 what(p); // note: allows get_info<> to diagnose the issue
83 struct unary_category;
84 struct binary_category;
86 template <typename Subject, typename Derived>
87 struct unary_parser : parser<Derived>
89 typedef unary_category category;
90 typedef Subject subject_type;
91 static bool const has_action = Subject::has_action;
93 unary_parser(Subject const& subject)
94 : subject(subject) { detail::assert_initialized_rule(subject); }
96 unary_parser const& get_unary() const { return *this; }
101 template <typename Left, typename Right, typename Derived>
102 struct binary_parser : parser<Derived>
104 typedef binary_category category;
105 typedef Left left_type;
106 typedef Right right_type;
107 static bool const has_action =
108 left_type::has_action || right_type::has_action;
110 binary_parser(Left const& left, Right const& right)
111 : left(left), right(right)
113 detail::assert_initialized_rule(left);
114 detail::assert_initialized_rule(right);
117 binary_parser const& get_binary() const { return *this; }
123 ///////////////////////////////////////////////////////////////////////////
124 // as_parser: convert a type, T, into a parser.
125 ///////////////////////////////////////////////////////////////////////////
130 namespace as_parser_guard
132 void as_spirit_parser(...);
134 template<typename T, typename R =
135 decltype(as_spirit_parser(boost::declval<T const&>()))>
136 struct deduce_as_parser
141 typename boost::remove_reference<R>::type
145 static type call(T const& v)
147 return as_spirit_parser(v);
151 struct deduce_as_parser<T, void>
154 using as_parser_guard::deduce_as_parser;
157 template <typename T, typename Enable = void>
158 struct as_parser : detail::deduce_as_parser<T> {};
161 struct as_parser<unused_type>
163 typedef unused_type type;
164 typedef unused_type value_type;
165 static type call(unused_type)
171 template <typename Derived>
172 struct as_parser<Derived
173 , typename enable_if<is_base_of<parser_base, Derived>>::type>
175 typedef Derived const& type;
176 typedef Derived value_type;
177 static type call(Derived const& p)
183 template <typename Derived>
184 struct as_parser<parser<Derived>>
186 typedef Derived const& type;
187 typedef Derived value_type;
188 static type call(parser<Derived> const& p)
195 template <typename T>
196 inline typename extension::as_parser<T>::type
197 as_parser(T const& x)
199 return extension::as_parser<T>::call(x);
202 template <typename Derived>
203 inline Derived const&
204 as_parser(parser<Derived> const& p)
209 ///////////////////////////////////////////////////////////////////////////
210 // The main what function
212 // Note: unlike Spirit2, spirit parsers are no longer required to have a
213 // "what" member function. In X3, we specialize the get_info struct
214 // below where needed. If a specialization is not provided, the default
215 // below will be used. The default "what" result will be the typeid
216 // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
218 ///////////////////////////////////////////////////////////////////////////
219 template <typename Parser, typename Enable = void>
222 typedef std::string result_type;
223 std::string operator()(Parser const&) const
225 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
226 return typeid(Parser).name();
233 template <typename Parser>
234 std::string what(Parser const& p)
236 return get_info<Parser>()(p);
240 namespace boost { namespace spirit { namespace x3 { namespace traits
242 template <typename Subject, typename Derived, typename Context>
243 struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
244 : has_attribute<Subject, Context> {};
246 template <typename Left, typename Right, typename Derived, typename Context>
247 struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
248 : mpl::bool_<has_attribute<Left, Context>::value ||
249 has_attribute<Right, Context>::value> {};