Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:30

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2011-2012 Thomas Bernard
0004 
0005     Distributed under the Boost Software License, Version 1.0. (See accompanying
0006     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     // Enablers
0055     ///////////////////////////////////////////////////////////////////////////
0056     template <>
0057     struct use_operator<qi::domain, proto::tag::divides > // enables /
0058       : mpl::true_ {};
0059 
0060     template <>
0061     struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
0062       : mpl::true_ {};
0063 }}
0064 
0065 namespace boost { namespace spirit { namespace repository { namespace qi
0066 {
0067 
0068     // kwd directive parser type identification
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     // kwd directive type query
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     // Keywords operator
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             // Put all the element attributes in a tuple
0105             typedef typename traits::build_attribute_sequence<
0106                 Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
0107             all_attributes;
0108 
0109             // Now, build a fusion vector over the attributes. Note
0110             // that build_fusion_vector 1) removes all unused attributes
0111             // and 2) may return unused_type if all elements have
0112             // unused_type(s).
0113             typedef typename
0114                 traits::build_fusion_vector<all_attributes>::type
0115             type;
0116         };
0117 
0118         /// Make sure that all subjects are of the kwd type
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         /// If the assertion fails here then you probably forgot to wrap a
0134         /// subject of the / operator in a kwd directive
0135         BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
0136 
0137         ///////////////////////////////////////////////////////////////////////////
0138         // build_parser_tags
0139         //
0140         // Builds a boost::variant from an mpl::range_c in order to "mark" every
0141         // parser of the fusion sequence. The integer constant is used in the parser
0142         // dispatcher functor in order to use the parser corresponding to the recognised
0143         // keyword.
0144         ///////////////////////////////////////////////////////////////////////////
0145 
0146         template <typename Sequence>
0147         struct build_parser_tags
0148         {
0149             // Get the sequence size
0150             typedef typename mpl::size< Sequence >::type sequence_size;
0151 
0152             // Create an integer_c constant for every parser in the sequence
0153             typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
0154 
0155             // Transform the range_c to an mpl vector in order to be able to transform it into a variant
0156             typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type type;
0157 
0158         };
0159         // Build an index mpl vector
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         // filter out the string kwd directives
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         // filter out the complex keywords
0177         typedef typename mpl::filter_view< parser_index_vector ,
0178                                          is_complex_kwd_parser_filter< mpl::_ >
0179                                             >::type complex_keywords_indexes;
0180 
0181         //typedef typename fusion::filter_view< Elements, is_complex_kwd_parser< mpl::_ > > complex_keywords_view;
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         // build a bool array and an integer array which will be used to
0190         // check that the repetition constraints of the kwd parsers are
0191         // met and bail out a soon as possible
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             // Select which parse function to call
0220             // We need to handle the case where kwd / ikwd directives have been mixed
0221             // This is where we decide which function should be called.
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_ /* one pass */) const
0232           {
0233 
0234             // wrap the attribute in a tuple if it is not a tuple
0235             typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
0236 
0237             flags_type flags(flags_init);
0238             //flags.assign(false);
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             // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
0258             // array.
0259             // The kwd directive sets and increments the counter when a successeful parse occurred
0260             // as well as the slot of the corresponding parser to true in the flags array as soon
0261             // the minimum repetition requirement is met and keeps that value to true as long as
0262             // the maximum repetition requirement is met.
0263             // The parsing takes place here in two steps:
0264             // 1) parse a keyword and fetch the parser index associated with that keyword
0265             // 2) call the associated parser and store the parsed value in the matching attribute.
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                   // restore the position to the last successful keyword parse
0278                   first = save;
0279                   if(!complex_keywords_inst.parse(complex_function))
0280                   {
0281                     first = save;
0282                     // Check that we are leaving the keywords parser in a successful state
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         // Handle the mixed kwd and ikwd case
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_ /* two passes */) const
0305           {
0306 
0307             // wrap the attribute in a tuple if it is not a tuple
0308             typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
0309 
0310             flags_type flags(flags_init);
0311             //flags.assign(false);
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             // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
0339             // array.
0340             // The kwd directive sets and increments the counter when a successeful parse occurred
0341             // as well as the slot of the corresponding parser to true in the flags array as soon
0342             // the minimum repetition requirement is met and keeps that value to true as long as
0343             // the maximum repetition requirement is met.
0344             // The parsing takes place here in two steps:
0345             // 1) parse a keyword and fetch the parser index associated with that keyword
0346             // 2) call the associated parser and store the parsed value in the matching attribute.
0347 
0348             for(;;)
0349             {
0350                 spirit::qi::skip_over(first, last, skipper);
0351                 Iterator save = first;
0352                 // String keywords pass
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                     // Check that we are leaving the keywords parser in a successful state
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     // Parser generators: make_xxx function (objects)
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     // We specialize this for keywords (see support/attributes.hpp).
0418     // For keywords, we only wrap the attribute in a tuple IFF
0419     // it is not already a fusion tuple.
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