boost/spirit/home/classic/utility/impl/confix.ipp
/*=============================================================================
Copyright (c) 2002-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_CONFIX_IPP
#define BOOST_SPIRIT_CONFIX_IPP
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/classic/meta/refactoring.hpp>
#include <boost/spirit/home/classic/core/composite/impl/directives.ipp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
//
// Types to distinguish nested and non-nested confix parsers
//
///////////////////////////////////////////////////////////////////////////////
struct is_nested {};
struct non_nested {};
///////////////////////////////////////////////////////////////////////////////
//
// Types to distinguish between confix parsers, which are implicitly lexems
// and without this behaviour
//
///////////////////////////////////////////////////////////////////////////////
struct is_lexeme {};
struct non_lexeme {};
///////////////////////////////////////////////////////////////////////////////
//
// confix_parser_type class implementation
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
///////////////////////////////////////////////////////////////////////////
// implicitly insert a lexeme_d into the parsing process
template <typename LexemeT>
struct select_confix_parse_lexeme;
template <>
struct select_confix_parse_lexeme<is_lexeme> {
template <typename ParserT, typename ScannerT>
static typename parser_result<ParserT, ScannerT>::type
parse(ParserT const& p, ScannerT const& scan)
{
typedef typename parser_result<ParserT, ScannerT>::type result_t;
return contiguous_parser_parse<result_t>(p, scan, scan);
}
};
template <>
struct select_confix_parse_lexeme<non_lexeme> {
template <typename ParserT, typename ScannerT>
static typename parser_result<ParserT, ScannerT>::type
parse(ParserT const& p, ScannerT const& scan)
{
return p.parse(scan);
}
};
///////////////////////////////////////////////////////////////////////////
// parse confix sequences with refactoring
template <typename NestedT>
struct select_confix_parse_refactor;
template <>
struct select_confix_parse_refactor<is_nested> {
template <
typename LexemeT, typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
LexemeT const &, ParserT const& this_, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
typedef refactor_action_gen<refactor_unary_gen<> > refactor_t;
const refactor_t refactor_body_d = refactor_t(refactor_unary_d);
return select_confix_parse_lexeme<LexemeT>::parse((
open
>> (this_ | refactor_body_d[expr - close])
>> close
), scan);
}
};
template <>
struct select_confix_parse_refactor<non_nested> {
template <
typename LexemeT, typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
LexemeT const &, ParserT const& /*this_*/, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
typedef refactor_action_gen<refactor_unary_gen<> > refactor_t;
const refactor_t refactor_body_d = refactor_t(refactor_unary_d);
return select_confix_parse_lexeme<LexemeT>::parse((
open
>> refactor_body_d[expr - close]
>> close
), scan);
}
};
///////////////////////////////////////////////////////////////////////////
// parse confix sequences without refactoring
template <typename NestedT>
struct select_confix_parse_no_refactor;
template <>
struct select_confix_parse_no_refactor<is_nested> {
template <
typename LexemeT, typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
LexemeT const &, ParserT const& this_, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
return select_confix_parse_lexeme<LexemeT>::parse((
open
>> (this_ | (expr - close))
>> close
), scan);
}
};
template <>
struct select_confix_parse_no_refactor<non_nested> {
template <
typename LexemeT, typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
LexemeT const &, ParserT const & /*this_*/, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
return select_confix_parse_lexeme<LexemeT>::parse((
open
>> (expr - close)
>> close
), scan);
}
};
// the refactoring is handled by the refactoring parsers, so here there
// is no need to pay attention to these issues.
template <typename CategoryT>
struct confix_parser_type {
template <
typename NestedT, typename LexemeT,
typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
NestedT const &, LexemeT const &lexeme,
ParserT const& this_, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
return select_confix_parse_refactor<NestedT>::
parse(lexeme, this_, scan, open, expr, close);
}
};
template <>
struct confix_parser_type<plain_parser_category> {
template <
typename NestedT, typename LexemeT,
typename ParserT, typename ScannerT,
typename OpenT, typename ExprT, typename CloseT
>
static typename parser_result<ParserT, ScannerT>::type
parse(
NestedT const &, LexemeT const &lexeme,
ParserT const& this_, ScannerT const& scan,
OpenT const& open, ExprT const& expr, CloseT const& close)
{
return select_confix_parse_no_refactor<NestedT>::
parse(lexeme, this_, scan, open, expr, close);
}
};
} // namespace impl
///////////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace boost::spirit
#endif