/*============================================================================= 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 #include #include #include // needs to be included before proto #include #include #include #include #include #include #include #include namespace boost { namespace spirit { // Some defaults... template struct use_operator : mpl::false_ {}; template struct use_function : mpl::false_ {}; template struct use_directive : mpl::false_ {}; template struct is_modifier_directive : mpl::false_ {}; template struct use_terminal : mpl::false_ {}; template struct flatten_tree : mpl::false_ {}; // Our meta-compiler. This is the main engine that hooks Spirit // to the proto expression template engine. template struct meta_compiler { struct meta_grammar; BOOST_SPIRIT_ASSERT_MSG(( !use_operator::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 struct case_ : proto::not_ {}; /////////////////////////////////////////////////////////////////// // terminals /////////////////////////////////////////////////////////////////// template struct case_ : proto::when< proto::if_()>, detail::make_terminal > {}; template struct case_ >::type> : proto::or_< /////////////////////////////////////////////////////////////////// // binary operators /////////////////////////////////////////////////////////////////// proto::when, detail::make_binary >, /////////////////////////////////////////////////////////////////// // unary operators /////////////////////////////////////////////////////////////////// proto::when, detail::make_unary > > {}; template struct case_ : proto::or_< /////////////////////////////////////////////////////////////////// // directives /////////////////////////////////////////////////////////////////// proto::when , proto::if_()> > , meta_grammar>, detail::make_directive >, /////////////////////////////////////////////////////////////////// // semantic actions /////////////////////////////////////////////////////////////////// proto::when, detail::make_action > > {}; }; #else // this part actually constitutes invalid C++ code, but it allows us to // convince VC7.1 to do what we want struct cases { template struct case_ : proto::not_ {}; /////////////////////////////////////////////////////////////////// // terminals /////////////////////////////////////////////////////////////////// template <> struct case_ : proto::when< proto::if_()>, detail::make_terminal > {}; template struct case_ : proto::or_< /////////////////////////////////////////////////////////////////// // binary operators /////////////////////////////////////////////////////////////////// proto::when, Tag>::type , meta_grammar, meta_grammar> , detail::make_binary >, /////////////////////////////////////////////////////////////////// // unary operators /////////////////////////////////////////////////////////////////// proto::when, Tag>::type , meta_grammar> , detail::make_unary > > {}; template <> struct case_ : proto::or_< /////////////////////////////////////////////////////////////////// // directives /////////////////////////////////////////////////////////////////// proto::when , proto::if_()> > , meta_grammar>, detail::make_directive >, /////////////////////////////////////////////////////////////////// // semantic actions /////////////////////////////////////////////////////////////////// proto::when, detail::make_action > > {}; }; #endif struct meta_grammar : proto::switch_ {}; }; namespace result_of { // Default case template struct compile { typedef typename meta_compiler::meta_grammar meta_grammar; typedef typename meta_grammar:: template result::type type; }; // If Expr is not a proto expression, make it a terminal template struct compile >::type> : compile::type, Modifiers> {}; } namespace traits { // Check if Expr matches the domain's grammar template struct matches : proto::matches< typename proto::result_of::as_expr< typename remove_reference::type>::type, typename meta_compiler::meta_grammar > { }; } namespace detail { template struct compiler { // Default case template static typename spirit::result_of::compile::type compile(Expr const& expr, Modifiers modifiers, mpl::true_) { typename meta_compiler::meta_grammar compiler; return compiler(expr, mpl::void_(), modifiers); } // If Expr is not a proto expression, make it a terminal template static typename spirit::result_of::compile::type compile(Expr const& expr, Modifiers modifiers, mpl::false_) { typename meta_compiler::meta_grammar compiler; typedef typename detail::as_meta_element::type expr_; typename proto::terminal::type term = {expr}; return compiler(term, mpl::void_(), modifiers); } }; } template inline typename result_of::compile::type compile(Expr const& expr) { typedef typename proto::is_expr::type is_expr; return detail::compiler::compile(expr, unused, is_expr()); } template inline typename result_of::compile::type compile(Expr const& expr, Modifiers modifiers) { typedef typename proto::is_expr::type is_expr; return detail::compiler::compile(expr, modifiers, is_expr()); } /////////////////////////////////////////////////////////////////////////// template class generator> struct make_unary_composite { typedef typename fusion::result_of::value_at_c::type element_type; typedef generator result_type; result_type operator()(Elements const& elements, unused_type) const { return result_type(fusion::at_c<0>(elements)); } }; template class generator> struct make_binary_composite { typedef typename fusion::result_of::value_at_c::type left_type; typedef typename fusion::result_of::value_at_c::type right_type; typedef generator 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 class generator> struct make_nary_composite { typedef generator result_type; result_type operator()(Elements const& elements, unused_type) const { return result_type(elements); } }; }} #endif