File indexing completed on 2025-01-18 09:52:30
0001
0002
0003
0004
0005
0006
0007
0008 #if !defined(BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM)
0009 #define BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM
0010
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014
0015 #include <boost/spirit/home/qi/domain.hpp>
0016 #include <boost/spirit/home/qi/meta_compiler.hpp>
0017 #include <boost/spirit/home/qi/parser.hpp>
0018 #include <boost/spirit/home/qi/reference.hpp>
0019 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
0020 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
0021 #include <boost/spirit/home/support/argument.hpp>
0022 #include <boost/spirit/home/support/assert_msg.hpp>
0023 #include <boost/spirit/home/qi/detail/attributes.hpp>
0024 #include <boost/spirit/home/support/info.hpp>
0025 #include <boost/spirit/home/support/unused.hpp>
0026 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
0027 #include <boost/spirit/home/support/nonterminal/locals.hpp>
0028 #include <boost/spirit/repository/home/support/subrule_context.hpp>
0029
0030 #include <boost/static_assert.hpp>
0031 #include <boost/fusion/include/as_map.hpp>
0032 #include <boost/fusion/include/at_key.hpp>
0033 #include <boost/fusion/include/cons.hpp>
0034 #include <boost/fusion/include/front.hpp>
0035 #include <boost/fusion/include/has_key.hpp>
0036 #include <boost/fusion/include/join.hpp>
0037 #include <boost/fusion/include/make_map.hpp>
0038 #include <boost/fusion/include/make_vector.hpp>
0039 #include <boost/fusion/include/size.hpp>
0040 #include <boost/fusion/include/vector.hpp>
0041 #include <boost/mpl/bool.hpp>
0042 #include <boost/mpl/identity.hpp>
0043 #include <boost/mpl/int.hpp>
0044 #include <boost/mpl/vector.hpp>
0045 #include <boost/proto/extends.hpp>
0046 #include <boost/proto/traits.hpp>
0047 #include <boost/type_traits/is_reference.hpp>
0048 #include <boost/type_traits/is_same.hpp>
0049 #include <boost/type_traits/remove_reference.hpp>
0050
0051 #if defined(BOOST_MSVC)
0052 # pragma warning(push)
0053 # pragma warning(disable: 4355)
0054 #endif
0055
0056
0057 namespace boost { namespace spirit { namespace repository { namespace qi
0058 {
0059
0060
0061
0062
0063
0064 template <typename Defs>
0065 struct subrule_group_parser
0066 : spirit::qi::parser<subrule_group_parser<Defs> >
0067 {
0068
0069
0070 typedef Defs defs_type;
0071
0072 typedef subrule_group_parser<Defs> this_type;
0073
0074 explicit subrule_group_parser(Defs const& defs)
0075 : defs(defs)
0076 {
0077 }
0078
0079
0080 template <int ID>
0081 struct def_type
0082 {
0083 typedef mpl::int_<ID> id_type;
0084
0085
0086
0087 BOOST_SPIRIT_ASSERT_MSG(
0088 (fusion::result_of::has_key<
0089 defs_type const, id_type>::type::value)
0090 , subrule_used_without_being_defined, (mpl::int_<ID>));
0091
0092 typedef typename
0093 fusion::result_of::at_key<defs_type const, id_type>::type
0094 type;
0095 };
0096
0097
0098 template <int ID>
0099 typename def_type<ID>::type def() const
0100 {
0101 return fusion::at_key<mpl::int_<ID> >(defs);
0102 }
0103
0104 template <typename Context, typename Iterator>
0105 struct attribute
0106
0107 : mpl::identity<
0108 typename remove_reference<
0109 typename fusion::result_of::front<Defs>::type
0110 >::type::second_type::attr_type> {};
0111
0112 template <typename Iterator, typename Context
0113 , typename Skipper, typename Attribute>
0114 bool parse(Iterator& first, Iterator const& last
0115 , Context& context, Skipper const& skipper
0116 , Attribute& attr) const
0117 {
0118
0119 return parse_subrule(fusion::front(defs).second
0120 , first, last, context, skipper, attr);
0121 }
0122
0123 template <typename Iterator, typename Context
0124 , typename Skipper, typename Attribute, typename Params>
0125 bool parse(Iterator& first, Iterator const& last
0126 , Context& context, Skipper const& skipper
0127 , Attribute& attr, Params const& params) const
0128 {
0129
0130 return parse_subrule(fusion::front(defs).second
0131 , first, last, context, skipper, attr, params);
0132 }
0133
0134 template <int ID, typename Iterator, typename Context
0135 , typename Skipper, typename Attribute>
0136 bool parse_subrule_id(Iterator& first, Iterator const& last
0137 , Context& context, Skipper const& skipper
0138 , Attribute& attr) const
0139 {
0140 return parse_subrule(def<ID>()
0141 , first, last, context, skipper, attr);
0142 }
0143
0144 template <int ID, typename Iterator, typename Context
0145 , typename Skipper, typename Attribute, typename Params>
0146 bool parse_subrule_id(Iterator& first, Iterator const& last
0147 , Context& context, Skipper const& skipper
0148 , Attribute& attr, Params const& params) const
0149 {
0150 return parse_subrule(def<ID>()
0151 , first, last, context, skipper, attr, params);
0152 }
0153
0154 template <typename Def
0155 , typename Iterator, typename Context
0156 , typename Skipper, typename Attribute>
0157 bool parse_subrule(Def const& def
0158 , Iterator& first, Iterator const& last
0159 , Context& , Skipper const& skipper
0160 , Attribute& attr) const
0161 {
0162
0163 typedef typename Def::locals_type subrule_locals_type;
0164 typedef typename Def::attr_type subrule_attr_type;
0165 typedef typename Def::attr_reference_type subrule_attr_reference_type;
0166 typedef typename Def::parameter_types subrule_parameter_types;
0167
0168 typedef
0169 subrule_context<
0170 this_type
0171 , fusion::cons<
0172 subrule_attr_reference_type, subrule_parameter_types>
0173 , subrule_locals_type
0174 >
0175 context_type;
0176
0177
0178
0179 typedef traits::transform_attribute<
0180 Attribute, subrule_attr_type, spirit::qi::domain>
0181 transform;
0182
0183 typename transform::type attr_ = transform::pre(attr);
0184
0185
0186
0187
0188 context_type context(*this, attr_);
0189
0190 if (def.binder(first, last, context, skipper))
0191 {
0192
0193
0194 transform::post(attr, attr_);
0195 return true;
0196 }
0197
0198
0199 transform::fail(attr);
0200 return false;
0201 }
0202
0203 template <typename Def
0204 , typename Iterator, typename Context
0205 , typename Skipper, typename Attribute, typename Params>
0206 bool parse_subrule(Def const& def
0207 , Iterator& first, Iterator const& last
0208 , Context& caller_context, Skipper const& skipper
0209 , Attribute& attr, Params const& params) const
0210 {
0211
0212 typedef typename Def::locals_type subrule_locals_type;
0213 typedef typename Def::attr_type subrule_attr_type;
0214 typedef typename Def::attr_reference_type subrule_attr_reference_type;
0215 typedef typename Def::parameter_types subrule_parameter_types;
0216
0217 typedef
0218 subrule_context<
0219 this_type
0220 , fusion::cons<
0221 subrule_attr_reference_type, subrule_parameter_types>
0222 , subrule_locals_type
0223 >
0224 context_type;
0225
0226
0227
0228 typedef traits::transform_attribute<
0229 Attribute, subrule_attr_type, spirit::qi::domain>
0230 transform;
0231
0232 typename transform::type attr_ = transform::pre(attr);
0233
0234
0235
0236
0237 context_type context(*this, attr_, params, caller_context);
0238
0239 if (def.binder(first, last, context, skipper))
0240 {
0241
0242
0243 transform::post(attr, attr_);
0244 return true;
0245 }
0246
0247
0248 transform::fail(attr);
0249 return false;
0250 }
0251
0252 template <typename Context>
0253 info what(Context& context) const
0254 {
0255
0256 return fusion::front(defs).second.binder.p.what(context);
0257 }
0258
0259 Defs defs;
0260 };
0261
0262
0263
0264
0265
0266
0267 template <typename Defs>
0268 struct subrule_group
0269 : proto::extends<
0270 typename proto::terminal<
0271 subrule_group_parser<Defs>
0272 >::type
0273 , subrule_group<Defs>
0274 >
0275 {
0276 typedef subrule_group_parser<Defs> parser_type;
0277 typedef typename proto::terminal<parser_type>::type terminal;
0278
0279 static size_t const params_size =
0280
0281 remove_reference<
0282 typename fusion::result_of::front<Defs>::type
0283 >::type::second_type::params_size;
0284
0285 explicit subrule_group(Defs const& defs)
0286 : subrule_group::proto_extends(terminal::make(parser_type(defs)))
0287 {
0288 }
0289
0290 parser_type const& parser() const { return proto::value(*this); }
0291
0292 Defs const& defs() const { return parser().defs; }
0293
0294 template <typename Defs2>
0295 subrule_group<
0296 typename fusion::result_of::as_map<
0297 typename fusion::result_of::join<
0298 Defs const, Defs2 const>::type>::type>
0299 operator,(subrule_group<Defs2> const& other) const
0300 {
0301 typedef subrule_group<
0302 typename fusion::result_of::as_map<
0303 typename fusion::result_of::join<
0304 Defs const, Defs2 const>::type>::type> result_type;
0305 return result_type(fusion::as_map(fusion::join(defs(), other.defs())));
0306 }
0307
0308
0309 template <typename Defs2>
0310 friend subrule_group<
0311 typename fusion::result_of::as_map<
0312 typename fusion::result_of::join<
0313 Defs const, Defs2 const>::type>::type>
0314 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0315 operator,(subrule_group&& left, subrule_group<Defs2>&& other)
0316 #else
0317 operator,(subrule_group& left, subrule_group<Defs2>& other)
0318 #endif
0319 {
0320 return static_cast<subrule_group const&>(left)
0321 .operator,(static_cast<subrule_group<Defs2> const&>(other));
0322 }
0323
0324
0325 parser_type const& get_parameterized_subject() const { return parser(); }
0326 typedef parser_type parameterized_subject_type;
0327 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0328 };
0329
0330
0331
0332
0333 template <
0334 int ID_
0335 , typename Locals
0336 , typename Attr
0337 , typename AttrRef
0338 , typename Parameters
0339 , size_t ParamsSize
0340 , typename Subject
0341 , bool Auto_
0342 >
0343 struct subrule_definition
0344 {
0345 typedef mpl::int_<ID_> id_type;
0346 BOOST_STATIC_CONSTANT(int, ID = ID_);
0347
0348 typedef Locals locals_type;
0349 typedef Attr attr_type;
0350 typedef AttrRef attr_reference_type;
0351 typedef Parameters parameter_types;
0352 static size_t const params_size = ParamsSize;
0353
0354 typedef Subject subject_type;
0355 typedef mpl::bool_<Auto_> auto_type;
0356 BOOST_STATIC_CONSTANT(bool, Auto = Auto_);
0357
0358 typedef spirit::qi::detail::parser_binder<
0359 Subject, auto_type> binder_type;
0360
0361 subrule_definition(Subject const& subject, std::string const& name)
0362 : binder(subject), name(name)
0363 {
0364 }
0365
0366 binder_type const binder;
0367 std::string const name;
0368 };
0369
0370
0371
0372
0373
0374
0375 template <
0376 int ID_
0377 , typename T1 = unused_type
0378 , typename T2 = unused_type
0379 >
0380 struct subrule
0381 : proto::extends<
0382 typename proto::terminal<
0383 spirit::qi::reference<subrule<ID_, T1, T2> const>
0384 >::type
0385 , subrule<ID_, T1, T2>
0386 >
0387 , spirit::qi::parser<subrule<ID_, T1, T2> >
0388 {
0389 typedef mpl::int_<ID_> id_type;
0390 BOOST_STATIC_CONSTANT(int, ID = ID_);
0391
0392 typedef subrule<ID_, T1, T2> this_type;
0393 typedef spirit::qi::reference<this_type const> reference_;
0394 typedef typename proto::terminal<reference_>::type terminal;
0395 typedef proto::extends<terminal, this_type> base_type;
0396
0397 typedef mpl::vector<T1, T2> template_params;
0398
0399
0400 typedef typename
0401 spirit::detail::extract_locals<template_params>::type
0402 locals_type;
0403
0404
0405 typedef typename
0406 spirit::detail::extract_encoding<template_params>::type
0407 encoding_type;
0408
0409
0410 typedef typename
0411 spirit::detail::extract_sig<template_params, encoding_type
0412 , spirit::qi::domain>::type
0413 sig_type;
0414
0415
0416 typedef typename
0417 spirit::detail::attr_from_sig<sig_type>::type
0418 attr_type;
0419 BOOST_STATIC_ASSERT_MSG(
0420 !is_reference<attr_type>::value,
0421 "Reference qualifier on Qi subrule attribute type is meaningless");
0422 typedef attr_type& attr_reference_type;
0423
0424
0425 typedef typename
0426 spirit::detail::params_from_sig<sig_type>::type
0427 parameter_types;
0428
0429 static size_t const params_size =
0430 fusion::result_of::size<parameter_types>::type::value;
0431
0432 explicit subrule(std::string const& name_ = "unnamed-subrule")
0433 : base_type(terminal::make(reference_(*this)))
0434 , name_(name_)
0435 {
0436 }
0437
0438
0439 template <typename Expr, bool Auto>
0440 struct def_type_helper
0441 {
0442
0443
0444
0445 BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, Expr);
0446
0447 typedef typename result_of::compile<
0448 spirit::qi::domain, Expr>::type subject_type;
0449
0450 typedef subrule_definition<
0451 ID_
0452 , locals_type
0453 , attr_type
0454 , attr_reference_type
0455 , parameter_types
0456 , params_size
0457 , subject_type
0458 , Auto
0459 > const type;
0460 };
0461
0462
0463
0464 template <typename Expr, bool Auto>
0465 struct group_type_helper
0466 {
0467 typedef typename def_type_helper<Expr, Auto>::type def_type;
0468
0469
0470 typedef typename
0471 #ifndef BOOST_FUSION_HAS_VARIADIC_MAP
0472 fusion::result_of::make_map<id_type, def_type>::type
0473 #else
0474 fusion::result_of::make_map<id_type>::template apply<def_type>::type
0475 #endif
0476 defs_type;
0477
0478 typedef subrule_group<defs_type> type;
0479 };
0480
0481 template <typename Expr>
0482 typename group_type_helper<Expr, false>::type
0483 operator=(Expr const& expr) const
0484 {
0485 typedef group_type_helper<Expr, false> helper;
0486 typedef typename helper::def_type def_type;
0487 typedef typename helper::type result_type;
0488 return result_type(fusion::make_map<id_type>(
0489 def_type(compile<spirit::qi::domain>(expr), name_)));
0490 }
0491
0492 #define BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(lhs_ref, rhs_ref) \
0493 template <typename Expr> \
0494 friend typename group_type_helper<Expr, true>::type \
0495 operator%=(subrule lhs_ref sr, Expr rhs_ref expr) \
0496 { \
0497 typedef group_type_helper<Expr, true> helper; \
0498 typedef typename helper::def_type def_type; \
0499 typedef typename helper::type result_type; \
0500 return result_type(fusion::make_map<id_type>( \
0501 def_type(compile<spirit::qi::domain>(expr), sr.name_))); \
0502 } \
0503
0504
0505
0506 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, const&)
0507 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0508 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &&)
0509 #else
0510 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &)
0511 #endif
0512 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, const&)
0513 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0514 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &&)
0515 #else
0516 BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &)
0517 #endif
0518
0519 #undef BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR
0520
0521 std::string const& name() const
0522 {
0523 return name_;
0524 }
0525
0526 void name(std::string const& str)
0527 {
0528 name_ = str;
0529 }
0530
0531 template <typename Context, typename Iterator>
0532 struct attribute
0533 {
0534 typedef attr_type type;
0535 };
0536
0537 template <typename Iterator, typename Group
0538 , typename Attributes, typename Locals
0539 , typename Skipper, typename Attribute>
0540 bool parse(Iterator& first, Iterator const& last
0541 , subrule_context<Group, Attributes, Locals>& context
0542 , Skipper const& skipper, Attribute& attr) const
0543 {
0544 return context.group.template parse_subrule_id<ID_>(
0545 first, last, context, skipper, attr);
0546 }
0547
0548 template <typename Iterator, typename Context
0549 , typename Skipper, typename Attribute>
0550 bool parse(Iterator& , Iterator const&
0551 , Context&
0552 , Skipper const& , Attribute& ) const
0553 {
0554
0555
0556 BOOST_SPIRIT_ASSERT_FAIL(Iterator
0557 , subrule_used_outside_subrule_group, (id_type));
0558
0559 return false;
0560 }
0561
0562 template <typename Iterator, typename Group
0563 , typename Attributes, typename Locals
0564 , typename Skipper, typename Attribute
0565 , typename Params>
0566 bool parse(Iterator& first, Iterator const& last
0567 , subrule_context<Group, Attributes, Locals>& context
0568 , Skipper const& skipper, Attribute& attr
0569 , Params const& params) const
0570 {
0571 return context.group.template parse_subrule_id<ID_>(
0572 first, last, context, skipper, attr, params);
0573 }
0574
0575 template <typename Iterator, typename Context
0576 , typename Skipper, typename Attribute
0577 , typename Params>
0578 bool parse(Iterator& , Iterator const&
0579 , Context&
0580 , Skipper const& , Attribute&
0581 , Params const& ) const
0582 {
0583
0584
0585 BOOST_SPIRIT_ASSERT_FAIL(Iterator
0586 , subrule_used_outside_subrule_group, (id_type));
0587
0588 return false;
0589 }
0590
0591 template <typename Context>
0592 info what(Context& ) const
0593 {
0594 return info(name_);
0595 }
0596
0597
0598 this_type const& get_parameterized_subject() const { return *this; }
0599 typedef this_type parameterized_subject_type;
0600 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0601
0602 std::string name_;
0603 };
0604 }}}}
0605
0606 #if defined(BOOST_MSVC)
0607 # pragma warning(pop)
0608 #endif
0609
0610 #endif