blob: 1ace07f1edee9938abb618f63e7a1b3f30f14da3 [file] [log] [blame]
/*==============================================================================
Copyright (c) 2005-2007 Dan Marsden
Copyright (c) 2005-2010 Joel de Guzman
Copyright (c) 2010 Thomas Heller
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_PHOENIX_STATEMENT_TRY_CATCH_HPP
#define BOOST_PHOENIX_STATEMENT_TRY_CATCH_HPP
#include <boost/phoenix/core/limits.hpp>
#include <boost/phoenix/core/call.hpp>
#include <boost/phoenix/core/expression.hpp>
#include <boost/phoenix/core/meta_grammar.hpp>
#include <boost/phoenix/core/is_nullary.hpp>
#include <boost/proto/functional/fusion/pop_front.hpp>
namespace boost { namespace phoenix
{
template <typename Expr>
struct try_catch_actor;
template <typename Exception>
struct catch_exception
{
typedef Exception type;
};
namespace tag
{
struct try_catch {};
struct catch_ {};
struct catch_all {};
}
namespace expression
{
template <
typename Try
, BOOST_PHOENIX_typename_A_void(BOOST_PHOENIX_CATCH_LIMIT)
, typename Dummy = void
>
struct try_catch;
// bring in the expression definitions
#include <boost/phoenix/statement/detail/try_catch_expression.hpp>
template <typename A0, typename A1>
struct catch_
: proto::binary_expr<tag::catch_, A0, A1>
{};
template <typename A0>
struct catch_all
: proto::unary_expr<tag::catch_all, A0>
{};
}
namespace rule
{
struct catch_
: expression::catch_<
proto::terminal<catch_exception<proto::_> >
, meta_grammar
>
{};
struct catch_all
: expression::catch_all<
meta_grammar
>
{};
struct try_catch
: proto::or_<
expression::try_catch<
meta_grammar
, proto::vararg<rule::catch_>
>
, expression::try_catch<
meta_grammar
, rule::catch_all
>
, expression::try_catch<
meta_grammar
, proto::vararg<rule::catch_>
, rule::catch_all
>
>
{};
}
template <typename Dummy>
struct meta_grammar::case_<tag::try_catch, Dummy>
: enable_rule<rule::try_catch, Dummy>
{};
struct try_catch_eval
{
typedef void result_type;
// bring in the operator overloads
#include <boost/phoenix/statement/detail/try_catch_eval.hpp>
};
template <typename Dummy>
struct default_actions::when<rule::try_catch, Dummy>
: call<try_catch_eval, Dummy>
{};
namespace detail
{
struct try_catch_is_nullary
: proto::or_<
proto::when<
phoenix::rule::catch_all
, evaluator(proto::_child_c<0>, proto::_data, proto::make<int()>)
>
, proto::when<
phoenix::rule::catch_
, evaluator(proto::_child_c<1>, proto::_data, proto::make<int()>)
>
, proto::when<
phoenix::rule::try_catch
, mpl::and_<
evaluator(proto::_child_c<0>, proto::_data, proto::make<int()>)
, proto::fold<
proto::call<proto::functional::pop_front(proto::_)>
, proto::make<mpl::true_()>
, mpl::and_<
proto::_state
, proto::call<
try_catch_is_nullary(
proto::_
, proto::make<int()>
, proto::_data
)
>
>()
>
>()
>
>
{};
template <
typename TryCatch
, typename Exception
, typename Expr
, long Arity = proto::arity_of<TryCatch>::value
>
struct catch_push_back;
template <typename TryCatch, typename Exception, typename Expr>
struct catch_push_back<TryCatch, Exception, Expr, 1>
{
typedef
typename proto::result_of::make_expr<
phoenix::tag::catch_
, proto::basic_default_domain
, catch_exception<Exception>
, Expr
>::type
catch_expr;
typedef
phoenix::expression::try_catch<
TryCatch
, catch_expr
>
gen_type;
typedef typename gen_type::type type;
static type make(TryCatch const & try_catch, Expr const & catch_)
{
return
gen_type::make(
try_catch
, proto::make_expr<
phoenix::tag::catch_
, proto::basic_default_domain
>(catch_exception<Exception>(), catch_)
);
}
};
template <
typename TryCatch
, typename Expr
, long Arity = proto::arity_of<TryCatch>::value
>
struct catch_all_push_back;
template <typename TryCatch, typename Expr>
struct catch_all_push_back<TryCatch, Expr, 1>
{
typedef
typename proto::result_of::make_expr<
phoenix::tag::catch_all
, proto::basic_default_domain
, Expr
>::type
catch_expr;
typedef
phoenix::expression::try_catch<
TryCatch
, catch_expr
>
gen_type;
typedef typename gen_type::type type;
static type make(TryCatch const& try_catch, Expr const& catch_)
{
return
gen_type::make(
try_catch
, proto::make_expr<
phoenix::tag::catch_all
, proto::basic_default_domain
>(catch_)
);
}
};
#include <boost/phoenix/statement/detail/catch_push_back.hpp>
}
template <typename Dummy>
struct is_nullary::when<rule::try_catch, Dummy>
: proto::call<detail::try_catch_is_nullary(proto::_, int(), _context)>
{};
template <typename TryCatch, typename Exception>
struct catch_gen
{
catch_gen(TryCatch const& try_catch) : try_catch(try_catch) {}
template <typename Expr>
typename boost::disable_if<
proto::matches<
typename proto::result_of::child_c<
TryCatch
, proto::arity_of<TryCatch>::value - 1
>::type
, rule::catch_all
>
, typename detail::catch_push_back<TryCatch, Exception, Expr>::type
>::type
operator[](Expr const& expr) const
{
return
detail::catch_push_back<TryCatch, Exception, Expr>::make(
try_catch, expr
);
}
TryCatch const & try_catch;
};
template <typename TryCatch>
struct catch_all_gen
{
catch_all_gen(TryCatch const& try_catch) : try_catch(try_catch) {}
template <typename Expr>
typename boost::disable_if<
proto::matches<
typename proto::result_of::child_c<
TryCatch
, proto::arity_of<TryCatch>::value - 1
>::type
, rule::catch_all
>
, typename detail::catch_all_push_back<TryCatch, Expr>::type
>::type
operator[](Expr const& expr) const
{
return detail::catch_all_push_back<TryCatch, Expr>::make(
try_catch, expr
);
}
TryCatch const & try_catch;
};
template <
typename Expr
>
struct try_catch_actor;
template <typename Expr>
struct try_catch_actor
: actor<Expr>
{
typedef try_catch_actor<Expr> that_type;
typedef actor<Expr> base_type;
try_catch_actor(base_type const& expr)
: base_type(expr)
, catch_all(*this)
{
}
template <typename Exception>
catch_gen<that_type, Exception> const
catch_() const
{
return catch_gen<that_type, Exception>(*this);
}
catch_all_gen<that_type> const catch_all;
};
struct try_gen
{
template <typename Try>
typename expression::try_catch<Try>::type const
operator[](Try const & try_) const
{
return expression::try_catch<Try>::make(try_);
}
};
#ifndef BOOST_PHOENIX_NO_PREDEFINED_TERMINALS
try_gen const try_ = {};
#endif
}}
#endif