Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:09:16

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_OPERATOR_LIST_HPP
0008 #define BOOST_SPIRIT_KARMA_OPERATOR_LIST_HPP
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/karma/domain.hpp>
0015 #include <boost/spirit/home/karma/generator.hpp>
0016 #include <boost/spirit/home/karma/meta_compiler.hpp>
0017 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
0018 #include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
0019 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
0020 #include <boost/spirit/home/karma/detail/pass_container.hpp>
0021 #include <boost/spirit/home/karma/detail/fail_function.hpp>
0022 #include <boost/spirit/home/support/info.hpp>
0023 #include <boost/spirit/home/support/unused.hpp>
0024 #include <boost/spirit/home/support/container.hpp>
0025 #include <boost/spirit/home/support/handles_container.hpp>
0026 #include <boost/spirit/home/karma/detail/attributes.hpp>
0027 #include <boost/proto/operators.hpp>
0028 #include <boost/proto/tags.hpp>
0029 
0030 namespace boost { namespace spirit
0031 {
0032     ///////////////////////////////////////////////////////////////////////////
0033     // Enablers
0034     ///////////////////////////////////////////////////////////////////////////
0035     template <>
0036     struct use_operator<karma::domain, proto::tag::modulus> // enables g % d
0037       : mpl::true_ {};
0038 }}
0039 
0040 ///////////////////////////////////////////////////////////////////////////////
0041 namespace boost { namespace spirit { namespace karma
0042 {
0043     template <typename Left, typename Right, typename Strict, typename Derived>
0044     struct base_list : binary_generator<Derived>
0045     {
0046     private:
0047         // iterate over the given container until its exhausted or the embedded
0048         // (left) generator succeeds
0049         template <typename F, typename Attribute>
0050         bool generate_left(F f, Attribute const&, mpl::false_) const
0051         {
0052             // Failing subject generators are just skipped. This allows to
0053             // selectively generate items in the provided attribute.
0054             while (!f.is_at_end())
0055             {
0056                 bool r = !f(left);
0057                 if (r)
0058                     return true;
0059                 if (!f.is_at_end())
0060                     f.next();
0061             }
0062             return false;
0063         }
0064 
0065         template <typename F, typename Attribute>
0066         bool generate_left(F f, Attribute const&, mpl::true_) const
0067         {
0068             return !f(left);
0069         }
0070 
0071         // There is no way to distinguish a failed generator from a
0072         // generator to be skipped. We assume the user takes responsibility
0073         // for ending the loop if no attribute is specified.
0074         template <typename F>
0075         bool generate_left(F f, unused_type, mpl::false_) const
0076         {
0077             return !f(left);
0078         }
0079 
0080     public:
0081         typedef Left left_type;
0082         typedef Right right_type;
0083 
0084         typedef mpl::int_<
0085             left_type::properties::value
0086           | right_type::properties::value
0087           | generator_properties::buffering
0088           | generator_properties::counting
0089         > properties;
0090 
0091         // Build a std::vector from the LHS's attribute. Note
0092         // that build_std_vector may return unused_type if the
0093         // subject's attribute is an unused_type.
0094         template <typename Context, typename Iterator>
0095         struct attribute
0096           : traits::build_std_vector<
0097                 typename traits::attribute_of<Left, Context, Iterator>::type>
0098         {};
0099 
0100         base_list(Left const& left, Right const& right)
0101           : left(left), right(right)
0102         {}
0103 
0104         template <
0105             typename OutputIterator, typename Context, typename Delimiter
0106           , typename Attribute>
0107         bool generate(OutputIterator& sink, Context& ctx
0108           , Delimiter const& d, Attribute const& attr) const
0109         {
0110             typedef detail::fail_function<
0111                 OutputIterator, Context, Delimiter
0112             > fail_function;
0113 
0114             typedef typename traits::container_iterator<
0115                 typename add_const<Attribute>::type
0116             >::type iterator_type;
0117 
0118             typedef
0119                 typename traits::make_indirect_iterator<iterator_type>::type
0120             indirect_iterator_type;
0121             typedef detail::pass_container<
0122                 fail_function, Attribute, indirect_iterator_type, mpl::false_>
0123             pass_container;
0124 
0125             iterator_type it = traits::begin(attr);
0126             iterator_type end = traits::end(attr);
0127 
0128             pass_container pass(fail_function(sink, ctx, d),
0129                 indirect_iterator_type(it), indirect_iterator_type(end));
0130 
0131             if (generate_left(pass, attr, Strict()))
0132             {
0133                 while (!pass.is_at_end())
0134                 {
0135                     // wrap the given output iterator as generate_left might fail
0136                     detail::enable_buffering<OutputIterator> buffering(sink);
0137                     {
0138                         detail::disable_counting<OutputIterator> nocounting(sink);
0139 
0140                         if (!right.generate(sink, ctx, d, unused))
0141                             return false;     // shouldn't happen
0142 
0143                         if (!generate_left(pass, attr, Strict()))
0144                             break;            // return true as one item succeeded
0145                     }
0146                     buffering.buffer_copy();
0147                 }
0148                 return detail::sink_is_good(sink);
0149             }
0150             return false;
0151         }
0152 
0153         template <typename Context>
0154         info what(Context& context) const
0155         {
0156             return info("list",
0157                 std::make_pair(left.what(context), right.what(context)));
0158         }
0159 
0160         Left left;
0161         Right right;
0162     };
0163 
0164     template <typename Left, typename Right>
0165     struct list
0166       : base_list<Left, Right, mpl::false_, list<Left, Right> >
0167     {
0168         typedef base_list<Left, Right, mpl::false_, list> base_list_;
0169 
0170         list(Left const& left, Right const& right)
0171           : base_list_(left, right) {}
0172     };
0173 
0174     template <typename Left, typename Right>
0175     struct strict_list
0176       : base_list<Left, Right, mpl::true_, strict_list<Left, Right> >
0177     {
0178         typedef base_list<Left, Right, mpl::true_, strict_list> base_list_;
0179 
0180         strict_list (Left const& left, Right const& right)
0181           : base_list_(left, right) {}
0182     };
0183 
0184     ///////////////////////////////////////////////////////////////////////////
0185     // Generator generators: make_xxx function (objects)
0186     ///////////////////////////////////////////////////////////////////////////
0187     namespace detail
0188     {
0189         template <typename Subject, bool strict_mode = false>
0190         struct make_list
0191           : make_binary_composite<Subject, list>
0192         {};
0193 
0194         template <typename Subject>
0195         struct make_list<Subject, true>
0196           : make_binary_composite<Subject, strict_list>
0197         {};
0198     }
0199 
0200     template <typename Subject, typename Modifiers>
0201     struct make_composite<proto::tag::modulus, Subject, Modifiers>
0202       : detail::make_list<Subject, detail::get_stricttag<Modifiers>::value>
0203     {};
0204 }}}
0205 
0206 namespace boost { namespace spirit { namespace traits
0207 {
0208     ///////////////////////////////////////////////////////////////////////////
0209     template <typename Left, typename Right>
0210     struct has_semantic_action<karma::list<Left, Right> >
0211       : binary_has_semantic_action<Left, Right> {};
0212 
0213     template <typename Left, typename Right>
0214     struct has_semantic_action<karma::strict_list<Left, Right> >
0215       : binary_has_semantic_action<Left, Right> {};
0216 
0217     ///////////////////////////////////////////////////////////////////////////
0218     template <typename Left, typename Right, typename Attribute
0219       , typename Context, typename Iterator>
0220     struct handles_container<karma::list<Left, Right>, Attribute
0221           , Context, Iterator>
0222       : mpl::true_ {};
0223 
0224     template <typename Left, typename Right, typename Attribute
0225       , typename Context, typename Iterator>
0226     struct handles_container<karma::strict_list<Left, Right>, Attribute
0227           , Context, Iterator>
0228       : mpl::true_ {};
0229 }}}
0230 
0231 #endif