| // Copyright (c) 2001-2007 Joel de Guzman |
| // Copyright (c) 2001-2009 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_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM) |
| #define BOOST_SPIRIT_KARMA_NONTERMINAL_DIRECTOR_MAR_05_2007_0524PM |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| #pragma once // MS compatible compilers support #pragma once |
| #endif |
| |
| #include <boost/spirit/home/support/nonterminal/nonterminal.hpp> |
| #include <boost/spirit/home/support/nonterminal/detail/expand_arg.hpp> |
| #include <boost/spirit/home/karma/domain.hpp> |
| #include <boost/spirit/home/support/component.hpp> |
| #include <boost/spirit/home/support/attribute_transform.hpp> |
| #include <boost/spirit/home/support/detail/values.hpp> |
| #include <boost/fusion/include/transform.hpp> |
| #include <boost/fusion/include/join.hpp> |
| #include <boost/fusion/include/single_view.hpp> |
| #include <boost/intrusive_ptr.hpp> |
| #include <boost/mpl/at.hpp> |
| #include <boost/type_traits/is_same.hpp> |
| #include <boost/type_traits/remove_const.hpp> |
| |
| namespace boost { namespace spirit { namespace karma |
| { |
| struct nonterminal_director |
| { |
| // The attribute (parameter) of nonterminals is the type given to them |
| // as the return value of the function signature. |
| template <typename Component, typename Context, typename Unused> |
| struct attribute |
| { |
| typedef typename |
| result_of::subject<Component>::type |
| nonterminal_holder; |
| typedef typename |
| nonterminal_holder::nonterminal_type::attribute_type |
| type; |
| }; |
| |
| // the nonterminal_holder holds an actual nonterminal_object |
| template < |
| typename NonterminalContext, typename Nonterminal, |
| typename OutputIterator, typename Context, typename Delimiter, |
| typename Parameter> |
| static bool generate_nonterminal( |
| nonterminal_object<Nonterminal> const& x, |
| OutputIterator& sink, Context&, Delimiter const& delim, |
| Parameter const& param) |
| { |
| typedef typename Nonterminal::locals_type locals_type; |
| fusion::vector<Parameter const&> front(param); |
| NonterminalContext context(front, locals_type()); |
| return x.obj.generate(sink, context, delim); |
| } |
| |
| // the nonterminal_holder holds a pointer to a nonterminal |
| template < |
| typename NonterminalContext, typename Nonterminal, |
| typename OutputIterator, typename Context, typename Delimiter, |
| typename Parameter> |
| static bool generate_nonterminal( |
| Nonterminal const* ptr, |
| OutputIterator& sink, Context&, Delimiter const& delim, |
| Parameter const& param) |
| { |
| typedef typename Nonterminal::locals_type locals_type; |
| fusion::vector<Parameter const&> front(param); |
| NonterminalContext context(front, locals_type()); |
| return ptr->generate(sink, context, delim); |
| } |
| |
| // the nonterminal_holder holds a parameterized_nonterminal |
| template < |
| typename NonterminalContext, typename Nonterminal, |
| typename FSequence, typename OutputIterator, |
| typename Context, typename Delimiter, typename Parameter> |
| static bool generate_nonterminal( |
| parameterized_nonterminal<Nonterminal, FSequence> const& x, |
| OutputIterator& sink, Context& context_, Delimiter const& delim, |
| Parameter const& param) |
| { |
| typedef typename Nonterminal::locals_type locals_type; |
| fusion::single_view<Parameter const&> front(param); |
| NonterminalContext context( |
| fusion::join( |
| front, |
| fusion::transform( |
| x.fseq, |
| spirit::detail::expand_arg<Context>(context_) |
| ) |
| ), |
| locals_type() |
| ); |
| return x.ptr->generate(sink, context, delim); |
| } |
| |
| /////////////////////////////////////////////////////////////////////// |
| // main entry point |
| /////////////////////////////////////////////////////////////////////// |
| template < |
| typename Component, typename OutputIterator, typename Context, |
| typename Delimiter, typename Parameter> |
| static bool generate( |
| Component const& component, OutputIterator& sink, |
| Context& context, Delimiter const& delim, Parameter const& param) |
| { |
| typedef typename |
| result_of::subject<Component>::type |
| nonterminal_holder; |
| |
| // The overall context_type consists of a tuple with: |
| // 1) a tuple of the attribute and parameters |
| // 2) the locals |
| // if no signature is specified the first tuple contains |
| // the attribute at position zero only. |
| typedef typename |
| nonterminal_holder::nonterminal_type::context_type |
| context_type; |
| |
| return generate_nonterminal<context_type>( |
| subject(component).held, sink, context, delim, param); |
| } |
| |
| template <typename Nonterminal> |
| static std::string what_nonterminal(nonterminal_object<Nonterminal> const& x) |
| { |
| // the nonterminal_holder holds an actual nonterminal_object |
| return x.obj.what(); |
| } |
| |
| template <typename Nonterminal> |
| static std::string what_nonterminal(Nonterminal const* ptr) |
| { |
| // the nonterminal_holder holds a pointer to a nonterminal |
| return ptr->what(); |
| } |
| |
| template <typename Nonterminal, typename FSequence> |
| static std::string what_nonterminal( |
| parameterized_nonterminal<Nonterminal, FSequence> const& x) |
| { |
| // the nonterminal_holder holds a parameterized_nonterminal |
| return x.ptr->what(); |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return what_nonterminal(subject(component).held); |
| } |
| }; |
| |
| }}} |
| |
| #endif |