288 lines
9.3 KiB
C++
288 lines
9.3 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2002-2003 Hartmut Kaiser
|
|
http://spirit.sourceforge.net/
|
|
|
|
Distributed under 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_REFACTORING_HPP
|
|
#define BOOST_SPIRIT_REFACTORING_HPP
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/spirit/home/classic/namespace.hpp>
|
|
#include <boost/spirit/home/classic/meta/as_parser.hpp>
|
|
#include <boost/spirit/home/classic/core/parser.hpp>
|
|
#include <boost/spirit/home/classic/core/composite/composite.hpp>
|
|
#include <boost/spirit/home/classic/meta/impl/refactoring.ipp>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit {
|
|
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
|
|
|
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4512) //assignment operator could not be generated
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// refactor_unary_parser class
|
|
//
|
|
// This helper template allows to attach an unary operation to a newly
|
|
// constructed parser, which combines the subject of the left operand of
|
|
// the original given parser (BinaryT) with the right operand of the
|
|
// original binary parser through the original binary operation and
|
|
// rewraps the resulting parser with the original unary operator.
|
|
//
|
|
// For instance given the parser:
|
|
// *some_parser - another_parser
|
|
//
|
|
// will be refactored to:
|
|
// *(some_parser - another_parser)
|
|
//
|
|
// If the parser to refactor is not a unary parser, no refactoring is done
|
|
// at all.
|
|
//
|
|
// The original parser should be a binary_parser_category parser,
|
|
// else the compilation will fail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename NestedT = non_nested_refactoring>
|
|
class refactor_unary_gen;
|
|
|
|
template <typename BinaryT, typename NestedT = non_nested_refactoring>
|
|
class refactor_unary_parser :
|
|
public parser<refactor_unary_parser<BinaryT, NestedT> > {
|
|
|
|
public:
|
|
// the parser to refactor has to be at least a binary_parser_category
|
|
// parser
|
|
BOOST_STATIC_ASSERT((
|
|
boost::is_convertible<typename BinaryT::parser_category_t,
|
|
binary_parser_category>::value
|
|
));
|
|
|
|
refactor_unary_parser(BinaryT const& binary_, NestedT const& nested_)
|
|
: binary(binary_), nested(nested_) {}
|
|
|
|
typedef refactor_unary_parser<BinaryT, NestedT> self_t;
|
|
typedef refactor_unary_gen<NestedT> parser_generator_t;
|
|
typedef typename BinaryT::left_t::parser_category_t parser_category_t;
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
return impl::refactor_unary_type<NestedT>::
|
|
parse(*this, scan, binary, nested);
|
|
}
|
|
|
|
private:
|
|
typename as_parser<BinaryT>::type::embed_t binary;
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename NestedT>
|
|
class refactor_unary_gen {
|
|
|
|
public:
|
|
typedef refactor_unary_gen<NestedT> embed_t;
|
|
|
|
refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring())
|
|
: nested(nested_) {}
|
|
|
|
template <typename ParserT>
|
|
refactor_unary_parser<ParserT, NestedT>
|
|
operator[](parser<ParserT> const& subject) const
|
|
{
|
|
return refactor_unary_parser<ParserT, NestedT>
|
|
(subject.derived(), nested);
|
|
}
|
|
|
|
private:
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
const refactor_unary_gen<> refactor_unary_d = refactor_unary_gen<>();
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// refactor_action_parser class
|
|
//
|
|
// This helper template allows to attach an action taken from the left
|
|
// operand of the given binary parser to a newly constructed parser,
|
|
// which combines the subject of the left operand of the original binary
|
|
// parser with the right operand of the original binary parser by means of
|
|
// the original binary operator parser.
|
|
//
|
|
// For instance the parser:
|
|
// some_parser[some_attached_functor] - another_parser
|
|
//
|
|
// will be refactored to:
|
|
// (some_parser - another_parser)[some_attached_functor]
|
|
//
|
|
// If the left operand to refactor is not an action parser, no refactoring
|
|
// is done at all.
|
|
//
|
|
// The original parser should be a binary_parser_category parser,
|
|
// else the compilation will fail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename NestedT = non_nested_refactoring>
|
|
class refactor_action_gen;
|
|
|
|
template <typename BinaryT, typename NestedT = non_nested_refactoring>
|
|
class refactor_action_parser :
|
|
public parser<refactor_action_parser<BinaryT, NestedT> > {
|
|
|
|
public:
|
|
// the parser to refactor has to be at least a binary_parser_category
|
|
// parser
|
|
BOOST_STATIC_ASSERT((
|
|
boost::is_convertible<typename BinaryT::parser_category_t,
|
|
binary_parser_category>::value
|
|
));
|
|
|
|
refactor_action_parser(BinaryT const& binary_, NestedT const& nested_)
|
|
: binary(binary_), nested(nested_) {}
|
|
|
|
typedef refactor_action_parser<BinaryT, NestedT> self_t;
|
|
typedef refactor_action_gen<NestedT> parser_generator_t;
|
|
typedef typename BinaryT::left_t::parser_category_t parser_category_t;
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
return impl::refactor_action_type<NestedT>::
|
|
parse(*this, scan, binary, nested);
|
|
}
|
|
|
|
private:
|
|
typename as_parser<BinaryT>::type::embed_t binary;
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename NestedT>
|
|
class refactor_action_gen {
|
|
|
|
public:
|
|
typedef refactor_action_gen<NestedT> embed_t;
|
|
|
|
refactor_action_gen(NestedT const& nested_ = non_nested_refactoring())
|
|
: nested(nested_) {}
|
|
|
|
template <typename ParserT>
|
|
refactor_action_parser<ParserT, NestedT>
|
|
operator[](parser<ParserT> const& subject) const
|
|
{
|
|
return refactor_action_parser<ParserT, NestedT>
|
|
(subject.derived(), nested);
|
|
}
|
|
|
|
private:
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
const refactor_action_gen<> refactor_action_d = refactor_action_gen<>();
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// attach_action_parser class
|
|
//
|
|
// This helper template allows to attach an action given separately
|
|
// to all parsers, out of which the given parser is constructed and
|
|
// reconstructs a new parser having the same structure.
|
|
//
|
|
// For instance the parser:
|
|
// (some_parser >> another_parser)[some_attached_functor]
|
|
//
|
|
// will be refactored to:
|
|
// some_parser[some_attached_functor]
|
|
// >> another_parser[some_attached_functor]
|
|
//
|
|
// The original parser should be a action_parser_category parser,
|
|
// else the compilation will fail.
|
|
//
|
|
// If the parser, to which the action is attached is not an binary parser,
|
|
// no refactoring is done at all.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename NestedT = non_nested_refactoring>
|
|
class attach_action_gen;
|
|
|
|
template <typename ActionT, typename NestedT = non_nested_refactoring>
|
|
class attach_action_parser :
|
|
public parser<attach_action_parser<ActionT, NestedT> > {
|
|
|
|
public:
|
|
// the parser to refactor has to be at least a action_parser_category
|
|
// parser
|
|
BOOST_STATIC_ASSERT((
|
|
boost::is_convertible<typename ActionT::parser_category_t,
|
|
action_parser_category>::value
|
|
));
|
|
|
|
attach_action_parser(ActionT const& actor_, NestedT const& nested_)
|
|
: actor(actor_), nested(nested_) {}
|
|
|
|
typedef attach_action_parser<ActionT, NestedT> self_t;
|
|
typedef attach_action_gen<NestedT> parser_generator_t;
|
|
typedef typename ActionT::parser_category_t parser_category_t;
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse(ScannerT const& scan) const
|
|
{
|
|
return impl::attach_action_type<NestedT>::
|
|
parse(*this, scan, actor, nested);
|
|
}
|
|
|
|
private:
|
|
typename as_parser<ActionT>::type::embed_t actor;
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename NestedT>
|
|
class attach_action_gen {
|
|
|
|
public:
|
|
typedef attach_action_gen<NestedT> embed_t;
|
|
|
|
attach_action_gen(NestedT const& nested_ = non_nested_refactoring())
|
|
: nested(nested_) {}
|
|
|
|
template <typename ParserT, typename ActionT>
|
|
attach_action_parser<action<ParserT, ActionT>, NestedT>
|
|
operator[](action<ParserT, ActionT> const& actor) const
|
|
{
|
|
return attach_action_parser<action<ParserT, ActionT>, NestedT>
|
|
(actor, nested);
|
|
}
|
|
|
|
private:
|
|
typename NestedT::embed_t nested;
|
|
};
|
|
|
|
const attach_action_gen<> attach_action_d = attach_action_gen<>();
|
|
|
|
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
|
|
|
}} // namespace BOOST_SPIRIT_CLASSIC_NS
|
|
|
|
#endif // BOOST_SPIRIT_REFACTORING_HPP
|
|
|