| /*============================================================================= |
| Copyright (c) 2001-2007 Joel de Guzman |
| Copyright (c) 2001-2009 Hartmut Kaiser |
| http://spirit.sourceforge.net/ |
| |
| 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_VALUES_JAN_07_2007_0802PM) |
| #define BOOST_SPIRIT_VALUES_JAN_07_2007_0802PM |
| |
| #include <boost/fusion/include/is_sequence.hpp> |
| #include <boost/fusion/include/vector.hpp> |
| #include <boost/spirit/home/support/unused.hpp> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/and.hpp> |
| #include <boost/variant.hpp> |
| |
| namespace boost { namespace spirit { namespace detail |
| { |
| template <typename T> |
| struct not_is_variant |
| : mpl::true_ {}; |
| |
| template <BOOST_VARIANT_ENUM_PARAMS(typename T)> |
| struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > |
| : mpl::false_ {}; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // All parsers and generators have specific attribute or parameter types. |
| // Spirit parsers are passed an attribute and Spirit generators |
| // are passed a parameter; these are either references to the expected |
| // type, or an unused_type -- to flag that we do not care about the |
| // attribute/parameter. For semantic actions, however, we need to have a |
| // real value to pass to the semantic action. If the client did not |
| // provide one, we will have to synthesize the value. This class |
| // takes care of that. |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename ValueType> |
| struct make_value |
| { |
| static ValueType call(unused_type) |
| { |
| return ValueType(); // synthesize the attribute/parameter |
| } |
| |
| template <typename T> |
| static T& call(T& value) |
| { |
| return value; // just pass the one provided |
| } |
| |
| template <typename T> |
| static T const& call(T const& value) |
| { |
| return value; // just pass the one provided |
| } |
| }; |
| |
| template <typename ValueType> |
| struct make_value<ValueType&> : make_value<ValueType> |
| { |
| }; |
| |
| template <> |
| struct make_value<unused_type> |
| { |
| static unused_type call(unused_type) |
| { |
| return unused; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // pass_value determines how we pass attributes and parameters to semantic |
| // actions. Basically, all SAs receive the arguments in a tuple. So, if |
| // the argument to be passed is not a tuple, wrap it in one. |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename ValueType> |
| struct pass_value |
| { |
| typedef |
| mpl::and_< |
| fusion::traits::is_sequence<ValueType> |
| , detail::not_is_variant<ValueType> |
| > |
| is_sequence; |
| |
| typedef typename |
| mpl::if_< |
| is_sequence |
| , ValueType& |
| , fusion::vector<ValueType&> const |
| >::type |
| type; |
| |
| static ValueType& |
| call(ValueType& arg, mpl::true_) |
| { |
| // arg is a fusion sequence (except a variant) return it as-is. |
| return arg; |
| } |
| |
| static fusion::vector<ValueType&> const |
| call(ValueType& seq, mpl::false_) |
| { |
| // arg is a not fusion sequence wrap it in a fusion::vector. |
| return fusion::vector<ValueType&>(seq); |
| } |
| |
| static type |
| call(ValueType& arg) |
| { |
| return call(arg, is_sequence()); |
| } |
| }; |
| }}} |
| |
| #endif |