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