1 /////////////////////////////////////////////////////////////////////////////// 2 // alternate_matcher.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_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005 9 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_MATCHER_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/version.hpp> 17 #if BOOST_VERSION <= 103200 18 // WORKAROUND for Fusion bug in Boost 1.32 19 namespace boost { namespace fusion 20 { 21 namespace detail { struct iterator_root; } 22 using detail::iterator_root; 23 }} 24 #endif 25 26 #include <boost/xpressive/detail/detail_fwd.hpp> 27 #include <boost/xpressive/detail/core/quant_style.hpp> 28 #include <boost/xpressive/detail/core/state.hpp> 29 #include <boost/xpressive/detail/dynamic/matchable.hpp> 30 #include <boost/xpressive/detail/utility/hash_peek_bitset.hpp> 31 #include <boost/xpressive/detail/utility/algorithm.hpp> 32 #include <boost/xpressive/detail/utility/any.hpp> 33 34 namespace boost { namespace xpressive { namespace detail 35 { 36 37 /////////////////////////////////////////////////////////////////////////////// 38 // alt_match_pred 39 // 40 template<typename BidiIter, typename Next> 41 struct alt_match_pred 42 { alt_match_predboost::xpressive::detail::alt_match_pred43 alt_match_pred(match_state<BidiIter> &state) 44 : state_(&state) 45 { 46 } 47 48 template<typename Xpr> operator ()boost::xpressive::detail::alt_match_pred49 bool operator ()(Xpr const &xpr) const 50 { 51 return xpr.BOOST_NESTED_TEMPLATE push_match<Next>(*this->state_); 52 } 53 54 private: 55 match_state<BidiIter> *state_; 56 }; 57 58 /////////////////////////////////////////////////////////////////////////////// 59 // alt_match 60 // 61 template<typename BidiIter, typename Next> alt_match(alternates_vector<BidiIter> const & alts,match_state<BidiIter> & state,Next const &)62 inline bool alt_match 63 ( 64 alternates_vector<BidiIter> const &alts, match_state<BidiIter> &state, Next const & 65 ) 66 { 67 return detail::any(alts.begin(), alts.end(), alt_match_pred<BidiIter, Next>(state)); 68 } 69 70 template<typename Head, typename Tail, typename BidiIter, typename Next> alt_match(alternates_list<Head,Tail> const & alts,match_state<BidiIter> & state,Next const &)71 inline bool alt_match 72 ( 73 alternates_list<Head, Tail> const &alts, match_state<BidiIter> &state, Next const & 74 ) 75 { 76 return fusion::any(alts, alt_match_pred<BidiIter, Next>(state)); 77 } 78 79 /////////////////////////////////////////////////////////////////////////////// 80 // alternate_matcher 81 template<typename Alternates, typename Traits> 82 struct alternate_matcher 83 : quant_style< 84 Alternates::width != unknown_width::value && Alternates::pure ? quant_fixed_width : quant_variable_width 85 , Alternates::width 86 , Alternates::pure 87 > 88 { 89 typedef Alternates alternates_type; 90 typedef typename Traits::char_type char_type; 91 92 Alternates alternates_; 93 mutable hash_peek_bitset<char_type> bset_; 94 alternate_matcherboost::xpressive::detail::alternate_matcher95 explicit alternate_matcher(Alternates const &alternates = Alternates()) 96 : alternates_(alternates) 97 , bset_() 98 { 99 } 100 101 template<typename BidiIter, typename Next> matchboost::xpressive::detail::alternate_matcher102 bool match(match_state<BidiIter> &state, Next const &next) const 103 { 104 if(!state.eos() && !this->can_match_(*state.cur_, traits_cast<Traits>(state))) 105 { 106 return false; 107 } 108 109 return detail::alt_match(this->alternates_, state, next); 110 } 111 get_widthboost::xpressive::detail::alternate_matcher112 detail::width get_width() const 113 { 114 // Only called when constructing static regexes, and this is a 115 // set of same-width alternates where the widths are known at compile 116 // time, as in: sregex rx = +(_ | 'a' | _n); 117 BOOST_MPL_ASSERT_RELATION(unknown_width::value, !=, Alternates::width); 118 return Alternates::width; 119 } 120 121 private: 122 alternate_matcher &operator =(alternate_matcher const &); 123 can_match_boost::xpressive::detail::alternate_matcher124 bool can_match_(char_type ch, Traits const &tr) const 125 { 126 return this->bset_.test(ch, tr); 127 } 128 }; 129 130 }}} 131 132 #endif 133