diff options
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/support/terminal.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/support/terminal.hpp | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/support/terminal.hpp b/3rdParty/Boost/src/boost/spirit/home/support/terminal.hpp new file mode 100644 index 0000000..0926772 --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/support/terminal.hpp @@ -0,0 +1,535 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + + 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) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM) +#define BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/proto/proto.hpp> +#include <boost/fusion/include/void.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_function.hpp> +#include <boost/spirit/home/support/meta_compiler.hpp> +#include <boost/spirit/home/support/detail/make_vector.hpp> +#include <boost/spirit/home/support/unused.hpp> + +namespace boost { namespace spirit +{ + template <typename Terminal, typename Args> + struct terminal_ex + { + typedef Terminal terminal_type; + typedef Args args_type; + + terminal_ex(Args const& args) + : args(args) {} + terminal_ex(Args const& args, Terminal const& term) + : args(args), term(term) {} + + Args args; // Args is guaranteed to be a fusion::vectorN so you + // can use that template for detection and specialization + Terminal term; + }; + + template <typename Terminal, typename Actor, int Arity> + struct lazy_terminal + { + typedef Terminal terminal_type; + typedef Actor actor_type; + static int const arity = Arity; + + lazy_terminal(Actor const& actor) + : actor(actor) {} + lazy_terminal(Actor const& actor, Terminal const& term) + : actor(actor), term(term) {} + + Actor actor; + Terminal term; + }; + + template <typename Domain, typename Terminal, int Arity, typename Enable = void> + struct use_lazy_terminal : mpl::false_ {}; + + template <typename Domain, typename Terminal, int Arity, typename Enable = void> + struct use_lazy_directive : mpl::false_ {}; + + template <typename Domain, typename Terminal, int Arity, typename Actor> + struct use_terminal<Domain, lazy_terminal<Terminal, Actor, Arity> > + : use_lazy_terminal<Domain, Terminal, Arity> {}; + + template <typename Domain, typename Terminal, int Arity, typename Actor> + struct use_directive<Domain, lazy_terminal<Terminal, Actor, Arity> > + : use_lazy_directive<Domain, Terminal, Arity> {}; + + template < + typename F + , typename A0 = unused_type + , typename A1 = unused_type + , typename A2 = unused_type + , typename Unused = unused_type + > + struct make_lazy; + + template <typename F, typename A0> + struct make_lazy<F, A0> + { + typedef typename + proto::terminal< + lazy_terminal< + typename F::terminal_type + , phoenix::actor< + typename phoenix::as_composite< + phoenix::detail::function_eval<1>, F, A0 + >::type + > + , 1 // arity + > + >::type + result_type; + typedef result_type type; + + result_type + operator()(F f, A0 const& _0) const + { + typedef typename result_type::proto_child0 child_type; + return result_type::make(child_type( + phoenix::compose<phoenix::detail::function_eval<1> >(f, _0) + , f.proto_base().child0 + )); + } + }; + + template <typename F, typename A0, typename A1> + struct make_lazy<F, A0, A1> + { + typedef typename + proto::terminal< + lazy_terminal< + typename F::terminal_type + , phoenix::actor< + typename phoenix::as_composite< + phoenix::detail::function_eval<2>, F, A0, A1 + >::type + > + , 2 // arity + > + >::type + result_type; + typedef result_type type; + + result_type + operator()(F f, A0 const& _0, A1 const& _1) const + { + typedef typename result_type::proto_child0 child_type; + return result_type::make(child_type( + phoenix::compose<phoenix::detail::function_eval<2> >(f, _0, _1) + , f.proto_base().child0 + )); + } + }; + + template <typename F, typename A0, typename A1, typename A2> + struct make_lazy<F, A0, A1, A2> + { + typedef typename + proto::terminal< + lazy_terminal< + typename F::terminal_type + , phoenix::actor< + typename phoenix::as_composite< + phoenix::detail::function_eval<3>, F, A0, A1, A2 + >::type + > + , 3 // arity + > + >::type + result_type; + typedef result_type type; + + result_type + operator()(F f, A0 const& _0, A1 const& _1, A2 const& _2) const + { + typedef typename result_type::proto_child0 child_type; + return result_type::make(child_type( + phoenix::compose<phoenix::detail::function_eval<3> >(f, _0, _1, _2) + , f.proto_base().child0 + )); + } + }; + + namespace detail + { + // Helper struct for SFINAE purposes + template <bool C> + struct bool_; + template <> + struct bool_<true> : mpl::bool_<true> + { typedef bool_<true>* is_true; }; + template <> + struct bool_<false> : mpl::bool_<false> + { typedef bool_<false>* is_false; }; + + // Metafunction to detect if at least one arg is a Phoenix actor + template < + typename A0 + , typename A1 = unused_type + , typename A2 = unused_type + > + struct contains_actor + : bool_< + phoenix::is_actor<A0>::value + || phoenix::is_actor<A1>::value + || phoenix::is_actor<A2>::value + > + {}; + + // to_lazy_arg: convert a terminal arg type to the type make_lazy needs + template <typename A> + struct to_lazy_arg + : phoenix::as_actor<A> // wrap A in a Phoenix actor if not already one + {}; + + template <typename A> + struct to_lazy_arg<const A> + : to_lazy_arg<A> + {}; + + template <> + struct to_lazy_arg<unused_type> + { + // unused arg: make_lazy wants unused_type + typedef unused_type type; + }; + + // to_nonlazy_arg: convert a terminal arg type to the type make_vector needs + template <typename A> + struct to_nonlazy_arg + { + // identity + typedef A type; + }; + + template <typename A> + struct to_nonlazy_arg<const A> + : to_nonlazy_arg<A> + {}; + + template <> + struct to_nonlazy_arg<unused_type> + { + // unused arg: make_vector wants fusion::void_ + typedef fusion::void_ type; + }; + } + + template <typename Terminal> + struct terminal + : proto::extends< + typename proto::terminal<Terminal>::type + , terminal<Terminal> + > + { + typedef terminal<Terminal> this_type; + typedef Terminal terminal_type; + + typedef proto::extends< + typename proto::terminal<Terminal>::type + , terminal<Terminal> + > base_type; + + terminal() {} + + terminal(Terminal const& t) + : base_type(proto::terminal<Terminal>::type::make(t)) {} + + template < + bool Lazy + , typename A0 + , typename A1 + , typename A2 + > + struct result_helper; + + template < + typename A0 + , typename A1 + , typename A2 + > + struct result_helper<false, A0, A1, A2> + { + typedef typename + proto::terminal< + terminal_ex< + Terminal + , typename detail::result_of::make_vector< + typename detail::to_nonlazy_arg<A0>::type + , typename detail::to_nonlazy_arg<A1>::type + , typename detail::to_nonlazy_arg<A2>::type>::type> + >::type + type; + }; + + template < + typename A0 + , typename A1 + , typename A2 + > + struct result_helper<true, A0, A1, A2> + { + typedef typename + make_lazy<this_type + , typename detail::to_lazy_arg<A0>::type + , typename detail::to_lazy_arg<A1>::type + , typename detail::to_lazy_arg<A2>::type>::type + type; + }; + + // FIXME: we need to change this to conform to the result_of protocol + template < + typename A0 + , typename A1 = unused_type + , typename A2 = unused_type // Support up to 3 args + > + struct result + { + typedef typename + result_helper< + detail::contains_actor<A0, A1, A2>::value + , A0, A1, A2 + >::type + type; + }; + + // Note: in the following overloads, SFINAE cannot + // be done on return type because of gcc bug #24915: + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915 + // Hence an additional, fake argument is used for SFINAE, + // using a type which can never be a real argument type. + + // Non-lazy overloads. Only enabled when all + // args are immediates (no Phoenix actor). + + template <typename A0> + typename result<A0>::type + operator()(A0 const& _0 + , typename detail::contains_actor<A0>::is_false = 0) const + { + typedef typename result<A0>::type result_type; + typedef typename result_type::proto_child0 child_type; + return result_type::make( + child_type( + detail::make_vector(_0) + , this->proto_base().child0) + ); + } + + template <typename A0, typename A1> + typename result<A0, A1>::type + operator()(A0 const& _0, A1 const& _1 + , typename detail::contains_actor<A0, A1>::is_false = 0) const + { + typedef typename result<A0, A1>::type result_type; + typedef typename result_type::proto_child0 child_type; + return result_type::make( + child_type( + detail::make_vector(_0, _1) + , this->proto_base().child0) + ); + } + + template <typename A0, typename A1, typename A2> + typename result<A0, A1, A2>::type + operator()(A0 const& _0, A1 const& _1, A2 const& _2 + , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const + { + typedef typename result<A0, A1, A2>::type result_type; + typedef typename result_type::proto_child0 child_type; + return result_type::make( + child_type( + detail::make_vector(_0, _1, _2) + , this->proto_base().child0) + ); + } + + // Lazy overloads. Enabled when at + // least one arg is a Phoenix actor. + + template <typename A0> + typename result<A0>::type + operator()(A0 const& _0 + , typename detail::contains_actor<A0>::is_true = 0) const + { + return make_lazy<this_type + , typename phoenix::as_actor<A0>::type>()(*this + , phoenix::as_actor<A0>::convert(_0)); + } + + template <typename A0, typename A1> + typename result<A0, A1>::type + operator()(A0 const& _0, A1 const& _1 + , typename detail::contains_actor<A0, A1>::is_true = 0) const + { + return make_lazy<this_type + , typename phoenix::as_actor<A0>::type + , typename phoenix::as_actor<A1>::type>()(*this + , phoenix::as_actor<A0>::convert(_0) + , phoenix::as_actor<A1>::convert(_1)); + } + + template <typename A0, typename A1, typename A2> + typename result<A0, A1, A2>::type + operator()(A0 const& _0, A1 const& _1, A2 const& _2 + , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const + { + return make_lazy<this_type + , typename phoenix::as_actor<A0>::type + , typename phoenix::as_actor<A1>::type + , typename phoenix::as_actor<A2>::type>()(*this + , phoenix::as_actor<A0>::convert(_0) + , phoenix::as_actor<A1>::convert(_1) + , phoenix::as_actor<A2>::convert(_2)); + } + + private: + // silence MSVC warning C4512: assignment operator could not be generated + terminal& operator= (terminal const&); + }; + + /////////////////////////////////////////////////////////////////////////// + namespace result_of + { + // Calculate the type of the compound terminal if generated by one of + // the spirit::terminal::operator() overloads above + + // The terminal type itself is passed through without modification + template <typename Tag> + struct terminal + { + typedef spirit::terminal<Tag> type; + }; + + template <typename Tag, typename A0> + struct terminal<Tag(A0)> + { + typedef typename spirit::terminal<Tag>:: + template result<A0>::type type; + }; + + template <typename Tag, typename A0, typename A1> + struct terminal<Tag(A0, A1)> + { + typedef typename spirit::terminal<Tag>:: + template result<A0, A1>::type type; + }; + + template <typename Tag, typename A0, typename A1, typename A2> + struct terminal<Tag(A0, A1, A2)> + { + typedef typename spirit::terminal<Tag>:: + template result<A0, A1, A2>::type type; + }; + } + + /////////////////////////////////////////////////////////////////////////// + // support for stateful tag types + namespace tag + { + template <typename Data, typename Tag + , typename DataTag1 = unused_type, typename DataTag2 = unused_type> + struct stateful_tag + { + typedef Data data_type; + + stateful_tag() {} + stateful_tag(data_type const& data) : data_(data) {} + + data_type data_; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + stateful_tag& operator= (stateful_tag const&); + }; + } + + template <typename Data, typename Tag + , typename DataTag1 = unused_type, typename DataTag2 = unused_type> + struct stateful_tag_type + : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> > + { + typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type; + + stateful_tag_type() {} + stateful_tag_type(Data const& data) + : spirit::terminal<tag_type>(data) {} + + private: + // silence MSVC warning C4512: assignment operator could not be generated + stateful_tag_type& operator= (stateful_tag_type const&); + }; + + namespace detail + { + // extract expression if this is a Tag + template <typename StatefulTag> + struct get_stateful_data + { + typedef typename StatefulTag::data_type data_type; + + // is invoked if given tag is != Tag + template <typename Tag_> + static data_type call(Tag_) { return data_type(); } + + // this is invoked if given tag is same as'Tag' + static data_type const& call(StatefulTag const& t) { return t.data_; } + }; + } + +}} + +// Define a spirit terminal. This macro may be placed in any namespace. +// Common placeholders are placed in the main boost::spirit namespace +// (see common_terminals.hpp) + +#define BOOST_SPIRIT_TERMINAL(name) \ + namespace tag { struct name {}; } \ + typedef boost::proto::terminal<tag::name>::type name##_type; \ + name##_type const name = {{}}; \ + inline void silence_unused_warnings__##name() { (void) name; } \ + /***/ + +#define BOOST_SPIRIT_DEFINE_TERMINALS_A(r, _, name) \ + BOOST_SPIRIT_TERMINAL(name) \ + /***/ + +#define BOOST_SPIRIT_DEFINE_TERMINALS(seq) \ + BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_A, _, seq) \ + /***/ + +// Define a spirit extended terminal. This macro may be placed in any namespace. +// Common placeholders are placed in the main boost::spirit namespace +// (see common_terminals.hpp) + +#define BOOST_SPIRIT_TERMINAL_EX(name) \ + namespace tag { struct name {}; } \ + typedef boost::spirit::terminal<tag::name> name##_type; \ + name##_type const name = name##_type(); \ + inline void silence_unused_warnings__##name() { (void) name; } \ + /***/ + +#define BOOST_SPIRIT_DEFINE_TERMINALS_EX_A(r, _, name) \ + BOOST_SPIRIT_TERMINAL_EX(name) \ + /***/ + +#define BOOST_SPIRIT_DEFINE_TERMINALS_EX(seq) \ + BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_EX_A, _, seq) \ + /***/ + +#endif + + |