Chris@16: // Copyright (c) 2001-2011 Joel de Guzman Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM) Chris@16: #define BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Enablers Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template <> Chris@16: struct use_operator // enables +g Chris@16: : mpl::true_ {}; Chris@16: }} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace karma Chris@16: { Chris@16: template Chris@16: struct base_plus : unary_generator Chris@16: { Chris@16: private: Chris@16: // Ignore return value in relaxed mode (failing subject generators Chris@16: // are just skipped). This allows to selectively generate items in Chris@16: // the provided attribute. Chris@16: template Chris@16: bool generate_subject(F f, Attribute const&, bool& result, mpl::false_) const Chris@16: { Chris@16: bool r = !f(subject); Chris@16: if (r) Chris@16: result = true; Chris@16: else if (!f.is_at_end()) Chris@16: f.next(); Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool generate_subject(F f, Attribute const&, bool& result, mpl::true_) const Chris@16: { Chris@16: bool r = !f(subject); Chris@16: if (r) Chris@16: result = true; Chris@16: return r; Chris@16: } Chris@16: Chris@16: // There is no way to distinguish a failed generator from a Chris@16: // generator to be skipped. We assume the user takes responsibility Chris@16: // for ending the loop if no attribute is specified. Chris@16: template Chris@16: bool generate_subject(F f, unused_type, bool& result, mpl::false_) const Chris@16: { Chris@16: bool r = f(subject); Chris@16: if (!r) Chris@16: result = true; Chris@16: return !r; Chris@16: } Chris@16: Chris@16: // template Chris@16: // bool generate_subject(F f, unused_type, bool& result, mpl::true_) const Chris@16: // { Chris@16: // bool r = f(subject); Chris@16: // if (!r) Chris@16: // result = true; Chris@16: // return !r; Chris@16: // } Chris@16: Chris@16: public: Chris@16: typedef Subject subject_type; Chris@16: typedef typename subject_type::properties properties; Chris@16: Chris@16: // Build a std::vector from the subjects attribute. Note Chris@16: // that build_std_vector may return unused_type if the Chris@16: // subject's attribute is an unused_type. Chris@16: template Chris@16: struct attribute Chris@16: : traits::build_std_vector< Chris@16: typename traits::attribute_of::type Chris@16: > Chris@16: {}; Chris@16: Chris@16: base_plus(Subject const& subject) Chris@16: : subject(subject) {} Chris@16: Chris@16: template < Chris@16: typename OutputIterator, typename Context, typename Delimiter Chris@16: , typename Attribute> Chris@16: bool generate(OutputIterator& sink, Context& ctx Chris@16: , Delimiter const& d, Attribute const& attr) const Chris@16: { Chris@16: typedef detail::fail_function< Chris@16: OutputIterator, Context, Delimiter> fail_function; Chris@16: Chris@16: typedef typename traits::container_iterator< Chris@16: typename add_const::type Chris@16: >::type iterator_type; Chris@16: Chris@16: typedef Chris@16: typename traits::make_indirect_iterator::type Chris@16: indirect_iterator_type; Chris@16: typedef detail::pass_container< Chris@16: fail_function, Attribute, indirect_iterator_type, mpl::false_> Chris@16: pass_container; Chris@16: Chris@16: iterator_type it = traits::begin(attr); Chris@16: iterator_type end = traits::end(attr); Chris@16: Chris@16: // plus fails if the parameter is empty Chris@16: if (traits::compare(it, end)) Chris@16: return false; Chris@16: Chris@16: pass_container pass(fail_function(sink, ctx, d), Chris@16: indirect_iterator_type(it), indirect_iterator_type(end)); Chris@16: Chris@16: // from now on plus fails if the underlying output fails or overall Chris@16: // no subject generators succeeded Chris@16: bool result = false; Chris@16: while (!pass.is_at_end()) Chris@16: { Chris@16: if (!generate_subject(pass, attr, result, Strict())) Chris@16: break; Chris@16: } Chris@16: return result && detail::sink_is_good(sink); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("plus", subject.what(context)); Chris@16: } Chris@16: Chris@16: Subject subject; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct plus Chris@16: : base_plus > Chris@16: { Chris@16: typedef base_plus base_plus_; Chris@16: Chris@16: plus(Subject const& subject) Chris@16: : base_plus_(subject) {} Chris@16: }; Chris@16: Chris@16: template Chris@16: struct strict_plus Chris@16: : base_plus > Chris@16: { Chris@16: typedef base_plus base_plus_; Chris@16: Chris@16: strict_plus(Subject const& subject) Chris@16: : base_plus_(subject) {} Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Generator generators: make_xxx function (objects) Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct make_plus Chris@16: : make_unary_composite Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct make_plus Chris@16: : make_unary_composite Chris@16: {}; Chris@16: } Chris@16: Chris@16: template Chris@16: struct make_composite Chris@16: : detail::make_plus::value> Chris@16: {}; Chris@16: }}} Chris@16: Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct has_semantic_action > Chris@16: : unary_has_semantic_action {}; Chris@16: Chris@16: template Chris@16: struct has_semantic_action > Chris@16: : unary_has_semantic_action {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct handles_container, Attribute Chris@16: , Context, Iterator> Chris@16: : mpl::true_ {}; Chris@16: Chris@16: template Chris@16: struct handles_container, Attribute Chris@16: , Context, Iterator> Chris@16: : mpl::true_ {}; Chris@16: }}} Chris@16: Chris@16: #endif