/////////////////////////////////////////////////////////////////////////////// /// \file regex_actions.hpp /// Defines the syntax elements of xpressive's action expressions. // // Copyright 2007 Eric Niebler. 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_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007 #define BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007 // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // These are very often needed by client code. #include #include // Doxygen can't handle proto :-( #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED # include # include #endif /// INTERNAL ONLY /// #define UNREF(x) typename remove_reference::type /// INTERNAL ONLY /// #define UNCVREF(x) typename remove_cv::type>::type namespace boost { namespace xpressive { namespace detail { template struct action_arg { typedef T type; typedef typename add_reference::type reference; reference cast(void *pv) const { return *static_cast(pv); } }; template struct value_wrapper { value_wrapper() : value() {} value_wrapper(T const &t) : value(t) {} T value; }; struct check_tag {}; template struct BindArg : Grammar { template struct apply { typedef State type; }; template static State call(Expr const &expr, State const &state, Visitor &visitor) { visitor.let(expr); return state; } }; struct let_tag {}; struct BindArgs : boost::proto::transform::fold< boost::proto::function< boost::proto::transform::state > , boost::proto::vararg< BindArg< boost::proto::assign > > > > {}; struct let_domain : boost::proto::domain > {}; template struct let_ { BOOST_PROTO_EXTENDS(Expr, let_, let_domain) BOOST_PROTO_EXTENDS_FUNCTION(Expr, let_, let_domain) }; template void bind_args(let_ const &args, match_results &what) { BindArgs::call(args, 0, what); } } namespace op { struct push { typedef void result_type; template void operator()(Sequence &seq, Value const &val) const { seq.push(val); } }; struct push_back { typedef void result_type; template void operator()(Sequence &seq, Value const &val) const { seq.push_back(val); } }; struct push_front { typedef void result_type; template void operator()(Sequence &seq, Value const &val) const { seq.push_front(val); } }; struct pop { typedef void result_type; template void operator()(Sequence &seq) const { seq.pop(); } }; struct pop_back { typedef void result_type; template void operator()(Sequence &seq) const { seq.pop_back(); } }; struct pop_front { typedef void result_type; template void operator()(Sequence &seq) const { seq.pop_front(); } }; struct front { template struct result {}; template struct result { typedef UNREF(Sequence) sequence_type; typedef typename mpl::if_< is_const , typename sequence_type::const_reference , typename sequence_type::reference >::type type; }; template typename result::type operator()(Sequence &seq) const { return seq.front(); } }; struct back { template struct result {}; template struct result { typedef UNREF(Sequence) sequence_type; typedef typename mpl::if_< is_const , typename sequence_type::const_reference , typename sequence_type::reference >::type type; }; template typename result::type operator()(Sequence &seq) const { return seq.back(); } }; struct top { template struct result {}; template struct result { typedef UNREF(Sequence) sequence_type; typedef typename mpl::if_< is_const , typename sequence_type::value_type const & , typename sequence_type::value_type & >::type type; }; template typename result::type operator()(Sequence &seq) const { return seq.top(); } }; struct first { template struct result {}; template struct result { typedef UNREF(Pair)::first_type type; }; template typename Pair::first_type operator()(Pair const &p) const { return p.first; } }; struct second { template struct result {}; template struct result { typedef UNREF(Pair)::second_type type; }; template typename Pair::second_type operator()(Pair const &p) const { return p.second; } }; struct matched { typedef bool result_type; template bool operator()(Sub const &sub) const { return sub.matched; } }; struct length { template struct result {}; template struct result { typedef UNREF(Sub)::difference_type type; }; template typename Sub::difference_type operator()(Sub const &sub) const { return sub.length(); } }; struct str { template struct result {}; template struct result { typedef UNREF(Sub)::string_type type; }; template typename Sub::string_type operator()(Sub const &sub) const { return sub.str(); } }; // This codifies the return types of the various insert member // functions found in sequence containers, the 2 flavors of // associative containers, and strings. struct insert { template struct result {}; // assoc containers template struct result { typedef UNREF(Cont) cont_type; typedef UNREF(Value) value_type; static cont_type &scont_; static value_type &svalue_; typedef char yes_type; typedef char (&no_type)[2]; static yes_type check_insert_return(typename cont_type::iterator); static no_type check_insert_return(std::pair); BOOST_STATIC_CONSTANT(bool, is_iterator = (sizeof(yes_type) == sizeof(check_insert_return(scont_.insert(svalue_))))); typedef typename mpl::if_c< is_iterator , typename cont_type::iterator , std::pair >::type type; }; // sequence containers, assoc containers, strings template struct result, is_same > >::type> { typedef UNREF(Cont)::iterator type; }; // strings template struct result >::type> { typedef UNREF(Cont) &type; }; // assoc containers template struct result { typedef void type; }; // sequence containers, strings template struct result >::type> { typedef void type; }; // strings template struct result >::type> { typedef UNREF(Cont) &type; }; /// operator() /// template typename result::type operator()(Cont &cont, A0 const &a0) const { return cont.insert(a0); } /// \overload /// template typename result::type operator()(Cont &cont, A0 const &a0, A1 const &a1) const { return cont.insert(a0, a1); } /// \overload /// template typename result::type operator()(Cont &cont, A0 const &a0, A1 const &a1, A2 const &a2) const { return cont.insert(a0, a1, a2); } }; struct make_pair { template struct result {}; template struct result { typedef std::pair type; }; template std::pair operator()(First const &first, Second const &second) const { return std::make_pair(first, second); } }; template struct as { typedef T result_type; template T operator()(Value const &val) const { return lexical_cast(val); } }; template struct static_cast_ { typedef T result_type; template T operator()(Value const &val) const { return static_cast(val); } }; template struct dynamic_cast_ { typedef T result_type; template T operator()(Value const &val) const { return dynamic_cast(val); } }; template struct const_cast_ { typedef T result_type; template T operator()(Value const &val) const { return const_cast(val); } }; template struct construct { typedef T result_type; T operator()() const { return T(); } template T operator()(A0 const &a0) const { return T(a0); } template T operator()(A0 const &a0, A1 const &a1) const { return T(a0, a1); } template T operator()(A0 const &a0, A1 const &a1, A2 const &a2) const { return T(a0, a1, a2); } }; template struct throw_ { typedef void result_type; void operator()() const { boost::throw_exception(Except()); } template void operator()(A0 const &a0) const { boost::throw_exception(Except(a0)); } template void operator()(A0 const &a0, A1 const &a1) const { boost::throw_exception(Except(a0, a1)); } template void operator()(A0 const &a0, A1 const &a1, A2 const &a2) const { boost::throw_exception(Except(a0, a1, a2)); } }; } template struct function { typedef typename proto::terminal::type type; }; function::type const push = {{}}; function::type const push_back = {{}}; function::type const push_front = {{}}; function::type const pop = {{}}; function::type const pop_back = {{}}; function::type const pop_front = {{}}; function::type const top = {{}}; function::type const back = {{}}; function::type const front = {{}}; function::type const first = {{}}; function::type const second = {{}}; function::type const matched = {{}}; function::type const length = {{}}; function::type const str = {{}}; function::type const insert = {{}}; function::type const make_pair = {{}}; template struct value : proto::extends::type, value > { typedef proto::extends::type, value > base_type; value() : base_type() {} explicit value(T const &t) : base_type(base_type::proto_base_expr::make(t)) {} using base_type::operator =; T &get() { return proto::arg(*this); } T const &get() const { return proto::arg(*this); } }; template struct reference : proto::extends >::type, reference > { typedef proto::extends >::type, reference > base_type; explicit reference(T &t) : base_type(base_type::proto_base_expr::make(boost::ref(t))) {} using base_type::operator =; T &get() const { return proto::arg(*this).get(); } }; template struct local : private noncopyable , detail::value_wrapper , proto::terminal >::type { typedef typename proto::terminal >::type base_type; local() : noncopyable() , detail::value_wrapper() , base_type(base_type::make(boost::ref(detail::value_wrapper::value))) {} explicit local(T const &t) : noncopyable() , detail::value_wrapper(t) , base_type(base_type::make(boost::ref(detail::value_wrapper::value))) {} using base_type::operator =; T &get() { return proto::arg(*this); } T const &get() const { return proto::arg(*this); } }; /// as (a.k.a., lexical_cast) /// BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , as , boost::proto::default_domain , (boost::proto::tag::function) , ((op::as)(typename)) ) /// static_cast_ /// BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , static_cast_ , boost::proto::default_domain , (boost::proto::tag::function) , ((op::static_cast_)(typename)) ) /// dynamic_cast_ /// BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , dynamic_cast_ , boost::proto::default_domain , (boost::proto::tag::function) , ((op::dynamic_cast_)(typename)) ) /// const_cast_ /// BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , const_cast_ , boost::proto::default_domain , (boost::proto::tag::function) , ((op::const_cast_)(typename)) ) /// val() /// template value const val(T const &t) { return value(t); } /// ref() /// template reference const ref(T &t) { return reference(t); } /// cref() /// template reference const cref(T const &t) { return reference(t); } /// check(), for testing custom assertions /// proto::terminal::type const check = {{}}; /// let(), for binding references to non-local variables /// detail::let_::type> const let = {{{}}}; /// placeholder, for defining a placeholder to stand in fo /// a variable of type T in a semantic action. /// template struct placeholder { typedef placeholder this_type; typedef typename proto::terminal > >::type action_arg_type; BOOST_PROTO_EXTENDS(action_arg_type, this_type, proto::default_domain) BOOST_PROTO_EXTENDS_ASSIGN(action_arg_type, this_type, proto::default_domain) BOOST_PROTO_EXTENDS_SUBSCRIPT(action_arg_type, this_type, proto::default_domain) BOOST_PROTO_EXTENDS_FUNCTION(action_arg_type, this_type, proto::default_domain) }; /// Usage: construct\(arg1, arg2) /// BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( construct , boost::proto::default_domain , (boost::proto::tag::function) , ((op::construct)(typename)) ) /// Usage: throw_\(arg1, arg2) /// BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( throw_ , boost::proto::default_domain , (boost::proto::tag::function) , ((op::throw_)(typename)) ) namespace detail { inline void ignore_unused_regex_actions() { ignore_unused(xpressive::push); ignore_unused(xpressive::push_back); ignore_unused(xpressive::push_front); ignore_unused(xpressive::pop); ignore_unused(xpressive::pop_back); ignore_unused(xpressive::pop_front); ignore_unused(xpressive::top); ignore_unused(xpressive::back); ignore_unused(xpressive::front); ignore_unused(xpressive::first); ignore_unused(xpressive::second); ignore_unused(xpressive::matched); ignore_unused(xpressive::length); ignore_unused(xpressive::str); ignore_unused(xpressive::insert); ignore_unused(xpressive::make_pair); ignore_unused(xpressive::check); ignore_unused(xpressive::let); } } }} #undef UNREF #undef UNCVREF #endif // BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007