File indexing completed on 2025-01-18 09:52:30
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_SPIRIT_REPOSITORY_QI_OPERATOR_KEYWORDS_HPP
0009 #define BOOST_SPIRIT_REPOSITORY_QI_OPERATOR_KEYWORDS_HPP
0010
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014
0015 #include <boost/spirit/home/qi/meta_compiler.hpp>
0016 #include <boost/spirit/home/qi/domain.hpp>
0017 #include <boost/spirit/home/qi/detail/permute_function.hpp>
0018 #include <boost/spirit/home/qi/detail/attributes.hpp>
0019 #include <boost/spirit/home/support/detail/what_function.hpp>
0020 #include <boost/spirit/home/support/info.hpp>
0021 #include <boost/spirit/home/support/unused.hpp>
0022 #include <boost/fusion/include/iter_fold.hpp>
0023 #include <boost/fusion/include/at.hpp>
0024 #include <boost/fusion/include/value_at.hpp>
0025 #include <boost/fusion/include/mpl.hpp>
0026 #include <boost/optional.hpp>
0027 #include <boost/array.hpp>
0028 #include <boost/spirit/home/qi/string/symbols.hpp>
0029 #include <boost/spirit/home/qi/string/lit.hpp>
0030 #include <boost/spirit/home/qi/action/action.hpp>
0031 #include <boost/spirit/home/qi/directive/hold.hpp>
0032 #include <boost/mpl/count_if.hpp>
0033 #include <boost/mpl/greater.hpp>
0034 #include <boost/mpl/range_c.hpp>
0035 #include <boost/mpl/copy.hpp>
0036 #include <boost/mpl/size.hpp>
0037 #include <boost/mpl/equal_to.hpp>
0038 #include <boost/mpl/back_inserter.hpp>
0039 #include <boost/mpl/filter_view.hpp>
0040 #include <boost/fusion/include/zip_view.hpp>
0041 #include <boost/fusion/include/as_vector.hpp>
0042 #include <boost/variant/static_visitor.hpp>
0043 #include <boost/proto/operators.hpp>
0044 #include <boost/proto/tags.hpp>
0045 #include <boost/type_traits/remove_const.hpp>
0046 #include <boost/type_traits/is_same.hpp>
0047 #include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
0048 #include <boost/fusion/include/any.hpp>
0049
0050
0051 namespace boost { namespace spirit
0052 {
0053
0054
0055
0056 template <>
0057 struct use_operator<qi::domain, proto::tag::divides >
0058 : mpl::true_ {};
0059
0060 template <>
0061 struct flatten_tree<qi::domain, proto::tag::divides>
0062 : mpl::true_ {};
0063 }}
0064
0065 namespace boost { namespace spirit { namespace repository { namespace qi
0066 {
0067
0068
0069 namespace detail
0070 {
0071 BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
0072 BOOST_MPL_HAS_XXX_TRAIT_DEF(complex_kwd_parser_id)
0073
0074
0075 }
0076
0077
0078 template <typename T>
0079 struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
0080
0081 template <typename Subject, typename Action>
0082 struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
0083
0084 template <typename Subject>
0085 struct is_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_kwd_parser_id<Subject> {};
0086
0087 template <typename T>
0088 struct is_complex_kwd_parser : detail::has_complex_kwd_parser_id<T> {};
0089
0090 template <typename Subject, typename Action>
0091 struct is_complex_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_complex_kwd_parser_id<Subject> {};
0092
0093 template <typename Subject>
0094 struct is_complex_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_complex_kwd_parser_id<Subject> {};
0095
0096
0097
0098 template <typename Elements, typename Modifiers>
0099 struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
0100 {
0101 template <typename Context, typename Iterator>
0102 struct attribute
0103 {
0104
0105 typedef typename traits::build_attribute_sequence<
0106 Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
0107 all_attributes;
0108
0109
0110
0111
0112
0113 typedef typename
0114 traits::build_fusion_vector<all_attributes>::type
0115 type;
0116 };
0117
0118
0119 typedef typename mpl::count_if<
0120 Elements,
0121 mpl::not_<
0122 mpl::or_<
0123 is_kwd_parser<
0124 mpl::_1
0125 > ,
0126 is_complex_kwd_parser<
0127 mpl::_1
0128 >
0129 >
0130 >
0131 > non_kwd_subject_count;
0132
0133
0134
0135 BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 template <typename Sequence>
0147 struct build_parser_tags
0148 {
0149
0150 typedef typename mpl::size< Sequence >::type sequence_size;
0151
0152
0153 typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
0154
0155
0156 typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type type;
0157
0158 };
0159
0160 typedef typename build_parser_tags< Elements >::type parser_index_vector;
0161
0162 template <typename idx>
0163 struct is_complex_kwd_parser_filter : is_complex_kwd_parser< typename mpl::at<Elements, idx>::type >
0164 {};
0165
0166 template <typename idx>
0167 struct is_kwd_parser_filter : is_kwd_parser< typename mpl::at<Elements, idx>::type >
0168 {};
0169
0170
0171 typedef typename mpl::filter_view< Elements, is_kwd_parser<mpl::_> >::type string_keywords;
0172
0173 typedef typename mpl::filter_view< parser_index_vector ,
0174 is_kwd_parser_filter< mpl::_ >
0175 >::type string_keyword_indexes;
0176
0177 typedef typename mpl::filter_view< parser_index_vector ,
0178 is_complex_kwd_parser_filter< mpl::_ >
0179 >::type complex_keywords_indexes;
0180
0181
0182
0183 typedef typename mpl::if_<
0184 typename mpl::empty<complex_keywords_indexes>::type,
0185 detail::empty_keywords_list,
0186 detail::complex_keywords< complex_keywords_indexes >
0187 >::type complex_keywords_type;
0188
0189
0190
0191
0192 typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
0193 typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
0194
0195 typedef typename mpl::if_<
0196 typename mpl::empty<string_keyword_indexes>::type,
0197 detail::empty_keywords_list,
0198 detail::string_keywords<
0199 Elements,
0200 string_keywords,
0201 string_keyword_indexes,
0202 flags_type,
0203 Modifiers>
0204 >::type string_keywords_type;
0205
0206 keywords(Elements const& elements_) :
0207 elements(elements_)
0208 , string_keywords_inst(elements,flags_init)
0209 , complex_keywords_inst(elements,flags_init)
0210 {
0211 }
0212
0213 template <typename Iterator, typename Context
0214 , typename Skipper, typename Attribute>
0215 bool parse(Iterator& first, Iterator const& last
0216 , Context& context, Skipper const& skipper
0217 , Attribute& attr_) const
0218 {
0219
0220
0221
0222 return parse_impl(first, last, context, skipper, attr_,
0223 typename string_keywords_type::requires_one_pass()
0224 );
0225 }
0226
0227 template <typename Iterator, typename Context
0228 , typename Skipper, typename Attribute>
0229 bool parse_impl(Iterator& first, Iterator const& last
0230 , Context& context, Skipper const& skipper
0231 , Attribute& attr_,mpl::true_ ) const
0232 {
0233
0234
0235 typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
0236
0237 flags_type flags(flags_init);
0238
0239
0240 counters_type counters;
0241 counters.assign(0);
0242
0243 typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
0244 , flags_type, counters_type
0245 , typename traits::wrap_if_not_tuple<Attribute>::type
0246 , mpl::false_ > parser_visitor_type;
0247
0248 parser_visitor_type parse_visitor(elements, first, last
0249 , context, skipper, flags
0250 , counters, attr);
0251
0252 typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
0253
0254 complex_kwd_function_type
0255 complex_function(first,last,context,skipper,parse_visitor);
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 for(;;)
0268 {
0269
0270 spirit::qi::skip_over(first, last, skipper);
0271 Iterator save = first;
0272 if (string_keywords_inst.parse(first, last,parse_visitor,skipper))
0273 {
0274 save = first;
0275 }
0276 else {
0277
0278 first = save;
0279 if(!complex_keywords_inst.parse(complex_function))
0280 {
0281 first = save;
0282
0283 for(typename flags_type::size_type i = 0, size = flags.size(); i < size; ++i)
0284 {
0285 if(!flags[i])
0286 {
0287 return false;
0288 }
0289 }
0290 return true;
0291 }
0292 else
0293 save = first;
0294 }
0295 }
0296 BOOST_UNREACHABLE_RETURN(false)
0297 }
0298
0299
0300 template <typename Iterator, typename Context
0301 , typename Skipper, typename Attribute>
0302 bool parse_impl(Iterator& first, Iterator const& last
0303 , Context& context, Skipper const& skipper
0304 , Attribute& attr_,mpl::false_ ) const
0305 {
0306
0307
0308 typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
0309
0310 flags_type flags(flags_init);
0311
0312
0313 counters_type counters;
0314 counters.assign(0);
0315
0316 typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
0317 , flags_type, counters_type
0318 , typename traits::wrap_if_not_tuple<Attribute>::type
0319 , mpl::false_> parser_visitor_type;
0320
0321 typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
0322 , flags_type, counters_type
0323 , typename traits::wrap_if_not_tuple<Attribute>::type
0324 , mpl::true_> no_case_parser_visitor_type;
0325
0326
0327 parser_visitor_type parse_visitor(elements,first,last
0328 ,context,skipper,flags,counters,attr);
0329 no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
0330 ,context,skipper,flags,counters,attr);
0331
0332 typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
0333
0334 complex_kwd_function_type
0335 complex_function(first,last,context,skipper,parse_visitor);
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 for(;;)
0349 {
0350 spirit::qi::skip_over(first, last, skipper);
0351 Iterator save = first;
0352
0353 if (string_keywords_inst.parse(first,last,parse_visitor,no_case_parse_visitor,skipper))
0354 {
0355 save = first;
0356 }
0357 else {
0358 first = save;
0359
0360 if(!complex_keywords_inst.parse(complex_function))
0361 {
0362 first = save;
0363
0364 for(typename flags_type::size_type i = 0, size = flags.size(); i < size; ++i)
0365 {
0366 if(!flags[i])
0367 {
0368 return false;
0369 }
0370 }
0371 return true;
0372 }
0373 else
0374 {
0375 save = first;
0376 }
0377 }
0378 }
0379 BOOST_UNREACHABLE_RETURN(false)
0380 }
0381
0382 template <typename Context>
0383 info what(Context& context) const
0384 {
0385 info result("keywords");
0386 fusion::for_each(elements,
0387 spirit::detail::what_function<Context>(result, context));
0388 return result;
0389 }
0390 flags_type flags_init;
0391 Elements elements;
0392 string_keywords_type string_keywords_inst;
0393 complex_keywords_type complex_keywords_inst;
0394
0395 };
0396 }}}}
0397
0398 namespace boost { namespace spirit { namespace qi {
0399
0400
0401
0402 template <typename Elements, typename Modifiers >
0403 struct make_composite<proto::tag::divides, Elements, Modifiers >
0404 {
0405 typedef repository::qi::keywords<Elements,Modifiers> result_type;
0406 result_type operator()(Elements ref, unused_type) const
0407 {
0408 return result_type(ref);
0409 }
0410 };
0411
0412
0413 }}}
0414
0415 namespace boost { namespace spirit { namespace traits
0416 {
0417
0418
0419
0420 template <typename Elements, typename Modifiers,typename Attribute>
0421 struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
0422 : wrap_if_not_tuple<Attribute> {};
0423
0424 template <typename Elements, typename Modifiers>
0425 struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
0426 : nary_has_semantic_action<Elements> {};
0427
0428 template <typename Elements, typename Attribute, typename Context
0429 , typename Iterator, typename Modifiers>
0430 struct handles_container<repository::qi::keywords<Elements,Modifiers>, Attribute
0431 , Context, Iterator>
0432 : nary_handles_container<Elements, Attribute, Context, Iterator> {};
0433
0434
0435 }}}
0436
0437 #endif
0438