Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/spirit/home/x3/nonterminal/detail/rule.hpp @ 102:f46d142149f5
Whoops, finish that update
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:13:41 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
101:c530137014c0 | 102:f46d142149f5 |
---|---|
1 /*============================================================================= | |
2 Copyright (c) 2001-2014 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_X3_DETAIL_RULE_JAN_08_2012_0326PM) | |
8 #define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM | |
9 | |
10 #if defined(_MSC_VER) | |
11 #pragma once | |
12 #endif | |
13 | |
14 #include <boost/spirit/home/x3/core/parser.hpp> | |
15 #include <boost/spirit/home/x3/support/traits/make_attribute.hpp> | |
16 #include <boost/spirit/home/x3/support/utility/sfinae.hpp> | |
17 #include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp> | |
18 #include <boost/utility/addressof.hpp> | |
19 | |
20 #if defined(BOOST_SPIRIT_X3_DEBUG) | |
21 #include <boost/spirit/home/x3/nonterminal/simple_trace.hpp> | |
22 #endif | |
23 | |
24 namespace boost { namespace spirit { namespace x3 | |
25 { | |
26 template <typename ID> | |
27 struct identity; | |
28 | |
29 template <typename ID, typename Attribute = unused_type> | |
30 struct rule; | |
31 | |
32 struct parse_pass_context_tag; | |
33 | |
34 namespace detail | |
35 { | |
36 // we use this so we can detect if the default parse_rule | |
37 // is the being called. | |
38 struct default_parse_rule_result | |
39 { | |
40 default_parse_rule_result(bool r) | |
41 : r(r) {} | |
42 operator bool() const { return r; } | |
43 bool r; | |
44 }; | |
45 } | |
46 | |
47 // default parse_rule implementation | |
48 template <typename ID, typename Attribute, typename Iterator | |
49 , typename Context, typename ActualAttribute> | |
50 inline detail::default_parse_rule_result | |
51 parse_rule( | |
52 rule<ID, Attribute> rule_ | |
53 , Iterator& first, Iterator const& last | |
54 , Context const& context, ActualAttribute& attr); | |
55 }}} | |
56 | |
57 namespace boost { namespace spirit { namespace x3 { namespace detail | |
58 { | |
59 #if defined(BOOST_SPIRIT_X3_DEBUG) | |
60 template <typename Iterator, typename Attribute> | |
61 struct context_debug | |
62 { | |
63 context_debug( | |
64 char const* rule_name | |
65 , Iterator const& first, Iterator const& last | |
66 , Attribute const& attr | |
67 , bool const& ok_parse //was parse successful? | |
68 ) | |
69 : ok_parse(ok_parse), rule_name(rule_name) | |
70 , first(first), last(last) | |
71 , attr(attr) | |
72 , f(detail::get_simple_trace()) | |
73 { | |
74 f(first, last, attr, pre_parse, rule_name); | |
75 } | |
76 | |
77 ~context_debug() | |
78 { | |
79 auto status = ok_parse ? successful_parse : failed_parse ; | |
80 f(first, last, attr, status, rule_name); | |
81 } | |
82 | |
83 bool const& ok_parse; | |
84 char const* rule_name; | |
85 Iterator const& first; | |
86 Iterator const& last; | |
87 Attribute const& attr; | |
88 detail::simple_trace_type& f; | |
89 }; | |
90 #endif | |
91 | |
92 template <typename ID, typename Iterator, typename Context, typename Enable = void> | |
93 struct has_on_error : mpl::false_ {}; | |
94 | |
95 template <typename ID, typename Iterator, typename Context> | |
96 struct has_on_error<ID, Iterator, Context, | |
97 typename disable_if_substitution_failure< | |
98 decltype( | |
99 std::declval<ID>().on_error( | |
100 std::declval<Iterator&>() | |
101 , std::declval<Iterator>() | |
102 , std::declval<expectation_failure<Iterator>>() | |
103 , std::declval<Context>() | |
104 ) | |
105 )>::type | |
106 > | |
107 : mpl::true_ | |
108 {}; | |
109 | |
110 template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void> | |
111 struct has_on_success : mpl::false_ {}; | |
112 | |
113 template <typename ID, typename Iterator, typename Attribute, typename Context> | |
114 struct has_on_success<ID, Iterator, Context, Attribute, | |
115 typename disable_if_substitution_failure< | |
116 decltype( | |
117 std::declval<ID>().on_success( | |
118 std::declval<Iterator&>() | |
119 , std::declval<Iterator>() | |
120 , std::declval<Attribute&>() | |
121 , std::declval<Context>() | |
122 ) | |
123 )>::type | |
124 > | |
125 : mpl::true_ | |
126 {}; | |
127 | |
128 template <typename ID> | |
129 struct make_id | |
130 { | |
131 typedef identity<ID> type; | |
132 }; | |
133 | |
134 template <typename ID> | |
135 struct make_id<identity<ID>> | |
136 { | |
137 typedef identity<ID> type; | |
138 }; | |
139 | |
140 template <typename ID, typename RHS, typename Context> | |
141 Context const& | |
142 make_rule_context(RHS const& rhs, Context const& context | |
143 , mpl::false_ /* is_default_parse_rule */) | |
144 { | |
145 return context; | |
146 } | |
147 | |
148 template <typename ID, typename RHS, typename Context> | |
149 auto make_rule_context(RHS const& rhs, Context const& context | |
150 , mpl::true_ /* is_default_parse_rule */ ) | |
151 { | |
152 return make_unique_context<ID>(rhs, context); | |
153 } | |
154 | |
155 template <typename Attribute, typename ID> | |
156 struct rule_parser | |
157 { | |
158 template <typename Iterator, typename Context, typename ActualAttribute> | |
159 static bool call_on_success( | |
160 Iterator& first, Iterator const& last | |
161 , Context const& context, ActualAttribute& attr | |
162 , mpl::false_ /* No on_success handler */ ) | |
163 { | |
164 return true; | |
165 } | |
166 | |
167 template <typename Iterator, typename Context, typename ActualAttribute> | |
168 static bool call_on_success( | |
169 Iterator& first, Iterator const& last | |
170 , Context const& context, ActualAttribute& attr | |
171 , mpl::true_ /* Has on_success handler */) | |
172 { | |
173 bool pass = true; | |
174 ID().on_success( | |
175 first | |
176 , last | |
177 , attr | |
178 , make_context<parse_pass_context_tag>(pass, context) | |
179 ); | |
180 return pass; | |
181 } | |
182 | |
183 template <typename RHS, typename Iterator, typename Context | |
184 , typename RContext, typename ActualAttribute> | |
185 static bool parse_rhs_main( | |
186 RHS const& rhs | |
187 , Iterator& first, Iterator const& last | |
188 , Context const& context, RContext& rcontext, ActualAttribute& attr | |
189 , mpl::false_) | |
190 { | |
191 // see if the user has a BOOST_SPIRIT_DEFINE for this rule | |
192 typedef | |
193 decltype(parse_rule( | |
194 rule<ID, Attribute>(), first, last | |
195 , make_unique_context<ID>(rhs, context), attr)) | |
196 parse_rule_result; | |
197 | |
198 // If there is no BOOST_SPIRIT_DEFINE for this rule, | |
199 // we'll make a context for this rule tagged by its ID | |
200 // so we can extract the rule later on in the default | |
201 // (generic) parse_rule function. | |
202 typedef | |
203 is_same<parse_rule_result, default_parse_rule_result> | |
204 is_default_parse_rule; | |
205 | |
206 Iterator i = first; | |
207 bool r = rhs.parse( | |
208 i | |
209 , last | |
210 , make_rule_context<ID>(rhs, context, is_default_parse_rule()) | |
211 , rcontext | |
212 , attr | |
213 ); | |
214 | |
215 if (r) | |
216 { | |
217 auto first_ = first; | |
218 x3::skip_over(first_, last, context); | |
219 r = call_on_success(first_, i, context, attr | |
220 , has_on_success<ID, Iterator, Context, ActualAttribute>()); | |
221 } | |
222 | |
223 if (r) | |
224 first = i; | |
225 return r; | |
226 } | |
227 | |
228 template <typename RHS, typename Iterator, typename Context | |
229 , typename RContext, typename ActualAttribute> | |
230 static bool parse_rhs_main( | |
231 RHS const& rhs | |
232 , Iterator& first, Iterator const& last | |
233 , Context const& context, RContext& rcontext, ActualAttribute& attr | |
234 , mpl::true_ /* on_error is found */) | |
235 { | |
236 for (;;) | |
237 { | |
238 try | |
239 { | |
240 return parse_rhs_main( | |
241 rhs, first, last, context, rcontext, attr, mpl::false_()); | |
242 } | |
243 catch (expectation_failure<Iterator> const& x) | |
244 { | |
245 switch (ID().on_error(first, last, x, context)) | |
246 { | |
247 case error_handler_result::fail: | |
248 return false; | |
249 case error_handler_result::retry: | |
250 continue; | |
251 case error_handler_result::accept: | |
252 return true; | |
253 case error_handler_result::rethrow: | |
254 throw; | |
255 } | |
256 } | |
257 } | |
258 } | |
259 | |
260 template <typename RHS, typename Iterator | |
261 , typename Context, typename RContext, typename ActualAttribute> | |
262 static bool parse_rhs_main( | |
263 RHS const& rhs | |
264 , Iterator& first, Iterator const& last | |
265 , Context const& context, RContext& rcontext, ActualAttribute& attr) | |
266 { | |
267 return parse_rhs_main( | |
268 rhs, first, last, context, rcontext, attr | |
269 , has_on_error<ID, Iterator, Context>() | |
270 ); | |
271 } | |
272 | |
273 template <typename RHS, typename Iterator | |
274 , typename Context, typename RContext, typename ActualAttribute> | |
275 static bool parse_rhs( | |
276 RHS const& rhs | |
277 , Iterator& first, Iterator const& last | |
278 , Context const& context, RContext& rcontext, ActualAttribute& attr | |
279 , mpl::false_) | |
280 { | |
281 return parse_rhs_main(rhs, first, last, context, rcontext, attr); | |
282 } | |
283 | |
284 template <typename RHS, typename Iterator | |
285 , typename Context, typename RContext, typename ActualAttribute> | |
286 static bool parse_rhs( | |
287 RHS const& rhs | |
288 , Iterator& first, Iterator const& last | |
289 , Context const& context, RContext& rcontext, ActualAttribute& attr | |
290 , mpl::true_) | |
291 { | |
292 return parse_rhs_main(rhs, first, last, context, rcontext, unused); | |
293 } | |
294 | |
295 template <typename RHS, typename Iterator, typename Context | |
296 , typename ActualAttribute, typename ExplicitAttrPropagation> | |
297 static bool call_rule_definition( | |
298 RHS const& rhs | |
299 , char const* rule_name | |
300 , Iterator& first, Iterator const& last | |
301 , Context const& context, ActualAttribute& attr | |
302 , ExplicitAttrPropagation) | |
303 { | |
304 typedef traits::make_attribute<Attribute, ActualAttribute> make_attribute; | |
305 | |
306 // do down-stream transformation, provides attribute for | |
307 // rhs parser | |
308 typedef traits::transform_attribute< | |
309 typename make_attribute::type, Attribute, parser_id> | |
310 transform; | |
311 | |
312 typedef typename make_attribute::value_type value_type; | |
313 typedef typename transform::type transform_attr; | |
314 value_type made_attr = make_attribute::call(attr); | |
315 transform_attr attr_ = transform::pre(made_attr); | |
316 | |
317 bool ok_parse | |
318 //Creates a place to hold the result of parse_rhs | |
319 //called inside the following scope. | |
320 ; | |
321 { | |
322 //Create a scope to cause the dbg variable below (within | |
323 //the #if...#endif) to call it's DTOR before any | |
324 //modifications are made to the attribute, attr_ passed | |
325 //to parse_rhs (such as might be done in | |
326 //traits::post_transform when, for example, | |
327 //ActualAttribute is a recursive variant). | |
328 #if defined(BOOST_SPIRIT_X3_DEBUG) | |
329 context_debug<Iterator, typename make_attribute::value_type> | |
330 dbg(rule_name, first, last, attr_, ok_parse); | |
331 #endif | |
332 ok_parse=parse_rhs(rhs, first, last, context, attr_, attr_ | |
333 , mpl::bool_ | |
334 < ( RHS::has_action | |
335 && !ExplicitAttrPropagation::value | |
336 ) | |
337 >() | |
338 ); | |
339 } | |
340 if(ok_parse) | |
341 { | |
342 // do up-stream transformation, this integrates the results | |
343 // back into the original attribute value, if appropriate | |
344 traits::post_transform(attr, attr_); | |
345 } | |
346 return ok_parse; | |
347 } | |
348 | |
349 // template <typename RuleDef, typename Iterator, typename Context | |
350 // , typename ActualAttribute, typename AttributeContext> | |
351 // static bool call_from_rule( | |
352 // RuleDef const& rule_def | |
353 // , char const* rule_name | |
354 // , Iterator& first, Iterator const& last | |
355 // , Context const& context, ActualAttribute& attr, AttributeContext& attr_ctx) | |
356 // { | |
357 // // This is called when a rule-body has already been established. | |
358 // // The rule body is already established by the rule_definition class, | |
359 // // we will not do it again. We'll simply call the RHS by calling | |
360 // // call_rule_definition. | |
361 // | |
362 // return call_rule_definition( | |
363 // rule_def.rhs, rule_name, first, last | |
364 // , context, attr, attr_ctx.attr_ptr | |
365 // , mpl::bool_<(RuleDef::explicit_attribute_propagation)>()); | |
366 // } | |
367 // | |
368 // template <typename RuleDef, typename Iterator, typename Context | |
369 // , typename ActualAttribute> | |
370 // static bool call_from_rule( | |
371 // RuleDef const& rule_def | |
372 // , char const* rule_name | |
373 // , Iterator& first, Iterator const& last | |
374 // , Context const& context, ActualAttribute& attr, unused_type) | |
375 // { | |
376 // // This is called when a rule-body has *not yet* been established. | |
377 // // The rule body is established by the rule_definition class, so | |
378 // // we call it to parse and establish the rule-body. | |
379 // | |
380 // return rule_def.parse(first, last, context, unused, attr); // $$$ fix unused param $$$ | |
381 // } | |
382 }; | |
383 }}}} | |
384 | |
385 #endif |