123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- /*=============================================================================
- Copyright (c) 2003 Hartmut Kaiser
- http://spirit.sourceforge.net/
- Use, modification and distribution is subject to 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_SPIRIT_SWITCH_IPP
- #define BOOST_SPIRIT_SWITCH_IPP
- #include <boost/mpl/if.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/core/ignore_unused.hpp>
- #include <boost/preprocessor/cat.hpp>
- #include <boost/preprocessor/inc.hpp>
- #include <boost/preprocessor/repeat.hpp>
- #include <boost/preprocessor/repeat_from_to.hpp>
- #include <boost/spirit/home/classic/core/parser.hpp>
- #include <boost/spirit/home/classic/core/primitives/primitives.hpp>
- #include <boost/spirit/home/classic/core/composite/composite.hpp>
- #include <boost/spirit/home/classic/meta/as_parser.hpp>
- #include <boost/spirit/home/classic/phoenix/actor.hpp>
- #include <boost/spirit/home/classic/phoenix/tuples.hpp>
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit {
- BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
- // forward declaration
- template <int N, typename ParserT, bool IsDefault> struct case_parser;
- ///////////////////////////////////////////////////////////////////////////////
- namespace impl {
- ///////////////////////////////////////////////////////////////////////////////
- // parse helper functions
- template <typename ParserT, typename ScannerT>
- inline typename parser_result<ParserT, ScannerT>::type
- delegate_parse(ParserT const &p, ScannerT const &scan,
- typename ScannerT::iterator_t const save)
- {
- typedef typename parser_result<ParserT, ScannerT>::type result_t;
- result_t result (p.subject().parse(scan));
- if (!result)
- scan.first = save;
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // General default case handling (no default_p case branch given).
- // First try to match the current parser node (if the condition value is
- // matched) and, if that fails, return a no_match
- template <int N, bool IsDefault, bool HasDefault>
- struct default_delegate_parse {
- template <
- typename ParserT, typename DefaultT,
- typename ValueT, typename ScannerT
- >
- static typename parser_result<ParserT, ScannerT>::type
- parse (ValueT const &value, ParserT const &p, DefaultT const &,
- ScannerT const &scan, typename ScannerT::iterator_t const save)
- {
- if (value == N)
- return delegate_parse(p, scan, save);
- return scan.no_match();
- }
- };
- // The current case parser node is the default parser.
- // Ignore the given case value and try to match the given default parser.
- template <int N, bool HasDefault>
- struct default_delegate_parse<N, true, HasDefault> {
- template <
- typename ParserT, typename DefaultT,
- typename ValueT, typename ScannerT
- >
- static typename parser_result<ParserT, ScannerT>::type
- parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d,
- ScannerT const &scan, typename ScannerT::iterator_t const save)
- {
- // Since there is a default_p case branch defined, the corresponding
- // parser shouldn't be the nothing_parser
- BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
- return delegate_parse(d, scan, save);
- }
- };
- // The current case parser node is not the default parser, but there is a
- // default_p branch given inside the switch_p parser.
- // First try to match the current parser node (if the condition value is
- // matched) and, if that fails, match the given default_p parser.
- template <int N>
- struct default_delegate_parse<N, false, true> {
- template <
- typename ParserT, typename DefaultT,
- typename ValueT, typename ScannerT
- >
- static typename parser_result<ParserT, ScannerT>::type
- parse (ValueT const &value, ParserT const &p, DefaultT const &d,
- ScannerT const &scan, typename ScannerT::iterator_t const save)
- {
- // Since there is a default_p case branch defined, the corresponding
- // parser shouldn't be the nothing_parser
- BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
- if (value == N)
- return delegate_parse(p, scan, save);
- return delegate_parse(d, scan, save);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Look through the case parser chain to test, if there is a default case
- // branch defined (returned by 'value').
- template <typename CaseT, bool IsSimple = CaseT::is_simple>
- struct default_case;
- ////////////////////////////////////////
- template <typename ResultT, bool IsDefault>
- struct get_default_parser {
- template <typename ParserT>
- static ResultT
- get(parser<ParserT> const &p)
- {
- return default_case<typename ParserT::derived_t::left_t>::
- get(p.derived().left());
- }
- };
- template <typename ResultT>
- struct get_default_parser<ResultT, true> {
- template <typename ParserT>
- static ResultT
- get(parser<ParserT> const &p) { return p.derived().right(); }
- };
- ////////////////////////////////////////
- template <typename CaseT, bool IsSimple>
- struct default_case {
- // The 'value' constant is true, if the current case_parser or one of its
- // left siblings is a default_p generated case_parser.
- BOOST_STATIC_CONSTANT(bool, value =
- (CaseT::is_default || default_case<typename CaseT::left_t>::value));
- // The 'is_epsilon' constant is true, if the current case_parser or one of
- // its left siblings is a default_p generated parser with an attached
- // epsilon_p (this is generated by the plain default_p).
- BOOST_STATIC_CONSTANT(bool, is_epsilon = (
- (CaseT::is_default && CaseT::is_epsilon) ||
- default_case<typename CaseT::left_t>::is_epsilon
- ));
- // The computed 'type' represents the type of the default case branch
- // parser (if there is one) or nothing_parser (if there isn't any default
- // case branch).
- typedef typename boost::mpl::if_c<
- CaseT::is_default, typename CaseT::right_embed_t,
- typename default_case<typename CaseT::left_t>::type
- >::type type;
- // The get function returns the parser attached to the default case branch
- // (if there is one) or an instance of a nothing_parser (if there isn't
- // any default case branch).
- template <typename ParserT>
- static type
- get(parser<ParserT> const &p)
- { return get_default_parser<type, CaseT::is_default>::get(p); }
- };
- ////////////////////////////////////////
- template <typename ResultT, bool IsDefault>
- struct get_default_parser_simple {
- template <typename ParserT>
- static ResultT
- get(parser<ParserT> const &p) { return p.derived(); }
- };
- template <typename ResultT>
- struct get_default_parser_simple<ResultT, false> {
- template <typename ParserT>
- static nothing_parser
- get(parser<ParserT> const &) { return nothing_p; }
- };
- ////////////////////////////////////////
- // Specialization of the default_case template for the last (leftmost) element
- // of the case parser chain.
- template <typename CaseT>
- struct default_case<CaseT, true> {
- // The 'value' and 'is_epsilon' constant, the 'type' type and the function
- // 'get' are described above.
- BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default);
- BOOST_STATIC_CONSTANT(bool, is_epsilon = (
- CaseT::is_default && CaseT::is_epsilon
- ));
- typedef typename boost::mpl::if_c<
- CaseT::is_default, CaseT, nothing_parser
- >::type type;
- template <typename ParserT>
- static type
- get(parser<ParserT> const &p)
- { return get_default_parser_simple<type, value>::get(p); }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // The case_chain template calculates recursively the depth of the left
- // subchain of the given case branch node.
- template <typename CaseT, bool IsSimple = CaseT::is_simple>
- struct case_chain {
- BOOST_STATIC_CONSTANT(int, depth = (
- case_chain<typename CaseT::left_t>::depth + 1
- ));
- };
- template <typename CaseT>
- struct case_chain<CaseT, true> {
- BOOST_STATIC_CONSTANT(int, depth = 0);
- };
- ///////////////////////////////////////////////////////////////////////////////
- // The chain_parser template is used to extract the type and the instance of
- // a left or a right parser, buried arbitrary deep inside the case parser
- // chain.
- template <int Depth, typename CaseT>
- struct chain_parser {
- typedef typename CaseT::left_t our_left_t;
- typedef typename chain_parser<Depth-1, our_left_t>::left_t left_t;
- typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t;
- static left_t
- left(CaseT const &p)
- { return chain_parser<Depth-1, our_left_t>::left(p.left()); }
- static right_t
- right(CaseT const &p)
- { return chain_parser<Depth-1, our_left_t>::right(p.left()); }
- };
- template <typename CaseT>
- struct chain_parser<1, CaseT> {
- typedef typename CaseT::left_t left_t;
- typedef typename CaseT::right_t right_t;
- static left_t left(CaseT const &p) { return p.left(); }
- static right_t right(CaseT const &p) { return p.right(); }
- };
- template <typename CaseT>
- struct chain_parser<0, CaseT>; // shouldn't be instantiated
- ///////////////////////////////////////////////////////////////////////////////
- // Type computing meta function for calculating the type of the return value
- // of the used conditional switch expression
- template <typename TargetT, typename ScannerT>
- struct condition_result {
- typedef typename TargetT::template result<ScannerT>::type type;
- };
- ///////////////////////////////////////////////////////////////////////////////
- template <typename LeftT, typename RightT, bool IsDefault>
- struct compound_case_parser
- : public binary<LeftT, RightT,
- parser<compound_case_parser<LeftT, RightT, IsDefault> > >
- {
- typedef compound_case_parser<LeftT, RightT, IsDefault> self_t;
- typedef binary_parser_category parser_category_t;
- typedef binary<LeftT, RightT, parser<self_t> > base_t;
- BOOST_STATIC_CONSTANT(int, value = RightT::value);
- BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
- BOOST_STATIC_CONSTANT(bool, is_simple = false);
- BOOST_STATIC_CONSTANT(bool, is_epsilon = (
- is_default &&
- boost::is_same<typename RightT::subject_t, epsilon_parser>::value
- ));
- compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs)
- : base_t(lhs.derived(), rhs.derived())
- {}
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- template <typename ScannerT, typename CondT>
- typename parser_result<self_t, ScannerT>::type
- parse(ScannerT const& scan, CondT const &cond) const;
- template <int N1, typename ParserT1, bool IsDefault1>
- compound_case_parser<
- self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
- >
- operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
- {
- // If the following compile time assertion fires, you've probably used
- // more than one default_p case inside the switch_p parser construct.
- BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1);
- // If this compile time assertion fires, you've probably want to use
- // more case_p/default_p case branches, than possible.
- BOOST_STATIC_ASSERT(
- case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT
- );
- typedef case_parser<N1, ParserT1, IsDefault1> rhs_t;
- return compound_case_parser<self_t, rhs_t, IsDefault1>(*this, p);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // The parse_switch::do_ functions dispatch to the correct parser, which is
- // selected through the given conditional switch value.
- template <int Value, int Depth, bool IsDefault>
- struct parse_switch;
- ///////////////////////////////////////////////////////////////////////////////
- //
- // The following generates a couple of parse_switch template specializations
- // with an increasing number of handled case branches (for 1..N).
- //
- // template <int Value, bool IsDefault>
- // struct parse_switch<Value, N, IsDefault> {
- //
- // template <typename ParserT, typename ScannerT>
- // static typename parser_result<ParserT, ScannerT>::type
- // do_(ParserT const &p, ScannerT const &scan, long cond_value,
- // typename ScannerT::iterator_t const &save)
- // {
- // typedef ParserT left_t0;
- // typedef typename left_t0::left left_t1;
- // ...
- //
- // switch (cond_value) {
- // case left_tN::value:
- // return delegate_parse(chain_parser<
- // case_chain<ParserT>::depth, ParserT
- // >::left(p), scan, save);
- // ...
- // case left_t1::value:
- // return delegate_parse(chain_parser<
- // 1, left_t1
- // >::right(p.left()), scan, save);
- //
- // case left_t0::value:
- // default:
- // typedef default_case<ParserT> default_t;
- // typedef default_delegate_parse<
- // Value, IsDefault, default_t::value>
- // default_parse_t;
- //
- // return default_parse_t::parse(cond_value, p.right(),
- // default_t::get(p), scan, save);
- // }
- // }
- // };
- //
- ///////////////////////////////////////////////////////////////////////////////
- #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _) \
- typedef typename BOOST_PP_CAT(left_t, N)::left_t \
- BOOST_PP_CAT(left_t, BOOST_PP_INC(N)); \
- /**/
- #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _) \
- case (long)(BOOST_PP_CAT(left_t, N)::value): \
- return delegate_parse(chain_parser<N, left_t1>::right(p.left()), \
- scan, save); \
- /**/
- #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _) \
- template <int Value, bool IsDefault> \
- struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> { \
- \
- template <typename ParserT, typename ScannerT> \
- static typename parser_result<ParserT, ScannerT>::type \
- do_(ParserT const &p, ScannerT const &scan, long cond_value, \
- typename ScannerT::iterator_t const &save) \
- { \
- typedef ParserT left_t0; \
- BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N), \
- BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _) \
- \
- switch (cond_value) { \
- case (long)(BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value): \
- return delegate_parse( \
- chain_parser< \
- case_chain<ParserT>::depth, ParserT \
- >::left(p), scan, save); \
- \
- BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N), \
- BOOST_SPIRIT_PARSE_SWITCH_CASES, _) \
- \
- case (long)(left_t0::value): \
- default: \
- typedef default_case<ParserT> default_t; \
- typedef \
- default_delegate_parse<Value, IsDefault, default_t::value> \
- default_parse_t; \
- \
- return default_parse_t::parse(cond_value, p.right(), \
- default_t::get(p), scan, save); \
- } \
- } \
- }; \
- /**/
- BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT),
- BOOST_SPIRIT_PARSE_SWITCHES, _)
- #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS
- #undef BOOST_SPIRIT_PARSE_SWITCH_CASES
- #undef BOOST_SPIRIT_PARSE_SWITCHES
- ///////////////////////////////////////////////////////////////////////////////
- template <typename LeftT, typename RightT, bool IsDefault>
- template <typename ScannerT, typename CondT>
- inline typename parser_result<
- compound_case_parser<LeftT, RightT, IsDefault>, ScannerT
- >::type
- compound_case_parser<LeftT, RightT, IsDefault>::
- parse(ScannerT const& scan, CondT const &cond) const
- {
- ignore_unused(scan.at_end()); // allow skipper to take effect
- return parse_switch<value, case_chain<self_t>::depth, is_default>::
- do_(*this, scan, cond(scan), scan.first);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // The switch condition is to be evaluated from a parser result value.
- template <typename ParserT>
- struct cond_functor {
- typedef cond_functor<ParserT> self_t;
- cond_functor(ParserT const &p_)
- : p(p_)
- {}
- template <typename ScannerT>
- struct result
- {
- typedef typename parser_result<ParserT, ScannerT>::type::attr_t type;
- };
- template <typename ScannerT>
- typename condition_result<self_t, ScannerT>::type
- operator()(ScannerT const &scan) const
- {
- typedef typename parser_result<ParserT, ScannerT>::type result_t;
- typedef typename result_t::attr_t attr_t;
- result_t result(p.parse(scan));
- return !result ? attr_t() : result.value();
- }
- typename ParserT::embed_t p;
- };
- template <typename ParserT>
- struct make_cond_functor {
- typedef as_parser<ParserT> as_parser_t;
- static cond_functor<typename as_parser_t::type>
- do_(ParserT const &cond)
- {
- return cond_functor<typename as_parser_t::type>(
- as_parser_t::convert(cond));
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // The switch condition is to be evaluated from a phoenix actor
- template <typename ActorT>
- struct cond_actor {
- typedef cond_actor<ActorT> self_t;
- cond_actor(ActorT const &actor_)
- : actor(actor_)
- {}
- template <typename ScannerT>
- struct result
- {
- typedef typename ::phoenix::actor_result<ActorT, ::phoenix::tuple<> >::type
- type;
- };
- template <typename ScannerT>
- typename condition_result<self_t, ScannerT>::type
- operator()(ScannerT const& /*scan*/) const
- {
- return actor();
- }
- ActorT const &actor;
- };
- template <typename ActorT>
- struct make_cond_functor< ::phoenix::actor<ActorT> > {
- static cond_actor< ::phoenix::actor<ActorT> >
- do_(::phoenix::actor<ActorT> const &actor)
- {
- return cond_actor< ::phoenix::actor<ActorT> >(actor);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // The switch condition is to be taken directly from the input stream
- struct get_next_token_cond {
- typedef get_next_token_cond self_t;
- template <typename ScannerT>
- struct result
- {
- typedef typename ScannerT::value_t type;
- };
- template <typename ScannerT>
- typename condition_result<self_t, ScannerT>::type
- operator()(ScannerT const &scan) const
- {
- typename ScannerT::value_t val(*scan);
- ++scan.first;
- return val;
- }
- };
- template <>
- struct make_cond_functor<get_next_token_cond> {
- static get_next_token_cond
- do_(get_next_token_cond const &cond)
- {
- return cond;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- } // namespace impl
- BOOST_SPIRIT_CLASSIC_NAMESPACE_END
- }} // namespace boost::spirit
- #endif // BOOST_SPIRIT_SWITCH_IPP
|