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