PageRenderTime 15ms CodeModel.GetById 1ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/spirit/home/karma/operator/kleene.hpp

http://hadesmem.googlecode.com/
C++ Header | 208 lines | 147 code | 32 blank | 29 comment | 4 complexity | d342717c1cdc3e7ff6f38c7ec990ec0c MD5 | raw file
  1//  Copyright (c) 2001-2011 Joel de Guzman
  2//  Copyright (c) 2001-2011 Hartmut Kaiser
  3//
  4//  Distributed under the Boost Software License, Version 1.0. (See accompanying
  5//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6
  7#if !defined(BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM)
  8#define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
  9
 10#if defined(_MSC_VER)
 11#pragma once
 12#endif
 13
 14#include <boost/spirit/home/karma/domain.hpp>
 15#include <boost/spirit/home/karma/generator.hpp>
 16#include <boost/spirit/home/karma/meta_compiler.hpp>
 17#include <boost/spirit/home/karma/detail/output_iterator.hpp>
 18#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
 19#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
 20#include <boost/spirit/home/karma/detail/pass_container.hpp>
 21#include <boost/spirit/home/karma/detail/fail_function.hpp>
 22#include <boost/spirit/home/support/info.hpp>
 23#include <boost/spirit/home/support/unused.hpp>
 24#include <boost/spirit/home/support/container.hpp>
 25#include <boost/spirit/home/support/handles_container.hpp>
 26#include <boost/spirit/home/karma/detail/attributes.hpp>
 27
 28#include <boost/type_traits/add_const.hpp>
 29
 30namespace boost { namespace spirit
 31{
 32    ///////////////////////////////////////////////////////////////////////////
 33    // Enablers
 34    ///////////////////////////////////////////////////////////////////////////
 35    template <>
 36    struct use_operator<karma::domain, proto::tag::dereference> // enables *g
 37      : mpl::true_ {};
 38}}
 39
 40///////////////////////////////////////////////////////////////////////////////
 41namespace boost { namespace spirit { namespace karma
 42{
 43    template <typename Subject, typename Strict, typename Derived>
 44    struct base_kleene : unary_generator<Derived>
 45    {
 46    private:
 47        // Ignore return value in relaxed mode (failing subject generators 
 48        // are just skipped). This allows to selectively generate items in 
 49        // the provided attribute.
 50        template <typename F, typename Attribute>
 51        bool generate_subject(F f, Attribute const&, mpl::false_) const
 52        {
 53            bool r = !f(subject);
 54            if (!r && !f.is_at_end())
 55                f.next();
 56            return true;
 57        }
 58
 59        template <typename F, typename Attribute>
 60        bool generate_subject(F f, Attribute const&, mpl::true_) const
 61        {
 62            return !f(subject);
 63        }
 64
 65        // There is no way to distinguish a failed generator from a 
 66        // generator to be skipped. We assume the user takes responsibility 
 67        // for ending the loop if no attribute is specified.
 68        template <typename F>
 69        bool generate_subject(F f, unused_type, mpl::false_) const
 70        {
 71            return !f(subject);
 72        }
 73
 74//         template <typename F>
 75//         bool generate_subject(F f, unused_type, mpl::true_) const
 76//         {
 77//             return !f(subject);
 78//         }
 79
 80    public:
 81        typedef Subject subject_type;
 82        typedef typename subject_type::properties properties;
 83
 84        // Build a std::vector from the subject's attribute. Note
 85        // that build_std_vector may return unused_type if the
 86        // subject's attribute is an unused_type.
 87        template <typename Context, typename Iterator>
 88        struct attribute
 89          : traits::build_std_vector<
 90                typename traits::attribute_of<Subject, Context, Iterator>::type
 91            >
 92        {};
 93
 94        base_kleene(Subject const& subject)
 95          : subject(subject) {}
 96
 97        template <
 98            typename OutputIterator, typename Context, typename Delimiter
 99          , typename Attribute>
100        bool generate(OutputIterator& sink, Context& ctx
101          , Delimiter const& d, Attribute const& attr) const
102        {
103            typedef detail::fail_function<
104                OutputIterator, Context, Delimiter> fail_function;
105
106            typedef typename traits::container_iterator<
107                typename add_const<Attribute>::type
108            >::type iterator_type;
109
110            typedef 
111                typename traits::make_indirect_iterator<iterator_type>::type 
112            indirect_iterator_type;
113            typedef detail::pass_container<
114                fail_function, Attribute, indirect_iterator_type, mpl::false_>
115            pass_container;
116
117            iterator_type it = traits::begin(attr);
118            iterator_type end = traits::end(attr);
119
120            pass_container pass(fail_function(sink, ctx, d), 
121                indirect_iterator_type(it), indirect_iterator_type(end));
122
123            // kleene fails only if the underlying output fails
124            while (!pass.is_at_end())
125            {
126                if (!generate_subject(pass, attr, Strict()))
127                    break;
128            }
129            return detail::sink_is_good(sink);
130        }
131
132        template <typename Context>
133        info what(Context& context) const
134        {
135            return info("kleene", subject.what(context));
136        }
137
138        Subject subject;
139    };
140
141    template <typename Subject>
142    struct kleene 
143      : base_kleene<Subject, mpl::false_, kleene<Subject> >
144    {
145        typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
146
147        kleene(Subject const& subject)
148          : base_kleene_(subject) {}
149    };
150
151    template <typename Subject>
152    struct strict_kleene 
153      : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
154    {
155        typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
156
157        strict_kleene(Subject const& subject)
158          : base_kleene_(subject) {}
159    };
160
161    ///////////////////////////////////////////////////////////////////////////
162    // Generator generators: make_xxx function (objects)
163    ///////////////////////////////////////////////////////////////////////////
164    namespace detail
165    {
166        template <typename Subject, bool strict_mode = false>
167        struct make_kleene 
168          : make_unary_composite<Subject, kleene>
169        {};
170
171        template <typename Subject>
172        struct make_kleene<Subject, true> 
173          : make_unary_composite<Subject, strict_kleene>
174        {};
175    }
176
177    template <typename Subject, typename Modifiers>
178    struct make_composite<proto::tag::dereference, Subject, Modifiers>
179      : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
180    {};
181}}}
182
183namespace boost { namespace spirit { namespace traits
184{
185    ///////////////////////////////////////////////////////////////////////////
186    template <typename Subject>
187    struct has_semantic_action<karma::kleene<Subject> >
188      : unary_has_semantic_action<Subject> {};
189
190    template <typename Subject>
191    struct has_semantic_action<karma::strict_kleene<Subject> >
192      : unary_has_semantic_action<Subject> {};
193
194    ///////////////////////////////////////////////////////////////////////////
195    template <typename Subject, typename Attribute, typename Context
196      , typename Iterator>
197    struct handles_container<karma::kleene<Subject>, Attribute
198          , Context, Iterator> 
199      : mpl::true_ {};
200
201    template <typename Subject, typename Attribute, typename Context
202      , typename Iterator>
203    struct handles_container<karma::strict_kleene<Subject>, Attribute
204          , Context, Iterator> 
205      : mpl::true_ {};
206}}}
207
208#endif