| /////////////////////////////////////////////////////////////////////////////// |
| // static.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_STATIC_STATIC_HPP_EAN_10_04_2005 |
| #define BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_HPP_EAN_10_04_2005 |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <boost/mpl/assert.hpp> |
| #include <boost/xpressive/detail/detail_fwd.hpp> |
| #include <boost/xpressive/detail/core/state.hpp> |
| #include <boost/xpressive/detail/core/linker.hpp> |
| #include <boost/xpressive/detail/core/peeker.hpp> |
| #include <boost/xpressive/detail/static/placeholders.hpp> |
| #include <boost/xpressive/detail/utility/width.hpp> |
| |
| // Random thoughts: |
| // - must support indirect repeat counts {$n,$m} |
| // - add ws to eat whitespace (make *ws illegal) |
| // - a{n,m} -> repeat<n,m>(a) |
| // - a{$n,$m} -> repeat(n,m)(a) |
| // - add nil to match nothing |
| // - instead of s1, s2, etc., how about s[1], s[2], etc.? Needlessly verbose? |
| |
| namespace boost { namespace xpressive { namespace detail |
| { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // stacked_xpression |
| // |
| template<typename Top, typename Next> |
| struct stacked_xpression |
| : Next |
| { |
| // match |
| // delegates to Next |
| template<typename BidiIter> |
| bool match(match_state<BidiIter> &state) const |
| { |
| return static_cast<Next const *>(this)-> |
| BOOST_NESTED_TEMPLATE push_match<Top>(state); |
| } |
| |
| // top_match |
| // jump back to the xpression on top of the xpression stack, |
| // and keep the xpression on the stack. |
| template<typename BidiIter> |
| static bool top_match(match_state<BidiIter> &state, void const *top) |
| { |
| return static_cast<Top const *>(top)-> |
| BOOST_NESTED_TEMPLATE push_match<Top>(state); |
| } |
| |
| // pop_match |
| // jump back to the xpression on top of the xpression stack, |
| // pop the xpression off the stack. |
| template<typename BidiIter> |
| static bool pop_match(match_state<BidiIter> &state, void const *top) |
| { |
| return static_cast<Top const *>(top)->match(state); |
| } |
| |
| // skip_match |
| // pop the xpression off the top of the stack and ignore it; call |
| // match on next. |
| template<typename BidiIter> |
| bool skip_match(match_state<BidiIter> &state) const |
| { |
| // could be static_xpression::skip_impl or stacked_xpression::skip_impl |
| // depending on if there is 1 or more than 1 xpression on the |
| // xpression stack |
| return Top::skip_impl(*static_cast<Next const *>(this), state); |
| } |
| |
| //protected: |
| |
| // skip_impl |
| // implementation of skip_match. |
| template<typename That, typename BidiIter> |
| static bool skip_impl(That const &that, match_state<BidiIter> &state) |
| { |
| return that.BOOST_NESTED_TEMPLATE push_match<Top>(state); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // stacked_xpression_cast |
| // |
| template<typename Top, typename Next> |
| inline stacked_xpression<Top, Next> const &stacked_xpression_cast(Next const &next) |
| { |
| // NOTE: this is a little white lie. The "next" object doesn't really have |
| // the type to which we're casting it. It is harmless, though. We are only using |
| // the cast to decorate the next object with type information. It is done |
| // this way to save stack space. |
| BOOST_MPL_ASSERT_RELATION(sizeof(stacked_xpression<Top, Next>), ==, sizeof(Next)); |
| return *static_cast<stacked_xpression<Top, Next> const *>(&next); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // static_xpression |
| // |
| template<typename Matcher, typename Next> |
| struct static_xpression |
| : Matcher |
| { |
| Next next_; |
| |
| BOOST_STATIC_CONSTANT(bool, pure = Matcher::pure && Next::pure); |
| BOOST_STATIC_CONSTANT( |
| std::size_t |
| , width = |
| Matcher::width != unknown_width::value && Next::width != unknown_width::value |
| ? Matcher::width + Next::width |
| : unknown_width::value |
| ); |
| |
| static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next()) |
| : Matcher(matcher) |
| , next_(next) |
| { |
| } |
| |
| // match |
| // delegates to the Matcher |
| template<typename BidiIter> |
| bool match(match_state<BidiIter> &state) const |
| { |
| return this->Matcher::match(state, this->next_); |
| } |
| |
| // push_match |
| // call match on this, but also push "Top" onto the xpression |
| // stack so we know what we are jumping back to later. |
| template<typename Top, typename BidiIter> |
| bool push_match(match_state<BidiIter> &state) const |
| { |
| return this->Matcher::match(state, stacked_xpression_cast<Top>(this->next_)); |
| } |
| |
| // skip_impl |
| // implementation of skip_match, called from stacked_xpression::skip_match |
| template<typename That, typename BidiIter> |
| static bool skip_impl(That const &that, match_state<BidiIter> &state) |
| { |
| return that.match(state); |
| } |
| |
| // for linking a compiled regular xpression |
| template<typename Char> |
| void link(xpression_linker<Char> &linker) const |
| { |
| linker.accept(*static_cast<Matcher const *>(this), &this->next_); |
| this->next_.link(linker); |
| } |
| |
| // for building a lead-follow |
| template<typename Char> |
| void peek(xpression_peeker<Char> &peeker) const |
| { |
| this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker); |
| } |
| |
| // for getting xpression width |
| detail::width get_width() const |
| { |
| return this->get_width_(mpl::size_t<width>()); |
| } |
| |
| private: |
| |
| static_xpression &operator =(static_xpression const &); |
| |
| template<typename Char> |
| void peek_next_(mpl::true_, xpression_peeker<Char> &peeker) const |
| { |
| this->next_.peek(peeker); |
| } |
| |
| template<typename Char> |
| void peek_next_(mpl::false_, xpression_peeker<Char> &) const |
| { |
| // no-op |
| } |
| |
| template<std::size_t Width> |
| detail::width get_width_(mpl::size_t<Width>) const |
| { |
| return Width; |
| } |
| |
| detail::width get_width_(unknown_width) const |
| { |
| // Should only be called in contexts where the width is |
| // known to be fixed. |
| return this->Matcher::get_width() + this->next_.get_width(); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // make_static |
| // |
| template<typename Matcher> |
| inline static_xpression<Matcher> const |
| make_static(Matcher const &matcher) |
| { |
| return static_xpression<Matcher>(matcher); |
| } |
| |
| template<typename Matcher, typename Next> |
| inline static_xpression<Matcher, Next> const |
| make_static(Matcher const &matcher, Next const &next) |
| { |
| return static_xpression<Matcher, Next>(matcher, next); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // no_next |
| // |
| struct no_next |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, width = 0); |
| BOOST_STATIC_CONSTANT(bool, pure = true); |
| |
| template<typename Char> |
| void link(xpression_linker<Char> &) const |
| { |
| } |
| |
| template<typename Char> |
| void peek(xpression_peeker<Char> &peeker) const |
| { |
| peeker.fail(); |
| } |
| |
| detail::width get_width() const |
| { |
| return 0; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // get_mark_number |
| // |
| inline int get_mark_number(basic_mark_tag const &mark) |
| { |
| return proto::value(mark).mark_number_; |
| } |
| |
| }}} // namespace boost::xpressive::detail |
| |
| #endif |