📄 switch.ipp
字号:
/*============================================================================= 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/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 declarationtemplate <int N, typename ParserT, bool IsDefault> struct case_parser;///////////////////////////////////////////////////////////////////////////////namespace impl {///////////////////////////////////////////////////////////////////////////////// parse helper functionstemplate <typename ParserT, typename ScannerT>inline typename parser_result<ParserT, ScannerT>::typedelegate_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_matchtemplate <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 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 expressiontemplate <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> > >{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -