boost/xpressive/detail/static/transforms/as_quantifier.hpp
///////////////////////////////////////////////////////////////////////////////
// as_quantifier.hpp
//
// Copyright 2007 Eric Niebler. 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_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/static.hpp>
#include <boost/xpressive/proto/transform/arg.hpp>
#include <boost/xpressive/proto/transform/compose.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// generic_quant_tag
template<uint_t Min, uint_t Max>
struct generic_quant_tag
{
typedef mpl::integral_c<uint_t, Min> min_type;
typedef mpl::integral_c<uint_t, Max> max_type;
};
///////////////////////////////////////////////////////////////////////////////
// min_type / max_type
template<typename Tag>
struct min_type : Tag::min_type {};
template<>
struct min_type<proto::tag::posit> : mpl::integral_c<uint_t, 1> {};
template<>
struct min_type<proto::tag::dereference> : mpl::integral_c<uint_t, 0> {};
template<>
struct min_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 0> {};
template<typename Tag>
struct max_type : Tag::max_type {};
template<>
struct max_type<proto::tag::posit> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::tag::dereference> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 1> {};
///////////////////////////////////////////////////////////////////////////////
// as_simple_quantifier
template<typename Grammar, bool Greedy>
struct as_simple_quantifier
: Grammar
{
typedef proto::transform::arg<Grammar> grammar_type;
as_simple_quantifier();
template<typename Expr, typename State, typename Visitor>
struct apply
{
typedef typename grammar_type::template apply<Expr, true_xpression, Visitor>::type xpr_type;
typedef simple_repeat_matcher<xpr_type, Greedy> matcher_type;
typedef typename proto::terminal<matcher_type>::type type;
};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &, Visitor &visitor)
{
typename apply<Expr, State, Visitor>::xpr_type const &xpr =
grammar_type::call(expr, true_xpression(), visitor);
return apply<Expr, State, Visitor>::type::make(
typename apply<Expr, State, Visitor>::matcher_type(
xpr
, min_type<typename Expr::proto_tag>::value
, max_type<typename Expr::proto_tag>::value
, xpr.get_width().value()
)
);
}
};
///////////////////////////////////////////////////////////////////////////////
// add_hidden_mark
template<typename Grammar>
struct add_hidden_mark
: Grammar
{
add_hidden_mark();
template<typename Expr, typename, typename>
struct apply
: proto::shift_right<
proto::terminal<mark_begin_matcher>::type
, typename proto::shift_right<
Expr
, proto::terminal<mark_end_matcher>::type
>::type
>
{};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &, Visitor &visitor)
{
// we're inserting a hidden mark ... so grab the next hidden mark number.
int mark_nbr = visitor.get_hidden_mark();
mark_begin_matcher begin(mark_nbr);
mark_end_matcher end(mark_nbr);
typename apply<Expr, State, Visitor>::type that = {{begin}, {expr, {end}}};
return that;
}
};
///////////////////////////////////////////////////////////////////////////////
// InsertMark
struct InsertMark
: proto::or_<
proto::assign<basic_mark_tag, proto::_>
, add_hidden_mark<proto::_>
>
{};
///////////////////////////////////////////////////////////////////////////////
// as_default_quantifier_impl
template<bool Greedy, uint_t Min, uint_t Max>
struct as_default_quantifier_impl
{
template<typename Expr, typename State, typename Visitor>
struct apply
: proto::shift_right<
proto::terminal<repeat_begin_matcher>::type
, typename proto::shift_right<
typename InsertMark::apply<typename proto::result_of::arg<Expr>::type, State, Visitor>::type
, typename proto::terminal<repeat_end_matcher<Greedy> >::type
>::type
>
{};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &state, Visitor &visitor)
{
// Ensure this sub-expression is book-ended with mark matchers
typedef typename proto::result_of::arg<Expr>::type arg_type;
typename InsertMark::apply<arg_type, State, Visitor>::type const &
marked_sub = InsertMark::call(proto::arg(expr), state, visitor);
// Get the mark_number from the begin_mark_matcher
int mark_number = proto::arg(proto::left(marked_sub)).mark_number_;
BOOST_ASSERT(0 != mark_number);
unsigned min_ = min_type<typename Expr::proto_tag>::value;
unsigned max_ = max_type<typename Expr::proto_tag>::value;
repeat_begin_matcher begin(mark_number);
repeat_end_matcher<Greedy> end(mark_number, min_, max_);
typename apply<Expr, State, Visitor>::type that = {{begin}, {marked_sub, {end}}};
return that;
}
};
///////////////////////////////////////////////////////////////////////////////
// optional_tag
template<bool Greedy>
struct optional_tag
{};
///////////////////////////////////////////////////////////////////////////////
// as_default_optional
template<typename Grammar, bool Greedy>
struct as_default_optional
: Grammar
{
as_default_optional();
template<typename Expr, typename State, typename Visitor>
struct apply
{
typedef optional_matcher<
typename Grammar::template apply<Expr, alternate_end_xpression, Visitor>::type
, Greedy
> type;
};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &, Visitor &visitor)
{
return typename apply<Expr, State, Visitor>::type(
Grammar::call(expr, alternate_end_xpression(), visitor)
);
}
};
///////////////////////////////////////////////////////////////////////////////
// as_mark_optional
template<typename Grammar, bool Greedy>
struct as_mark_optional
: Grammar
{
as_mark_optional();
template<typename Expr, typename State, typename Visitor>
struct apply
{
typedef optional_mark_matcher<
typename Grammar::template apply<Expr, alternate_end_xpression, Visitor>::type
, Greedy
> type;
};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &, Visitor &visitor)
{
int mark_number = proto::arg(proto::left(expr)).mark_number_;
return typename apply<Expr, State, Visitor>::type(
Grammar::call(expr, alternate_end_xpression(), visitor)
, mark_number
);
}
};
///////////////////////////////////////////////////////////////////////////////
// IsMarkerOrRepeater
struct IsMarkerOrRepeater
: proto::or_<
proto::shift_right<proto::terminal<repeat_begin_matcher>, proto::_>
, proto::assign<proto::terminal<mark_placeholder>, proto::_>
>
{};
///////////////////////////////////////////////////////////////////////////////
// as_optional
template<typename Grammar, bool Greedy>
struct as_optional
: proto::if_<
proto::matches<mpl::_, IsMarkerOrRepeater>
, as_mark_optional<Grammar, Greedy>
, as_default_optional<Grammar, Greedy>
>
{
as_optional();
};
///////////////////////////////////////////////////////////////////////////////
// make_optional_
template<bool Greedy>
struct make_optional_
{
template<typename Expr, typename State, typename Visitor>
struct apply
: proto::unary_expr<optional_tag<Greedy>, Expr>
{};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &, Visitor &)
{
typename apply<Expr, State, Visitor>::type that = {expr};
return that;
}
};
///////////////////////////////////////////////////////////////////////////////
// as_default_quantifier_impl
template<bool Greedy, uint_t Max>
struct as_default_quantifier_impl<Greedy, 0, Max>
: proto::transform::compose<
as_default_quantifier_impl<Greedy, 1, Max>
, make_optional_<Greedy>
>
{};
///////////////////////////////////////////////////////////////////////////////
// as_default_quantifier_impl
template<bool Greedy>
struct as_default_quantifier_impl<Greedy, 0, 1>
: proto::transform::compose<
proto::transform::arg<proto::_>
, make_optional_<Greedy>
>
{};
///////////////////////////////////////////////////////////////////////////////
// as_default_quantifier
template<typename Grammar, bool Greedy>
struct as_default_quantifier
: Grammar
{
as_default_quantifier();
template<typename Expr, typename State, typename Visitor>
struct apply
: as_default_quantifier_impl<
Greedy
, min_type<typename Expr::proto_tag>::value
, max_type<typename Expr::proto_tag>::value
>::template apply<Expr, State, Visitor>
{};
template<typename Expr, typename State, typename Visitor>
static typename apply<Expr, State, Visitor>::type
call(Expr const &expr, State const &state, Visitor &visitor)
{
return as_default_quantifier_impl<
Greedy
, min_type<typename Expr::proto_tag>::value
, max_type<typename Expr::proto_tag>::value
>::call(expr, state, visitor);
}
};
}}}
#endif