1/*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2013 Agustin Berge
4
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
10
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/core/ignore_unused.hpp>
21#include <boost/assert.hpp>
22#include <string>
23
24#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
25#include <typeinfo>
26#endif
27
28namespace boost { namespace spirit { namespace x3
29{
30 template <typename Subject, typename Action>
31 struct action;
32
33 template <typename Subject, typename Handler>
34 struct guard;
35
36 struct parser_base {};
37 struct parser_id;
38
39 template <typename Derived>
40 struct parser : parser_base
41 {
42 typedef Derived derived_type;
43 static bool const handles_container = false;
44 static bool const is_pass_through_unary = false;
45 static bool const has_action = false;
46
47 constexpr Derived const& derived() const
48 {
49 return *static_cast<Derived const*>(this);
50 }
51
52 template <typename Action>
53 constexpr action<Derived, Action> operator[](Action f) const
54 {
55 return { this->derived(), f };
56 }
57
58 template <typename Handler>
59 constexpr guard<Derived, Handler> on_error(Handler f) const
60 {
61 return { this->derived(), f };
62 }
63 };
64
65 struct unary_category;
66 struct binary_category;
67
68 template <typename Subject, typename Derived>
69 struct unary_parser : parser<Derived>
70 {
71 typedef unary_category category;
72 typedef Subject subject_type;
73 static bool const has_action = Subject::has_action;
74
75 constexpr unary_parser(Subject const& subject)
76 : subject(subject) {}
77
78 unary_parser const& get_unary() const { return *this; }
79
80 Subject subject;
81 };
82
83 template <typename Left, typename Right, typename Derived>
84 struct binary_parser : parser<Derived>
85 {
86 typedef binary_category category;
87 typedef Left left_type;
88 typedef Right right_type;
89 static bool const has_action =
90 left_type::has_action || right_type::has_action;
91
92 constexpr binary_parser(Left const& left, Right const& right)
93 : left(left), right(right) {}
94
95 binary_parser const& get_binary() const { return *this; }
96
97 Left left;
98 Right right;
99 };
100
101 ///////////////////////////////////////////////////////////////////////////
102 // as_parser: convert a type, T, into a parser.
103 ///////////////////////////////////////////////////////////////////////////
104 namespace extension
105 {
106 namespace detail
107 {
108 namespace as_parser_guard
109 {
110 void as_spirit_parser(...);
111
112 template<typename T, typename R =
113 decltype(as_spirit_parser(boost::declval<T const&>()))>
114 struct deduce_as_parser
115 {
116 typedef R type;
117 typedef typename
118 boost::remove_cv<
119 typename boost::remove_reference<R>::type
120 >::type
121 value_type;
122
123 static type call(T const& v)
124 {
125 return as_spirit_parser(v);
126 }
127 };
128 template<typename T>
129 struct deduce_as_parser<T, void>
130 {};
131 }
132 using as_parser_guard::deduce_as_parser;
133 }
134
135 template <typename T, typename Enable = void>
136 struct as_parser : detail::deduce_as_parser<T> {};
137
138 template <>
139 struct as_parser<unused_type>
140 {
141 typedef unused_type type;
142 typedef unused_type value_type;
143 static constexpr type call(unused_type)
144 {
145 return unused;
146 }
147 };
148
149 template <typename Derived>
150 struct as_parser<Derived
151 , typename enable_if<is_base_of<parser_base, Derived>>::type>
152 {
153 typedef Derived const& type;
154 typedef Derived value_type;
155 static constexpr type call(Derived const& p)
156 {
157 return p;
158 }
159 };
160
161 template <typename Derived>
162 struct as_parser<parser<Derived>>
163 {
164 typedef Derived const& type;
165 typedef Derived value_type;
166 static constexpr type call(parser<Derived> const& p)
167 {
168 return p.derived();
169 }
170 };
171 }
172
173 template <typename T>
174 constexpr typename extension::as_parser<T>::type
175 as_parser(T const& x)
176 {
177 return extension::as_parser<T>::call(x);
178 }
179
180 template <typename Derived>
181 constexpr Derived const&
182 as_parser(parser<Derived> const& p)
183 {
184 return p.derived();
185 }
186
187 ///////////////////////////////////////////////////////////////////////////
188 // The main what function
189 //
190 // Note: unlike Spirit2, spirit parsers are no longer required to have a
191 // "what" member function. In X3, we specialize the get_info struct
192 // below where needed. If a specialization is not provided, the default
193 // below will be used. The default "what" result will be the typeid
194 // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
195 // "undefined"
196 ///////////////////////////////////////////////////////////////////////////
197 template <typename Parser, typename Enable = void>
198 struct get_info
199 {
200 typedef std::string result_type;
201 std::string operator()(Parser const&) const
202 {
203#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
204 return typeid(Parser).name();
205#else
206 return "undefined";
207#endif
208 }
209 };
210
211 template <typename Parser>
212 std::string what(Parser const& p)
213 {
214 return get_info<Parser>()(p);
215 }
216}}}
217
218namespace boost { namespace spirit { namespace x3 { namespace traits
219{
220 template <typename Subject, typename Derived, typename Context>
221 struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
222 : has_attribute<Subject, Context> {};
223
224 template <typename Left, typename Right, typename Derived, typename Context>
225 struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
226 : mpl::bool_<has_attribute<Left, Context>::value ||
227 has_attribute<Right, Context>::value> {};
228}}}}
229
230#endif
231

source code of boost/libs/spirit/include/boost/spirit/home/x3/core/parser.hpp