|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r66465 - branches/release/boost/spirit/home/classic/dynamic/impl
From: hartmut.kaiser_at_[hidden]
Date: 2010-11-08 17:41:30
Author: hkaiser
Date: 2010-11-08 17:41:27 EST (Mon, 08 Nov 2010)
New Revision: 66465
URL: http://svn.boost.org/trac/boost/changeset/66465
Log:
Spirit: fixed #4825: boost/spirit/home/classic/dynamic/impl/switch.ipp missing a chunk in release branch
Text files modified:
branches/release/boost/spirit/home/classic/dynamic/impl/switch.ipp | 307 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 307 insertions(+), 0 deletions(-)
Modified: branches/release/boost/spirit/home/classic/dynamic/impl/switch.ipp
==============================================================================
--- branches/release/boost/spirit/home/classic/dynamic/impl/switch.ipp (original)
+++ branches/release/boost/spirit/home/classic/dynamic/impl/switch.ipp 2010-11-08 17:41:27 EST (Mon, 08 Nov 2010)
@@ -103,6 +103,313 @@
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 recursivly 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, burried 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> right_t;
+ return compound_case_parser<self_t, right_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-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk