PageRenderTime 41ms CodeModel.GetById 19ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/support/meta_compiler.hpp

http://hadesmem.googlecode.com/
C++ Header | 320 lines | 237 code | 33 blank | 50 comment | 0 complexity | 4bc202ab13408e11ad6c6313a66ec78b MD5 | raw file
  1/*=============================================================================
  2  Copyright (c) 2001-2011 Joel de Guzman
  3  http://spirit.sourceforge.net/
  4
  5  Distributed under the Boost Software License, Version 1.0. (See accompanying
  6  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7=============================================================================*/
  8#ifndef BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
  9#define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
 10
 11#if defined(_MSC_VER)
 12#pragma once
 13#endif
 14
 15#include <boost/config.hpp>
 16#include <boost/spirit/include/phoenix_limits.hpp>
 17#include <boost/detail/workaround.hpp>
 18#include <boost/spirit/include/phoenix_limits.hpp>      // needs to be included before proto
 19#include <boost/proto/proto.hpp>
 20#include <boost/spirit/home/support/make_component.hpp>
 21#include <boost/spirit/home/support/modify.hpp>
 22#include <boost/spirit/home/support/detail/make_cons.hpp>
 23#include <boost/spirit/home/support/unused.hpp>
 24#include <boost/spirit/home/support/assert_msg.hpp>
 25#include <boost/utility/enable_if.hpp>
 26#include <boost/type_traits/remove_reference.hpp>
 27
 28namespace boost { namespace spirit
 29{
 30    // Some defaults...
 31
 32    template <typename Domain, typename Tag, typename Enable = void>
 33    struct use_operator : mpl::false_ {};
 34
 35    template <typename Domain, typename T, typename Enable = void>
 36    struct use_function : mpl::false_ {};
 37
 38    template <typename Domain, typename T, typename Enable = void>
 39    struct use_directive : mpl::false_ {};
 40
 41    template <typename Domain, typename T, typename Enable /* = void */>
 42    struct is_modifier_directive : mpl::false_ {};
 43
 44    template <typename Domain, typename T, typename Enable = void>
 45    struct use_terminal : mpl::false_ {};
 46
 47    template <typename Domain, typename T, typename Enable /*= void*/>
 48    struct flatten_tree : mpl::false_ {};
 49
 50    // Our meta-compiler. This is the main engine that hooks Spirit
 51    // to the proto expression template engine.
 52
 53    template <typename Domain>
 54    struct meta_compiler
 55    {
 56        struct meta_grammar;
 57
 58        BOOST_SPIRIT_ASSERT_MSG((
 59            !use_operator<Domain, proto::tag::subscript>::value
 60        ), error_proto_tag_subscript_cannot_be_used, ());
 61
 62#if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
 63        // this is the non-broken part for compilers properly supporting 
 64        // partial template specialization (VC7.1 does not)
 65        struct cases
 66        {
 67            template <typename Tag, typename Enable = void>
 68            struct case_
 69              : proto::not_<proto::_>
 70            {};
 71
 72            ///////////////////////////////////////////////////////////////////
 73            // terminals
 74            ///////////////////////////////////////////////////////////////////
 75            template <typename Enable>
 76            struct case_<proto::tag::terminal, Enable>
 77              : proto::when<
 78                    proto::if_<use_terminal<Domain, proto::_value>()>,
 79                    detail::make_terminal<Domain>
 80                >
 81            {};
 82
 83            template <typename Tag>
 84            struct case_<Tag, typename enable_if<use_operator<Domain, Tag> >::type>
 85              : proto::or_<
 86            ///////////////////////////////////////////////////////////////////
 87            // binary operators
 88            ///////////////////////////////////////////////////////////////////
 89                    proto::when<proto::binary_expr<Tag, meta_grammar, meta_grammar>,
 90                        detail::make_binary<Domain, Tag, meta_grammar>
 91                    >,
 92            ///////////////////////////////////////////////////////////////////
 93            // unary operators
 94            ///////////////////////////////////////////////////////////////////
 95                    proto::when<proto::unary_expr<Tag, meta_grammar>,
 96                        detail::make_unary<Domain, Tag, meta_grammar>
 97                    >
 98                >
 99            {};
100
101            template <typename Enable>
102            struct case_<proto::tag::subscript, Enable>
103              : proto::or_<
104            ///////////////////////////////////////////////////////////////////
105            // directives
106            ///////////////////////////////////////////////////////////////////
107                    proto::when<proto::binary_expr<proto::tag::subscript
108                      , proto::and_<
109                            proto::terminal<proto::_>
110                          , proto::if_<use_directive<Domain, proto::_value >()> >
111                      , meta_grammar>,
112                        detail::make_directive<Domain, meta_grammar>
113                    >,
114            ///////////////////////////////////////////////////////////////////
115            // semantic actions
116            ///////////////////////////////////////////////////////////////////
117                    proto::when<proto::binary_expr<proto::tag::subscript
118                      , meta_grammar, proto::_>,
119                        detail::make_action<Domain, meta_grammar>
120                    >
121                >
122            {};
123        };
124#else
125        // this part actually constitutes invalid C++ code, but it allows us to
126        // convince VC7.1 to do what we want
127        struct cases
128        {
129            template <typename Tag, typename Enable = void>
130            struct case_
131              : proto::not_<proto::_>
132            {};
133
134            ///////////////////////////////////////////////////////////////////
135            // terminals
136            ///////////////////////////////////////////////////////////////////
137            template <>
138            struct case_<proto::tag::terminal>
139              : proto::when<
140                    proto::if_<use_terminal<Domain, proto::_value>()>,
141                    detail::make_terminal<Domain>
142                >
143            {};
144
145            template <typename Tag>
146            struct case_<Tag>
147              : proto::or_<
148            ///////////////////////////////////////////////////////////////////
149            // binary operators
150            ///////////////////////////////////////////////////////////////////
151                    proto::when<proto::binary_expr<
152                        typename enable_if<use_operator<Domain, Tag>, Tag>::type
153                          , meta_grammar, meta_grammar>
154                      , detail::make_binary<Domain, Tag, meta_grammar>
155                    >,
156            ///////////////////////////////////////////////////////////////////
157            // unary operators
158            ///////////////////////////////////////////////////////////////////
159                    proto::when<proto::unary_expr<
160                        typename enable_if<use_operator<Domain, Tag>, Tag>::type
161                          , meta_grammar>
162                      , detail::make_unary<Domain, Tag, meta_grammar>
163                    >
164                >
165            {};
166
167            template <>
168            struct case_<proto::tag::subscript>
169              : proto::or_<
170            ///////////////////////////////////////////////////////////////////
171            // directives
172            ///////////////////////////////////////////////////////////////////
173                    proto::when<proto::binary_expr<proto::tag::subscript
174                      , proto::and_<
175                            proto::terminal<proto::_>
176                          , proto::if_<use_directive<Domain, proto::_value >()> >
177                      , meta_grammar>,
178                        detail::make_directive<Domain, meta_grammar>
179                    >,
180            ///////////////////////////////////////////////////////////////////
181            // semantic actions
182            ///////////////////////////////////////////////////////////////////
183                    proto::when<proto::binary_expr<proto::tag::subscript
184                      , meta_grammar, proto::_>,
185                        detail::make_action<Domain, meta_grammar>
186                    >
187                >
188            {};
189        };
190#endif
191
192        struct meta_grammar
193          : proto::switch_<cases>
194        {};
195    };
196
197    namespace result_of
198    {
199        // Default case
200        template <typename Domain, typename Expr
201          , typename Modifiers = unused_type, typename Enable = void>
202        struct compile
203        {
204            typedef typename meta_compiler<Domain>::meta_grammar meta_grammar;
205            typedef typename meta_grammar::
206                template result<meta_grammar(Expr, mpl::void_, Modifiers)>::type
207            type;
208        };
209
210        // If Expr is not a proto expression, make it a terminal
211        template <typename Domain, typename Expr, typename Modifiers>
212        struct compile<Domain, Expr, Modifiers,
213            typename disable_if<proto::is_expr<Expr> >::type>
214          : compile<Domain, typename proto::terminal<Expr>::type, Modifiers> {};
215    }
216
217    namespace traits
218    {
219        // Check if Expr matches the domain's grammar
220        template <typename Domain, typename Expr>
221        struct matches :
222            proto::matches<
223                typename proto::result_of::as_expr<
224                    typename remove_reference<Expr>::type>::type,
225                typename meta_compiler<Domain>::meta_grammar
226            >
227        {
228        };
229    }
230
231    namespace detail
232    {
233        template <typename Domain>
234        struct compiler
235        {
236            // Default case
237            template <typename Expr, typename Modifiers>
238            static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
239            compile(Expr const& expr, Modifiers modifiers, mpl::true_)
240            {
241                typename meta_compiler<Domain>::meta_grammar compiler;
242                return compiler(expr, mpl::void_(), modifiers);
243            }
244
245            // If Expr is not a proto expression, make it a terminal
246            template <typename Expr, typename Modifiers>
247            static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
248            compile(Expr const& expr, Modifiers modifiers, mpl::false_)
249            {
250                typename meta_compiler<Domain>::meta_grammar compiler;
251                typedef typename detail::as_meta_element<Expr>::type expr_;
252                typename proto::terminal<expr_>::type term = {expr};
253                return compiler(term, mpl::void_(), modifiers);
254            }
255        };
256    }
257
258    template <typename Domain, typename Expr>
259    inline typename result_of::compile<Domain, Expr, unused_type>::type
260    compile(Expr const& expr)
261    {
262        typedef typename proto::is_expr<Expr>::type is_expr;
263        return detail::compiler<Domain>::compile(expr, unused, is_expr());
264    }
265
266    template <typename Domain, typename Expr, typename Modifiers>
267    inline typename result_of::compile<Domain, Expr, Modifiers>::type
268    compile(Expr const& expr, Modifiers modifiers)
269    {
270        typedef typename proto::is_expr<Expr>::type is_expr;
271        return detail::compiler<Domain>::compile(expr, modifiers, is_expr());
272    }
273
274    ///////////////////////////////////////////////////////////////////////////
275    template <typename Elements, template <typename Subject> class generator>
276    struct make_unary_composite
277    {
278        typedef typename
279            fusion::result_of::value_at_c<Elements, 0>::type
280        element_type;
281        typedef generator<element_type> result_type;
282        result_type operator()(Elements const& elements, unused_type) const
283        {
284            return result_type(fusion::at_c<0>(elements));
285        }
286    };
287
288    template <typename Elements, template <typename Left, typename Right> class generator>
289    struct make_binary_composite
290    {
291        typedef typename
292            fusion::result_of::value_at_c<Elements, 0>::type
293        left_type;
294        typedef typename
295            fusion::result_of::value_at_c<Elements, 1>::type
296        right_type;
297        typedef generator<left_type, right_type> result_type;
298
299        result_type operator()(Elements const& elements, unused_type) const
300        {
301            return result_type(
302                fusion::at_c<0>(elements)
303              , fusion::at_c<1>(elements)
304            );
305        }
306    };
307
308    template <typename Elements, template <typename Elements_> class generator>
309    struct make_nary_composite
310    {
311        typedef generator<Elements> result_type;
312        result_type operator()(Elements const& elements, unused_type) const
313        {
314            return result_type(elements);
315        }
316    };
317
318}}
319
320#endif