1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
///////////////////////////////////////////////////////////////////////////////
// matchable.hpp
//
// Copyright 2008 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_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/utility/counted_base.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/sequence.hpp>
#include <boost/xpressive/regex_error.hpp>
namespace boost { namespace xpressive { namespace detail
{
//////////////////////////////////////////////////////////////////////////
// quant_spec
struct quant_spec
{
unsigned int min_;
unsigned int max_;
bool greedy_;
std::size_t *hidden_mark_count_;
};
///////////////////////////////////////////////////////////////////////////////
// matchable
template<typename BidiIter>
struct matchable
{
typedef BidiIter iterator_type;
typedef typename iterator_value<iterator_type>::type char_type;
virtual ~matchable() {}
virtual bool match(match_state<BidiIter> &state) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// matchable_ex
template<typename BidiIter>
struct matchable_ex
: matchable<BidiIter>
, counted_base<matchable_ex<BidiIter> >
{
typedef BidiIter iterator_type;
typedef typename iterator_value<iterator_type>::type char_type;
virtual void link(xpression_linker<char_type> &) const
{
}
virtual void peek(xpression_peeker<char_type> &peeker) const
{
peeker.fail();
}
virtual void repeat(quant_spec const &, sequence<BidiIter> &) const
{
BOOST_THROW_EXCEPTION(
regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// The following 4 functions (push_match, top_match, pop_match and skip_match) are
// used to implement looping and branching across the matchers. Call push_match to record
// a position. Then, another matcher further down the xpression chain has the
// option to call either top_match, pop_match or skip_match. top_match and pop_match will
// jump back to the place recorded by push_match, whereas skip_match will skip the jump and
// pass execution down the xpression chain. top_match will leave the xpression on top of the
// stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for
// statically bound xpressions and one for dynamically bound xpressions.
//
template<typename Top>
bool push_match(match_state<BidiIter> &state) const
{
BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
return this->match(state);
}
static bool top_match(match_state<BidiIter> &state, void const *top)
{
return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
}
static bool pop_match(match_state<BidiIter> &state, void const *top)
{
return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
}
bool skip_match(match_state<BidiIter> &state) const
{
return this->match(state);
}
};
///////////////////////////////////////////////////////////////////////////////
// shared_matchable
template<typename BidiIter>
struct shared_matchable
{
typedef BidiIter iterator_type;
typedef typename iterator_value<BidiIter>::type char_type;
typedef intrusive_ptr<matchable_ex<BidiIter> const> matchable_ptr;
BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
BOOST_STATIC_CONSTANT(bool, pure = false);
shared_matchable(matchable_ptr const &xpr = matchable_ptr())
: xpr_(xpr)
{
}
bool operator !() const
{
return !this->xpr_;
}
friend bool operator ==(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
{
return left.xpr_ == right.xpr_;
}
friend bool operator !=(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
{
return left.xpr_ != right.xpr_;
}
matchable_ptr const &matchable() const
{
return this->xpr_;
}
bool match(match_state<BidiIter> &state) const
{
return this->xpr_->match(state);
}
void link(xpression_linker<char_type> &linker) const
{
this->xpr_->link(linker);
}
void peek(xpression_peeker<char_type> &peeker) const
{
this->xpr_->peek(peeker);
}
// BUGBUG yuk!
template<typename Top>
bool push_match(match_state<BidiIter> &state) const
{
BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
return this->match(state);
}
private:
matchable_ptr xpr_;
};
}}} // namespace boost::xpressive::detail
#endif
|