123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- ///////////////////////////////////////////////////////////////////////////////
- // dynamic.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_DYNAMIC_HPP_EAN_10_04_2005
- #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
- // MS compatible compilers support #pragma once
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <vector>
- #include <utility>
- #include <algorithm>
- #include <boost/assert.hpp>
- #include <boost/mpl/int.hpp>
- #include <boost/mpl/assert.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/xpressive/detail/detail_fwd.hpp>
- #include <boost/xpressive/detail/core/quant_style.hpp>
- #include <boost/xpressive/detail/dynamic/matchable.hpp>
- #include <boost/xpressive/detail/dynamic/sequence.hpp>
- #include <boost/xpressive/detail/core/icase.hpp>
- namespace boost { namespace xpressive { namespace detail
- {
- ///////////////////////////////////////////////////////////////////////////////
- // invalid_xpression
- template<typename BidiIter>
- struct invalid_xpression
- : matchable_ex<BidiIter>
- {
- invalid_xpression()
- : matchable_ex<BidiIter>()
- {
- intrusive_ptr_add_ref(this); // keep alive forever
- }
- bool match(match_state<BidiIter> &) const
- {
- BOOST_ASSERT(false);
- return false;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // get_invalid_xpression
- template<typename BidiIter>
- inline shared_matchable<BidiIter> const &get_invalid_xpression()
- {
- static invalid_xpression<BidiIter> const invalid_xpr;
- static intrusive_ptr<matchable_ex<BidiIter> const> const invalid_ptr(&invalid_xpr);
- static shared_matchable<BidiIter> const invalid_matchable(invalid_ptr);
- return invalid_matchable;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // dynamic_xpression
- template<typename Matcher, typename BidiIter>
- struct dynamic_xpression
- : Matcher
- , matchable_ex<BidiIter>
- {
- typedef typename iterator_value<BidiIter>::type char_type;
- dynamic_xpression(Matcher const &matcher = Matcher())
- : Matcher(matcher)
- , next_(get_invalid_xpression<BidiIter>())
- {
- }
- virtual bool match(match_state<BidiIter> &state) const
- {
- return this->Matcher::match(state, *this->next_.matchable());
- }
- virtual void link(xpression_linker<char_type> &linker) const
- {
- linker.accept(*static_cast<Matcher const *>(this), this->next_.matchable().get());
- this->next_.link(linker);
- }
- virtual void peek(xpression_peeker<char_type> &peeker) const
- {
- this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
- }
- virtual void repeat(quant_spec const &spec, sequence<BidiIter> &seq) const
- {
- this->repeat_(spec, seq, quant_type<Matcher>(), is_same<Matcher, mark_begin_matcher>());
- }
- private:
- friend struct sequence<BidiIter>;
- void peek_next_(mpl::true_, xpression_peeker<char_type> &peeker) const
- {
- this->next_.peek(peeker);
- }
- void peek_next_(mpl::false_, xpression_peeker<char_type> &) const
- {
- // no-op
- }
- void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_none>, mpl::false_) const
- {
- if(quant_none == seq.quant())
- {
- BOOST_THROW_EXCEPTION(
- regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
- );
- }
- else
- {
- this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
- }
- }
- void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::false_) const
- {
- if(this->next_ == get_invalid_xpression<BidiIter>())
- {
- make_simple_repeat(spec, seq, matcher_wrapper<Matcher>(*this));
- }
- else
- {
- this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
- }
- }
- void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_variable_width>, mpl::false_) const
- {
- if(!is_unknown(seq.width()) && seq.pure())
- {
- make_simple_repeat(spec, seq);
- }
- else
- {
- make_repeat(spec, seq);
- }
- }
- void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::true_) const
- {
- make_repeat(spec, seq, this->mark_number_);
- }
- shared_matchable<BidiIter> next_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // make_dynamic
- template<typename BidiIter, typename Matcher>
- inline sequence<BidiIter> make_dynamic(Matcher const &matcher)
- {
- typedef dynamic_xpression<Matcher, BidiIter> xpression_type;
- intrusive_ptr<xpression_type> xpr(new xpression_type(matcher));
- return sequence<BidiIter>(xpr);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // alternates_vector
- template<typename BidiIter>
- struct alternates_vector
- : std::vector<shared_matchable<BidiIter> >
- {
- BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
- BOOST_STATIC_CONSTANT(bool, pure = false);
- };
- ///////////////////////////////////////////////////////////////////////////////
- // matcher_wrapper
- template<typename Matcher>
- struct matcher_wrapper
- : Matcher
- {
- matcher_wrapper(Matcher const &matcher = Matcher())
- : Matcher(matcher)
- {
- }
- template<typename BidiIter>
- bool match(match_state<BidiIter> &state) const
- {
- return this->Matcher::match(state, matcher_wrapper<true_matcher>());
- }
- template<typename Char>
- void link(xpression_linker<Char> &linker) const
- {
- linker.accept(*static_cast<Matcher const *>(this), 0);
- }
- template<typename Char>
- void peek(xpression_peeker<Char> &peeker) const
- {
- peeker.accept(*static_cast<Matcher const *>(this));
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // make_simple_repeat
- template<typename BidiIter, typename Xpr>
- inline void
- make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq, Xpr const &xpr)
- {
- if(spec.greedy_)
- {
- simple_repeat_matcher<Xpr, mpl::true_> quant(xpr, spec.min_, spec.max_, seq.width().value());
- seq = make_dynamic<BidiIter>(quant);
- }
- else
- {
- simple_repeat_matcher<Xpr, mpl::false_> quant(xpr, spec.min_, spec.max_, seq.width().value());
- seq = make_dynamic<BidiIter>(quant);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // make_simple_repeat
- template<typename BidiIter>
- inline void
- make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
- {
- seq += make_dynamic<BidiIter>(true_matcher());
- make_simple_repeat(spec, seq, seq.xpr());
- }
- //////////////////////////////////////////////////////////////////////////
- // make_optional
- template<typename BidiIter>
- inline void
- make_optional(quant_spec const &spec, sequence<BidiIter> &seq)
- {
- typedef shared_matchable<BidiIter> xpr_type;
- seq += make_dynamic<BidiIter>(alternate_end_matcher());
- if(spec.greedy_)
- {
- optional_matcher<xpr_type, mpl::true_> opt(seq.xpr());
- seq = make_dynamic<BidiIter>(opt);
- }
- else
- {
- optional_matcher<xpr_type, mpl::false_> opt(seq.xpr());
- seq = make_dynamic<BidiIter>(opt);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // make_optional
- template<typename BidiIter>
- inline void
- make_optional(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
- {
- typedef shared_matchable<BidiIter> xpr_type;
- seq += make_dynamic<BidiIter>(alternate_end_matcher());
- if(spec.greedy_)
- {
- optional_mark_matcher<xpr_type, mpl::true_> opt(seq.xpr(), mark_nbr);
- seq = make_dynamic<BidiIter>(opt);
- }
- else
- {
- optional_mark_matcher<xpr_type, mpl::false_> opt(seq.xpr(), mark_nbr);
- seq = make_dynamic<BidiIter>(opt);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // make_repeat
- template<typename BidiIter>
- inline void
- make_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
- {
- // only bother creating a repeater if max is greater than one
- if(1 < spec.max_)
- {
- // create a hidden mark so this expression can be quantified
- int mark_nbr = -static_cast<int>(++*spec.hidden_mark_count_);
- seq = make_dynamic<BidiIter>(mark_begin_matcher(mark_nbr)) + seq
- + make_dynamic<BidiIter>(mark_end_matcher(mark_nbr));
- make_repeat(spec, seq, mark_nbr);
- return;
- }
- // if min is 0, the repeat must be made optional
- if(0 == spec.min_)
- {
- make_optional(spec, seq);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // make_repeat
- template<typename BidiIter>
- inline void
- make_repeat(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
- {
- BOOST_ASSERT(spec.max_); // we should never get here if max is 0
- // only bother creating a repeater if max is greater than one
- if(1 < spec.max_)
- {
- // TODO: statically bind the repeat matchers to the mark matchers for better perf
- unsigned int min = spec.min_ ? spec.min_ : 1U;
- repeat_begin_matcher repeat_begin(mark_nbr);
- if(spec.greedy_)
- {
- repeat_end_matcher<mpl::true_> repeat_end(mark_nbr, min, spec.max_);
- seq = make_dynamic<BidiIter>(repeat_begin) + seq
- + make_dynamic<BidiIter>(repeat_end);
- }
- else
- {
- repeat_end_matcher<mpl::false_> repeat_end(mark_nbr, min, spec.max_);
- seq = make_dynamic<BidiIter>(repeat_begin) + seq
- + make_dynamic<BidiIter>(repeat_end);
- }
- }
- // if min is 0, the repeat must be made optional
- if(0 == spec.min_)
- {
- make_optional(spec, seq, mark_nbr);
- }
- }
- }}} // namespace boost::xpressive::detail
- #endif
|