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