boost/xpressive/detail/static/static.hpp
///////////////////////////////////////////////////////////////////////////////
// static.hpp
//
// Copyright 2004 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>
// 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
{
#ifdef BOOST_XPR_DEBUG_STACK
///////////////////////////////////////////////////////////////////////////////
// top_type
//
template<typename Top>
struct top_type
{
typedef Top type;
};
///////////////////////////////////////////////////////////////////////////////
// top_type
//
template<typename Top, typename Next>
struct top_type<stacked_xpression<Top, Next> >
{
typedef Next type;
};
#endif
///////////////////////////////////////////////////////////////////////////////
// stacked_xpression
//
template<typename Top, typename Next>
struct stacked_xpression
: Next
{
// match
// delegates to Next
template<typename BidiIter>
bool match(state_type<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(state_type<BidiIter> &state, xpression_base const *top)
{
BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<Top>::type));
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(state_type<BidiIter> &state, xpression_base const *top)
{
BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<Top>::type));
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(state_type<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, state_type<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_;
static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next())
: Matcher(matcher)
, next_(next)
{
}
// match
// delegates to the Matcher
template<typename BidiIter>
bool match(state_type<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(state_type<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, state_type<BidiIter> &state)
{
return that.match(state);
}
// for linking a compiled regular xpression
template<typename Char>
void link(xpression_linker<Char> &linker) const
{
linker.link(*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.peek(*static_cast<Matcher const *>(this)), peeker);
}
// for getting xpression width
template<typename BidiIter>
std::size_t get_width(state_type<BidiIter> *state) const
{
// BUGBUG this gets called from the simple_repeat_matcher::match(), so this is slow.
// or will the compiler be able to optimize this all away?
std::size_t this_width = this->Matcher::get_width(state);
if(this_width == unknown_width())
return unknown_width();
std::size_t that_width = this->next_.get_width(state);
if(that_width == unknown_width())
return unknown_width();
return this_width + that_width;
}
private: // hide this
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>
static void peek_next_(mpl::false_, xpression_peeker<Char> &)
{
// no-op
}
using Matcher::width;
using Matcher::pure;
};
// syntactic sugar so this xpression can be treated the same as
// (a smart pointer to) a dynamic xpression from templates
template<typename Matcher, typename Next>
inline static_xpression<Matcher, Next> const *
get_pointer(static_xpression<Matcher, Next> const &xpr)
{
return &xpr;
}
///////////////////////////////////////////////////////////////////////////////
// make_static_xpression
//
template<typename Matcher>
inline static_xpression<Matcher> const
make_static_xpression(Matcher const &matcher)
{
return static_xpression<Matcher>(matcher);
}
template<typename Matcher, typename Next>
inline static_xpression<Matcher, Next> const
make_static_xpression(Matcher const &matcher, Next const &next)
{
return static_xpression<Matcher, Next>(matcher, next);
}
///////////////////////////////////////////////////////////////////////////////
// no_next
//
struct no_next
: xpression_base
{
template<typename Char>
void link(xpression_linker<Char> &) const
{
}
template<typename Char>
void peek(xpression_peeker<Char> &peeker) const
{
peeker.fail();
}
template<typename BidiIter>
static std::size_t get_width(state_type<BidiIter> *)
{
return 0;
}
};
///////////////////////////////////////////////////////////////////////////////
// alternates_list
//
template<typename Alternates>
struct alternates_list
: Alternates
{
alternates_list(Alternates const &alternates)
: Alternates(alternates)
{
}
private:
alternates_list &operator =(alternates_list const &);
};
///////////////////////////////////////////////////////////////////////////////
// get_mark_number
//
inline int get_mark_number(mark_tag const &mark)
{
return proto::arg(mark).mark_number_;
}
}}} // namespace boost::xpressive::detail
#endif