1 /////////////////////////////////////////////////////////////////////////////// 2 // linker.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_LINKER_HPP_EAN_10_04_2005 9 #define BOOST_XPRESSIVE_DETAIL_CORE_LINKER_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/config.hpp> 17 #ifndef BOOST_NO_STD_LOCALE 18 # include <locale> 19 #endif 20 #include <stack> 21 #include <limits> 22 #include <typeinfo> 23 #include <boost/shared_ptr.hpp> 24 #include <boost/type_traits/is_same.hpp> 25 #include <boost/version.hpp> 26 27 #if BOOST_VERSION >= 103500 28 # include <boost/fusion/include/for_each.hpp> 29 #else 30 # include <boost/spirit/fusion/algorithm/for_each.hpp> 31 #endif 32 33 #include <boost/xpressive/detail/detail_fwd.hpp> 34 #include <boost/xpressive/detail/dynamic/matchable.hpp> 35 #include <boost/xpressive/detail/core/matchers.hpp> 36 #include <boost/xpressive/detail/core/peeker.hpp> 37 #include <boost/xpressive/detail/utility/never_true.hpp> 38 39 namespace boost { namespace xpressive { namespace detail 40 { 41 42 /////////////////////////////////////////////////////////////////////////////// 43 // icase_modifier 44 // 45 // wrapped by the modifier<> template and inserted into the xpression 46 // template with the icase() helper function. icase_modifier morphs 47 // a case-sensitive visitor into a case-insensitive visitor, which 48 // causes all matchers visited to become case-insensitive. 49 // 50 struct icase_modifier 51 { 52 template<typename Visitor> 53 struct apply {}; 54 55 template<typename BidiIter, typename ICase, typename Traits> 56 struct apply<xpression_visitor<BidiIter, ICase, Traits> > 57 { 58 typedef xpression_visitor<BidiIter, mpl::true_, Traits> type; 59 }; 60 61 template<typename Visitor> 62 static typename apply<Visitor>::type callboost::xpressive::detail::icase_modifier63 call(Visitor &visitor) 64 { 65 return typename apply<Visitor>::type(visitor.traits(), visitor.self()); 66 } 67 }; 68 69 /////////////////////////////////////////////////////////////////////////////// 70 // regex_traits_type : wrap a locale in the appropriate regex_traits 71 // 72 template<typename Locale, typename BidiIter> 73 struct regex_traits_type 74 { 75 #ifndef BOOST_NO_STD_LOCALE 76 77 typedef typename iterator_value<BidiIter>::type char_type; 78 79 // if Locale is std::locale, wrap it in a cpp_regex_traits<Char> 80 typedef typename mpl::if_c 81 < 82 is_same<Locale, std::locale>::value 83 , cpp_regex_traits<char_type> 84 , Locale 85 >::type type; 86 87 #else 88 89 typedef Locale type; 90 91 #endif 92 }; 93 94 /////////////////////////////////////////////////////////////////////////////// 95 // locale_modifier 96 // 97 // wrapped by the modifier<> template and inserted into the xpression 98 // template with the imbue() helper function. Causes a sub-xpression to 99 // use the specified Locale 100 // 101 template<typename Locale> 102 struct locale_modifier 103 { 104 typedef Locale locale_type; 105 locale_modifierboost::xpressive::detail::locale_modifier106 locale_modifier(Locale const &loc) 107 : loc_(loc) 108 { 109 } 110 111 template<typename Visitor> 112 struct apply {}; 113 114 template<typename BidiIter, typename ICase, typename OtherTraits> 115 struct apply<xpression_visitor<BidiIter, ICase, OtherTraits> > 116 { 117 typedef typename regex_traits_type<Locale, BidiIter>::type traits_type; 118 typedef xpression_visitor<BidiIter, ICase, traits_type> type; 119 }; 120 121 template<typename Visitor> 122 typename apply<Visitor>::type callboost::xpressive::detail::locale_modifier123 call(Visitor &visitor) const 124 { 125 return typename apply<Visitor>::type(this->loc_, visitor.self()); 126 } 127 getlocboost::xpressive::detail::locale_modifier128 Locale getloc() const 129 { 130 return this->loc_; 131 } 132 133 private: 134 Locale loc_; 135 }; 136 137 /////////////////////////////////////////////////////////////////////////////// 138 // xpression_linker 139 // 140 template<typename Char> 141 struct xpression_linker 142 { 143 template<typename Traits> xpression_linkerboost::xpressive::detail::xpression_linker144 explicit xpression_linker(Traits const &tr) 145 : back_stack_() 146 , traits_(&tr) 147 , traits_type_(&typeid(Traits)) 148 , has_backrefs_(false) 149 { 150 } 151 152 template<typename Matcher> acceptboost::xpressive::detail::xpression_linker153 void accept(Matcher const &, void const *) 154 { 155 // no-op 156 } 157 158 template<typename Traits, typename ICase> acceptboost::xpressive::detail::xpression_linker159 void accept(mark_matcher<Traits, ICase> const &, void const *) 160 { 161 this->has_backrefs_ = true; 162 } 163 164 template<typename Action> acceptboost::xpressive::detail::xpression_linker165 void accept(action_matcher<Action> const &, void const *) 166 { 167 this->has_backrefs_ = true; 168 } 169 170 template<typename Predicate> acceptboost::xpressive::detail::xpression_linker171 void accept(predicate_matcher<Predicate> const &, void const *) 172 { 173 this->has_backrefs_ = true; 174 } 175 acceptboost::xpressive::detail::xpression_linker176 void accept(repeat_begin_matcher const &, void const *next) 177 { 178 this->back_stack_.push(next); 179 } 180 181 template<typename Greedy> acceptboost::xpressive::detail::xpression_linker182 void accept(repeat_end_matcher<Greedy> const &matcher, void const *) 183 { 184 matcher.back_ = this->back_stack_.top(); 185 this->back_stack_.pop(); 186 } 187 188 template<typename Alternates, typename Traits> acceptboost::xpressive::detail::xpression_linker189 void accept(alternate_matcher<Alternates, Traits> const &matcher, void const *next) 190 { 191 xpression_peeker<Char> peeker(matcher.bset_, this->get_traits<Traits>()); 192 this->alt_link(matcher.alternates_, next, &peeker); 193 } 194 acceptboost::xpressive::detail::xpression_linker195 void accept(alternate_end_matcher const &matcher, void const *) 196 { 197 matcher.back_ = this->back_stack_.top(); 198 this->back_stack_.pop(); 199 } 200 201 template<typename Xpr, typename Greedy> acceptboost::xpressive::detail::xpression_linker202 void accept(optional_matcher<Xpr, Greedy> const &matcher, void const *next) 203 { 204 this->back_stack_.push(next); 205 matcher.xpr_.link(*this); 206 } 207 208 template<typename Xpr, typename Greedy> acceptboost::xpressive::detail::xpression_linker209 void accept(optional_mark_matcher<Xpr, Greedy> const &matcher, void const *next) 210 { 211 this->back_stack_.push(next); 212 matcher.xpr_.link(*this); 213 } 214 215 template<typename Xpr> acceptboost::xpressive::detail::xpression_linker216 void accept(keeper_matcher<Xpr> const &matcher, void const *) 217 { 218 matcher.xpr_.link(*this); 219 } 220 221 template<typename Xpr> acceptboost::xpressive::detail::xpression_linker222 void accept(lookahead_matcher<Xpr> const &matcher, void const *) 223 { 224 matcher.xpr_.link(*this); 225 } 226 227 template<typename Xpr> acceptboost::xpressive::detail::xpression_linker228 void accept(lookbehind_matcher<Xpr> const &matcher, void const *) 229 { 230 matcher.xpr_.link(*this); 231 } 232 233 template<typename Xpr, typename Greedy> acceptboost::xpressive::detail::xpression_linker234 void accept(simple_repeat_matcher<Xpr, Greedy> const &matcher, void const *) 235 { 236 matcher.xpr_.link(*this); 237 } 238 239 // accessors has_backrefsboost::xpressive::detail::xpression_linker240 bool has_backrefs() const 241 { 242 return this->has_backrefs_; 243 } 244 245 // for use by alt_link_pred below 246 template<typename Xpr> alt_branch_linkboost::xpressive::detail::xpression_linker247 void alt_branch_link(Xpr const &xpr, void const *next, xpression_peeker<Char> *peeker) 248 { 249 this->back_stack_.push(next); 250 xpr.link(*this); 251 xpr.peek(*peeker); 252 } 253 254 private: 255 256 /////////////////////////////////////////////////////////////////////////////// 257 // alt_link_pred 258 // 259 struct alt_link_pred 260 { 261 xpression_linker<Char> *linker_; 262 xpression_peeker<Char> *peeker_; 263 void const *next_; 264 alt_link_predboost::xpressive::detail::xpression_linker::alt_link_pred265 alt_link_pred 266 ( 267 xpression_linker<Char> *linker 268 , xpression_peeker<Char> *peeker 269 , void const *next 270 ) 271 : linker_(linker) 272 , peeker_(peeker) 273 , next_(next) 274 { 275 } 276 277 template<typename Xpr> operator ()boost::xpressive::detail::xpression_linker::alt_link_pred278 void operator ()(Xpr const &xpr) const 279 { 280 this->linker_->alt_branch_link(xpr, this->next_, this->peeker_); 281 } 282 }; 283 284 template<typename BidiIter> alt_linkboost::xpressive::detail::xpression_linker285 void alt_link 286 ( 287 alternates_vector<BidiIter> const &alternates 288 , void const *next 289 , xpression_peeker<Char> *peeker 290 ) 291 { 292 std::for_each(alternates.begin(), alternates.end(), alt_link_pred(this, peeker, next)); 293 } 294 295 template<typename Alternates> alt_linkboost::xpressive::detail::xpression_linker296 void alt_link 297 ( 298 fusion::sequence_base<Alternates> const &alternates 299 , void const *next 300 , xpression_peeker<Char> *peeker 301 ) 302 { 303 #if BOOST_VERSION >= 103500 304 fusion::for_each(alternates.derived(), alt_link_pred(this, peeker, next)); 305 #else 306 fusion::for_each(alternates.cast(), alt_link_pred(this, peeker, next)); 307 #endif 308 } 309 310 template<typename Traits> get_traitsboost::xpressive::detail::xpression_linker311 Traits const &get_traits() const 312 { 313 BOOST_ASSERT(*this->traits_type_ == typeid(Traits)); 314 return *static_cast<Traits const *>(this->traits_); 315 } 316 317 std::stack<void const *> back_stack_; 318 void const *traits_; 319 std::type_info const *traits_type_; 320 bool has_backrefs_; 321 }; 322 323 }}} // namespace boost::xpressive::detail 324 325 #endif 326