Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:37

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //  Copyright (c) 2001-2011 Joel de Guzman
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_SPIRIT_KARMA_DIRECTIVE_REPEAT_HPP
0008 #define BOOST_SPIRIT_KARMA_DIRECTIVE_REPEAT_HPP
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/karma/meta_compiler.hpp>
0015 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
0016 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
0017 #include <boost/spirit/home/karma/generator.hpp>
0018 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0019 #include <boost/spirit/home/karma/operator/kleene.hpp>
0020 #include <boost/spirit/home/support/container.hpp>
0021 #include <boost/spirit/home/support/common_terminals.hpp>
0022 #include <boost/spirit/home/support/has_semantic_action.hpp>
0023 #include <boost/spirit/home/support/handles_container.hpp>
0024 #include <boost/spirit/home/karma/detail/attributes.hpp>
0025 #include <boost/spirit/home/support/info.hpp>
0026 #include <boost/fusion/include/at.hpp>
0027 
0028 namespace boost { namespace spirit
0029 {
0030     ///////////////////////////////////////////////////////////////////////////
0031     // Enablers
0032     ///////////////////////////////////////////////////////////////////////////
0033     template <>
0034     struct use_directive<karma::domain, tag::repeat>   // enables repeat[p]
0035       : mpl::true_ {};
0036 
0037     template <typename T>
0038     struct use_directive<karma::domain
0039       , terminal_ex<tag::repeat                     // enables repeat(exact)[p]
0040         , fusion::vector1<T> >
0041     > : mpl::true_ {};
0042 
0043     template <typename T>
0044     struct use_directive<karma::domain
0045       , terminal_ex<tag::repeat                     // enables repeat(min, max)[p]
0046         , fusion::vector2<T, T> >
0047     > : mpl::true_ {};
0048 
0049     template <typename T>
0050     struct use_directive<karma::domain
0051       , terminal_ex<tag::repeat                     // enables repeat(min, inf)[p]
0052         , fusion::vector2<T, inf_type> >
0053     > : mpl::true_ {};
0054 
0055     template <>                                     // enables *lazy* repeat(exact)[p]
0056     struct use_lazy_directive<
0057         karma::domain
0058       , tag::repeat
0059       , 1 // arity
0060     > : mpl::true_ {};
0061 
0062     template <>                                     // enables *lazy* repeat(min, max)[p]
0063     struct use_lazy_directive<                      // and repeat(min, inf)[p]
0064         karma::domain
0065       , tag::repeat
0066       , 2 // arity
0067     > : mpl::true_ {};
0068 }}
0069 
0070 namespace boost { namespace spirit { namespace karma
0071 {
0072 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0073     using spirit::repeat;
0074     using spirit::inf;
0075 #endif
0076     using spirit::repeat_type;
0077     using spirit::inf_type;
0078 
0079     ///////////////////////////////////////////////////////////////////////////
0080 #ifdef _MSC_VER
0081 #  pragma warning(push)
0082 #  pragma warning(disable: 4512) // assignment operator could not be generated.
0083 #endif
0084     // handles repeat(exact)[p]
0085     template <typename T>
0086     struct exact_iterator
0087     {
0088         exact_iterator(T const exact)
0089           : exact(exact) {}
0090 
0091         typedef T type;
0092         T start() const { return 0; }
0093         bool got_max(T i) const { return i >= exact; }
0094         bool got_min(T i) const { return i >= exact; }
0095 
0096         T const exact;
0097     };
0098 
0099     // handles repeat(min, max)[p]
0100     template <typename T>
0101     struct finite_iterator
0102     {
0103         finite_iterator(T const min, T const max)
0104           : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
0105           , max BOOST_PREVENT_MACRO_SUBSTITUTION (max) {}
0106 
0107         typedef T type;
0108         T start() const { return 0; }
0109         bool got_max(T i) const { return i >= max; }
0110         bool got_min(T i) const { return i >= min; }
0111 
0112         T const min;
0113         T const max;
0114     };
0115 
0116     // handles repeat(min, inf)[p]
0117     template <typename T>
0118     struct infinite_iterator
0119     {
0120         infinite_iterator(T const min)
0121           : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
0122 
0123         typedef T type;
0124         T start() const { return 0; }
0125         bool got_max(T /*i*/) const { return false; }
0126         bool got_min(T i) const { return i >= min; }
0127 
0128         T const min;
0129     };
0130 #ifdef _MSC_VER
0131 #  pragma warning(pop)
0132 #endif
0133 
0134     ///////////////////////////////////////////////////////////////////////////
0135     template <typename Subject, typename LoopIter, typename Strict
0136       , typename Derived>
0137     struct base_repeat_generator : unary_generator<Derived>
0138     {
0139     private:
0140         // iterate over the given container until its exhausted or the embedded
0141         // generator succeeds
0142         template <typename F, typename Attribute>
0143         bool generate_subject(F f, Attribute const&, mpl::false_) const
0144         {
0145             // Failing subject generators are just skipped. This allows to 
0146             // selectively generate items in the provided attribute.
0147             while (!f.is_at_end())
0148             {
0149                 bool r = !f(subject);
0150                 if (r) 
0151                     return true;
0152                 if (!f.is_at_end())
0153                     f.next();
0154             }
0155             return false;
0156         }
0157 
0158         template <typename F, typename Attribute>
0159         bool generate_subject(F f, Attribute const&, mpl::true_) const
0160         {
0161             return !f(subject);
0162         }
0163 
0164         // There is no way to distinguish a failed generator from a 
0165         // generator to be skipped. We assume the user takes responsibility
0166         // for ending the loop if no attribute is specified.
0167         template <typename F>
0168         bool generate_subject(F f, unused_type, mpl::false_) const
0169         {
0170             return !f(subject);
0171         }
0172 
0173     public:
0174         typedef Subject subject_type;
0175 
0176         typedef mpl::int_<subject_type::properties::value> properties;
0177 
0178         // Build a std::vector from the subject's attribute. Note
0179         // that build_std_vector may return unused_type if the
0180         // subject's attribute is an unused_type.
0181         template <typename Context, typename Iterator>
0182         struct attribute
0183           : traits::build_std_vector<
0184                 typename traits::attribute_of<Subject, Context, Iterator>::type
0185             >
0186         {};
0187 
0188         base_repeat_generator(Subject const& subject, LoopIter const& iter)
0189           : subject(subject), iter(iter) {}
0190 
0191         template <typename OutputIterator, typename Context, typename Delimiter
0192           , typename Attribute>
0193         bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
0194           , Attribute const& attr) const
0195         {
0196             typedef detail::fail_function<
0197                 OutputIterator, Context, Delimiter
0198             > fail_function;
0199 
0200             typedef typename traits::container_iterator<
0201                 typename add_const<Attribute>::type
0202             >::type iterator_type;
0203 
0204             typedef 
0205                 typename traits::make_indirect_iterator<iterator_type>::type 
0206             indirect_iterator_type;
0207 
0208             typedef detail::pass_container<
0209                 fail_function, Attribute, indirect_iterator_type, mpl::false_>
0210             pass_container;
0211 
0212             iterator_type it = traits::begin(attr);
0213             iterator_type end = traits::end(attr);
0214 
0215             pass_container pass(fail_function(sink, ctx, d), 
0216                 indirect_iterator_type(it), indirect_iterator_type(end));
0217 
0218             // generate the minimal required amount of output
0219             typename LoopIter::type i = iter.start();
0220             for (/**/; !pass.is_at_end() && !iter.got_min(i); ++i)
0221             {
0222                 if (!generate_subject(pass, attr, Strict()))
0223                 {
0224                     // if we fail before reaching the minimum iteration
0225                     // required, do not output anything and return false
0226                     return false;
0227                 }
0228             }
0229 
0230             if (pass.is_at_end() && !iter.got_min(i))
0231                 return false;   // insufficient attribute elements
0232 
0233             // generate some more up to the maximum specified
0234             for (/**/; !pass.is_at_end() && !iter.got_max(i); ++i)
0235             {
0236                 if (!generate_subject(pass, attr, Strict()))
0237                     break;
0238             }
0239             return detail::sink_is_good(sink);
0240         }
0241 
0242         template <typename Context>
0243         info what(Context& context) const
0244         {
0245             return info("repeat", subject.what(context));
0246         }
0247 
0248         Subject subject;
0249         LoopIter iter;
0250     };
0251 
0252     template <typename Subject, typename LoopIter>
0253     struct repeat_generator 
0254       : base_repeat_generator<
0255             Subject, LoopIter, mpl::false_
0256           , repeat_generator<Subject, LoopIter> >
0257     {
0258         typedef base_repeat_generator<
0259             Subject, LoopIter, mpl::false_, repeat_generator
0260         > base_repeat_generator_;
0261 
0262         repeat_generator(Subject const& subject, LoopIter const& iter)
0263           : base_repeat_generator_(subject, iter) {}
0264     };
0265 
0266     template <typename Subject, typename LoopIter>
0267     struct strict_repeat_generator 
0268       : base_repeat_generator<
0269             Subject, LoopIter, mpl::true_
0270           , strict_repeat_generator<Subject, LoopIter> >
0271     {
0272         typedef base_repeat_generator<
0273             Subject, LoopIter, mpl::true_, strict_repeat_generator
0274         > base_repeat_generator_;
0275 
0276         strict_repeat_generator(Subject const& subject, LoopIter const& iter)
0277           : base_repeat_generator_(subject, iter) {}
0278     };
0279 
0280     ///////////////////////////////////////////////////////////////////////////
0281     // Generator generators: make_xxx function (objects)
0282     ///////////////////////////////////////////////////////////////////////////
0283     template <typename Subject, typename Modifiers>
0284     struct make_directive<tag::repeat, Subject, Modifiers>
0285     {
0286         typedef typename mpl::if_<
0287             detail::get_stricttag<Modifiers>
0288           , strict_kleene<Subject>, kleene<Subject>
0289         >::type result_type;
0290 
0291         result_type operator()(unused_type, Subject const& subject
0292           , unused_type) const
0293         {
0294             return result_type(subject);
0295         }
0296     };
0297 
0298     template <typename T, typename Subject, typename Modifiers>
0299     struct make_directive<
0300         terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
0301     {
0302         typedef exact_iterator<T> iterator_type;
0303 
0304         typedef typename mpl::if_<
0305             detail::get_stricttag<Modifiers>
0306           , strict_repeat_generator<Subject, iterator_type>
0307           , repeat_generator<Subject, iterator_type>
0308         >::type result_type;
0309 
0310         template <typename Terminal>
0311         result_type operator()(
0312             Terminal const& term, Subject const& subject, unused_type) const
0313         {
0314             return result_type(subject, fusion::at_c<0>(term.args));
0315         }
0316     };
0317 
0318     template <typename T, typename Subject, typename Modifiers>
0319     struct make_directive<
0320         terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
0321     {
0322         typedef finite_iterator<T> iterator_type;
0323 
0324         typedef typename mpl::if_<
0325             detail::get_stricttag<Modifiers>
0326           , strict_repeat_generator<Subject, iterator_type>
0327           , repeat_generator<Subject, iterator_type>
0328         >::type result_type;
0329 
0330         template <typename Terminal>
0331         result_type operator()(
0332             Terminal const& term, Subject const& subject, unused_type) const
0333         {
0334             return result_type(subject,
0335                 iterator_type(
0336                     fusion::at_c<0>(term.args)
0337                   , fusion::at_c<1>(term.args)
0338                 )
0339             );
0340         }
0341     };
0342 
0343     template <typename T, typename Subject, typename Modifiers>
0344     struct make_directive<
0345         terminal_ex<tag::repeat
0346         , fusion::vector2<T, inf_type> >, Subject, Modifiers>
0347     {
0348         typedef infinite_iterator<T> iterator_type;
0349 
0350         typedef typename mpl::if_<
0351             detail::get_stricttag<Modifiers>
0352           , strict_repeat_generator<Subject, iterator_type>
0353           , repeat_generator<Subject, iterator_type>
0354         >::type result_type;
0355 
0356         template <typename Terminal>
0357         result_type operator()(
0358             Terminal const& term, Subject const& subject, unused_type) const
0359         {
0360             return result_type(subject, fusion::at_c<0>(term.args));
0361         }
0362     };
0363 }}}
0364 
0365 namespace boost { namespace spirit { namespace traits
0366 {
0367     ///////////////////////////////////////////////////////////////////////////
0368     template <typename Subject, typename LoopIter>
0369     struct has_semantic_action<karma::repeat_generator<Subject, LoopIter> >
0370       : unary_has_semantic_action<Subject> {};
0371 
0372     template <typename Subject, typename LoopIter>
0373     struct has_semantic_action<karma::strict_repeat_generator<Subject, LoopIter> >
0374       : unary_has_semantic_action<Subject> {};
0375 
0376     ///////////////////////////////////////////////////////////////////////////
0377     template <typename Subject, typename LoopIter, typename Attribute
0378       , typename Context, typename Iterator>
0379     struct handles_container<
0380             karma::repeat_generator<Subject, LoopIter>, Attribute
0381           , Context, Iterator> 
0382       : mpl::true_ {};
0383 
0384     template <typename Subject, typename LoopIter, typename Attribute
0385       , typename Context, typename Iterator>
0386     struct handles_container<
0387             karma::strict_repeat_generator<Subject, LoopIter>, Attribute
0388           , Context, Iterator> 
0389       : mpl::true_ {};
0390 }}}
0391 
0392 #endif