Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / spirit / home / x3 / core / action.hpp
1 /*=============================================================================
2     Copyright (arg) 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(SPIRIT_ACTION_JANUARY_07_2007_1128AM)
8 #define SPIRIT_ACTION_JANUARY_07_2007_1128AM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13
14 #include <boost/spirit/home/x3/support/context.hpp>
15 #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
16 #include <boost/spirit/home/x3/support/traits/make_attribute.hpp>
17 #include <boost/spirit/home/x3/core/call.hpp>
18 #include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
19 #include <boost/range/iterator_range.hpp>
20
21 namespace boost { namespace spirit { namespace x3
22 {
23     struct raw_attribute_type;
24     struct parse_pass_context_tag;
25
26     template <typename Context>
27     inline bool& _pass(Context const& context)
28     {
29         return x3::get<parse_pass_context_tag>(context);
30     }
31
32     template <typename Subject, typename Action>
33     struct action : unary_parser<Subject, action<Subject, Action>>
34     {
35         typedef unary_parser<Subject, action<Subject, Action>> base_type;
36         static bool const is_pass_through_unary = true;
37         static bool const has_action = true;
38
39         action(Subject const& subject, Action f)
40           : base_type(subject), f(f) {}
41
42         template <typename Iterator, typename Context, typename RuleContext, typename Attribute>
43         bool call_action(
44             Iterator& first, Iterator const& last
45           , Context const& context, RuleContext& rcontext, Attribute& attr) const
46         {
47             bool pass = true;
48             auto action_context = make_context<parse_pass_context_tag>(pass, context);
49             call(f, first, last, action_context, rcontext, attr);
50             return pass;
51         }
52
53         template <typename Iterator, typename Context
54           , typename RuleContext, typename Attribute>
55         bool parse_main(Iterator& first, Iterator const& last
56           , Context const& context, RuleContext& rcontext, Attribute& attr) const
57         {
58             Iterator save = first;
59             if (this->subject.parse(first, last, context, rcontext, attr))
60             {
61                 if (call_action(first, last, context, rcontext, attr))
62                     return true;
63
64                 // reset iterators if semantic action failed the match
65                 // retrospectively
66                 first = save;
67             }
68             return false;
69         }
70         
71         // attr==raw_attribute_type, action wants iterator_range (see raw.hpp)
72         template <typename Iterator, typename Context, typename RuleContext>
73         bool parse_main(Iterator& first, Iterator const& last
74           , Context const& context, RuleContext& rcontext, raw_attribute_type&) const
75         {
76             boost::iterator_range<Iterator> rng;
77             // synthesize the attribute since one is not supplied
78             return parse_main(first, last, context, rcontext, rng);
79         }
80
81         // attr==unused, action wants attribute
82         template <typename Iterator, typename Context, typename RuleContext>
83         bool parse(Iterator& first, Iterator const& last
84           , Context const& context, RuleContext& rcontext, unused_type) const
85         {
86             typedef typename
87                 traits::attribute_of<action<Subject, Action>, Context>::type
88             attribute_type;
89             typedef traits::make_attribute<attribute_type, unused_type> make_attribute;
90             typedef traits::transform_attribute<
91                 typename make_attribute::type, attribute_type, parser_id>
92             transform;
93
94             // synthesize the attribute since one is not supplied
95             typename make_attribute::type made_attr = make_attribute::call(unused_type());
96             typename transform::type attr = transform::pre(made_attr);
97             return parse_main(first, last, context, rcontext, attr);
98         }
99         
100         // main parse function
101         template <typename Iterator, typename Context
102             , typename RuleContext, typename Attribute>
103         bool parse(Iterator& first, Iterator const& last
104           , Context const& context, RuleContext& rcontext, Attribute& attr) const
105         {
106             return parse_main(first, last, context, rcontext, attr);
107         }
108
109         Action f;
110     };
111
112     template <typename P, typename Action>
113     inline action<typename extension::as_parser<P>::value_type, Action>
114     operator/(P const& p, Action f)
115     {
116         return {as_parser(p), f};
117     }
118 }}}
119
120 #endif