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