// Copyright (c) 2001-2011 Hartmut Kaiser // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0339PM) #define BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0339PM #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { /////////////////////////////////////////////////////////////////////////// // Enablers /////////////////////////////////////////////////////////////////////////// template <> struct use_terminal // enables auto_ : mpl::true_ {}; template struct use_terminal > > : mpl::true_ {}; template <> // enables auto_(f) struct use_lazy_terminal< karma::domain, tag::auto_, 1 /*arity*/ > : mpl::true_ {}; }} /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace karma { #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS using spirit::auto_; #endif using spirit::auto_type; /////////////////////////////////////////////////////////////////////////// template struct auto_generator : generator > { typedef mpl::int_ properties; template struct attribute { typedef spirit::basic_hold_any type; }; auto_generator(Modifiers const& modifiers) : modifiers_(modifiers) {} // auto_generator has an attached attribute template < typename OutputIterator, typename Context, typename Delimiter , typename Attribute> bool generate(OutputIterator& sink, Context& context , Delimiter const& d, Attribute const& attr) const { return compile(create_generator(), modifiers_) .generate(sink, context, d, attr); } // this auto_generator has no attribute attached, it needs to have been // initialized from a value/variable template static bool generate(OutputIterator&, Context&, Delimiter const&, unused_type) { // It is not possible (doesn't make sense) to use auto_ generators // without providing any attribute, as the generator doesn't 'know' // what to output. The following assertion fires if this situation // is detected in your code. BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, auto_not_usable_without_attribute, ()); return false; } template info what(Context& /*context*/) const { return info("auto_"); } Modifiers modifiers_; }; /////////////////////////////////////////////////////////////////////////// template struct lit_auto_generator : generator > { typedef mpl::int_ properties; template struct attribute { typedef unused_type type; }; lit_auto_generator(typename add_reference::type t, Modifiers const& modifiers) : t_(t) , generator_(compile(create_generator(), modifiers)) {} // auto_generator has an attached attribute template < typename OutputIterator, typename Context, typename Delimiter , typename Attribute> bool generate(OutputIterator& sink, Context& context , Delimiter const& d, Attribute const&) const { return generator_.generate(sink, context, d, t_); } template info what(Context& /*context*/) const { return info("auto_"); } typedef typename spirit::result_of::create_generator::type generator_type; typedef typename spirit::result_of::compile< karma::domain, generator_type, Modifiers>::type generator_impl_type; T t_; generator_impl_type generator_; private: // silence MSVC warning C4512: assignment operator could not be generated lit_auto_generator& operator= (lit_auto_generator const&); }; /////////////////////////////////////////////////////////////////////////// // Generator generators: make_xxx function (objects) /////////////////////////////////////////////////////////////////////////// // auto_ template struct make_primitive { typedef auto_generator result_type; result_type operator()(unused_type, Modifiers const& modifiers) const { return result_type(modifiers); } }; // auto_(...) template struct make_primitive< terminal_ex >, Modifiers> { typedef typename add_const::type const_attribute; typedef lit_auto_generator result_type; template result_type operator()(Terminal const& term, Modifiers const& modifiers) const { return result_type(fusion::at_c<0>(term.args), modifiers); } }; }}} #endif