Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/spirit/home/qi/nonterminal/rule.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 /*============================================================================= | |
2 Copyright (c) 2001-2011 Joel de Guzman | |
3 | |
4 Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 ==============================================================================*/ | |
7 #if !defined(BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM) | |
8 #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM | |
9 | |
10 #if defined(_MSC_VER) | |
11 #pragma once | |
12 #endif | |
13 | |
14 #include <boost/assert.hpp> | |
15 #include <boost/config.hpp> | |
16 #include <boost/function.hpp> | |
17 #include <boost/mpl/vector.hpp> | |
18 #include <boost/type_traits/add_reference.hpp> | |
19 #include <boost/type_traits/is_same.hpp> | |
20 | |
21 #include <boost/fusion/include/vector.hpp> | |
22 #include <boost/fusion/include/size.hpp> | |
23 #include <boost/fusion/include/make_vector.hpp> | |
24 #include <boost/fusion/include/cons.hpp> | |
25 #include <boost/fusion/include/as_list.hpp> | |
26 #include <boost/fusion/include/as_vector.hpp> | |
27 | |
28 #include <boost/spirit/home/support/unused.hpp> | |
29 #include <boost/spirit/home/support/argument.hpp> | |
30 #include <boost/spirit/home/support/context.hpp> | |
31 #include <boost/spirit/home/support/info.hpp> | |
32 #include <boost/spirit/home/qi/detail/attributes.hpp> | |
33 #include <boost/spirit/home/support/nonterminal/extract_param.hpp> | |
34 #include <boost/spirit/home/support/nonterminal/locals.hpp> | |
35 #include <boost/spirit/home/qi/reference.hpp> | |
36 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp> | |
37 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp> | |
38 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp> | |
39 #include <boost/spirit/home/qi/skip_over.hpp> | |
40 | |
41 #if defined(BOOST_MSVC) | |
42 # pragma warning(push) | |
43 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning | |
44 #endif | |
45 | |
46 namespace boost { namespace spirit { namespace qi | |
47 { | |
48 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _) | |
49 | |
50 using spirit::_pass_type; | |
51 using spirit::_val_type; | |
52 using spirit::_a_type; | |
53 using spirit::_b_type; | |
54 using spirit::_c_type; | |
55 using spirit::_d_type; | |
56 using spirit::_e_type; | |
57 using spirit::_f_type; | |
58 using spirit::_g_type; | |
59 using spirit::_h_type; | |
60 using spirit::_i_type; | |
61 using spirit::_j_type; | |
62 | |
63 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
64 | |
65 using spirit::_pass; | |
66 using spirit::_val; | |
67 using spirit::_a; | |
68 using spirit::_b; | |
69 using spirit::_c; | |
70 using spirit::_d; | |
71 using spirit::_e; | |
72 using spirit::_f; | |
73 using spirit::_g; | |
74 using spirit::_h; | |
75 using spirit::_i; | |
76 using spirit::_j; | |
77 | |
78 #endif | |
79 | |
80 using spirit::info; | |
81 using spirit::locals; | |
82 | |
83 template < | |
84 typename Iterator, typename T1, typename T2, typename T3 | |
85 , typename T4> | |
86 struct rule | |
87 : proto::extends< | |
88 typename proto::terminal< | |
89 reference<rule<Iterator, T1, T2, T3, T4> const> | |
90 >::type | |
91 , rule<Iterator, T1, T2, T3, T4> | |
92 > | |
93 , parser<rule<Iterator, T1, T2, T3, T4> > | |
94 { | |
95 typedef Iterator iterator_type; | |
96 typedef rule<Iterator, T1, T2, T3, T4> this_type; | |
97 typedef reference<this_type const> reference_; | |
98 typedef typename proto::terminal<reference_>::type terminal; | |
99 typedef proto::extends<terminal, this_type> base_type; | |
100 typedef mpl::vector<T1, T2, T3, T4> template_params; | |
101 | |
102 // The rule's locals_type: a sequence of types to be used as local variables | |
103 typedef typename | |
104 spirit::detail::extract_locals<template_params>::type | |
105 locals_type; | |
106 | |
107 // The rule's skip-parser type | |
108 typedef typename | |
109 spirit::detail::extract_component< | |
110 qi::domain, template_params>::type | |
111 skipper_type; | |
112 | |
113 // The rule's signature | |
114 typedef typename | |
115 spirit::detail::extract_sig<template_params>::type | |
116 sig_type; | |
117 | |
118 // The rule's encoding type | |
119 typedef typename | |
120 spirit::detail::extract_encoding<template_params>::type | |
121 encoding_type; | |
122 | |
123 // This is the rule's attribute type | |
124 typedef typename | |
125 spirit::detail::attr_from_sig<sig_type>::type | |
126 attr_type; | |
127 typedef typename add_reference<attr_type>::type attr_reference_type; | |
128 | |
129 // parameter_types is a sequence of types passed as parameters to the rule | |
130 typedef typename | |
131 spirit::detail::params_from_sig<sig_type>::type | |
132 parameter_types; | |
133 | |
134 static size_t const params_size = | |
135 fusion::result_of::size<parameter_types>::type::value; | |
136 | |
137 typedef context< | |
138 fusion::cons<attr_reference_type, parameter_types> | |
139 , locals_type> | |
140 context_type; | |
141 | |
142 typedef function< | |
143 bool(Iterator& first, Iterator const& last | |
144 , context_type& context | |
145 , skipper_type const& skipper | |
146 )> | |
147 function_type; | |
148 | |
149 typedef typename | |
150 mpl::if_< | |
151 is_same<encoding_type, unused_type> | |
152 , unused_type | |
153 , tag::char_code<tag::encoding, encoding_type> | |
154 >::type | |
155 encoding_modifier_type; | |
156 | |
157 explicit rule(std::string const& name = "unnamed-rule") | |
158 : base_type(terminal::make(reference_(*this))) | |
159 , name_(name) | |
160 { | |
161 } | |
162 | |
163 rule(rule const& rhs) | |
164 : base_type(terminal::make(reference_(*this))) | |
165 , name_(rhs.name_) | |
166 , f(rhs.f) | |
167 { | |
168 } | |
169 | |
170 template <typename Auto, typename Expr> | |
171 static void define(rule& /*lhs*/, Expr const& /*expr*/, mpl::false_) | |
172 { | |
173 // Report invalid expression error as early as possible. | |
174 // If you got an error_invalid_expression error message here, | |
175 // then the expression (expr) is not a valid spirit qi expression. | |
176 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr); | |
177 } | |
178 | |
179 template <typename Auto, typename Expr> | |
180 static void define(rule& lhs, Expr const& expr, mpl::true_) | |
181 { | |
182 lhs.f = detail::bind_parser<Auto>( | |
183 compile<qi::domain>(expr, encoding_modifier_type())); | |
184 } | |
185 | |
186 template <typename Expr> | |
187 rule(Expr const& expr, std::string const& name = "unnamed-rule") | |
188 : base_type(terminal::make(reference_(*this))) | |
189 , name_(name) | |
190 { | |
191 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>()); | |
192 } | |
193 | |
194 rule& operator=(rule const& rhs) | |
195 { | |
196 // The following assertion fires when you try to initialize a rule | |
197 // from an uninitialized one. Did you mean to refer to the right | |
198 // hand side rule instead of assigning from it? In this case you | |
199 // should write lhs = rhs.alias(); | |
200 BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?"); | |
201 | |
202 f = rhs.f; | |
203 name_ = rhs.name_; | |
204 return *this; | |
205 } | |
206 | |
207 std::string const& name() const | |
208 { | |
209 return name_; | |
210 } | |
211 | |
212 void name(std::string const& str) | |
213 { | |
214 name_ = str; | |
215 } | |
216 | |
217 template <typename Expr> | |
218 rule& operator=(Expr const& expr) | |
219 { | |
220 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>()); | |
221 return *this; | |
222 } | |
223 | |
224 // VC7.1 has problems to resolve 'rule' without explicit template parameters | |
225 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400) | |
226 // g++ 3.3 barfs if this is a member function :( | |
227 template <typename Expr> | |
228 friend rule& operator%=(rule& r, Expr const& expr) | |
229 { | |
230 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); | |
231 return r; | |
232 } | |
233 | |
234 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
235 // non-const version needed to suppress proto's %= kicking in | |
236 template <typename Expr> | |
237 friend rule& operator%=(rule& r, Expr& expr) | |
238 { | |
239 return r %= static_cast<Expr const&>(expr); | |
240 } | |
241 #else | |
242 // for rvalue references | |
243 template <typename Expr> | |
244 friend rule& operator%=(rule& r, Expr&& expr) | |
245 { | |
246 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); | |
247 return r; | |
248 } | |
249 #endif | |
250 | |
251 #else | |
252 // both friend functions have to be defined out of class as VC7.1 | |
253 // will complain otherwise | |
254 template <typename OutputIterator_, typename T1_, typename T2_ | |
255 , typename T3_, typename T4_, typename Expr> | |
256 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( | |
257 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr); | |
258 | |
259 // non-const version needed to suppress proto's %= kicking in | |
260 template <typename OutputIterator_, typename T1_, typename T2_ | |
261 , typename T3_, typename T4_, typename Expr> | |
262 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( | |
263 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr); | |
264 #endif | |
265 | |
266 template <typename Context, typename Iterator_> | |
267 struct attribute | |
268 { | |
269 typedef attr_type type; | |
270 }; | |
271 | |
272 template <typename Context, typename Skipper, typename Attribute> | |
273 bool parse(Iterator& first, Iterator const& last | |
274 , Context& /*context*/, Skipper const& skipper | |
275 , Attribute& attr_param) const | |
276 { | |
277 if (f) | |
278 { | |
279 // do a preskip if this is an implied lexeme | |
280 if (is_same<skipper_type, unused_type>::value) | |
281 qi::skip_over(first, last, skipper); | |
282 | |
283 typedef traits::make_attribute<attr_type, Attribute> make_attribute; | |
284 | |
285 // do down-stream transformation, provides attribute for | |
286 // rhs parser | |
287 typedef traits::transform_attribute< | |
288 typename make_attribute::type, attr_type, domain> | |
289 transform; | |
290 | |
291 typename make_attribute::type made_attr = make_attribute::call(attr_param); | |
292 typename transform::type attr_ = transform::pre(made_attr); | |
293 | |
294 // If you are seeing a compilation error here, you are probably | |
295 // trying to use a rule or a grammar which has inherited | |
296 // attributes, without passing values for them. | |
297 context_type context(attr_); | |
298 | |
299 // If you are seeing a compilation error here stating that the | |
300 // fourth parameter can't be converted to a required target type | |
301 // then you are probably trying to use a rule or a grammar with | |
302 // an incompatible skipper type. | |
303 if (f(first, last, context, skipper)) | |
304 { | |
305 // do up-stream transformation, this integrates the results | |
306 // back into the original attribute value, if appropriate | |
307 traits::post_transform(attr_param, attr_); | |
308 return true; | |
309 } | |
310 | |
311 // inform attribute transformation of failed rhs | |
312 traits::fail_transform(attr_param, attr_); | |
313 } | |
314 return false; | |
315 } | |
316 | |
317 template <typename Context, typename Skipper | |
318 , typename Attribute, typename Params> | |
319 bool parse(Iterator& first, Iterator const& last | |
320 , Context& caller_context, Skipper const& skipper | |
321 , Attribute& attr_param, Params const& params) const | |
322 { | |
323 if (f) | |
324 { | |
325 // do a preskip if this is an implied lexeme | |
326 if (is_same<skipper_type, unused_type>::value) | |
327 qi::skip_over(first, last, skipper); | |
328 | |
329 typedef traits::make_attribute<attr_type, Attribute> make_attribute; | |
330 | |
331 // do down-stream transformation, provides attribute for | |
332 // rhs parser | |
333 typedef traits::transform_attribute< | |
334 typename make_attribute::type, attr_type, domain> | |
335 transform; | |
336 | |
337 typename make_attribute::type made_attr = make_attribute::call(attr_param); | |
338 typename transform::type attr_ = transform::pre(made_attr); | |
339 | |
340 // If you are seeing a compilation error here, you are probably | |
341 // trying to use a rule or a grammar which has inherited | |
342 // attributes, passing values of incompatible types for them. | |
343 context_type context(attr_, params, caller_context); | |
344 | |
345 // If you are seeing a compilation error here stating that the | |
346 // fourth parameter can't be converted to a required target type | |
347 // then you are probably trying to use a rule or a grammar with | |
348 // an incompatible skipper type. | |
349 if (f(first, last, context, skipper)) | |
350 { | |
351 // do up-stream transformation, this integrates the results | |
352 // back into the original attribute value, if appropriate | |
353 traits::post_transform(attr_param, attr_); | |
354 return true; | |
355 } | |
356 | |
357 // inform attribute transformation of failed rhs | |
358 traits::fail_transform(attr_param, attr_); | |
359 } | |
360 return false; | |
361 } | |
362 | |
363 template <typename Context> | |
364 info what(Context& /*context*/) const | |
365 { | |
366 return info(name_); | |
367 } | |
368 | |
369 reference_ alias() const | |
370 { | |
371 return reference_(*this); | |
372 } | |
373 | |
374 typename proto::terminal<this_type>::type copy() const | |
375 { | |
376 typename proto::terminal<this_type>::type result = {*this}; | |
377 return result; | |
378 } | |
379 | |
380 // bring in the operator() overloads | |
381 rule const& get_parameterized_subject() const { return *this; } | |
382 typedef rule parameterized_subject_type; | |
383 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp> | |
384 | |
385 std::string name_; | |
386 function_type f; | |
387 }; | |
388 | |
389 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) | |
390 template <typename OutputIterator_, typename T1_, typename T2_ | |
391 , typename T3_, typename T4_, typename Expr> | |
392 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( | |
393 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr) | |
394 { | |
395 // Report invalid expression error as early as possible. | |
396 // If you got an error_invalid_expression error message here, | |
397 // then the expression (expr) is not a valid spirit qi expression. | |
398 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr); | |
399 | |
400 typedef typename | |
401 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type | |
402 encoding_modifier_type; | |
403 | |
404 r.f = detail::bind_parser<mpl::true_>( | |
405 compile<qi::domain>(expr, encoding_modifier_type())); | |
406 return r; | |
407 } | |
408 | |
409 template <typename Iterator_, typename T1_, typename T2_ | |
410 , typename T3_, typename T4_, typename Expr> | |
411 rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=( | |
412 rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr) | |
413 { | |
414 return r %= static_cast<Expr const&>(expr); | |
415 } | |
416 #endif | |
417 }}} | |
418 | |
419 namespace boost { namespace spirit { namespace traits | |
420 { | |
421 /////////////////////////////////////////////////////////////////////////// | |
422 template < | |
423 typename IteratorA, typename IteratorB, typename Attribute | |
424 , typename Context, typename T1, typename T2, typename T3, typename T4> | |
425 struct handles_container< | |
426 qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB> | |
427 : traits::is_container< | |
428 typename attribute_of< | |
429 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB | |
430 >::type | |
431 > | |
432 {}; | |
433 }}} | |
434 | |
435 #if defined(BOOST_MSVC) | |
436 # pragma warning(pop) | |
437 #endif | |
438 | |
439 #endif |