File indexing completed on 2025-01-31 10:02:36
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM)
0008 #define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM
0009
0010 #include <boost/spirit/home/x3/nonterminal/detail/rule.hpp>
0011 #include <boost/type_traits/is_same.hpp>
0012 #include <boost/spirit/home/x3/support/context.hpp>
0013 #include <boost/preprocessor/variadic/to_seq.hpp>
0014 #include <boost/preprocessor/variadic/elem.hpp>
0015 #include <boost/preprocessor/seq/for_each.hpp>
0016 #include <type_traits>
0017
0018 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
0019 #include <typeinfo>
0020 #endif
0021
0022 namespace boost { namespace spirit { namespace x3
0023 {
0024
0025 template <typename ID, typename Iterator
0026 , typename Context, typename ActualAttribute>
0027 inline detail::default_parse_rule_result
0028 parse_rule(
0029 detail::rule_id<ID>
0030 , Iterator& first, Iterator const& last
0031 , Context const& context, ActualAttribute& attr)
0032 {
0033 static_assert(!is_same<decltype(x3::get<ID>(context)), unused_type>::value,
0034 "BOOST_SPIRIT_DEFINE undefined for this rule.");
0035 return x3::get<ID>(context).parse(first, last, context, unused, attr);
0036 }
0037
0038 template <typename ID, typename RHS, typename Attribute, bool force_attribute_, bool skip_definition_injection = false>
0039 struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection>>
0040 {
0041 typedef rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection> this_type;
0042 typedef ID id;
0043 typedef RHS rhs_type;
0044 typedef rule<ID, Attribute, force_attribute_> lhs_type;
0045 typedef Attribute attribute_type;
0046
0047 static bool const has_attribute =
0048 !is_same<Attribute, unused_type>::value;
0049 static bool const handles_container =
0050 traits::is_container<Attribute>::value;
0051 static bool const force_attribute =
0052 force_attribute_;
0053
0054 constexpr rule_definition(RHS const& rhs, char const* name)
0055 : rhs(rhs), name(name) {}
0056
0057 template <typename Iterator, typename Context, typename Attribute_>
0058 bool parse(Iterator& first, Iterator const& last
0059 , Context const& context, unused_type, Attribute_& attr) const
0060 {
0061 return detail::rule_parser<attribute_type, ID, skip_definition_injection>
0062 ::call_rule_definition(
0063 rhs, name, first, last
0064 , context
0065 , attr
0066 , mpl::bool_<force_attribute>());
0067 }
0068
0069 RHS rhs;
0070 char const* name;
0071 };
0072
0073 template <typename ID, typename Attribute, bool force_attribute_>
0074 struct rule : parser<rule<ID, Attribute, force_attribute_>>
0075 {
0076 static_assert(!std::is_reference<Attribute>::value,
0077 "Reference qualifier on rule attribute type is meaningless");
0078
0079 typedef ID id;
0080 typedef Attribute attribute_type;
0081 static bool const has_attribute =
0082 !std::is_same<std::remove_const_t<Attribute>, unused_type>::value;
0083 static bool const handles_container =
0084 traits::is_container<Attribute>::value;
0085 static bool const force_attribute = force_attribute_;
0086
0087 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
0088 rule() : name(typeid(rule).name()) {}
0089 #else
0090 constexpr rule() : name("unnamed") {}
0091 #endif
0092
0093 constexpr rule(char const* name)
0094 : name(name) {}
0095
0096 constexpr rule(rule const& r)
0097 : name(r.name)
0098 {
0099
0100
0101
0102 BOOST_ASSERT_MSG(r.name, "uninitialized rule");
0103 }
0104
0105 template <typename RHS>
0106 constexpr rule_definition<
0107 ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
0108 operator=(RHS const& rhs) const&
0109 {
0110 return { as_parser(rhs), name };
0111 }
0112
0113 template <typename RHS>
0114 constexpr rule_definition<
0115 ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
0116 operator%=(RHS const& rhs) const&
0117 {
0118 return { as_parser(rhs), name };
0119 }
0120
0121
0122
0123
0124
0125 template <typename RHS>
0126 constexpr rule_definition<
0127 ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_, true>
0128 operator=(RHS const& rhs) const&&
0129 {
0130 return { as_parser(rhs), name };
0131 }
0132
0133 template <typename RHS>
0134 constexpr rule_definition<
0135 ID, typename extension::as_parser<RHS>::value_type, Attribute, true, true>
0136 operator%=(RHS const& rhs) const&&
0137 {
0138 return { as_parser(rhs), name };
0139 }
0140
0141
0142 template <typename Iterator, typename Context, typename Attribute_>
0143 bool parse(Iterator& first, Iterator const& last
0144 , Context const& context, unused_type, Attribute_& attr) const
0145 {
0146 static_assert(has_attribute,
0147 "The rule does not have an attribute. Check your parser.");
0148
0149 using transform = traits::transform_attribute<
0150 Attribute_, attribute_type, parser_id>;
0151
0152 using transform_attr = typename transform::type;
0153 transform_attr attr_ = transform::pre(attr);
0154
0155 if (parse_rule(detail::rule_id<ID>{}, first, last, context, attr_)) {
0156 transform::post(attr, std::forward<transform_attr>(attr_));
0157 return true;
0158 }
0159 return false;
0160 }
0161
0162 template <typename Iterator, typename Context>
0163 bool parse(Iterator& first, Iterator const& last
0164 , Context const& context, unused_type, unused_type) const
0165 {
0166
0167 attribute_type no_attr{};
0168 return parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr);
0169 }
0170
0171 char const* name;
0172 };
0173
0174 namespace traits
0175 {
0176 template <typename T, typename Enable = void>
0177 struct is_rule : mpl::false_ {};
0178
0179 template <typename ID, typename Attribute, bool force_attribute>
0180 struct is_rule<rule<ID, Attribute, force_attribute>> : mpl::true_ {};
0181
0182 template <typename ID, typename Attribute, typename RHS, bool force_attribute, bool skip_definition_injection>
0183 struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute, skip_definition_injection>> : mpl::true_ {};
0184 }
0185
0186 template <typename T>
0187 struct get_info<T, typename enable_if<traits::is_rule<T>>::type>
0188 {
0189 typedef std::string result_type;
0190 std::string operator()(T const& r) const
0191 {
0192 BOOST_ASSERT_MSG(r.name, "uninitialized rule");
0193 return r.name? r.name : "uninitialized";
0194 }
0195 };
0196
0197 #define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \
0198 template <typename Iterator, typename Context> \
0199 bool parse_rule( \
0200 ::boost::spirit::x3::detail::rule_id<rule_type::id> \
0201 , Iterator& first, Iterator const& last \
0202 , Context const& context, rule_type::attribute_type& attr); \
0203
0204
0205 #define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \
0206 BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
0207
0208
0209 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0210 #define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
0211 using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name); \
0212 template <typename Iterator, typename Context> \
0213 inline bool parse_rule( \
0214 ::boost::spirit::x3::detail::rule_id<BOOST_PP_CAT(rule_name, _synonym)::id> \
0215 , Iterator& first, Iterator const& last \
0216 , Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
0217 { \
0218 using rule_t = BOOST_JOIN(rule_name, _synonym); \
0219 return ::boost::spirit::x3::detail \
0220 ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
0221 ::call_rule_definition( \
0222 BOOST_JOIN(rule_name, _def), rule_name.name \
0223 , first, last, context, attr \
0224 , ::boost::mpl::bool_<rule_t::force_attribute>()); \
0225 } \
0226
0227 #else
0228 #define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
0229 template <typename Iterator, typename Context> \
0230 inline bool parse_rule( \
0231 ::boost::spirit::x3::detail::rule_id<decltype(rule_name)::id> \
0232 , Iterator& first, Iterator const& last \
0233 , Context const& context, decltype(rule_name)::attribute_type& attr) \
0234 { \
0235 using rule_t = decltype(rule_name); \
0236 return ::boost::spirit::x3::detail \
0237 ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
0238 ::call_rule_definition( \
0239 BOOST_JOIN(rule_name, _def), rule_name.name \
0240 , first, last, context, attr \
0241 , ::boost::mpl::bool_<rule_t::force_attribute>()); \
0242 } \
0243
0244 #endif
0245
0246 #define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \
0247 BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
0248
0249
0250 #define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \
0251 template bool parse_rule<Iterator, Context>( \
0252 ::boost::spirit::x3::detail::rule_id<rule_type::id> \
0253 , Iterator& first, Iterator const& last \
0254 , Context const& context, rule_type::attribute_type&); \
0255
0256
0257
0258 }}}
0259
0260 #endif