| // Copyright (c) 2001-2010 Hartmut Kaiser |
| // Copyright (c) 2001-2010 Joel de Guzman |
| // |
| // 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(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM) |
| #define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM |
| |
| #if defined(_MSC_VER) |
| #pragma once |
| #endif |
| |
| #include <boost/spirit/home/karma/detail/alternative_function.hpp> |
| #include <boost/spirit/home/karma/detail/get_stricttag.hpp> |
| #include <boost/spirit/home/karma/domain.hpp> |
| #include <boost/spirit/home/karma/generator.hpp> |
| #include <boost/spirit/home/karma/meta_compiler.hpp> |
| #include <boost/spirit/home/support/info.hpp> |
| #include <boost/spirit/home/support/unused.hpp> |
| #include <boost/spirit/home/support/detail/what_function.hpp> |
| #include <boost/fusion/include/any.hpp> |
| #include <boost/fusion/include/mpl.hpp> |
| #include <boost/fusion/include/for_each.hpp> |
| #include <boost/mpl/accumulate.hpp> |
| #include <boost/mpl/bitor.hpp> |
| |
| namespace boost { namespace spirit |
| { |
| /////////////////////////////////////////////////////////////////////////// |
| // Enablers |
| /////////////////////////////////////////////////////////////////////////// |
| template <> |
| struct use_operator<karma::domain, proto::tag::bitwise_or> // enables | |
| : mpl::true_ {}; |
| |
| template <> |
| struct flatten_tree<karma::domain, proto::tag::bitwise_or> // flattens | |
| : mpl::true_ {}; |
| |
| }} |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { namespace traits |
| { |
| // specialization for sequences |
| template <typename Elements> |
| struct alternative_properties |
| { |
| struct element_properties |
| { |
| template <typename T> |
| struct result; |
| |
| template <typename F, typename Element> |
| struct result<F(Element)> |
| { |
| typedef properties_of<Element> type; |
| }; |
| |
| // never called, but needed for decltype-based result_of (C++0x) |
| template <typename Element> |
| typename result<element_properties(Element)>::type |
| operator()(Element&) const; |
| }; |
| |
| typedef typename mpl::accumulate< |
| typename fusion::result_of::transform< |
| Elements, element_properties>::type |
| , mpl::int_<karma::generator_properties::countingbuffer> |
| , mpl::bitor_<mpl::_2, mpl::_1> |
| >::type type; |
| }; |
| |
| }}} |
| |
| namespace boost { namespace spirit { namespace karma |
| { |
| template <typename Elements, typename Strict, typename Derived> |
| struct base_alternative : nary_generator<Derived> |
| { |
| typedef typename traits::alternative_properties<Elements>::type |
| properties; |
| |
| template <typename Context, typename Iterator = unused_type> |
| struct attribute |
| { |
| // Put all the element attributes in a tuple |
| typedef typename traits::build_attribute_sequence< |
| Elements, Context, mpl::identity, Iterator |
| >::type all_attributes; |
| |
| // Ok, now make a variant over the attribute sequence. Note that |
| // build_variant makes sure that 1) all attributes in the variant |
| // are unique 2) puts the unused attribute, if there is any, to |
| // the front and 3) collapses single element variants, variant<T> |
| // to T. |
| typedef typename traits::build_variant<all_attributes>::type type; |
| }; |
| |
| base_alternative(Elements const& elements) |
| : elements(elements) {} |
| |
| template < |
| typename OutputIterator, typename Context, typename Delimiter |
| , typename Attribute> |
| bool generate(OutputIterator& sink, Context& ctx |
| , Delimiter const& d, Attribute const& attr) const |
| { |
| typedef detail::alternative_generate_function< |
| OutputIterator, Context, Delimiter, Attribute, Strict |
| > functor; |
| |
| // f return true if *any* of the parser succeeds |
| functor f (sink, ctx, d, attr); |
| return fusion::any(elements, f); |
| } |
| |
| template <typename Context> |
| info what(Context& context) const |
| { |
| info result("alternative"); |
| fusion::for_each(elements, |
| spirit::detail::what_function<Context>(result, context)); |
| return result; |
| } |
| |
| Elements elements; |
| }; |
| |
| template <typename Elements> |
| struct alternative |
| : base_alternative<Elements, mpl::false_, alternative<Elements> > |
| { |
| typedef base_alternative<Elements, mpl::false_, alternative> |
| base_alternative_; |
| |
| alternative(Elements const& elements) |
| : base_alternative_(elements) {} |
| }; |
| |
| template <typename Elements> |
| struct strict_alternative |
| : base_alternative<Elements, mpl::true_, strict_alternative<Elements> > |
| { |
| typedef base_alternative<Elements, mpl::true_, strict_alternative> |
| base_alternative_; |
| |
| strict_alternative(Elements const& elements) |
| : base_alternative_(elements) {} |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Generator generators: make_xxx function (objects) |
| /////////////////////////////////////////////////////////////////////////// |
| namespace detail |
| { |
| template <typename Elements, bool strict_mode = false> |
| struct make_alternative |
| : make_nary_composite<Elements, alternative> |
| {}; |
| |
| template <typename Elements> |
| struct make_alternative<Elements, true> |
| : make_nary_composite<Elements, strict_alternative> |
| {}; |
| } |
| |
| template <typename Elements, typename Modifiers> |
| struct make_composite<proto::tag::bitwise_or, Elements, Modifiers> |
| : detail::make_alternative<Elements |
| , detail::get_stricttag<Modifiers>::value> |
| {}; |
| |
| }}} |
| |
| namespace boost { namespace spirit { namespace traits |
| { |
| template <typename Elements> |
| struct has_semantic_action<karma::alternative<Elements> > |
| : nary_has_semantic_action<Elements> {}; |
| |
| template <typename Elements> |
| struct has_semantic_action<karma::strict_alternative<Elements> > |
| : nary_has_semantic_action<Elements> {}; |
| }}} |
| |
| #endif |