| /////////////////////////////////////////////////////////////////////////////// |
| // peeker.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_CORE_PEEKER_HPP_EAN_10_04_2005 |
| #define BOOST_XPRESSIVE_DETAIL_CORE_PEEKER_HPP_EAN_10_04_2005 |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <string> |
| #include <typeinfo> |
| #include <boost/assert.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/assert.hpp> |
| #include <boost/mpl/size_t.hpp> |
| #include <boost/mpl/equal_to.hpp> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/xpressive/detail/detail_fwd.hpp> |
| #include <boost/xpressive/detail/core/matchers.hpp> |
| #include <boost/xpressive/detail/utility/hash_peek_bitset.hpp> |
| #include <boost/xpressive/detail/utility/never_true.hpp> |
| #include <boost/xpressive/detail/utility/algorithm.hpp> |
| |
| namespace boost { namespace xpressive { namespace detail |
| { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // peeker_string |
| // |
| template<typename Char> |
| struct peeker_string |
| { |
| Char const *begin_; |
| Char const *end_; |
| bool icase_; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // char_sink |
| // |
| template<typename Traits, bool ICase> |
| struct char_sink |
| { |
| typedef typename Traits::char_type char_type; |
| |
| char_sink(hash_peek_bitset<char_type> &bset, Traits const &tr) |
| : bset_(bset) |
| , traits_(tr) |
| {} |
| |
| void operator()(char_type ch) const |
| { |
| this->bset_.set_char(ch, ICase, this->traits_); |
| } |
| |
| hash_peek_bitset<char_type> &bset_; |
| Traits const &traits_; |
| private: |
| char_sink &operator =(char_sink const &); |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // xpression_peeker |
| // |
| template<typename Char> |
| struct xpression_peeker |
| { |
| template<typename Traits> |
| xpression_peeker(hash_peek_bitset<Char> &bset, Traits const &tr, bool has_backrefs = false) |
| : bset_(bset) |
| , str_() |
| , line_start_(false) |
| , traits_(0) |
| , traits_type_(0) |
| , leading_simple_repeat_(0) |
| , has_backrefs_(has_backrefs) |
| { |
| this->set_traits(tr); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // accessors |
| peeker_string<Char> const &get_string() const |
| { |
| return this->str_; |
| } |
| |
| bool line_start() const |
| { |
| return this->line_start_; |
| } |
| |
| bool leading_simple_repeat() const |
| { |
| return 0 < this->leading_simple_repeat_; |
| } |
| |
| hash_peek_bitset<Char> const &bitset() const |
| { |
| return this->bset_; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // modifiers |
| void fail() |
| { |
| this->bset_.set_all(); |
| } |
| |
| template<typename Matcher> |
| mpl::false_ accept(Matcher const &) |
| { |
| this->fail(); |
| return mpl::false_(); |
| } |
| |
| mpl::true_ accept(mark_begin_matcher const &) |
| { |
| if(this->has_backrefs_) |
| { |
| --this->leading_simple_repeat_; |
| } |
| return mpl::true_(); |
| } |
| |
| mpl::true_ accept(repeat_begin_matcher const &) |
| { |
| --this->leading_simple_repeat_; |
| return mpl::true_(); |
| } |
| |
| template<typename Traits> |
| mpl::true_ accept(assert_bol_matcher<Traits> const &) |
| { |
| this->line_start_ = true; |
| return mpl::true_(); |
| } |
| |
| template<typename Traits, typename ICase> |
| mpl::false_ accept(literal_matcher<Traits, ICase, mpl::false_> const &xpr) |
| { |
| this->bset_.set_char(xpr.ch_, ICase(), this->get_traits_<Traits>()); |
| return mpl::false_(); |
| } |
| |
| template<typename Traits, typename ICase> |
| mpl::false_ accept(string_matcher<Traits, ICase> const &xpr) |
| { |
| this->bset_.set_char(xpr.str_[0], ICase(), this->get_traits_<Traits>()); |
| this->str_.begin_ = detail::data_begin(xpr.str_); |
| this->str_.end_ = detail::data_end(xpr.str_); |
| this->str_.icase_ = ICase::value; |
| return mpl::false_(); |
| } |
| |
| template<typename Alternates, typename Traits> |
| mpl::false_ accept(alternate_matcher<Alternates, Traits> const &xpr) |
| { |
| BOOST_ASSERT(0 != xpr.bset_.count()); |
| this->bset_.set_bitset(xpr.bset_); |
| return mpl::false_(); |
| } |
| |
| template<typename Matcher, typename Traits, typename ICase> |
| mpl::false_ accept(attr_matcher<Matcher, Traits, ICase> const &xpr) |
| { |
| xpr.sym_.peek(char_sink<Traits, ICase::value>(this->bset_, this->get_traits_<Traits>())); |
| return mpl::false_(); |
| } |
| |
| template<typename Xpr, typename Greedy> |
| mpl::false_ accept(optional_matcher<Xpr, Greedy> const &) |
| { |
| this->fail(); // a union of xpr and next |
| return mpl::false_(); |
| } |
| |
| template<typename Xpr, typename Greedy> |
| mpl::false_ accept(optional_mark_matcher<Xpr, Greedy> const &) |
| { |
| this->fail(); // a union of xpr and next |
| return mpl::false_(); |
| } |
| |
| //template<typename Xpr, typename Greedy> |
| //mpl::true_ accept(optional_matcher<Xpr, Greedy> const &xpr) |
| //{ |
| // xpr.xpr_.peek(*this); // a union of xpr and next |
| // return mpl::true_(); |
| //} |
| |
| //template<typename Xpr, typename Greedy> |
| //mpl::true_ accept(optional_mark_matcher<Xpr, Greedy> const &xpr) |
| //{ |
| // xpr.xpr_.peek(*this); // a union of xpr and next |
| // return mpl::true_(); |
| //} |
| |
| template<typename Traits> |
| mpl::false_ accept(posix_charset_matcher<Traits> const &xpr) |
| { |
| this->bset_.set_class(xpr.mask_, xpr.not_, this->get_traits_<Traits>()); |
| return mpl::false_(); |
| } |
| |
| template<typename ICase, typename Traits> |
| typename enable_if<is_narrow_char<typename Traits::char_type>, mpl::false_>::type |
| accept(charset_matcher<Traits, ICase, basic_chset<Char> > const &xpr) |
| { |
| BOOST_ASSERT(0 != xpr.charset_.base().count()); |
| this->bset_.set_charset(xpr.charset_, ICase()); |
| return mpl::false_(); |
| } |
| |
| template<typename Traits, typename ICase> |
| mpl::false_ accept(range_matcher<Traits, ICase> const &xpr) |
| { |
| this->bset_.set_range(xpr.ch_min_, xpr.ch_max_, xpr.not_, ICase(), this->get_traits_<Traits>()); |
| return mpl::false_(); |
| } |
| |
| template<typename Xpr, typename Greedy> |
| mpl::false_ accept(simple_repeat_matcher<Xpr, Greedy> const &xpr) |
| { |
| if(Greedy() && 1U == xpr.width_) |
| { |
| ++this->leading_simple_repeat_; |
| xpr.leading_ = this->leading_simple_repeat(); |
| } |
| 0 != xpr.min_ ? xpr.xpr_.peek(*this) : this->fail(); // could be a union of xpr and next |
| return mpl::false_(); |
| } |
| |
| template<typename Xpr> |
| mpl::false_ accept(keeper_matcher<Xpr> const &xpr) |
| { |
| xpr.xpr_.peek(*this); |
| return mpl::false_(); |
| } |
| |
| template<typename Traits> |
| void set_traits(Traits const &tr) |
| { |
| if(0 == this->traits_) |
| { |
| this->traits_ = &tr; |
| this->traits_type_ = &typeid(Traits); |
| } |
| else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr) |
| { |
| this->fail(); // traits mis-match! set all and bail |
| } |
| } |
| |
| private: |
| xpression_peeker(xpression_peeker const &); |
| xpression_peeker &operator =(xpression_peeker const &); |
| |
| template<typename Traits> |
| Traits const &get_traits_() const |
| { |
| BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits))); |
| return *static_cast<Traits const *>(this->traits_); |
| } |
| |
| hash_peek_bitset<Char> &bset_; |
| peeker_string<Char> str_; |
| bool str_icase_; |
| bool line_start_; |
| void const *traits_; |
| std::type_info const *traits_type_; |
| int leading_simple_repeat_; |
| bool has_backrefs_; |
| }; |
| |
| }}} // namespace boost::xpressive::detail |
| |
| #endif |