Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2011 Joel de Guzman Chris@16: http://spirit.sourceforge.net/ Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #ifndef BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM Chris@16: #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // needs to be included before proto Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: // Some defaults... Chris@16: Chris@16: template Chris@16: struct use_operator : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct use_function : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct use_directive : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct is_modifier_directive : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct use_terminal : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct flatten_tree : mpl::false_ {}; Chris@16: Chris@16: // Our meta-compiler. This is the main engine that hooks Spirit Chris@16: // to the proto expression template engine. Chris@16: Chris@16: template Chris@16: struct meta_compiler Chris@16: { Chris@16: struct meta_grammar; Chris@16: Chris@16: BOOST_SPIRIT_ASSERT_MSG(( Chris@16: !use_operator::value Chris@16: ), error_proto_tag_subscript_cannot_be_used, ()); Chris@16: Chris@16: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400) Chris@16: // this is the non-broken part for compilers properly supporting Chris@16: // partial template specialization (VC7.1 does not) Chris@16: struct cases Chris@16: { Chris@16: template Chris@16: struct case_ Chris@16: : proto::not_ Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // terminals Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct case_ Chris@16: : proto::when< Chris@16: proto::if_()>, Chris@16: detail::make_terminal Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct case_ >::type> Chris@16: : proto::or_< Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // binary operators Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Chris@16: detail::make_binary Chris@16: >, Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // unary operators Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Chris@16: detail::make_unary Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct case_ Chris@16: : proto::or_< Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // directives Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when Chris@16: , proto::if_()> > Chris@16: , meta_grammar>, Chris@16: detail::make_directive Chris@16: >, Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // semantic actions Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Chris@16: detail::make_action Chris@16: > Chris@16: > Chris@16: {}; Chris@16: }; Chris@16: #else Chris@16: // this part actually constitutes invalid C++ code, but it allows us to Chris@16: // convince VC7.1 to do what we want Chris@16: struct cases Chris@16: { Chris@16: template Chris@16: struct case_ Chris@16: : proto::not_ Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // terminals Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: template <> Chris@16: struct case_ Chris@16: : proto::when< Chris@16: proto::if_()>, Chris@16: detail::make_terminal Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct case_ Chris@16: : proto::or_< Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // binary operators Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Tag>::type Chris@16: , meta_grammar, meta_grammar> Chris@16: , detail::make_binary Chris@16: >, Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // unary operators Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Tag>::type Chris@16: , meta_grammar> Chris@16: , detail::make_unary Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: template <> Chris@16: struct case_ Chris@16: : proto::or_< Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // directives Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when Chris@16: , proto::if_()> > Chris@16: , meta_grammar>, Chris@16: detail::make_directive Chris@16: >, Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: // semantic actions Chris@16: /////////////////////////////////////////////////////////////////// Chris@16: proto::when, Chris@16: detail::make_action Chris@16: > Chris@16: > Chris@16: {}; Chris@16: }; Chris@16: #endif Chris@16: Chris@16: struct meta_grammar Chris@16: : proto::switch_ Chris@16: {}; Chris@16: }; Chris@16: Chris@16: namespace result_of Chris@16: { Chris@16: // Default case Chris@16: template Chris@16: struct compile Chris@16: { Chris@16: typedef typename meta_compiler::meta_grammar meta_grammar; Chris@16: typedef typename meta_grammar:: Chris@16: template result::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: // If Expr is not a proto expression, make it a terminal Chris@16: template Chris@16: struct compile >::type> Chris@16: : compile::type, Modifiers> {}; Chris@16: } Chris@16: Chris@16: namespace traits Chris@16: { Chris@16: // Check if Expr matches the domain's grammar Chris@16: template Chris@16: struct matches : Chris@16: proto::matches< Chris@16: typename proto::result_of::as_expr< Chris@16: typename remove_reference::type>::type, Chris@16: typename meta_compiler::meta_grammar Chris@16: > Chris@16: { Chris@16: }; Chris@16: } Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct compiler Chris@16: { Chris@16: // Default case Chris@16: template Chris@16: static typename spirit::result_of::compile::type Chris@16: compile(Expr const& expr, Modifiers modifiers, mpl::true_) Chris@16: { Chris@16: typename meta_compiler::meta_grammar compiler; Chris@16: return compiler(expr, mpl::void_(), modifiers); Chris@16: } Chris@16: Chris@16: // If Expr is not a proto expression, make it a terminal Chris@16: template Chris@16: static typename spirit::result_of::compile::type Chris@16: compile(Expr const& expr, Modifiers modifiers, mpl::false_) Chris@16: { Chris@16: typename meta_compiler::meta_grammar compiler; Chris@16: typedef typename detail::as_meta_element::type expr_; Chris@16: typename proto::terminal::type term = {expr}; Chris@16: return compiler(term, mpl::void_(), modifiers); Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename result_of::compile::type Chris@16: compile(Expr const& expr) Chris@16: { Chris@16: typedef typename proto::is_expr::type is_expr; Chris@16: return detail::compiler::compile(expr, unused, is_expr()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename result_of::compile::type Chris@16: compile(Expr const& expr, Modifiers modifiers) Chris@16: { Chris@16: typedef typename proto::is_expr::type is_expr; Chris@16: return detail::compiler::compile(expr, modifiers, is_expr()); Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template class generator> Chris@16: struct make_unary_composite Chris@16: { Chris@16: typedef typename Chris@16: fusion::result_of::value_at_c::type Chris@16: element_type; Chris@16: typedef generator result_type; Chris@16: result_type operator()(Elements const& elements, unused_type) const Chris@16: { Chris@16: return result_type(fusion::at_c<0>(elements)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template class generator> Chris@16: struct make_binary_composite Chris@16: { Chris@16: typedef typename Chris@16: fusion::result_of::value_at_c::type Chris@16: left_type; Chris@16: typedef typename Chris@16: fusion::result_of::value_at_c::type Chris@16: right_type; Chris@16: typedef generator result_type; Chris@16: Chris@16: result_type operator()(Elements const& elements, unused_type) const Chris@16: { Chris@16: return result_type( Chris@16: fusion::at_c<0>(elements) Chris@16: , fusion::at_c<1>(elements) Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template class generator> Chris@16: struct make_nary_composite Chris@16: { Chris@16: typedef generator result_type; Chris@16: result_type operator()(Elements const& elements, unused_type) const Chris@16: { Chris@16: return result_type(elements); Chris@16: } Chris@16: }; Chris@16: Chris@16: }} Chris@16: Chris@16: #endif