/*============================================================================= | |
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 | |