Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file matches.hpp Chris@16: /// Contains definition of matches\<\> metafunction for determining if Chris@16: /// a given expression matches a given pattern. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006 Chris@16: #define BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006 Chris@16: 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: #include 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: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) Chris@16: #include Chris@16: #endif 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@101: #if defined(_MSC_VER) Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable:4305) // 'specialization' : truncation from 'const int' to 'bool' Chris@16: #endif Chris@16: Chris@16: #define BOOST_PROTO_LOGICAL_typename_G BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, typename G) Chris@16: #define BOOST_PROTO_LOGICAL_G BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, G) Chris@16: Chris@16: namespace boost { namespace proto Chris@16: { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct matches_; Chris@16: Chris@16: template Chris@16: struct and_2; Chris@16: Chris@16: template Chris@16: struct _and_impl; Chris@16: Chris@16: template Chris@16: struct array_matches Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct array_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct array_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct array_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template::value) Chris@16: > Chris@16: struct lambda_matches Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct lambda_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct lambda_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct lambda_matches Chris@16: : array_matches Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct lambda_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct lambda_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template class T, typename Expr0, typename Grammar0> Chris@16: struct lambda_matches, T BOOST_PROTO_TEMPLATE_ARITY_PARAM(1) > Chris@16: : lambda_matches Chris@16: {}; Chris@16: Chris@16: // vararg_matches_impl Chris@16: template Chris@16: struct vararg_matches_impl; Chris@16: Chris@16: // vararg_matches Chris@16: template Chris@16: struct vararg_matches Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct vararg_matches Chris@16: : matches_< Chris@16: Expr Chris@16: , proto::basic_expr Chris@16: , proto::basic_expr Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct vararg_matches Chris@16: : and_2< Chris@16: matches_< Chris@16: Expr Chris@16: , proto::basic_expr Chris@16: , proto::basic_expr Chris@16: >::value Chris@16: , vararg_matches_impl Chris@16: > Chris@16: {}; Chris@16: Chris@16: // How terminal_matches<> handles references and cv-qualifiers. Chris@16: // The cv and ref matter *only* if the grammar has a top-level ref. Chris@16: // Chris@16: // Expr | Grammar | Matches? Chris@16: // ------------------------------------- Chris@16: // T T yes Chris@16: // T & T yes Chris@16: // T const & T yes Chris@16: // T T & no Chris@16: // T & T & yes Chris@16: // T const & T & no Chris@16: // T T const & no Chris@16: // T & T const & no Chris@16: // T const & T const & yes Chris@16: Chris@16: template Chris@16: struct is_cv_ref_compatible Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_cv_ref_compatible Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_cv_ref_compatible Chris@16: : mpl::bool_::value == is_const::value> Chris@16: {}; Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) Chris@16: // MSVC-7.1 has lots of problems with array types that have been Chris@16: // deduced. Partially specializing terminal_matches<> on array types Chris@16: // doesn't seem to work. Chris@16: template< Chris@16: typename T Chris@16: , typename U Chris@16: , bool B = is_array::value Chris@16: > Chris@16: struct terminal_array_matches Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_array_matches Chris@16: : is_convertible Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_array_matches Chris@16: : is_convertible Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_array_matches Chris@16: : is_convertible Chris@16: {}; Chris@16: Chris@16: // terminal_matches Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::or_< Chris@16: mpl::and_< Chris@16: is_cv_ref_compatible Chris@16: , lambda_matches< Chris@16: BOOST_PROTO_UNCVREF(T) Chris@16: , BOOST_PROTO_UNCVREF(U) Chris@16: > Chris@16: > Chris@16: , terminal_array_matches Chris@16: > Chris@16: {}; Chris@16: #else Chris@16: // terminal_matches Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::and_< Chris@16: is_cv_ref_compatible Chris@16: , lambda_matches< Chris@16: BOOST_PROTO_UNCVREF(T) Chris@16: , BOOST_PROTO_UNCVREF(U) Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: // Avoid ambiguity errors on MSVC Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct terminal_matches > Chris@16: : is_convertible Chris@16: {}; Chris@16: Chris@16: // matches_ Chris@16: template Chris@16: struct matches_ Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, BasicExpr, proto::_ > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : vararg_matches< Expr, Args1, Args2, typename Args2::back_, (N1+2 > N2), (N2 > N1) > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : vararg_matches< Expr, Args1, Args2, typename Args2::back_, (N1+2 > N2), (N2 > N1) > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : terminal_matches Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : terminal_matches Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : matches_< Chris@16: typename detail::expr_traits::value_type::proto_derived_expr Chris@16: , typename detail::expr_traits::value_type::proto_grammar Chris@16: , typename Args2::child0::proto_grammar Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_< Expr, proto::basic_expr, proto::basic_expr > Chris@16: : matches_< Chris@16: typename detail::expr_traits::value_type::proto_derived_expr Chris@16: , typename detail::expr_traits::value_type::proto_grammar Chris@16: , typename Args2::child0::proto_grammar Chris@16: > Chris@16: {}; Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // handle proto::if_ Chris@16: template Chris@16: struct matches_, proto::if_ > Chris@16: : mpl::eval_if_c< Chris@16: static_cast( Chris@16: remove_reference< Chris@16: typename when<_, If>::template impl::result_type Chris@16: >::type::value Chris@16: ) Chris@16: , matches_, typename Then::proto_grammar> Chris@16: , matches_, typename Else::proto_grammar> Chris@16: >::type Chris@16: { Chris@16: typedef Chris@16: typename mpl::if_c< Chris@16: static_cast( Chris@16: remove_reference< Chris@16: typename when<_, If>::template impl::result_type Chris@16: >::type::value Chris@16: ) Chris@16: , Then Chris@16: , Else Chris@16: >::type Chris@16: which; Chris@16: }; Chris@16: Chris@16: // handle degenerate cases of proto::or_ Chris@16: template Chris@16: struct matches_ > Chris@16: : mpl::false_ Chris@16: { Chris@16: typedef not_<_> which; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matches_ > Chris@16: : matches_ Chris@16: { Chris@16: typedef G0 which; Chris@16: }; Chris@16: Chris@16: // handle degenerate cases of proto::and_ Chris@16: template Chris@16: struct matches_ > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct matches_ > Chris@16: : matches_ Chris@16: {}; Chris@16: Chris@16: // handle proto::not_ Chris@16: template Chris@16: struct matches_ > Chris@16: : mpl::not_ > Chris@16: {}; Chris@16: Chris@16: // handle proto::switch_ Chris@16: template Chris@16: struct matches_, switch_ > Chris@16: : matches_< Chris@16: Expr Chris@16: , proto::basic_expr Chris@16: , typename Cases::template case_< Chris@16: typename when<_,Transform>::template impl::result_type Chris@16: >::proto_grammar Chris@16: > Chris@16: { Chris@16: typedef Chris@16: typename Cases::template case_< Chris@16: typename when<_, Transform>::template impl::result_type Chris@16: > Chris@16: which; Chris@16: }; Chris@16: Chris@16: // handle proto::switch_ with the default Transform for specially for better compile times Chris@16: template Chris@16: struct matches_, switch_ > Chris@16: : matches_< Chris@16: Expr Chris@16: , proto::basic_expr Chris@16: , typename Cases::template case_::proto_grammar Chris@16: > Chris@16: { Chris@16: typedef typename Cases::template case_ which; Chris@16: }; Chris@16: } Chris@16: Chris@16: /// \brief A Boolean metafunction that evaluates whether a given Chris@16: /// expression type matches a grammar. Chris@16: /// Chris@16: /// matches\ inherits (indirectly) from Chris@16: /// \c mpl::true_ if Expr::proto_grammar matches Chris@16: /// Grammar::proto_grammar, and from \c mpl::false_ Chris@16: /// otherwise. Chris@16: /// Chris@16: /// Non-terminal expressions are matched against a grammar Chris@16: /// according to the following rules: Chris@16: /// Chris@16: /// \li The wildcard pattern, \c _, matches any expression. Chris@16: /// \li An expression expr\ \> Chris@16: /// matches a grammar expr\ \> Chris@16: /// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx for Chris@16: /// each \c x in [0,n). Chris@16: /// \li An expression expr\ \> Chris@16: /// matches a grammar expr\ \> \> Chris@16: /// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx Chris@16: /// for each \c x in [0,n) and if \c Ux matches \c V Chris@16: /// for each \c x in [0,m). Chris@16: /// \li An expression \c E matches or_\ if \c E Chris@16: /// matches some \c Bx for \c x in [0,n). Chris@16: /// \li An expression \c E matches and_\ if \c E Chris@16: /// matches all \c Bx for \c x in [0,n). Chris@16: /// \li An expression \c E matches if_\ if Chris@16: /// boost::result_of\(E,int,int)\>::type::value Chris@16: /// is \c true and \c E matches \c U; or, if Chris@16: /// boost::result_of\(E,int,int)\>::type::value Chris@16: /// is \c false and \c E matches \c V. (Note: \c U defaults to \c _ Chris@16: /// and \c V defaults to \c not_\<_\>.) Chris@16: /// \li An expression \c E matches not_\ if \c E does Chris@16: /// not match \c T. Chris@16: /// \li An expression \c E matches switch_\ if Chris@16: /// \c E matches C::case_\::type\>. Chris@16: /// (Note: T defaults to tag_of\<_\>().) Chris@16: /// Chris@16: /// A terminal expression expr\ \> matches Chris@16: /// a grammar expr\ \> if \c BT is \c AT or Chris@16: /// \c proto::_ and if one of the following is true: Chris@16: /// Chris@16: /// \li \c B is the wildcard pattern, \c _ Chris@16: /// \li \c A is \c B Chris@16: /// \li \c A is B & Chris@16: /// \li \c A is B const & Chris@16: /// \li \c B is exact\ Chris@16: /// \li \c B is convertible_to\ and Chris@16: /// is_convertible\::value is \c true. Chris@16: /// \li \c A is X[M] or X(&)[M] and Chris@16: /// \c B is X[proto::N]. Chris@16: /// \li \c A is X(&)[M] and \c B is X(&)[proto::N]. Chris@16: /// \li \c A is X[M] or X(&)[M] and Chris@16: /// \c B is X*. Chris@16: /// \li \c B lambda-matches \c A (see below). Chris@16: /// Chris@16: /// A type \c B lambda-matches \c A if one of the following is true: Chris@16: /// Chris@16: /// \li \c B is \c A Chris@16: /// \li \c B is the wildcard pattern, \c _ Chris@16: /// \li \c B is T\ and \c A is Chris@16: /// T\ and for each \c x in Chris@16: /// [0,n), \c Ax and \c Bx are types Chris@16: /// such that \c Ax lambda-matches \c Bx Chris@16: template Chris@16: struct matches Chris@16: : detail::matches_< Chris@16: typename Expr::proto_derived_expr Chris@16: , typename Expr::proto_grammar Chris@16: , typename Grammar::proto_grammar Chris@16: > Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct matches Chris@16: : detail::matches_< Chris@16: typename Expr::proto_derived_expr Chris@16: , typename Expr::proto_grammar Chris@16: , typename Grammar::proto_grammar Chris@16: > Chris@16: {}; Chris@16: Chris@16: /// \brief A wildcard grammar element that matches any expression, Chris@16: /// and a transform that returns the current expression unchanged. Chris@16: /// Chris@16: /// The wildcard type, \c _, is a grammar element such that Chris@16: /// matches\::value is \c true for any expression Chris@16: /// type \c E. Chris@16: /// Chris@16: /// The wildcard can also be used as a stand-in for a template Chris@16: /// argument when matching terminals. For instance, the following Chris@16: /// is a grammar that will match any std::complex\<\> Chris@16: /// terminal: Chris@16: /// Chris@16: /// \code Chris@16: /// BOOST_MPL_ASSERT(( Chris@16: /// matches< Chris@16: /// terminal >::type Chris@16: /// , terminal > Chris@16: /// > Chris@16: /// )); Chris@16: /// \endcode Chris@16: /// Chris@16: /// When used as a transform, \c _ returns the current expression Chris@16: /// unchanged. For instance, in the following, \c _ is used with Chris@16: /// the \c fold\<\> transform to fold the children of a node: Chris@16: /// Chris@16: /// \code Chris@16: /// struct CountChildren Chris@16: /// : or_< Chris@16: /// // Terminals have no children Chris@16: /// when, mpl::int_<0>()> Chris@16: /// // Use fold<> to count the children of non-terminals Chris@16: /// , otherwise< Chris@16: /// fold< Chris@16: /// _ // <-- fold the current expression Chris@16: /// , mpl::int_<0>() Chris@16: /// , mpl::plus<_state, mpl::int_<1> >() Chris@16: /// > Chris@16: /// > Chris@16: /// > Chris@16: /// {}; Chris@16: /// \endcode Chris@16: struct _ : transform<_> Chris@16: { Chris@16: typedef _ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl : transform_impl Chris@16: { Chris@16: typedef Expr result_type; Chris@16: Chris@16: /// \param expr An expression Chris@16: /// \return \c e Chris@16: BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) Chris@16: operator()( Chris@16: typename impl::expr_param e Chris@16: , typename impl::state_param Chris@16: , typename impl::data_param Chris@16: ) const Chris@16: { Chris@16: return e; Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct _and_impl, Expr, State, Data> Chris@16: : proto::_::impl Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct _and_impl, Expr, State, Data> Chris@16: : proto::when::template impl Chris@16: {}; Chris@16: } Chris@16: Chris@16: /// \brief Inverts the set of expressions matched by a grammar. When Chris@16: /// used as a transform, \c not_\<\> returns the current expression Chris@16: /// unchanged. Chris@16: /// Chris@16: /// If an expression type \c E does not match a grammar \c G, then Chris@16: /// \c E \e does match not_\. For example, Chris@16: /// not_\ \> will match any non-terminal. Chris@16: template Chris@16: struct not_ : transform > Chris@16: { Chris@16: typedef not_ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl : transform_impl Chris@16: { Chris@16: typedef Expr result_type; Chris@16: Chris@16: /// \param e An expression Chris@16: /// \pre matches\::value is \c true. Chris@16: /// \return \c e Chris@16: BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) Chris@16: operator()( Chris@16: typename impl::expr_param e Chris@16: , typename impl::state_param Chris@16: , typename impl::data_param Chris@16: ) const Chris@16: { Chris@16: return e; Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: /// \brief Used to select one grammar or another based on the result Chris@16: /// of a compile-time Boolean. When used as a transform, \c if_\<\> Chris@16: /// selects between two transforms based on a compile-time Boolean. Chris@16: /// Chris@16: /// When if_\ is used as a grammar, \c If Chris@16: /// must be a Proto transform and \c Then and \c Else must be grammars. Chris@16: /// An expression type \c E matches if_\ if Chris@16: /// boost::result_of\(E,int,int)\>::type::value Chris@16: /// is \c true and \c E matches \c U; or, if Chris@16: /// boost::result_of\(E,int,int)\>::type::value Chris@16: /// is \c false and \c E matches \c V. Chris@16: /// Chris@16: /// The template parameter \c Then defaults to \c _ Chris@16: /// and \c Else defaults to \c not\<_\>, so an expression type \c E Chris@16: /// will match if_\ if and only if Chris@16: /// boost::result_of\(E,int,int)\>::type::value Chris@16: /// is \c true. Chris@16: /// Chris@16: /// \code Chris@16: /// // A grammar that only matches integral terminals, Chris@16: /// // using is_integral<> from Boost.Type_traits. Chris@16: /// struct IsIntegral Chris@16: /// : and_< Chris@16: /// terminal<_> Chris@16: /// , if_< is_integral<_value>() > Chris@16: /// > Chris@16: /// {}; Chris@16: /// \endcode Chris@16: /// Chris@16: /// When if_\ is used as a transform, \c If, Chris@16: /// \c Then and \c Else must be Proto transforms. When applying Chris@16: /// the transform to an expression \c E, state \c S and data \c V, Chris@16: /// if boost::result_of\(E,S,V)\>::type::value Chris@16: /// is \c true then the \c Then transform is applied; otherwise Chris@16: /// the \c Else transform is applied. Chris@16: /// Chris@16: /// \code Chris@16: /// // Match a terminal. If the terminal is integral, return Chris@16: /// // mpl::true_; otherwise, return mpl::false_. Chris@16: /// struct IsIntegral2 Chris@16: /// : when< Chris@16: /// terminal<_> Chris@16: /// , if_< Chris@16: /// is_integral<_value>() Chris@16: /// , mpl::true_() Chris@16: /// , mpl::false_() Chris@16: /// > Chris@16: /// > Chris@16: /// {}; Chris@16: /// \endcode Chris@16: template< Chris@16: typename If Chris@16: , typename Then // = _ Chris@16: , typename Else // = not_<_> Chris@16: > Chris@16: struct if_ : transform > Chris@16: { Chris@16: typedef if_ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl : transform_impl Chris@16: { Chris@16: typedef Chris@16: typename when<_, If>::template impl::result_type Chris@16: condition; Chris@16: Chris@16: typedef Chris@16: typename mpl::if_c< Chris@16: static_cast(remove_reference::type::value) Chris@16: , when<_, Then> Chris@16: , when<_, Else> Chris@16: >::type Chris@16: which; Chris@16: Chris@16: typedef typename which::template impl::result_type result_type; Chris@16: Chris@16: /// \param e An expression Chris@16: /// \param s The current state Chris@16: /// \param d A data of arbitrary type Chris@16: /// \return which::impl()(e, s, d) Chris@16: result_type operator ()( Chris@16: typename impl::expr_param e Chris@16: , typename impl::state_param s Chris@16: , typename impl::data_param d Chris@16: ) const Chris@16: { Chris@16: return typename which::template impl()(e, s, d); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: /// \brief For matching one of a set of alternate grammars. Alternates Chris@16: /// tried in order to avoid ambiguity. When used as a transform, \c or_\<\> Chris@16: /// applies the transform associated with the first grammar that matches Chris@16: /// the expression. Chris@16: /// Chris@16: /// An expression type \c E matches or_\ if \c E Chris@16: /// matches any \c Bx for \c x in [0,n). Chris@16: /// Chris@16: /// When applying or_\ as a transform with an Chris@16: /// expression \c e of type \c E, state \c s and data \c d, it is Chris@16: /// equivalent to Bx()(e, s, d), where \c x is the lowest Chris@16: /// number such that matches\::value is \c true. Chris@16: template Chris@16: struct or_ : transform > Chris@16: { Chris@16: typedef or_ proto_grammar; Chris@16: Chris@16: /// \param e An expression Chris@16: /// \param s The current state Chris@16: /// \param d A data of arbitrary type Chris@16: /// \pre matches\::value is \c true. Chris@16: /// \return which()(e, s, d), where which is the Chris@16: /// sub-grammar that matched Expr. Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::matches_< Chris@16: typename Expr::proto_derived_expr Chris@16: , typename Expr::proto_grammar Chris@16: , or_ Chris@16: >::which::template impl Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::matches_< Chris@16: typename Expr::proto_derived_expr Chris@16: , typename Expr::proto_grammar Chris@16: , or_ Chris@16: >::which::template impl Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /// \brief For matching all of a set of grammars. When used as a Chris@16: /// transform, \c and_\<\> applies the transforms associated with Chris@16: /// the each grammar in the set, and returns the result of the last. Chris@16: /// Chris@16: /// An expression type \c E matches and_\ if \c E Chris@16: /// matches all \c Bx for \c x in [0,n). Chris@16: /// Chris@16: /// When applying and_\ as a transform with an Chris@16: /// expression \c e, state \c s and data \c d, it is Chris@16: /// equivalent to (B0()(e, s, d),B1()(e, s, d),...Bn()(e, s, d)). Chris@16: template Chris@16: struct and_ : transform > Chris@16: { Chris@16: typedef and_ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::_and_impl Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /// \brief For matching one of a set of alternate grammars, which Chris@16: /// are looked up based on some property of an expression. The Chris@16: /// property on which to dispatch is specified by the \c Transform Chris@16: /// template parameter, which defaults to tag_of\<_\>(). Chris@16: /// That is, when the \c Trannsform is not specified, the alternate Chris@16: /// grammar is looked up using the tag type of the current expression. Chris@16: /// Chris@16: /// When used as a transform, \c switch_\<\> applies the transform Chris@16: /// associated with the grammar that matches the expression. Chris@16: /// Chris@16: /// \note \c switch_\<\> is functionally identical to \c or_\<\> but Chris@16: /// is often more efficient. It does a fast, O(1) lookup using the Chris@16: /// result of the specified transform to find a sub-grammar that may Chris@16: /// potentially match the expression. Chris@16: /// Chris@16: /// An expression type \c E matches switch_\ if \c E Chris@16: /// matches C::case_\::type\>. Chris@16: /// Chris@16: /// When applying switch_\ as a transform with an Chris@16: /// expression \c e of type \c E, state \c s of type \S and data Chris@16: /// \c d of type \c D, it is equivalent to Chris@16: /// C::case_\::type\>()(e, s, d). Chris@16: template Chris@16: struct switch_ : transform > Chris@16: { Chris@16: typedef switch_ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : Cases::template case_< Chris@16: typename when<_, Transform>::template impl::result_type Chris@16: >::template impl Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY (This is merely a compile-time optimization for the common case) Chris@16: /// Chris@16: template Chris@16: struct switch_ : transform > Chris@16: { Chris@16: typedef switch_ proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : Cases::template case_::template impl Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : Cases::template case_::template impl Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /// \brief For forcing exact matches of terminal types. Chris@16: /// Chris@16: /// By default, matching terminals ignores references and Chris@16: /// cv-qualifiers. For instance, a terminal expression of Chris@16: /// type terminal\::type will match Chris@16: /// the grammar terminal\. If that is not Chris@16: /// desired, you can force an exact match with Chris@16: /// terminal\ \>. This will only Chris@16: /// match integer terminals where the terminal is held by Chris@16: /// value. Chris@16: template Chris@16: struct exact Chris@16: {}; Chris@16: Chris@16: /// \brief For matching terminals that are convertible to Chris@16: /// a type. Chris@16: /// Chris@16: /// Use \c convertible_to\<\> to match a terminal that is Chris@16: /// convertible to some type. For example, the grammar Chris@16: /// terminal\ \> will match Chris@16: /// any terminal whose argument is convertible to an integer. Chris@16: /// Chris@16: /// \note The trait \c is_convertible\<\> from Boost.Type_traits Chris@16: /// is used to determinal convertibility. Chris@16: template Chris@16: struct convertible_to Chris@16: {}; Chris@16: Chris@16: /// \brief For matching a Grammar to a variable number of Chris@16: /// sub-expressions. Chris@16: /// Chris@16: /// An expression type expr\ \> Chris@16: /// matches a grammar expr\ \> \> Chris@16: /// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx Chris@16: /// for each \c x in [0,n) and if \c Ux matches \c V Chris@16: /// for each \c x in [0,m). Chris@16: /// Chris@16: /// For example: Chris@16: /// Chris@16: /// \code Chris@16: /// // Match any function call expression, irregardless Chris@16: /// // of the number of function arguments: Chris@16: /// struct Function Chris@16: /// : function< vararg<_> > Chris@16: /// {}; Chris@16: /// \endcode Chris@16: /// Chris@16: /// When used as a transform, vararg\ applies Chris@16: /// G's transform. Chris@16: template Chris@16: struct vararg Chris@16: : Grammar Chris@16: { Chris@16: /// INTERNAL ONLY Chris@16: typedef void proto_is_vararg_; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: }} Chris@16: Chris@16: #undef BOOST_PROTO_LOGICAL_typename_G Chris@16: #undef BOOST_PROTO_LOGICAL_G Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif