File indexing completed on 2025-01-19 09:47:45
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM)
0008 #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/static_assert.hpp>
0016 #include <boost/config.hpp>
0017 #include <boost/function.hpp>
0018 #include <boost/mpl/vector.hpp>
0019 #include <boost/type_traits/is_convertible.hpp>
0020 #include <boost/type_traits/is_same.hpp>
0021
0022 #include <boost/fusion/include/vector.hpp>
0023 #include <boost/fusion/include/size.hpp>
0024 #include <boost/fusion/include/make_vector.hpp>
0025 #include <boost/fusion/include/cons.hpp>
0026 #include <boost/fusion/include/as_list.hpp>
0027 #include <boost/fusion/include/as_vector.hpp>
0028
0029 #include <boost/spirit/home/support/unused.hpp>
0030 #include <boost/spirit/home/support/argument.hpp>
0031 #include <boost/spirit/home/support/context.hpp>
0032 #include <boost/spirit/home/support/info.hpp>
0033 #include <boost/spirit/home/qi/detail/attributes.hpp>
0034 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
0035 #include <boost/spirit/home/support/nonterminal/locals.hpp>
0036 #include <boost/spirit/home/qi/reference.hpp>
0037 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
0038 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
0039 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
0040 #include <boost/spirit/home/qi/skip_over.hpp>
0041
0042 #include <boost/proto/extends.hpp>
0043 #include <boost/proto/traits.hpp>
0044 #include <boost/type_traits/is_reference.hpp>
0045
0046 #if defined(BOOST_MSVC)
0047 # pragma warning(push)
0048 # pragma warning(disable: 4355)
0049 # pragma warning(disable: 4127)
0050 #endif
0051
0052 namespace boost { namespace spirit { namespace qi
0053 {
0054 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
0055
0056 using spirit::_pass_type;
0057 using spirit::_val_type;
0058 using spirit::_a_type;
0059 using spirit::_b_type;
0060 using spirit::_c_type;
0061 using spirit::_d_type;
0062 using spirit::_e_type;
0063 using spirit::_f_type;
0064 using spirit::_g_type;
0065 using spirit::_h_type;
0066 using spirit::_i_type;
0067 using spirit::_j_type;
0068
0069 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0070
0071 using spirit::_pass;
0072 using spirit::_val;
0073 using spirit::_a;
0074 using spirit::_b;
0075 using spirit::_c;
0076 using spirit::_d;
0077 using spirit::_e;
0078 using spirit::_f;
0079 using spirit::_g;
0080 using spirit::_h;
0081 using spirit::_i;
0082 using spirit::_j;
0083
0084 #endif
0085
0086 using spirit::info;
0087 using spirit::locals;
0088
0089 template <
0090 typename Iterator, typename T1, typename T2, typename T3
0091 , typename T4>
0092 struct rule
0093 : proto::extends<
0094 typename proto::terminal<
0095 reference<rule<Iterator, T1, T2, T3, T4> const>
0096 >::type
0097 , rule<Iterator, T1, T2, T3, T4>
0098 >
0099 , parser<rule<Iterator, T1, T2, T3, T4> >
0100 {
0101 typedef Iterator iterator_type;
0102 typedef rule<Iterator, T1, T2, T3, T4> this_type;
0103 typedef reference<this_type const> reference_;
0104 typedef typename proto::terminal<reference_>::type terminal;
0105 typedef proto::extends<terminal, this_type> base_type;
0106 typedef mpl::vector<T1, T2, T3, T4> template_params;
0107
0108
0109 typedef typename
0110 spirit::detail::extract_locals<template_params>::type
0111 locals_type;
0112
0113
0114 typedef typename
0115 spirit::detail::extract_component<
0116 qi::domain, template_params>::type
0117 skipper_type;
0118
0119
0120 typedef typename
0121 spirit::detail::extract_encoding<template_params>::type
0122 encoding_type;
0123
0124
0125 typedef typename
0126 spirit::detail::extract_sig<template_params, encoding_type, qi::domain>::type
0127 sig_type;
0128
0129
0130 typedef typename
0131 spirit::detail::attr_from_sig<sig_type>::type
0132 attr_type;
0133 BOOST_STATIC_ASSERT_MSG(
0134 !is_reference<attr_type>::value,
0135 "Reference qualifier on Qi rule attribute is meaningless");
0136 typedef attr_type& attr_reference_type;
0137
0138
0139 typedef typename
0140 spirit::detail::params_from_sig<sig_type>::type
0141 parameter_types;
0142
0143 static size_t const params_size =
0144 fusion::result_of::size<parameter_types>::type::value;
0145
0146 typedef context<
0147 fusion::cons<attr_reference_type, parameter_types>
0148 , locals_type>
0149 context_type;
0150
0151 typedef function<
0152 bool(Iterator& first, Iterator const& last
0153 , context_type& context
0154 , skipper_type const& skipper
0155 )>
0156 function_type;
0157
0158 typedef typename
0159 mpl::if_<
0160 is_same<encoding_type, unused_type>
0161 , unused_type
0162 , tag::char_code<tag::encoding, encoding_type>
0163 >::type
0164 encoding_modifier_type;
0165
0166 explicit rule(std::string const& name = "unnamed-rule")
0167 : base_type(terminal::make(reference_(*this)))
0168 , name_(name)
0169 {
0170 }
0171
0172 rule(rule const& rhs)
0173 : base_type(terminal::make(reference_(*this)))
0174 , name_(rhs.name_)
0175 , f(rhs.f)
0176 {
0177 }
0178
0179 template <typename Auto, typename Expr>
0180 static void define(rule& , Expr const& , mpl::false_)
0181 {
0182
0183
0184
0185 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
0186 }
0187
0188 template <typename Auto, typename Expr>
0189 static void define(rule& lhs, Expr const& expr, mpl::true_)
0190 {
0191 lhs.f = detail::bind_parser<Auto>(
0192 compile<qi::domain>(expr, encoding_modifier_type()));
0193 }
0194
0195 template <typename Expr>
0196 rule(Expr const& expr, std::string const& name = "unnamed-rule")
0197 : base_type(terminal::make(reference_(*this)))
0198 , name_(name)
0199 {
0200 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
0201 }
0202
0203 rule& operator=(rule const& rhs)
0204 {
0205
0206
0207
0208
0209 BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
0210
0211 f = rhs.f;
0212 name_ = rhs.name_;
0213 return *this;
0214 }
0215
0216 std::string const& name() const
0217 {
0218 return name_;
0219 }
0220
0221 void name(std::string const& str)
0222 {
0223 name_ = str;
0224 }
0225
0226 template <typename Expr>
0227 rule& operator=(Expr const& expr)
0228 {
0229 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
0230 return *this;
0231 }
0232
0233
0234 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0235
0236 template <typename Expr>
0237 friend rule& operator%=(rule& r, Expr const& expr)
0238 {
0239 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
0240 return r;
0241 }
0242
0243 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0244
0245 template <typename Expr>
0246 friend rule& operator%=(rule& r, Expr& expr)
0247 {
0248 return r %= static_cast<Expr const&>(expr);
0249 }
0250 #else
0251
0252 template <typename Expr>
0253 friend rule& operator%=(rule& r, Expr&& expr)
0254 {
0255 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
0256 return r;
0257 }
0258 #endif
0259
0260 #else
0261
0262
0263 template <typename OutputIterator_, typename T1_, typename T2_
0264 , typename T3_, typename T4_, typename Expr>
0265 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0266 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr);
0267
0268
0269 template <typename OutputIterator_, typename T1_, typename T2_
0270 , typename T3_, typename T4_, typename Expr>
0271 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0272 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr);
0273 #endif
0274
0275 template <typename Context, typename Iterator_>
0276 struct attribute
0277 {
0278 typedef attr_type type;
0279 };
0280
0281 template <typename Context, typename Skipper, typename Attribute>
0282 bool parse(Iterator& first, Iterator const& last
0283 , Context& , Skipper const& skipper
0284 , Attribute& attr_param) const
0285 {
0286 BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
0287 !is_same<Skipper, unused_type>::value),
0288 "The rule was instantiated with a skipper type but you have not pass any. "
0289 "Did you use `parse` instead of `phrase_parse`?");
0290 BOOST_STATIC_ASSERT_MSG(
0291 (is_convertible<Skipper const&, skipper_type>::value),
0292 "The passed skipper is not compatible/convertible to one "
0293 "that the rule was instantiated with");
0294 if (f)
0295 {
0296
0297 if (is_same<skipper_type, unused_type>::value)
0298 qi::skip_over(first, last, skipper);
0299
0300
0301
0302 typedef traits::transform_attribute<
0303 Attribute, attr_type, domain>
0304 transform;
0305
0306 typename transform::type attr_ = transform::pre(attr_param);
0307
0308
0309
0310
0311 context_type context(attr_);
0312
0313
0314
0315
0316
0317 if (f(first, last, context, skipper))
0318 {
0319
0320
0321 transform::post(attr_param, attr_);
0322 return true;
0323 }
0324
0325
0326 transform::fail(attr_param);
0327 }
0328 return false;
0329 }
0330
0331 template <typename Context, typename Skipper
0332 , typename Attribute, typename Params>
0333 bool parse(Iterator& first, Iterator const& last
0334 , Context& caller_context, Skipper const& skipper
0335 , Attribute& attr_param, Params const& params) const
0336 {
0337 BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
0338 !is_same<Skipper, unused_type>::value),
0339 "The rule was instantiated with a skipper type but you have not pass any. "
0340 "Did you use `parse` instead of `phrase_parse`?");
0341 BOOST_STATIC_ASSERT_MSG(
0342 (is_convertible<Skipper const&, skipper_type>::value),
0343 "The passed skipper is not compatible/convertible to one "
0344 "that the rule was instantiated with");
0345 if (f)
0346 {
0347
0348 if (is_same<skipper_type, unused_type>::value)
0349 qi::skip_over(first, last, skipper);
0350
0351
0352
0353 typedef traits::transform_attribute<
0354 Attribute, attr_type, domain>
0355 transform;
0356
0357 typename transform::type attr_ = transform::pre(attr_param);
0358
0359
0360
0361
0362 context_type context(attr_, params, caller_context);
0363
0364
0365
0366
0367
0368 if (f(first, last, context, skipper))
0369 {
0370
0371
0372 transform::post(attr_param, attr_);
0373 return true;
0374 }
0375
0376
0377 transform::fail(attr_param);
0378 }
0379 return false;
0380 }
0381
0382 template <typename Context>
0383 info what(Context& ) const
0384 {
0385 return info(name_);
0386 }
0387
0388 reference_ alias() const
0389 {
0390 return reference_(*this);
0391 }
0392
0393 typename proto::terminal<this_type>::type copy() const
0394 {
0395 typename proto::terminal<this_type>::type result = {*this};
0396 return result;
0397 }
0398
0399
0400 rule const& get_parameterized_subject() const { return *this; }
0401 typedef rule parameterized_subject_type;
0402 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0403
0404 std::string name_;
0405 function_type f;
0406 };
0407
0408 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0409 template <typename OutputIterator_, typename T1_, typename T2_
0410 , typename T3_, typename T4_, typename Expr>
0411 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0412 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr)
0413 {
0414
0415
0416
0417 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
0418
0419 typedef typename
0420 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
0421 encoding_modifier_type;
0422
0423 r.f = detail::bind_parser<mpl::true_>(
0424 compile<qi::domain>(expr, encoding_modifier_type()));
0425 return r;
0426 }
0427
0428 template <typename Iterator_, typename T1_, typename T2_
0429 , typename T3_, typename T4_, typename Expr>
0430 rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=(
0431 rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
0432 {
0433 return r %= static_cast<Expr const&>(expr);
0434 }
0435 #endif
0436 }}}
0437
0438 namespace boost { namespace spirit { namespace traits
0439 {
0440
0441 template <
0442 typename IteratorA, typename IteratorB, typename Attribute
0443 , typename Context, typename T1, typename T2, typename T3, typename T4>
0444 struct handles_container<
0445 qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB>
0446 : traits::is_container<
0447 typename attribute_of<
0448 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0449 >::type
0450 >
0451 {};
0452 }}}
0453
0454 #if defined(BOOST_MSVC)
0455 # pragma warning(pop)
0456 #endif
0457
0458 #endif