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