Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/spirit/home/support/meta_compiler.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*=============================================================================
0002   Copyright (c) 2001-2011 Joel de Guzman
0003   http://spirit.sourceforge.net/
0004 
0005   Distributed under the Boost Software License, Version 1.0. (See accompanying
0006   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #ifndef BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
0009 #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
0010 
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014 
0015 #include <boost/config.hpp>
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/spirit/home/support/make_component.hpp>
0018 #include <boost/spirit/home/support/modify.hpp>
0019 #include <boost/spirit/home/support/detail/make_cons.hpp>
0020 #include <boost/spirit/home/support/unused.hpp>
0021 #include <boost/spirit/home/support/assert_msg.hpp>
0022 #include <boost/core/enable_if.hpp>
0023 #include <boost/proto/matches.hpp>
0024 #include <boost/proto/tags.hpp>
0025 #include <boost/proto/traits.hpp>
0026 #include <boost/proto/proto_fwd.hpp> // for transform placeholders
0027 #include <boost/type_traits/remove_reference.hpp>
0028 
0029 namespace boost { namespace spirit
0030 {
0031     // Some defaults...
0032 
0033     template <typename Domain, typename Tag, typename Enable = void>
0034     struct use_operator : mpl::false_ {};
0035 
0036     template <typename Domain, typename T, typename Enable = void>
0037     struct use_function : mpl::false_ {};
0038 
0039     template <typename Domain, typename T, typename Enable = void>
0040     struct use_directive : mpl::false_ {};
0041 
0042     template <typename Domain, typename T, typename Enable /* = void */>
0043     struct is_modifier_directive : mpl::false_ {};
0044 
0045     template <typename Domain, typename T, typename Enable = void>
0046     struct use_terminal : mpl::false_ {};
0047 
0048     template <typename Domain, typename T, typename Enable /*= void*/>
0049     struct flatten_tree : mpl::false_ {};
0050 
0051     // Our meta-compiler. This is the main engine that hooks Spirit
0052     // to the proto expression template engine.
0053 
0054     template <typename Domain>
0055     struct meta_compiler
0056     {
0057         struct meta_grammar;
0058 
0059         BOOST_SPIRIT_ASSERT_MSG((
0060             !use_operator<Domain, proto::tag::subscript>::value
0061         ), error_proto_tag_subscript_cannot_be_used, ());
0062 
0063 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0064         // this is the non-broken part for compilers properly supporting 
0065         // partial template specialization (VC7.1 does not)
0066         struct cases
0067         {
0068             template <typename Tag, typename Enable = void>
0069             struct case_
0070               : proto::not_<proto::_>
0071             {};
0072 
0073             ///////////////////////////////////////////////////////////////////
0074             // terminals
0075             ///////////////////////////////////////////////////////////////////
0076             template <typename Enable>
0077             struct case_<proto::tag::terminal, Enable>
0078               : proto::when<
0079                     proto::if_<use_terminal<Domain, proto::_value>()>,
0080                     detail::make_terminal<Domain>
0081                 >
0082             {};
0083 
0084             template <typename Tag>
0085             struct case_<Tag, typename enable_if<use_operator<Domain, Tag> >::type>
0086               : proto::or_<
0087             ///////////////////////////////////////////////////////////////////
0088             // binary operators
0089             ///////////////////////////////////////////////////////////////////
0090                     proto::when<proto::binary_expr<Tag, meta_grammar, meta_grammar>,
0091                         detail::make_binary<Domain, Tag, meta_grammar>
0092                     >,
0093             ///////////////////////////////////////////////////////////////////
0094             // unary operators
0095             ///////////////////////////////////////////////////////////////////
0096                     proto::when<proto::unary_expr<Tag, meta_grammar>,
0097                         detail::make_unary<Domain, Tag, meta_grammar>
0098                     >
0099                 >
0100             {};
0101 
0102             template <typename Enable>
0103             struct case_<proto::tag::subscript, Enable>
0104               : proto::or_<
0105             ///////////////////////////////////////////////////////////////////
0106             // directives
0107             ///////////////////////////////////////////////////////////////////
0108                     proto::when<proto::binary_expr<proto::tag::subscript
0109                       , proto::and_<
0110                             proto::terminal<proto::_>
0111                           , proto::if_<use_directive<Domain, proto::_value >()> >
0112                       , meta_grammar>,
0113                         detail::make_directive<Domain, meta_grammar>
0114                     >,
0115             ///////////////////////////////////////////////////////////////////
0116             // semantic actions
0117             ///////////////////////////////////////////////////////////////////
0118                     proto::when<proto::binary_expr<proto::tag::subscript
0119                       , meta_grammar, proto::_>,
0120                         detail::make_action<Domain, meta_grammar>
0121                     >
0122                 >
0123             {};
0124         };
0125 #else
0126         // this part actually constitutes invalid C++ code, but it allows us to
0127         // convince VC7.1 to do what we want
0128         struct cases
0129         {
0130             template <typename Tag, typename Enable = void>
0131             struct case_
0132               : proto::not_<proto::_>
0133             {};
0134 
0135             ///////////////////////////////////////////////////////////////////
0136             // terminals
0137             ///////////////////////////////////////////////////////////////////
0138             template <>
0139             struct case_<proto::tag::terminal>
0140               : proto::when<
0141                     proto::if_<use_terminal<Domain, proto::_value>()>,
0142                     detail::make_terminal<Domain>
0143                 >
0144             {};
0145 
0146             template <typename Tag>
0147             struct case_<Tag>
0148               : proto::or_<
0149             ///////////////////////////////////////////////////////////////////
0150             // binary operators
0151             ///////////////////////////////////////////////////////////////////
0152                     proto::when<proto::binary_expr<
0153                         typename enable_if<use_operator<Domain, Tag>, Tag>::type
0154                           , meta_grammar, meta_grammar>
0155                       , detail::make_binary<Domain, Tag, meta_grammar>
0156                     >,
0157             ///////////////////////////////////////////////////////////////////
0158             // unary operators
0159             ///////////////////////////////////////////////////////////////////
0160                     proto::when<proto::unary_expr<
0161                         typename enable_if<use_operator<Domain, Tag>, Tag>::type
0162                           , meta_grammar>
0163                       , detail::make_unary<Domain, Tag, meta_grammar>
0164                     >
0165                 >
0166             {};
0167 
0168             template <>
0169             struct case_<proto::tag::subscript>
0170               : proto::or_<
0171             ///////////////////////////////////////////////////////////////////
0172             // directives
0173             ///////////////////////////////////////////////////////////////////
0174                     proto::when<proto::binary_expr<proto::tag::subscript
0175                       , proto::and_<
0176                             proto::terminal<proto::_>
0177                           , proto::if_<use_directive<Domain, proto::_value >()> >
0178                       , meta_grammar>,
0179                         detail::make_directive<Domain, meta_grammar>
0180                     >,
0181             ///////////////////////////////////////////////////////////////////
0182             // semantic actions
0183             ///////////////////////////////////////////////////////////////////
0184                     proto::when<proto::binary_expr<proto::tag::subscript
0185                       , meta_grammar, proto::_>,
0186                         detail::make_action<Domain, meta_grammar>
0187                     >
0188                 >
0189             {};
0190         };
0191 #endif
0192 
0193         struct meta_grammar
0194           : proto::switch_<cases>
0195         {};
0196     };
0197 
0198     namespace result_of
0199     {
0200         // Default case
0201         template <typename Domain, typename Expr
0202           , typename Modifiers = unused_type, typename Enable = void>
0203         struct compile
0204         {
0205             typedef typename meta_compiler<Domain>::meta_grammar meta_grammar;
0206             typedef typename meta_grammar::
0207                 template result<meta_grammar(Expr, mpl::void_, Modifiers)>::type
0208             type;
0209         };
0210 
0211         // If Expr is not a proto expression, make it a terminal
0212         template <typename Domain, typename Expr, typename Modifiers>
0213         struct compile<Domain, Expr, Modifiers,
0214             typename disable_if<proto::is_expr<Expr> >::type>
0215           : compile<Domain, typename proto::terminal<Expr>::type, Modifiers> {};
0216     }
0217 
0218     namespace traits
0219     {
0220         // Check if Expr matches the domain's grammar
0221         template <typename Domain, typename Expr>
0222         struct matches :
0223             proto::matches<
0224                 typename proto::result_of::as_expr<
0225                     typename remove_reference<Expr>::type>::type,
0226                 typename meta_compiler<Domain>::meta_grammar
0227             >
0228         {
0229         };
0230     }
0231 
0232     namespace detail
0233     {
0234         template <typename Domain>
0235         struct compiler
0236         {
0237             // Default case
0238             template <typename Expr, typename Modifiers>
0239             static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
0240             compile(Expr const& expr, Modifiers modifiers, mpl::true_)
0241             {
0242                 typename meta_compiler<Domain>::meta_grammar compiler;
0243                 return compiler(expr, mpl::void_(), modifiers);
0244             }
0245 
0246             // If Expr is not a proto expression, make it a terminal
0247             template <typename Expr, typename Modifiers>
0248             static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
0249             compile(Expr const& expr, Modifiers modifiers, mpl::false_)
0250             {
0251                 typename meta_compiler<Domain>::meta_grammar compiler;
0252                 typedef typename detail::as_meta_element<Expr>::type expr_;
0253                 typename proto::terminal<expr_>::type term = {expr};
0254                 return compiler(term, mpl::void_(), modifiers);
0255             }
0256         };
0257     }
0258 
0259     template <typename Domain, typename Expr>
0260     inline typename result_of::compile<Domain, Expr, unused_type>::type
0261     compile(Expr const& expr)
0262     {
0263         typedef typename proto::is_expr<Expr>::type is_expr;
0264         return detail::compiler<Domain>::compile(expr, unused, is_expr());
0265     }
0266 
0267     template <typename Domain, typename Expr, typename Modifiers>
0268     inline typename result_of::compile<Domain, Expr, Modifiers>::type
0269     compile(Expr const& expr, Modifiers modifiers)
0270     {
0271         typedef typename proto::is_expr<Expr>::type is_expr;
0272         return detail::compiler<Domain>::compile(expr, modifiers, is_expr());
0273     }
0274 
0275     ///////////////////////////////////////////////////////////////////////////
0276     template <typename Elements, template <typename Subject> class generator>
0277     struct make_unary_composite
0278     {
0279         typedef typename
0280             fusion::result_of::value_at_c<Elements, 0>::type
0281         element_type;
0282         typedef generator<element_type> result_type;
0283         result_type operator()(Elements const& elements, unused_type) const
0284         {
0285             return result_type(fusion::at_c<0>(elements));
0286         }
0287     };
0288 
0289     template <typename Elements, template <typename Left, typename Right> class generator>
0290     struct make_binary_composite
0291     {
0292         typedef typename
0293             fusion::result_of::value_at_c<Elements, 0>::type
0294         left_type;
0295         typedef typename
0296             fusion::result_of::value_at_c<Elements, 1>::type
0297         right_type;
0298         typedef generator<left_type, right_type> result_type;
0299 
0300         result_type operator()(Elements const& elements, unused_type) const
0301         {
0302             return result_type(
0303                 fusion::at_c<0>(elements)
0304               , fusion::at_c<1>(elements)
0305             );
0306         }
0307     };
0308 
0309     template <typename Elements, template <typename Elements_> class generator>
0310     struct make_nary_composite
0311     {
0312         typedef generator<Elements> result_type;
0313         result_type operator()(Elements const& elements, unused_type) const
0314         {
0315             return result_type(elements);
0316         }
0317     };
0318 
0319 }}
0320 
0321 #endif