📄 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/core/parser.hpp>
#include <boost/spirit/core/primitives/primitives.hpp>
#include <boost/spirit/core/composite/composite.hpp>
#include <boost/spirit/meta/as_parser.hpp>
#include <boost/spirit/phoenix/actor.hpp>
#include <boost/spirit/phoenix/tuples.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
// 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 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> > >
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -