]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/x3/nonterminal/rule.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / nonterminal / rule.hpp
CommitLineData
7c673cae
FG
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_RULE_JAN_08_2012_0326PM)
8#define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM
9
10#include <boost/spirit/home/x3/nonterminal/detail/rule.hpp>
11#include <boost/type_traits/is_same.hpp>
12#include <boost/spirit/home/x3/support/context.hpp>
13#include <boost/preprocessor/variadic/to_seq.hpp>
14#include <boost/preprocessor/variadic/elem.hpp>
15#include <boost/preprocessor/seq/for_each.hpp>
92f5a8d4 16#include <type_traits>
7c673cae
FG
17
18#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
19#include <typeinfo>
20#endif
21
22namespace boost { namespace spirit { namespace x3
23{
7c673cae 24 // default parse_rule implementation
1e59de90 25 template <typename ID, typename Iterator
7c673cae
FG
26 , typename Context, typename ActualAttribute>
27 inline detail::default_parse_rule_result
28 parse_rule(
1e59de90 29 detail::rule_id<ID>
7c673cae
FG
30 , Iterator& first, Iterator const& last
31 , Context const& context, ActualAttribute& attr)
32 {
1e59de90 33 static_assert(!is_same<decltype(x3::get<ID>(context)), unused_type>::value,
7c673cae 34 "BOOST_SPIRIT_DEFINE undefined for this rule.");
1e59de90 35 return x3::get<ID>(context).parse(first, last, context, unused, attr);
7c673cae
FG
36 }
37
1e59de90 38 template <typename ID, typename RHS, typename Attribute, bool force_attribute_, bool skip_definition_injection = false>
7c673cae
FG
39 struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_>>
40 {
1e59de90 41 typedef rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection> this_type;
7c673cae
FG
42 typedef ID id;
43 typedef RHS rhs_type;
1e59de90 44 typedef rule<ID, Attribute, force_attribute_> lhs_type;
7c673cae
FG
45 typedef Attribute attribute_type;
46
47 static bool const has_attribute =
48 !is_same<Attribute, unused_type>::value;
49 static bool const handles_container =
50 traits::is_container<Attribute>::value;
51 static bool const force_attribute =
52 force_attribute_;
53
f67539c2 54 constexpr rule_definition(RHS const& rhs, char const* name)
7c673cae
FG
55 : rhs(rhs), name(name) {}
56
57 template <typename Iterator, typename Context, typename Attribute_>
58 bool parse(Iterator& first, Iterator const& last
59 , Context const& context, unused_type, Attribute_& attr) const
60 {
1e59de90 61 return detail::rule_parser<attribute_type, ID, skip_definition_injection>
7c673cae
FG
62 ::call_rule_definition(
63 rhs, name, first, last
64 , context
65 , attr
66 , mpl::bool_<force_attribute>());
67 }
68
69 RHS rhs;
70 char const* name;
71 };
72
73 template <typename ID, typename Attribute, bool force_attribute_>
1e59de90 74 struct rule : parser<rule<ID, Attribute, force_attribute_>>
7c673cae 75 {
f67539c2
TL
76 static_assert(!std::is_reference<Attribute>::value,
77 "Reference qualifier on rule attribute type is meaningless");
78
7c673cae
FG
79 typedef ID id;
80 typedef Attribute attribute_type;
81 static bool const has_attribute =
92f5a8d4 82 !std::is_same<std::remove_const_t<Attribute>, unused_type>::value;
7c673cae
FG
83 static bool const handles_container =
84 traits::is_container<Attribute>::value;
85 static bool const force_attribute = force_attribute_;
86
87#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
88 rule() : name(typeid(rule).name()) {}
89#else
f67539c2 90 constexpr rule() : name("unnamed") {}
7c673cae
FG
91#endif
92
f67539c2 93 constexpr rule(char const* name)
7c673cae
FG
94 : name(name) {}
95
f67539c2
TL
96 constexpr rule(rule const& r)
97 : name(r.name)
98 {
99 // Assert that we are not copying an unitialized static rule. If
100 // the static is in another TU, it may be initialized after we copy
101 // it. If so, its name member will be nullptr.
102 BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
103 }
104
7c673cae 105 template <typename RHS>
f67539c2 106 constexpr rule_definition<
7c673cae 107 ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
1e59de90 108 operator=(RHS const& rhs) const&
7c673cae
FG
109 {
110 return { as_parser(rhs), name };
111 }
112
113 template <typename RHS>
f67539c2 114 constexpr rule_definition<
7c673cae 115 ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
1e59de90
TL
116 operator%=(RHS const& rhs) const&
117 {
118 return { as_parser(rhs), name };
119 }
120
121 // When a rule placeholder constructed and immediately consumed it cannot be used recursively,
122 // that's why the rule definition injection into a parser context can be skipped.
123 // This optimization has a huge impact on compile times because immediate rules are commonly
124 // used to cast an attribute like `as`/`attr_cast` does in Qi.
125 template <typename RHS>
126 constexpr rule_definition<
127 ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_, true>
128 operator=(RHS const& rhs) const&&
129 {
130 return { as_parser(rhs), name };
131 }
132
133 template <typename RHS>
134 constexpr rule_definition<
135 ID, typename extension::as_parser<RHS>::value_type, Attribute, true, true>
136 operator%=(RHS const& rhs) const&&
7c673cae
FG
137 {
138 return { as_parser(rhs), name };
139 }
140
141
142 template <typename Iterator, typename Context, typename Attribute_>
143 bool parse(Iterator& first, Iterator const& last
144 , Context const& context, unused_type, Attribute_& attr) const
145 {
92f5a8d4
TL
146 static_assert(has_attribute,
147 "The rule does not have an attribute. Check your parser.");
148
149 using transform = traits::transform_attribute<
150 Attribute_, attribute_type, parser_id>;
151
152 using transform_attr = typename transform::type;
153 transform_attr attr_ = transform::pre(attr);
154
1e59de90 155 if (parse_rule(detail::rule_id<ID>{}, first, last, context, attr_)) {
92f5a8d4
TL
156 transform::post(attr, std::forward<transform_attr>(attr_));
157 return true;
158 }
159 return false;
160 }
161
162 template <typename Iterator, typename Context>
163 bool parse(Iterator& first, Iterator const& last
164 , Context const& context, unused_type, unused_type) const
165 {
166 // make sure we pass exactly the rule attribute type
f67539c2 167 attribute_type no_attr{};
1e59de90 168 return parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr);
7c673cae
FG
169 }
170
171 char const* name;
172 };
173
174 namespace traits
175 {
176 template <typename T, typename Enable = void>
177 struct is_rule : mpl::false_ {};
178
1e59de90
TL
179 template <typename ID, typename Attribute, bool force_attribute>
180 struct is_rule<rule<ID, Attribute, force_attribute>> : mpl::true_ {};
7c673cae 181
1e59de90
TL
182 template <typename ID, typename Attribute, typename RHS, bool force_attribute, bool skip_definition_injection>
183 struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute, skip_definition_injection>> : mpl::true_ {};
7c673cae
FG
184 }
185
186 template <typename T>
187 struct get_info<T, typename enable_if<traits::is_rule<T>>::type>
188 {
189 typedef std::string result_type;
190 std::string operator()(T const& r) const
191 {
b32b8144
FG
192 BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
193 return r.name? r.name : "uninitialized";
7c673cae
FG
194 }
195 };
196
197#define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \
92f5a8d4 198 template <typename Iterator, typename Context> \
7c673cae 199 bool parse_rule( \
1e59de90 200 ::boost::spirit::x3::detail::rule_id<rule_type::id> \
7c673cae 201 , Iterator& first, Iterator const& last \
92f5a8d4 202 , Context const& context, rule_type::attribute_type& attr); \
7c673cae
FG
203 /***/
204
205#define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \
206 BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
207 /***/
208
11fdf7f2
TL
209#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
210#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
211 using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name); \
92f5a8d4 212 template <typename Iterator, typename Context> \
11fdf7f2 213 inline bool parse_rule( \
1e59de90 214 ::boost::spirit::x3::detail::rule_id<BOOST_PP_CAT(rule_name, _synonym)::id> \
11fdf7f2 215 , Iterator& first, Iterator const& last \
92f5a8d4 216 , Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
11fdf7f2 217 { \
1e59de90
TL
218 using rule_t = BOOST_JOIN(rule_name, _synonym); \
219 return ::boost::spirit::x3::detail \
220 ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
221 ::call_rule_definition( \
222 BOOST_JOIN(rule_name, _def), rule_name.name \
223 , first, last, context, attr \
224 , ::boost::mpl::bool_<rule_t::force_attribute>()); \
11fdf7f2
TL
225 } \
226 /***/
227#else
7c673cae 228#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
92f5a8d4 229 template <typename Iterator, typename Context> \
7c673cae 230 inline bool parse_rule( \
1e59de90 231 ::boost::spirit::x3::detail::rule_id<decltype(rule_name)::id> \
7c673cae 232 , Iterator& first, Iterator const& last \
92f5a8d4 233 , Context const& context, decltype(rule_name)::attribute_type& attr) \
7c673cae 234 { \
1e59de90
TL
235 using rule_t = decltype(rule_name); \
236 return ::boost::spirit::x3::detail \
237 ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
238 ::call_rule_definition( \
239 BOOST_JOIN(rule_name, _def), rule_name.name \
240 , first, last, context, attr \
241 , ::boost::mpl::bool_<rule_t::force_attribute>()); \
7c673cae
FG
242 } \
243 /***/
11fdf7f2 244#endif
7c673cae
FG
245
246#define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \
247 BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
248 /***/
249
250#define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \
92f5a8d4 251 template bool parse_rule<Iterator, Context>( \
1e59de90 252 ::boost::spirit::x3::detail::rule_id<rule_type::id> \
7c673cae 253 , Iterator& first, Iterator const& last \
92f5a8d4 254 , Context const& context, rule_type::attribute_type&); \
7c673cae
FG
255 /***/
256
257
258}}}
259
260#endif