Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / spirit / home / x3 / nonterminal / detail / rule.hpp
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