blob: 7fc392b818051d96b4f880ec6ed1662572a7c736 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2002-2003 Joel de Guzman
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)
=============================================================================*/
#if !defined(BOOST_SPIRIT_TRAVERSE_HPP)
#define BOOST_SPIRIT_TRAVERSE_HPP
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/meta/impl/traverse.ipp>
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////
//
// Post-order traversal of auxilliary parsers.
//
///////////////////////////////////////////////////////////////////////////
struct post_order
{
// Return the parser type, which is generated as the result of the
// traverse function below.
template <typename MetaT, typename ParserT>
struct result
{
typedef typename
traverse_post_order_return<
MetaT
, ParserT
, traverse_post_order_env<0, 0, 0, 0>
>::type
type;
};
// Traverse a given parser and refactor it with the help of the given
// MetaT metafunction template.
template <typename MetaT, typename ParserT>
static typename result<MetaT, ParserT>::type
traverse(MetaT const &meta_, ParserT const &parser_)
{
typedef typename ParserT::parser_category_t parser_category_t;
return impl::traverse_post_order<parser_category_t>::generate(
meta_, parser_, traverse_post_order_env<0, 0, 0, 0>());
}
};
///////////////////////////////////////////////////////////////////////////
//
// Transform policies
//
// The following policy classes could be used to assemble some new
// transformation metafunction which uses identity transformations
// for some parser_category type parsers.
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// transform plain parsers
template <typename TransformT>
struct plain_identity_policy
{
template <typename ParserT, typename EnvT>
struct plain_result
{
// plain parsers should be embedded and returned correctly
typedef typename ParserT::embed_t type;
};
template <typename ParserT, typename EnvT>
typename parser_traversal_plain_result<TransformT, ParserT, EnvT>::type
generate_plain(ParserT const &parser_, EnvT const& /*env*/) const
{
return parser_;
}
};
//////////////////////////////////
// transform unary parsers
template <typename UnaryT, typename SubjectT>
struct unary_identity_policy_return
{
typedef typename UnaryT::parser_generator_t parser_generator_t;
typedef typename parser_generator_t
::template result<SubjectT>::type type;
};
template <typename TransformT>
struct unary_identity_policy
{
template <typename UnaryT, typename SubjectT, typename EnvT>
struct unary_result
{
typedef
typename unary_identity_policy_return<UnaryT, SubjectT>::type
type;
};
template <typename UnaryT, typename SubjectT, typename EnvT>
typename parser_traversal_unary_result<
TransformT, UnaryT, SubjectT, EnvT>::type
generate_unary(
UnaryT const &, SubjectT const &subject_, EnvT const& /*env*/) const
{
typedef typename UnaryT::parser_generator_t parser_generator_t;
return parser_generator_t::template generate<SubjectT>(subject_);
}
};
//////////////////////////////////
// transform action parsers
template <typename TransformT>
struct action_identity_policy
{
template <typename ActionT, typename SubjectT, typename EnvT>
struct action_result
{
typedef action<SubjectT, typename ActionT::predicate_t> type;
};
template <typename ActionT, typename SubjectT, typename EnvT>
typename parser_traversal_action_result<
TransformT, ActionT, SubjectT, EnvT
>::type
generate_action(ActionT const &action_, SubjectT const &subject_,
EnvT const& /*env*/) const
{
return subject_[action_.predicate()];
}
};
//////////////////////////////////
// transform binary parsers
template <typename BinaryT, typename LeftT, typename RightT>
struct binary_identity_policy_return
{
typedef typename BinaryT::parser_generator_t parser_generator_t;
typedef typename parser_generator_t
::template result<LeftT, RightT>::type type;
};
template <typename TransformT>
struct binary_identity_policy
{
template <typename BinaryT, typename LeftT
, typename RightT, typename EnvT>
struct binary_result {
typedef typename
binary_identity_policy_return<BinaryT, LeftT, RightT>::type
type;
};
template <typename BinaryT, typename LeftT
, typename RightT, typename EnvT>
typename parser_traversal_binary_result<
TransformT, BinaryT, LeftT, RightT, EnvT
>::type
generate_binary(
BinaryT const &, LeftT const& left_
, RightT const& right_, EnvT const& /*env*/) const
{
typedef typename BinaryT::parser_generator_t parser_generator_t;
return parser_generator_t::
template generate<LeftT, RightT>(left_, right_);
}
};
///////////////////////////////////////////////////////////////////////////
//
// transform_policies template
//
// The transform_policies template metafunction could serve as a
// base class for new metafunctions to be passed to the traverse meta
// template (see above), where only minimal parts have to be
// overwritten.
//
///////////////////////////////////////////////////////////////////////////
template <
typename TransformT,
typename PlainPolicyT = plain_identity_policy<TransformT>,
typename UnaryPolicyT = unary_identity_policy<TransformT>,
typename ActionPolicyT = action_identity_policy<TransformT>,
typename BinaryPolicyT = binary_identity_policy<TransformT>
>
struct transform_policies :
public PlainPolicyT,
public UnaryPolicyT,
public ActionPolicyT,
public BinaryPolicyT
{
};
///////////////////////////////////////////////////////////////////////////
//
// Identity transformation
//
// The identity_transform metafunction supplied to the traverse
// template will generate a new parser, which will be exactly
// identical to the parser given as the parameter to the traverse
// metafunction. I.e. the following conceptual 'equation' will be
// always true:
//
// some_parser ==
// post_order::traverse(identity_transform(), some_parser)
//
///////////////////////////////////////////////////////////////////////////
struct identity_transform : transform_policies<identity_transform> {};
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace BOOST_SPIRIT_CLASSIC_NS
#endif // !defined(BOOST_SPIRIT_TRAVERSE_HPP)