]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/support/meta_compiler.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / support / meta_compiler.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 http://spirit.sourceforge.net/
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 #ifndef BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
9 #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
10
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14
15 #include <boost/config.hpp>
16 #include <boost/spirit/include/phoenix_limits.hpp>
17 #include <boost/detail/workaround.hpp>
18 #include <boost/spirit/include/phoenix_limits.hpp> // needs to be included before proto
19 #include <boost/proto/proto.hpp>
20 #include <boost/spirit/home/support/make_component.hpp>
21 #include <boost/spirit/home/support/modify.hpp>
22 #include <boost/spirit/home/support/detail/make_cons.hpp>
23 #include <boost/spirit/home/support/unused.hpp>
24 #include <boost/spirit/home/support/assert_msg.hpp>
25 #include <boost/utility/enable_if.hpp>
26 #include <boost/type_traits/remove_reference.hpp>
27
28 namespace boost { namespace spirit
29 {
30 // Some defaults...
31
32 template <typename Domain, typename Tag, typename Enable = void>
33 struct use_operator : mpl::false_ {};
34
35 template <typename Domain, typename T, typename Enable = void>
36 struct use_function : mpl::false_ {};
37
38 template <typename Domain, typename T, typename Enable = void>
39 struct use_directive : mpl::false_ {};
40
41 template <typename Domain, typename T, typename Enable /* = void */>
42 struct is_modifier_directive : mpl::false_ {};
43
44 template <typename Domain, typename T, typename Enable = void>
45 struct use_terminal : mpl::false_ {};
46
47 template <typename Domain, typename T, typename Enable /*= void*/>
48 struct flatten_tree : mpl::false_ {};
49
50 // Our meta-compiler. This is the main engine that hooks Spirit
51 // to the proto expression template engine.
52
53 template <typename Domain>
54 struct meta_compiler
55 {
56 struct meta_grammar;
57
58 BOOST_SPIRIT_ASSERT_MSG((
59 !use_operator<Domain, proto::tag::subscript>::value
60 ), error_proto_tag_subscript_cannot_be_used, ());
61
62 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
63 // this is the non-broken part for compilers properly supporting
64 // partial template specialization (VC7.1 does not)
65 struct cases
66 {
67 template <typename Tag, typename Enable = void>
68 struct case_
69 : proto::not_<proto::_>
70 {};
71
72 ///////////////////////////////////////////////////////////////////
73 // terminals
74 ///////////////////////////////////////////////////////////////////
75 template <typename Enable>
76 struct case_<proto::tag::terminal, Enable>
77 : proto::when<
78 proto::if_<use_terminal<Domain, proto::_value>()>,
79 detail::make_terminal<Domain>
80 >
81 {};
82
83 template <typename Tag>
84 struct case_<Tag, typename enable_if<use_operator<Domain, Tag> >::type>
85 : proto::or_<
86 ///////////////////////////////////////////////////////////////////
87 // binary operators
88 ///////////////////////////////////////////////////////////////////
89 proto::when<proto::binary_expr<Tag, meta_grammar, meta_grammar>,
90 detail::make_binary<Domain, Tag, meta_grammar>
91 >,
92 ///////////////////////////////////////////////////////////////////
93 // unary operators
94 ///////////////////////////////////////////////////////////////////
95 proto::when<proto::unary_expr<Tag, meta_grammar>,
96 detail::make_unary<Domain, Tag, meta_grammar>
97 >
98 >
99 {};
100
101 template <typename Enable>
102 struct case_<proto::tag::subscript, Enable>
103 : proto::or_<
104 ///////////////////////////////////////////////////////////////////
105 // directives
106 ///////////////////////////////////////////////////////////////////
107 proto::when<proto::binary_expr<proto::tag::subscript
108 , proto::and_<
109 proto::terminal<proto::_>
110 , proto::if_<use_directive<Domain, proto::_value >()> >
111 , meta_grammar>,
112 detail::make_directive<Domain, meta_grammar>
113 >,
114 ///////////////////////////////////////////////////////////////////
115 // semantic actions
116 ///////////////////////////////////////////////////////////////////
117 proto::when<proto::binary_expr<proto::tag::subscript
118 , meta_grammar, proto::_>,
119 detail::make_action<Domain, meta_grammar>
120 >
121 >
122 {};
123 };
124 #else
125 // this part actually constitutes invalid C++ code, but it allows us to
126 // convince VC7.1 to do what we want
127 struct cases
128 {
129 template <typename Tag, typename Enable = void>
130 struct case_
131 : proto::not_<proto::_>
132 {};
133
134 ///////////////////////////////////////////////////////////////////
135 // terminals
136 ///////////////////////////////////////////////////////////////////
137 template <>
138 struct case_<proto::tag::terminal>
139 : proto::when<
140 proto::if_<use_terminal<Domain, proto::_value>()>,
141 detail::make_terminal<Domain>
142 >
143 {};
144
145 template <typename Tag>
146 struct case_<Tag>
147 : proto::or_<
148 ///////////////////////////////////////////////////////////////////
149 // binary operators
150 ///////////////////////////////////////////////////////////////////
151 proto::when<proto::binary_expr<
152 typename enable_if<use_operator<Domain, Tag>, Tag>::type
153 , meta_grammar, meta_grammar>
154 , detail::make_binary<Domain, Tag, meta_grammar>
155 >,
156 ///////////////////////////////////////////////////////////////////
157 // unary operators
158 ///////////////////////////////////////////////////////////////////
159 proto::when<proto::unary_expr<
160 typename enable_if<use_operator<Domain, Tag>, Tag>::type
161 , meta_grammar>
162 , detail::make_unary<Domain, Tag, meta_grammar>
163 >
164 >
165 {};
166
167 template <>
168 struct case_<proto::tag::subscript>
169 : proto::or_<
170 ///////////////////////////////////////////////////////////////////
171 // directives
172 ///////////////////////////////////////////////////////////////////
173 proto::when<proto::binary_expr<proto::tag::subscript
174 , proto::and_<
175 proto::terminal<proto::_>
176 , proto::if_<use_directive<Domain, proto::_value >()> >
177 , meta_grammar>,
178 detail::make_directive<Domain, meta_grammar>
179 >,
180 ///////////////////////////////////////////////////////////////////
181 // semantic actions
182 ///////////////////////////////////////////////////////////////////
183 proto::when<proto::binary_expr<proto::tag::subscript
184 , meta_grammar, proto::_>,
185 detail::make_action<Domain, meta_grammar>
186 >
187 >
188 {};
189 };
190 #endif
191
192 struct meta_grammar
193 : proto::switch_<cases>
194 {};
195 };
196
197 namespace result_of
198 {
199 // Default case
200 template <typename Domain, typename Expr
201 , typename Modifiers = unused_type, typename Enable = void>
202 struct compile
203 {
204 typedef typename meta_compiler<Domain>::meta_grammar meta_grammar;
205 typedef typename meta_grammar::
206 template result<meta_grammar(Expr, mpl::void_, Modifiers)>::type
207 type;
208 };
209
210 // If Expr is not a proto expression, make it a terminal
211 template <typename Domain, typename Expr, typename Modifiers>
212 struct compile<Domain, Expr, Modifiers,
213 typename disable_if<proto::is_expr<Expr> >::type>
214 : compile<Domain, typename proto::terminal<Expr>::type, Modifiers> {};
215 }
216
217 namespace traits
218 {
219 // Check if Expr matches the domain's grammar
220 template <typename Domain, typename Expr>
221 struct matches :
222 proto::matches<
223 typename proto::result_of::as_expr<
224 typename remove_reference<Expr>::type>::type,
225 typename meta_compiler<Domain>::meta_grammar
226 >
227 {
228 };
229 }
230
231 namespace detail
232 {
233 template <typename Domain>
234 struct compiler
235 {
236 // Default case
237 template <typename Expr, typename Modifiers>
238 static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
239 compile(Expr const& expr, Modifiers modifiers, mpl::true_)
240 {
241 typename meta_compiler<Domain>::meta_grammar compiler;
242 return compiler(expr, mpl::void_(), modifiers);
243 }
244
245 // If Expr is not a proto expression, make it a terminal
246 template <typename Expr, typename Modifiers>
247 static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
248 compile(Expr const& expr, Modifiers modifiers, mpl::false_)
249 {
250 typename meta_compiler<Domain>::meta_grammar compiler;
251 typedef typename detail::as_meta_element<Expr>::type expr_;
252 typename proto::terminal<expr_>::type term = {expr};
253 return compiler(term, mpl::void_(), modifiers);
254 }
255 };
256 }
257
258 template <typename Domain, typename Expr>
259 inline typename result_of::compile<Domain, Expr, unused_type>::type
260 compile(Expr const& expr)
261 {
262 typedef typename proto::is_expr<Expr>::type is_expr;
263 return detail::compiler<Domain>::compile(expr, unused, is_expr());
264 }
265
266 template <typename Domain, typename Expr, typename Modifiers>
267 inline typename result_of::compile<Domain, Expr, Modifiers>::type
268 compile(Expr const& expr, Modifiers modifiers)
269 {
270 typedef typename proto::is_expr<Expr>::type is_expr;
271 return detail::compiler<Domain>::compile(expr, modifiers, is_expr());
272 }
273
274 ///////////////////////////////////////////////////////////////////////////
275 template <typename Elements, template <typename Subject> class generator>
276 struct make_unary_composite
277 {
278 typedef typename
279 fusion::result_of::value_at_c<Elements, 0>::type
280 element_type;
281 typedef generator<element_type> result_type;
282 result_type operator()(Elements const& elements, unused_type) const
283 {
284 return result_type(fusion::at_c<0>(elements));
285 }
286 };
287
288 template <typename Elements, template <typename Left, typename Right> class generator>
289 struct make_binary_composite
290 {
291 typedef typename
292 fusion::result_of::value_at_c<Elements, 0>::type
293 left_type;
294 typedef typename
295 fusion::result_of::value_at_c<Elements, 1>::type
296 right_type;
297 typedef generator<left_type, right_type> result_type;
298
299 result_type operator()(Elements const& elements, unused_type) const
300 {
301 return result_type(
302 fusion::at_c<0>(elements)
303 , fusion::at_c<1>(elements)
304 );
305 }
306 };
307
308 template <typename Elements, template <typename Elements_> class generator>
309 struct make_nary_composite
310 {
311 typedef generator<Elements> result_type;
312 result_type operator()(Elements const& elements, unused_type) const
313 {
314 return result_type(elements);
315 }
316 };
317
318 }}
319
320 #endif