Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //  Copyright (c) 2001-2011 Joel de Guzman
0002 //  Copyright (c) 2001-2011 Hartmut Kaiser
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 #if !defined(BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM)
0008 #define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
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 #include <boost/type_traits/add_const.hpp>
0030 
0031 namespace boost { namespace spirit
0032 {
0033     ///////////////////////////////////////////////////////////////////////////
0034     // Enablers
0035     ///////////////////////////////////////////////////////////////////////////
0036     template <>
0037     struct use_operator<karma::domain, proto::tag::dereference> // enables *g
0038       : mpl::true_ {};
0039 }}
0040 
0041 ///////////////////////////////////////////////////////////////////////////////
0042 namespace boost { namespace spirit { namespace karma
0043 {
0044     template <typename Subject, typename Strict, typename Derived>
0045     struct base_kleene : unary_generator<Derived>
0046     {
0047     private:
0048         // Ignore return value in relaxed mode (failing subject generators 
0049         // are just skipped). This allows to selectively generate items in 
0050         // the provided attribute.
0051         template <typename F, typename Attribute>
0052         bool generate_subject(F f, Attribute const&, mpl::false_) const
0053         {
0054             bool r = !f(subject);
0055             if (!r && !f.is_at_end())
0056                 f.next();
0057             return true;
0058         }
0059 
0060         template <typename F, typename Attribute>
0061         bool generate_subject(F f, Attribute const&, mpl::true_) const
0062         {
0063             return !f(subject);
0064         }
0065 
0066         // There is no way to distinguish a failed generator from a 
0067         // generator to be skipped. We assume the user takes responsibility 
0068         // for ending the loop if no attribute is specified.
0069         template <typename F>
0070         bool generate_subject(F f, unused_type, mpl::false_) const
0071         {
0072             return !f(subject);
0073         }
0074 
0075 //         template <typename F>
0076 //         bool generate_subject(F f, unused_type, mpl::true_) const
0077 //         {
0078 //             return !f(subject);
0079 //         }
0080 
0081     public:
0082         typedef Subject subject_type;
0083         typedef typename subject_type::properties properties;
0084 
0085         // Build a std::vector from the subject's attribute. Note
0086         // that build_std_vector may return unused_type if the
0087         // subject's attribute is an unused_type.
0088         template <typename Context, typename Iterator>
0089         struct attribute
0090           : traits::build_std_vector<
0091                 typename traits::attribute_of<Subject, Context, Iterator>::type
0092             >
0093         {};
0094 
0095         base_kleene(Subject const& subject)
0096           : subject(subject) {}
0097 
0098         template <
0099             typename OutputIterator, typename Context, typename Delimiter
0100           , typename Attribute>
0101         bool generate(OutputIterator& sink, Context& ctx
0102           , Delimiter const& d, Attribute const& attr) const
0103         {
0104             typedef detail::fail_function<
0105                 OutputIterator, Context, Delimiter> fail_function;
0106 
0107             typedef typename traits::container_iterator<
0108                 typename add_const<Attribute>::type
0109             >::type iterator_type;
0110 
0111             typedef 
0112                 typename traits::make_indirect_iterator<iterator_type>::type 
0113             indirect_iterator_type;
0114             typedef detail::pass_container<
0115                 fail_function, Attribute, indirect_iterator_type, mpl::false_>
0116             pass_container;
0117 
0118             iterator_type it = traits::begin(attr);
0119             iterator_type end = traits::end(attr);
0120 
0121             pass_container pass(fail_function(sink, ctx, d), 
0122                 indirect_iterator_type(it), indirect_iterator_type(end));
0123 
0124             // kleene fails only if the underlying output fails
0125             while (!pass.is_at_end())
0126             {
0127                 if (!generate_subject(pass, attr, Strict()))
0128                     break;
0129             }
0130             return detail::sink_is_good(sink);
0131         }
0132 
0133         template <typename Context>
0134         info what(Context& context) const
0135         {
0136             return info("kleene", subject.what(context));
0137         }
0138 
0139         Subject subject;
0140     };
0141 
0142     template <typename Subject>
0143     struct kleene 
0144       : base_kleene<Subject, mpl::false_, kleene<Subject> >
0145     {
0146         typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
0147 
0148         kleene(Subject const& subject)
0149           : base_kleene_(subject) {}
0150     };
0151 
0152     template <typename Subject>
0153     struct strict_kleene 
0154       : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
0155     {
0156         typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
0157 
0158         strict_kleene(Subject const& subject)
0159           : base_kleene_(subject) {}
0160     };
0161 
0162     ///////////////////////////////////////////////////////////////////////////
0163     // Generator generators: make_xxx function (objects)
0164     ///////////////////////////////////////////////////////////////////////////
0165     namespace detail
0166     {
0167         template <typename Subject, bool strict_mode = false>
0168         struct make_kleene 
0169           : make_unary_composite<Subject, kleene>
0170         {};
0171 
0172         template <typename Subject>
0173         struct make_kleene<Subject, true> 
0174           : make_unary_composite<Subject, strict_kleene>
0175         {};
0176     }
0177 
0178     template <typename Subject, typename Modifiers>
0179     struct make_composite<proto::tag::dereference, Subject, Modifiers>
0180       : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
0181     {};
0182 }}}
0183 
0184 namespace boost { namespace spirit { namespace traits
0185 {
0186     ///////////////////////////////////////////////////////////////////////////
0187     template <typename Subject>
0188     struct has_semantic_action<karma::kleene<Subject> >
0189       : unary_has_semantic_action<Subject> {};
0190 
0191     template <typename Subject>
0192     struct has_semantic_action<karma::strict_kleene<Subject> >
0193       : unary_has_semantic_action<Subject> {};
0194 
0195     ///////////////////////////////////////////////////////////////////////////
0196     template <typename Subject, typename Attribute, typename Context
0197       , typename Iterator>
0198     struct handles_container<karma::kleene<Subject>, Attribute
0199           , Context, Iterator> 
0200       : mpl::true_ {};
0201 
0202     template <typename Subject, typename Attribute, typename Context
0203       , typename Iterator>
0204     struct handles_container<karma::strict_kleene<Subject>, Attribute
0205           , Context, Iterator> 
0206       : mpl::true_ {};
0207 }}}
0208 
0209 #endif