EVOLUTION-MANAGER
Edit File: meta_compiler.hpp
/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman 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) =============================================================================*/ #ifndef BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM #if defined(_MSC_VER) #pragma once #endif #include <boost/config.hpp> #include <boost/spirit/include/phoenix_limits.hpp> #include <boost/detail/workaround.hpp> #include <boost/spirit/include/phoenix_limits.hpp> // needs to be included before proto #include <boost/proto/proto.hpp> #include <boost/spirit/home/support/make_component.hpp> #include <boost/spirit/home/support/modify.hpp> #include <boost/spirit/home/support/detail/make_cons.hpp> #include <boost/spirit/home/support/unused.hpp> #include <boost/spirit/home/support/assert_msg.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/remove_reference.hpp> namespace boost { namespace spirit { // Some defaults... template <typename Domain, typename Tag, typename Enable = void> struct use_operator : mpl::false_ {}; template <typename Domain, typename T, typename Enable = void> struct use_function : mpl::false_ {}; template <typename Domain, typename T, typename Enable = void> struct use_directive : mpl::false_ {}; template <typename Domain, typename T, typename Enable /* = void */> struct is_modifier_directive : mpl::false_ {}; template <typename Domain, typename T, typename Enable = void> struct use_terminal : mpl::false_ {}; template <typename Domain, typename T, typename Enable /*= void*/> struct flatten_tree : mpl::false_ {}; // Our meta-compiler. This is the main engine that hooks Spirit // to the proto expression template engine. template <typename Domain> struct meta_compiler { struct meta_grammar; BOOST_SPIRIT_ASSERT_MSG(( !use_operator<Domain, proto::tag::subscript>::value ), error_proto_tag_subscript_cannot_be_used, ()); #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400) // this is the non-broken part for compilers properly supporting // partial template specialization (VC7.1 does not) struct cases { template <typename Tag, typename Enable = void> struct case_ : proto::not_<proto::_> {}; /////////////////////////////////////////////////////////////////// // terminals /////////////////////////////////////////////////////////////////// template <typename Enable> struct case_<proto::tag::terminal, Enable> : proto::when< proto::if_<use_terminal<Domain, proto::_value>()>, detail::make_terminal<Domain> > {}; template <typename Tag> struct case_<Tag, typename enable_if<use_operator<Domain, Tag> >::type> : proto::or_< /////////////////////////////////////////////////////////////////// // binary operators /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr<Tag, meta_grammar, meta_grammar>, detail::make_binary<Domain, Tag, meta_grammar> >, /////////////////////////////////////////////////////////////////// // unary operators /////////////////////////////////////////////////////////////////// proto::when<proto::unary_expr<Tag, meta_grammar>, detail::make_unary<Domain, Tag, meta_grammar> > > {}; template <typename Enable> struct case_<proto::tag::subscript, Enable> : proto::or_< /////////////////////////////////////////////////////////////////// // directives /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr<proto::tag::subscript , proto::and_< proto::terminal<proto::_> , proto::if_<use_directive<Domain, proto::_value >()> > , meta_grammar>, detail::make_directive<Domain, meta_grammar> >, /////////////////////////////////////////////////////////////////// // semantic actions /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr<proto::tag::subscript , meta_grammar, proto::_>, detail::make_action<Domain, meta_grammar> > > {}; }; #else // this part actually constitutes invalid C++ code, but it allows us to // convince VC7.1 to do what we want struct cases { template <typename Tag, typename Enable = void> struct case_ : proto::not_<proto::_> {}; /////////////////////////////////////////////////////////////////// // terminals /////////////////////////////////////////////////////////////////// template <> struct case_<proto::tag::terminal> : proto::when< proto::if_<use_terminal<Domain, proto::_value>()>, detail::make_terminal<Domain> > {}; template <typename Tag> struct case_<Tag> : proto::or_< /////////////////////////////////////////////////////////////////// // binary operators /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr< typename enable_if<use_operator<Domain, Tag>, Tag>::type , meta_grammar, meta_grammar> , detail::make_binary<Domain, Tag, meta_grammar> >, /////////////////////////////////////////////////////////////////// // unary operators /////////////////////////////////////////////////////////////////// proto::when<proto::unary_expr< typename enable_if<use_operator<Domain, Tag>, Tag>::type , meta_grammar> , detail::make_unary<Domain, Tag, meta_grammar> > > {}; template <> struct case_<proto::tag::subscript> : proto::or_< /////////////////////////////////////////////////////////////////// // directives /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr<proto::tag::subscript , proto::and_< proto::terminal<proto::_> , proto::if_<use_directive<Domain, proto::_value >()> > , meta_grammar>, detail::make_directive<Domain, meta_grammar> >, /////////////////////////////////////////////////////////////////// // semantic actions /////////////////////////////////////////////////////////////////// proto::when<proto::binary_expr<proto::tag::subscript , meta_grammar, proto::_>, detail::make_action<Domain, meta_grammar> > > {}; }; #endif struct meta_grammar : proto::switch_<cases> {}; }; namespace result_of { // Default case template <typename Domain, typename Expr , typename Modifiers = unused_type, typename Enable = void> struct compile { typedef typename meta_compiler<Domain>::meta_grammar meta_grammar; typedef typename meta_grammar:: template result<meta_grammar(Expr, mpl::void_, Modifiers)>::type type; }; // If Expr is not a proto expression, make it a terminal template <typename Domain, typename Expr, typename Modifiers> struct compile<Domain, Expr, Modifiers, typename disable_if<proto::is_expr<Expr> >::type> : compile<Domain, typename proto::terminal<Expr>::type, Modifiers> {}; } namespace traits { // Check if Expr matches the domain's grammar template <typename Domain, typename Expr> struct matches : proto::matches< typename proto::result_of::as_expr< typename remove_reference<Expr>::type>::type, typename meta_compiler<Domain>::meta_grammar > { }; } namespace detail { template <typename Domain> struct compiler { // Default case template <typename Expr, typename Modifiers> static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type compile(Expr const& expr, Modifiers modifiers, mpl::true_) { typename meta_compiler<Domain>::meta_grammar compiler; return compiler(expr, mpl::void_(), modifiers); } // If Expr is not a proto expression, make it a terminal template <typename Expr, typename Modifiers> static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type compile(Expr const& expr, Modifiers modifiers, mpl::false_) { typename meta_compiler<Domain>::meta_grammar compiler; typedef typename detail::as_meta_element<Expr>::type expr_; typename proto::terminal<expr_>::type term = {expr}; return compiler(term, mpl::void_(), modifiers); } }; } template <typename Domain, typename Expr> inline typename result_of::compile<Domain, Expr, unused_type>::type compile(Expr const& expr) { typedef typename proto::is_expr<Expr>::type is_expr; return detail::compiler<Domain>::compile(expr, unused, is_expr()); } template <typename Domain, typename Expr, typename Modifiers> inline typename result_of::compile<Domain, Expr, Modifiers>::type compile(Expr const& expr, Modifiers modifiers) { typedef typename proto::is_expr<Expr>::type is_expr; return detail::compiler<Domain>::compile(expr, modifiers, is_expr()); } /////////////////////////////////////////////////////////////////////////// template <typename Elements, template <typename Subject> class generator> struct make_unary_composite { typedef typename fusion::result_of::value_at_c<Elements, 0>::type element_type; typedef generator<element_type> result_type; result_type operator()(Elements const& elements, unused_type) const { return result_type(fusion::at_c<0>(elements)); } }; template <typename Elements, template <typename Left, typename Right> class generator> struct make_binary_composite { typedef typename fusion::result_of::value_at_c<Elements, 0>::type left_type; typedef typename fusion::result_of::value_at_c<Elements, 1>::type right_type; typedef generator<left_type, right_type> result_type; result_type operator()(Elements const& elements, unused_type) const { return result_type( fusion::at_c<0>(elements) , fusion::at_c<1>(elements) ); } }; template <typename Elements, template <typename Elements_> class generator> struct make_nary_composite { typedef generator<Elements> result_type; result_type operator()(Elements const& elements, unused_type) const { return result_type(elements); } }; }} #endif