PageRenderTime 20ms CodeModel.GetById 7ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/proto/transform/when.hpp

http://hadesmem.googlecode.com/
C++ Header | 197 lines | 64 code | 14 blank | 119 comment | 0 complexity | 2c0da20fa74cfe596d94065577e1410c MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file when.hpp
  3/// Definition of when transform.
  4//
  5//  Copyright 2008 Eric Niebler. Distributed under the Boost
  6//  Software License, Version 1.0. (See accompanying file
  7//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8
  9#ifndef BOOST_PROTO_TRANSFORM_WHEN_HPP_EAN_10_29_2007
 10#define BOOST_PROTO_TRANSFORM_WHEN_HPP_EAN_10_29_2007
 11
 12#include <boost/preprocessor/cat.hpp>
 13#include <boost/preprocessor/repetition/enum_params.hpp>
 14#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
 15#include <boost/preprocessor/iteration/iterate.hpp>
 16#include <boost/mpl/at.hpp>
 17#include <boost/mpl/if.hpp>
 18#include <boost/mpl/map.hpp>
 19#include <boost/proto/proto_fwd.hpp>
 20#include <boost/proto/traits.hpp>
 21#include <boost/proto/transform/call.hpp>
 22#include <boost/proto/transform/make.hpp>
 23#include <boost/proto/transform/impl.hpp>
 24
 25namespace boost { namespace proto
 26{
 27    /// \brief A grammar element and a PrimitiveTransform that associates
 28    /// a transform with the grammar.
 29    ///
 30    /// Use <tt>when\<\></tt> to override a grammar's default transform
 31    /// with a custom transform. It is for used when composing larger
 32    /// transforms by associating smaller transforms with individual
 33    /// rules in your grammar, as in the following transform which
 34    /// counts the number of terminals in an expression.
 35    ///
 36    /// \code
 37    /// // Count the terminals in an expression tree.
 38    /// // Must be invoked with initial state == mpl::int_<0>().
 39    /// struct CountLeaves
 40    ///   : or_<
 41    ///         when<terminal<_>, mpl::next<_state>()>
 42    ///       , otherwise<fold<_, _state, CountLeaves> >
 43    ///     >
 44    /// {};
 45    /// \endcode
 46    ///
 47    /// In <tt>when\<G, T\></tt>, when \c T is a class type it is a
 48    /// PrimitiveTransform and the following equivalencies hold:
 49    ///
 50    /// <tt>boost::result_of\<when\<G,T\>(E,S,V)\>::type</tt> is the same as
 51    /// <tt>boost::result_of\<T(E,S,V)\>::type</tt>.
 52    ///
 53    /// <tt>when\<G,T\>()(e,s,d)</tt> is the same as
 54    /// <tt>T()(e,s,d)</tt>.
 55    template<typename Grammar, typename PrimitiveTransform /*= Grammar*/>
 56    struct when
 57      : PrimitiveTransform
 58    {
 59        typedef Grammar first;
 60        typedef PrimitiveTransform second;
 61        typedef typename Grammar::proto_grammar proto_grammar;
 62    };
 63
 64    /// \brief A specialization that treats function pointer Transforms as
 65    /// if they were function type Transforms.
 66    ///
 67    /// This specialization requires that \c Fun is actually a function type.
 68    ///
 69    /// This specialization is required for nested transforms such as
 70    /// <tt>when\<G, T0(T1(_))\></tt>. In C++, functions that are used as
 71    /// parameters to other functions automatically decay to funtion
 72    /// pointer types. In other words, the type <tt>T0(T1(_))</tt> is
 73    /// indistinguishable from <tt>T0(T1(*)(_))</tt>. This specialization
 74    /// is required to handle these nested function pointer type transforms
 75    /// properly.
 76    template<typename Grammar, typename Fun>
 77    struct when<Grammar, Fun *>
 78      : when<Grammar, Fun>
 79    {};
 80
 81    /// \brief Syntactic sugar for <tt>when\<_, Fun\></tt>, for use
 82    /// in grammars to handle all the cases not yet handled.
 83    ///
 84    /// Use <tt>otherwise\<T\></tt> in your grammars as a synonym for
 85    /// <tt>when\<_, T\></tt> as in the following transform which
 86    /// counts the number of terminals in an expression.
 87    ///
 88    /// \code
 89    /// // Count the terminals in an expression tree.
 90    /// // Must be invoked with initial state == mpl::int_<0>().
 91    /// struct CountLeaves
 92    ///   : or_<
 93    ///         when<terminal<_>, mpl::next<_state>()>
 94    ///       , otherwise<fold<_, _state, CountLeaves> >
 95    ///     >
 96    /// {};
 97    /// \endcode
 98    template<typename Fun>
 99    struct otherwise
100      : when<_, Fun>
101    {};
102
103    /// \brief This specialization uses the Data parameter as a collection
104    /// of transforms that can be indexed by the specified rule.
105    ///
106    /// Use <tt>when\<T, external_transform\></tt> in your code when you would like
107    /// to define a grammar once and use it to evaluate expressions with
108    /// many different sets of transforms. The transforms are found by
109    /// using the Data parameter as a map from rules to transforms.
110    ///
111    /// See \c action_map for an example.
112    template<typename Grammar>
113    struct when<Grammar, external_transform>
114      : proto::transform<when<Grammar, external_transform> >
115    {
116        typedef Grammar first;
117        typedef external_transform second;
118        typedef typename Grammar::proto_grammar proto_grammar;
119
120        template<typename Expr, typename State, typename Data>
121        struct impl
122          : Data::template when<Grammar>::template impl<Expr, State, Data>
123        {};
124
125        template<typename Expr, typename State, typename Data>
126        struct impl<Expr, State, Data &>
127          : Data::template when<Grammar>::template impl<Expr, State, Data &>
128        {};
129    };
130
131    /// \brief For defining a map of Rule/Transform pairs for use with
132    /// <tt>when\<T, external_transform\></tt> to make transforms external to the grammar
133    ///
134    /// The following code defines a grammar with a couple of external transforms.
135    /// It also defines an action_map that maps from rules to transforms. It then
136    /// passes that transforms map at the Data parameter to the grammar. In this way,
137    /// the behavior of the grammar can be modified post-hoc by passing a different
138    /// action_map.
139    ///
140    /// \code
141    /// struct int_terminal
142    ///   : proto::terminal<int>
143    /// {};
144    /// 
145    /// struct char_terminal
146    ///   : proto::terminal<char>
147    /// {};
148    /// 
149    /// struct my_grammar
150    ///   : proto::or_<
151    ///         proto::when< int_terminal, proto::external_transform >
152    ///       , proto::when< char_terminal, proto::external_transform >
153    ///       , proto::when<
154    ///             proto::plus< my_grammar, my_grammar >
155    ///           , proto::fold< _, int(), my_grammar >
156    ///         >
157    ///     >
158    /// {};
159    /// 
160    /// struct my_transforms
161    ///   : proto::external_transforms<
162    ///         proto::when<int_terminal, print(proto::_value)>
163    ///       , proto::when<char_terminal, print(proto::_value)>
164    ///     >
165    /// {};
166    ///
167    /// proto::literal<int> i(1);
168    /// proto::literal<char> c('a');
169    /// my_transforms trx;
170    ///
171    /// // Evaluate "i+c" using my_grammar with the specified transforms:
172    /// my_grammar()(i + c, 0, trx);
173    /// \endcode
174    template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_LIMIT_MAP_SIZE, typename T, mpl::na)>
175    struct external_transforms
176    {
177        typedef mpl::map<BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_MAP_SIZE, T)> map_type;
178
179        template<typename Rule>
180        struct when
181          : proto::when<_, typename mpl::at<map_type, Rule>::type>
182        {};
183    };
184
185    // Other specializations of proto::when are generated by the preprocessor...
186    #include <boost/proto/transform/detail/when.hpp>
187
188    /// INTERNAL ONLY
189    ///
190    template<typename Grammar, typename Transform>
191    struct is_callable<when<Grammar, Transform> >
192      : mpl::true_
193    {};
194
195}} // namespace boost::proto
196
197#endif