xpressive 0.9.8

[SVN r31203]
This commit is contained in:
Eric Niebler
2005-10-06 00:42:53 +00:00
commit f0e4ac1bc2
149 changed files with 22860 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////////
/// \file basic_regex.hpp
/// Contains the definition of the basic_regex\<\> class template and its
/// associated helper functions.
//
// 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_BASIC_REGEX_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#ifndef NDEBUG
# include <iosfwd>
#endif
#include <boost/utility/enable_if.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/regex_traits.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/finder.hpp>
#include <boost/xpressive/detail/core/adaptor.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/static/type_traits.hpp>
#include <boost/xpressive/detail/static/productions/visitor.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// optimize_regex
//
template<typename BidiIterT, typename TraitsT>
inline typename enable_if<is_random<BidiIterT> >::type
optimize_regex(regex_impl<BidiIterT> &impl, TraitsT const &traits)
{
typedef typename iterator_value<BidiIterT>::type char_type;
// optimization: get the peek chars OR the boyer-moore search string
hash_peek_bitset<char_type> bset;
xpression_peeker<char_type> peeker(&bset, traits);
impl.xpr_->peek(peeker);
// if we have a leading string literal, initialize a boyer-moore struct with it
std::pair<std::basic_string<char_type> const *, bool> str = peeker.get_string();
if(0 != str.first)
{
impl.finder_.reset
(
new boyer_moore_finder<BidiIterT, TraitsT>
(
str.first->data()
, str.first->data() + str.first->size()
, traits
, str.second
)
);
}
else if(peeker.line_start())
{
impl.finder_.reset
(
new line_start_finder<BidiIterT, TraitsT>(traits)
);
}
else if(256 != bset.count())
{
impl.finder_.reset
(
new hash_peek_finder<BidiIterT, TraitsT>(bset)
);
}
}
///////////////////////////////////////////////////////////////////////////////
// optimize_regex
//
template<typename BidiIterT, typename TraitsT>
inline typename disable_if<is_random<BidiIterT> >::type
optimize_regex(regex_impl<BidiIterT> &impl, TraitsT const &traits)
{
typedef typename iterator_value<BidiIterT>::type char_type;
// optimization: get the peek chars OR the line start finder
hash_peek_bitset<char_type> bset;
xpression_peeker<char_type> peeker(&bset, traits);
impl.xpr_->peek(peeker);
if(peeker.line_start())
{
impl.finder_.reset
(
new line_start_finder<BidiIterT, TraitsT>(traits)
);
}
else if(256 != bset.count())
{
impl.finder_.reset
(
new hash_peek_finder<BidiIterT, TraitsT>(bset)
);
}
}
} // namespace detail
///////////////////////////////////////////////////////////////////////////////
// basic_regex
//
/// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression.
template<typename BidiIterT>
struct basic_regex
{
typedef BidiIterT iterator_type;
typedef typename iterator_value<BidiIterT>::type char_type;
typedef std::basic_string<char_type> string_type;
typedef regex_constants::syntax_option_type flag_type;
/// \post regex_id() == 0
/// \post mark_count() == 0
basic_regex()
: impl_()
{
}
/// \param that The basic_regex object to copy.
/// \post regex_id() == that.regex_id()
/// \post mark_count() == that.mark_count()
basic_regex(basic_regex<BidiIterT> const &that)
: impl_(that.impl_)
{
}
/// \param that The basic_regex object to copy.
/// \post regex_id() == that.regex_id()
/// \post mark_count() == that.mark_count()
/// \return *this
basic_regex<BidiIterT> &operator =(basic_regex<BidiIterT> const &that)
{
this->impl_ = that.impl_;
return *this;
}
/// Construct from a static regular expression.
///
/// \param xpr The static regular expression
/// \pre XprT is the type of a static regular expression.
/// \post regex_id() != 0
/// \post mark_count() \>= 0
template<typename XprT>
basic_regex(XprT const &xpr)
: impl_()
{
this->operator =(xpr);
}
/// Construct from a static regular expression.
///
/// \param xpr The static regular expression.
/// \pre XprT is the type of a static regular expression.
/// \post regex_id() != 0
/// \post mark_count() \>= 0
/// \throw std::bad_alloc on out of memory
/// \return *this
template<typename XprT>
basic_regex<BidiIterT> &operator =(XprT const &xpr)
{
// use default traits
typedef regex_traits<char_type> traits_type;
this->compile_(xpr, traits_type());
return *this;
}
/// INTERNAL ONLY
template<typename LocaleT, typename XprT>
basic_regex<BidiIterT> &operator =
(
proto::binary_op<detail::locale_modifier<LocaleT>, XprT, detail::modifier_tag> const &xpr
)
{
// use specified traits
typedef typename detail::regex_traits_type<LocaleT, BidiIterT>::type traits_type;
this->compile_(proto::right(xpr), traits_type(proto::left(xpr).getloc()));
return *this;
}
/// Returns the count of capturing sub-expressions in this regular expression
///
std::size_t mark_count() const
{
return this->impl_ ? this->impl_->mark_count_ : 0;
}
/// Returns a token which uniquely identifies this regular expression.
///
regex_id_type regex_id() const
{
return this->impl_ ? this->impl_->xpr_.get() : 0;
}
/// Swaps the contents of this basic_regex object with another.
///
/// \param that The other basic_regex object.
/// \attention This is a shallow swap that does not do reference tracking. If you embed
/// a basic_regex object by reference in another regular expression and then swap its
/// contents with another basic_regex object, the change will not be visible to the enclosing
/// regular expression. It is done this way to ensure that swap() cannot throw.
/// \throw nothrow
void swap(basic_regex<BidiIterT> &that) // throw()
{
this->impl_.swap(that.impl_);
}
/// Factory method for building a regex object from a string.
/// Equivalent to regex_compiler\< BidiIterT \>().compile(str, flags);
///
/// \param str The std::basic_string containing the regular expression.
/// \param flags Optional bitmask of type syntax_option_type to control how str is interpreted.
static basic_regex<BidiIterT> compile(string_type const &str, flag_type flags = regex_constants::ECMAScript)
{
return regex_compiler<BidiIterT>().compile(str, flags);
}
// for binding actions to this regex when it is nested statically in another regex
/// INTERNAL ONLY
template<typename ActionT>
proto::binary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_op<ActionT, proto::noop_tag>
, proto::right_shift_tag
> const
operator [](detail::action_matcher<ActionT> const &action) const
{
return proto::noop(*this) >> proto::noop(*static_cast<ActionT const *>(&action));
}
//{{AFX_DEBUG
#ifndef NDEBUG
// BUGBUG debug only
/// INTERNAL ONLY
friend std::ostream &operator <<(std::ostream &sout, basic_regex<BidiIterT> const &rex)
{
rex.dump_(sout);
return sout;
}
#endif
//}}AFX_DEBUG
private:
friend struct detail::core_access<BidiIterT>;
// Avoid a common programming mistake. Construction from a string is ambiguous. It could mean
// sregex rx = sregex::compile(str); // compile the string into a regex
// or
// sregex rx = str >> epsilon; // treat the string as a literal
// Since there is no easy way to disambiguate, disallow it and force users to say what they mean
/// INTERNAL ONLY
basic_regex(char_type const *);
/// INTERNAL ONLY
basic_regex(string_type const &);
// used from parser, via core_access
/// INTERNAL ONLY
explicit basic_regex(detail::regex_impl<BidiIterT> const &that)
: impl_()
{
this->impl_.tracking_copy(that);
}
/// INTERNAL ONLY
template<typename XprT, typename TraitsT>
void compile_(XprT const &xpr, TraitsT const &traits)
{
// "compile" the regex and wrap it in an xpression_adaptor
detail::xpression_visitor<BidiIterT, mpl::false_, TraitsT> visitor(traits, this->impl_.get());
visitor.impl().traits_.reset(new TraitsT(visitor.traits()));
visitor.impl().xpr_ =
detail::make_adaptor<BidiIterT>(proto::compile(xpr, detail::end_xpression(), visitor, detail::seq_tag()));
// "link" the regex
detail::xpression_linker<char_type> linker(visitor.traits());
visitor.impl().xpr_->link(linker);
// optimization: get the peek chars OR the boyer-moore search string
detail::optimize_regex(visitor.impl(), visitor.traits());
// copy the implementation
this->impl_.tracking_copy(visitor.impl());
}
/// INTERNAL ONLY
bool match_(detail::state_type<BidiIterT> &state) const
{
return this->impl_->xpr_->match(state);
}
// Returns true if this basic_regex object does not contain a valid regular expression.
/// INTERNAL ONLY
bool invalid_() const
{
return !this->impl_ || !this->impl_->xpr_;
}
/// INTERNAL ONLY
void dump_(std::ostream &sout) const;
// the tracking_ptr manages lazy-init, COW, cycle-breaking, and
// reference/dependency tracking.
detail::tracking_ptr<detail::regex_impl<BidiIterT> > impl_;
};
//{{AFX_DEBUG
#ifndef NDEBUG
///////////////////////////////////////////////////////////////////////////////
// dump_
/// INTERNAL ONLY
template<typename BidiIterT>
inline void basic_regex<BidiIterT>::dump_(std::ostream &sout) const
{
if(!this->impl_)
{
sout << "<null> refs={} deps={}";
}
else
{
sout << *this->impl_;
}
}
#endif
//}}AFX_DEBUG
///////////////////////////////////////////////////////////////////////////////
// swap
/// \brief Swaps the contents of two basic_regex objects.
/// \param left The first basic_regex object.
/// \param right The second basic_regex object.
/// \attention This is a shallow swap that does not do reference tracking.
/// If you embed a basic_regex object by reference in another regular expression
/// and then swap its contents with another basic_regex object, the change will
/// not be visible to the enclosing regular expression. It is done this way to
/// ensure that swap() cannot throw.
/// \throw nothrow
template<typename BidiIterT>
inline void swap(basic_regex<BidiIterT> &left, basic_regex<BidiIterT> &right) // throw()
{
left.swap(right);
}
}} // namespace boost::xpressive
#endif // BOOST_XPRESSIVE_REGEX_HPP_EAN_10_04_2005

View File

@@ -0,0 +1,131 @@
///////////////////////////////////////////////////////////////////////////////
// accesss.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_CORE_ACCESS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// core_access
//
template<typename BidiIterT>
struct core_access
{
// BUGBUG give basic_regex move semantics!
static basic_regex<BidiIterT> make_regex(regex_impl<BidiIterT> const &impl)
{
return basic_regex<BidiIterT>(impl);
}
static std::size_t get_hidden_mark_count(basic_regex<BidiIterT> const &rex)
{
return rex.impl_->hidden_mark_count_;
}
static bool invalid(basic_regex<BidiIterT> const &rex)
{
return rex.invalid_();
}
static bool match(basic_regex<BidiIterT> const &rex, state_type<BidiIterT> &state)
{
return rex.match_(state);
}
static shared_ptr<detail::regex_impl<BidiIterT> > const &
get_regex_impl(basic_regex<BidiIterT> const &rex)
{
return rex.impl_.get();
}
static void init_sub_match_vector
(
sub_match_vector<BidiIterT> &subs_vect
, sub_match_impl<BidiIterT> *subs_ptr
, std::size_t size
)
{
subs_vect.init_(subs_ptr, size);
}
static void init_sub_match_vector
(
sub_match_vector<BidiIterT> &subs_vect
, sub_match_impl<BidiIterT> *subs_ptr
, std::size_t size
, sub_match_vector<BidiIterT> const &that
)
{
subs_vect.init_(subs_ptr, size, that);
}
static void init_match_results
(
match_results<BidiIterT> &what
, regex_id_type regex_id
, sub_match_impl<BidiIterT> *sub_matches
, std::size_t size
)
{
what.init_(regex_id, sub_matches, size);
}
static sub_match_vector<BidiIterT> &get_sub_match_vector(match_results<BidiIterT> &what)
{
return what.sub_matches_;
}
static sub_match_impl<BidiIterT> *get_sub_matches(sub_match_vector<BidiIterT> &subs)
{
return subs.sub_matches_;
}
static results_extras<BidiIterT> &get_extras(match_results<BidiIterT> &what)
{
return what.get_extras_();
}
static nested_results<BidiIterT> &get_nested_results(match_results<BidiIterT> &what)
{
return what.nested_results_;
}
static action_state &get_action_state(match_results<BidiIterT> &what)
{
return what.action_state_;
}
static void set_prefix_suffix(match_results<BidiIterT> &what, BidiIterT begin, BidiIterT end)
{
what.set_prefix_suffix_(begin, end);
}
static void reset(match_results<BidiIterT> &what)
{
what.reset_();
}
static void set_base(match_results<BidiIterT> &what, BidiIterT base)
{
what.set_base_(base);
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// action.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_CORE_ACTION_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACTION_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <typeinfo>
#include <stdexcept>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/action_state.hpp>
#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
namespace boost { namespace xpressive
{
///////////////////////////////////////////////////////////////////////////////
// action
//
template<typename ActionT, typename SavedT>
struct action
: detail::action_matcher<ActionT>
{
typedef ActionT action_type;
typedef SavedT saved_type;
SavedT &save()
{
return *static_cast<SavedT *>(this);
}
template<typename BidiIterT>
bool operator ()(match_results<BidiIterT> const &match, BidiIterT cur)
{
return true;
}
void restore(SavedT const &saved)
{
this->action_() = saved;
}
};
template<typename ActionT>
struct action<ActionT, void>
: action<ActionT, int>
{
int save()
{
return 0;
}
void restore(int)
{
}
};
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,72 @@
///////////////////////////////////////////////////////////////////////////////
// action_state.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_CORE_ACTION_STATE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACTION_STATE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <typeinfo>
#include <stdexcept>
#include <boost/assert.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// type_info_ex
//
template<typename T>
struct type_info_ex
{
static std::type_info const *const type_info_ptr_;
};
template<typename T>
std::type_info const *const type_info_ex<T>::type_info_ptr_ = &typeid(T);
///////////////////////////////////////////////////////////////////////////////
// action_state
//
struct action_state
{
action_state()
: type_ptr_(0)
, ptr_(0)
{
}
template<typename StateT>
void set(StateT &state)
{
this->type_ptr_ = &type_info_ex<StateT>::type_info_ptr_;
this->ptr_ = &state;
}
template<typename StateT>
StateT &get() const
{
if(&type_info_ex<StateT>::type_info_ptr_ != this->type_ptr_ &&
(0 == this->type_ptr_ || **this->type_ptr_ != typeid(StateT)))
{
throw std::invalid_argument(std::string("bad action_state_cast"));
}
BOOST_ASSERT(0 != this->ptr_);
return *static_cast<StateT *>(this->ptr_);
}
std::type_info const *const *type_ptr_;
void *ptr_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,75 @@
///////////////////////////////////////////////////////////////////////////////
// adaptor.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_CORE_ADAPTOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ADAPTOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/shared_ptr.hpp>
#include <boost/call_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// xpression_adaptor
//
// wrap a static xpression in a matchable interface so it can be stored
// in and invoked from a basic_regex object.
template<typename XprT, typename BidiIterT>
struct xpression_adaptor
: matchable<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
XprT xpr_;
xpression_adaptor(typename call_traits<XprT>::param_type xpr)
: xpr_(xpr)
{
}
bool match(state_type<BidiIterT> &state) const
{
return this->xpr_.match(state);
}
std::size_t get_width(state_type<BidiIterT> *state) const
{
return this->xpr_.get_width(state);
}
void link(xpression_linker<char_type> &linker) const
{
this->xpr_.link(linker);
}
void peek(xpression_peeker<char_type> &peeker) const
{
this->xpr_.peek(peeker);
}
};
///////////////////////////////////////////////////////////////////////////////
// make_adaptor
//
template<typename BidiIterT, typename XprT>
inline shared_ptr<matchable<BidiIterT> const> make_adaptor(XprT const &xpr)
{
return shared_ptr<matchable<BidiIterT> const>(new xpression_adaptor<XprT, BidiIterT>(xpr));
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,180 @@
/// Contains the definition of the basic_regex\<\> class template and its associated helper functions.
//
// 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_CORE_FINDER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_FINDER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/utility/boyer_moore.hpp>
//#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// boyer_moore_finder
//
template<typename BidiIterT, typename TraitsT>
struct boyer_moore_finder
: finder<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
boyer_moore_finder(char_type const *begin, char_type const *end, TraitsT const &tr, bool icase)
: bm_(begin, end, tr, icase)
{
}
bool operator ()(state_type<BidiIterT> &state) const
{
TraitsT const &traits = traits_cast<TraitsT>(state);
state.cur_ = this->bm_.find(state.cur_, state.end_, traits);
return state.cur_ != state.end_;
}
private:
boyer_moore<BidiIterT, TraitsT> bm_;
};
///////////////////////////////////////////////////////////////////////////////
// hash_peek_finder
//
template<typename BidiIterT, typename TraitsT>
struct hash_peek_finder
: finder<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
hash_peek_finder(hash_peek_bitset<char_type> const &bset)
: bset_(bset)
{
}
bool operator ()(state_type<BidiIterT> &state) const
{
TraitsT const &traits = traits_cast<TraitsT>(state);
state.cur_ = (this->bset_.icase()
? this->find_(state.cur_, state.end_, traits, mpl::true_())
: this->find_(state.cur_, state.end_, traits, mpl::false_()));
return state.cur_ != state.end_;
}
private:
template<typename ICaseT>
BidiIterT find_(BidiIterT begin, BidiIterT end, TraitsT const &traits, ICaseT) const
{
for(; begin != end && !this->bset_.test(*begin, traits, ICaseT()); ++begin)
;
return begin;
}
hash_peek_bitset<char_type> bset_;
};
///////////////////////////////////////////////////////////////////////////////
// line_start_finder
//
template<typename BidiIterT, typename TraitsT, std::size_t SizeT = sizeof(typename iterator_value<BidiIterT>::type)>
struct line_start_finder
: finder<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef typename iterator_difference<BidiIterT>::type diff_type;
typedef typename TraitsT::char_class_type char_class_type;
line_start_finder(TraitsT const &traits)
: newline_(lookup_classname(traits, "newline"))
{
}
bool operator ()(state_type<BidiIterT> &state) const
{
if(state.bos() && state.flags_.match_bol_)
{
return true;
}
TraitsT const &traits = traits_cast<TraitsT>(state);
BidiIterT cur = state.cur_;
BidiIterT const end = state.end_;
std::advance(cur, static_cast<diff_type>(-!state.bos()));
for(; cur != end; ++cur)
{
if(traits.isctype(*cur, this->newline_))
{
state.cur_ = ++cur;
return true;
}
}
return false;
}
private:
char_class_type newline_;
};
///////////////////////////////////////////////////////////////////////////////
// line_start_finder
//
template<typename BidiIterT, typename TraitsT>
struct line_start_finder<BidiIterT, TraitsT, 1u>
: finder<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef typename iterator_difference<BidiIterT>::type diff_type;
typedef typename TraitsT::char_class_type char_class_type;
line_start_finder(TraitsT const &traits)
{
char_class_type newline = lookup_classname(traits, "newline");
for(int j = 0; j < 256; ++j)
{
this->bits_[j] = traits.isctype(static_cast<char_type>(static_cast<unsigned char>(j)), newline);
}
}
bool operator ()(state_type<BidiIterT> &state) const
{
if(state.bos() && state.flags_.match_bol_)
{
return true;
}
BidiIterT cur = state.cur_;
BidiIterT const end = state.end_;
std::advance(cur, static_cast<diff_type>(-!state.bos()));
for(; cur != end; ++cur)
{
if(this->bits_[static_cast<unsigned char>(*cur)])
{
state.cur_ = ++cur;
return true;
}
}
return false;
}
private:
bool bits_[256];
};
}}}
#endif

View File

@@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////
// flow_control.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_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// push_context_match
//
template<typename BidiIterT>
inline bool push_context_match
(
regex_impl<BidiIterT> const &impl
, state_type<BidiIterT> &state
, matchable<BidiIterT> const &next
)
{
// save state
match_context<BidiIterT> context = state.push_context(impl, next, context);
// match the nested regex
bool success = impl.xpr_->match(state);
// uninitialize the match context (reclaims the sub_match objects if necessary)
state.pop_context(impl, success);
return success;
}
///////////////////////////////////////////////////////////////////////////////
// pop_context_match
//
template<typename BidiIterT>
inline bool pop_context_match(state_type<BidiIterT> &state)
{
// save state
// BUGBUG nested regex could have changed state.traits_
match_context<BidiIterT> &context(*state.context_.prev_context_);
state.swap_context(context);
// Finished matching the nested regex; now match the rest of the enclosing regex
bool success = context.next_ptr_->match(state);
// restore state
state.swap_context(context);
return success;
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,30 @@
///////////////////////////////////////////////////////////////////////////////
// icase.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_CORE_ICASE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ICASE_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/static/modifier.hpp>
#include <boost/xpressive/detail/core/linker.hpp>
namespace boost { namespace xpressive
{
namespace regex_constants { namespace
{
detail::modifier_op<detail::icase_modifier> const icase = {{}, regex_constants::icase_};
}} // namespace regex_constants::anonymous-namespace
using regex_constants::icase;
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,260 @@
///////////////////////////////////////////////////////////////////////////////
// linker.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_CORE_LINKER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <stack>
#include <limits>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/spirit/fusion/algorithm/for_each.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/core/peeker.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// icase_modifier
//
// wrapped by the modifier<> template and inserted into the xpression
// template with the icase() helper function. icase_modifier morphs
// a case-sensitive visitor into a case-insensitive visitor, which
// causes all matchers visited to become case-insensitive.
//
struct icase_modifier
{
template<typename VisitorT>
struct apply;
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct apply<xpression_visitor<BidiIterT, ICaseT, TraitsT> >
{
typedef xpression_visitor<BidiIterT, mpl::true_, TraitsT> type;
};
template<typename VisitorT>
static typename apply<VisitorT>::type
call(VisitorT &visitor)
{
return typename apply<VisitorT>::type(visitor.traits(), visitor.self());
}
};
///////////////////////////////////////////////////////////////////////////////
// regex_traits_type : wrap a locale in the appropriate regex_traits
//
template<typename LocaleT, typename BidiIterT>
struct regex_traits_type
{
#ifndef BOOST_NO_STD_LOCALE
typedef typename iterator_value<BidiIterT>::type char_type;
// if LocaleT is std::locale, wrap it in a cpp_regex_traits<CharT>
typedef typename mpl::if_
<
is_same<LocaleT, std::locale>
, cpp_regex_traits<char_type>
, LocaleT
>::type type;
#else
typedef LocaleT type;
#endif
};
///////////////////////////////////////////////////////////////////////////////
// locale_modifier
//
// wrapped by the modifier<> template and inserted into the xpression
// template with the imbue() helper function. Causes a sub-xpression to
// use the specified LocaleT
//
template<typename LocaleT>
struct locale_modifier
{
locale_modifier(LocaleT const &loc)
: loc_(loc)
{
}
template<typename VisitorT>
struct apply;
template<typename BidiIterT, typename ICaseT, typename OtherTraitsT>
struct apply<xpression_visitor<BidiIterT, ICaseT, OtherTraitsT> >
{
typedef typename regex_traits_type<LocaleT, BidiIterT>::type traits_type;
typedef xpression_visitor<BidiIterT, ICaseT, traits_type> type;
};
template<typename VisitorT>
typename apply<VisitorT>::type
call(VisitorT &) const
{
return typename apply<VisitorT>::type(this->loc_);
}
LocaleT getloc() const
{
return this->loc_;
}
private:
LocaleT loc_;
};
///////////////////////////////////////////////////////////////////////////////
// xpression_linker
//
template<typename CharT>
struct xpression_linker
{
template<typename TraitsT>
explicit xpression_linker(TraitsT const &traits)
: back_stack_()
, traits_(&traits)
, traits_type_(&typeid(TraitsT))
{
}
template<typename MatcherT>
void link(MatcherT const &, xpression_base const *)
{
// no-op
}
void link(repeat_begin_matcher const &, xpression_base const *next)
{
this->back_stack_.push(next);
}
template<bool GreedyT>
void link(repeat_end_matcher<GreedyT> const &matcher, xpression_base const *)
{
matcher.back_ = this->back_stack_.top();
this->back_stack_.pop();
}
template<typename AlternatesT, typename TraitsT>
void link(alternate_matcher<AlternatesT, TraitsT> const &matcher, xpression_base const *next)
{
xpression_peeker<CharT> peeker(&matcher.bset_, this->get_traits<TraitsT>());
this->alt_link(matcher.alternates_, next, peeker);
}
void link(alternate_end_matcher const &matcher, xpression_base const *)
{
matcher.back_ = this->back_stack_.top();
this->back_stack_.pop();
}
template<typename XprT>
void link(keeper_matcher<XprT> const &matcher, xpression_base const *)
{
get_pointer(matcher.xpr_)->link(*this);
}
template<typename XprT>
void link(lookahead_matcher<XprT> const &matcher, xpression_base const *)
{
get_pointer(matcher.xpr_)->link(*this);
}
template<typename XprT>
void link(lookbehind_matcher<XprT> const &matcher, xpression_base const *)
{
get_pointer(matcher.xpr_)->link(*this);
}
template<typename XprT, bool GreedyT>
void link(simple_repeat_matcher<XprT, GreedyT> const &matcher, xpression_base const *)
{
matcher.xpr_.link(*this);
}
private:
///////////////////////////////////////////////////////////////////////////////
// alt_link_pred
//
struct alt_link_pred
{
xpression_linker<CharT> &linker_;
xpression_peeker<CharT> &peeker_;
xpression_base const *next_;
alt_link_pred
(
xpression_linker<CharT> &linker
, xpression_peeker<CharT> &peeker
, xpression_base const *next
)
: linker_(linker)
, peeker_(peeker)
, next_(next)
{
}
template<typename XprT>
void operator ()(XprT const &xpr) const
{
this->linker_.back_stack_.push(this->next_);
get_pointer(xpr)->link(this->linker_);
get_pointer(xpr)->peek(this->peeker_);
}
};
template<typename BidiIterT>
void alt_link
(
std::vector<shared_ptr<matchable<BidiIterT> const> > const &alternates
, xpression_base const *next
, xpression_peeker<CharT> &peeker
)
{
std::for_each(alternates.begin(), alternates.end(), alt_link_pred(*this, peeker, next));
}
template<typename AlternatesT>
void alt_link
(
fusion::sequence_base<AlternatesT> const &alternates
, xpression_base const *next
, xpression_peeker<CharT> &peeker
)
{
fusion::for_each(alternates.cast(), alt_link_pred(*this, peeker, next));
}
template<typename TraitsT>
TraitsT const &get_traits() const
{
BOOST_ASSERT(*this->traits_type_ == typeid(TraitsT));
return *static_cast<TraitsT const *>(this->traits_);
}
std::stack<xpression_base const *> back_stack_;
void const *traits_;
std::type_info const *traits_type_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
// action_matcher.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_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/access.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// action_matcher
//
template<typename ActionT>
struct action_matcher
: quant_style<quant_none, mpl::size_t<0>, mpl::false_>
{
ActionT *action_ptr_;
action_matcher()
: action_ptr_(&action_())
{
}
action_matcher(action_matcher const &)
: action_ptr_(&action_())
{
}
action_matcher &operator =(action_matcher const &)
{
return *this; // no-op
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
ActionT &action = *this->action_ptr_;
typename ActionT::saved_type saved(action.save());
// set the action state pointer, so that action_state_cast works correctly
core_access<BidiIterT>::get_action_state(*state.context_.results_ptr_) = state.action_state_;
match_results<BidiIterT> const &what = *state.context_.results_ptr_;
if(!action(what, state.cur_) || !next.match(state))
{
action.restore(saved);
return false;
}
return true;
}
protected:
ActionT &action_()
{
return *static_cast<ActionT *>(this);
}
};
}}}
#endif

View File

@@ -0,0 +1,45 @@
///////////////////////////////////////////////////////////////////////////////
// alternate_end_matcher.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_CORE_MATCHER_ALTERNATE_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alternate_end_matcher
//
struct alternate_end_matcher
: quant_style_assertion
{
mutable xpression_base const *back_;
alternate_end_matcher()
: back_(0)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
return next.pop_match(state, this->back_);
}
};
}}}
#endif

View File

@@ -0,0 +1,196 @@
///////////////////////////////////////////////////////////////////////////////
// alternate_matcher.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_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/spirit/fusion/sequence/range.hpp>
#include <boost/spirit/fusion/algorithm/any.hpp>
#include <boost/spirit/fusion/algorithm/for_each.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
#include <boost/xpressive/detail/static/is_pure.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alt_match_pred
//
template<typename BidiIterT, typename NextT>
struct alt_match_pred
{
state_type<BidiIterT> &state_;
alt_match_pred(state_type<BidiIterT> &state)
: state_(state)
{
}
template<typename XprT>
bool operator ()(XprT const &xpr) const
{
return get_pointer(xpr)->BOOST_NESTED_TEMPLATE push_match<NextT>(this->state_);
}
};
///////////////////////////////////////////////////////////////////////////////
// alt_match
//
template<typename BidiIterT>
inline bool alt_match
(
std::vector<shared_ptr<matchable<BidiIterT> const> > const &alternates
, state_type<BidiIterT> &state
, matchable<BidiIterT> const &
)
{
typedef alt_match_pred<BidiIterT, matchable<BidiIterT> > alt_match_pred;
return detail::any(alternates.begin(), alternates.end(), alt_match_pred(state));
}
template<typename BidiIterT, typename NextT, typename AlternatesT>
inline bool alt_match
(
fusion::sequence_base<AlternatesT> const &alternates
, state_type<BidiIterT> &state
, NextT const &
)
{
typedef alt_match_pred<BidiIterT, NextT> alt_match_pred;
return fusion::any(alternates.cast(), alt_match_pred(state));
}
///////////////////////////////////////////////////////////////////////////////
// make_range
template<typename BeginT, typename EndT>
inline fusion::range<BeginT, EndT> make_range(BeginT const &begin, EndT const &end)
{
return fusion::range<BeginT, EndT>(begin, end);
}
///////////////////////////////////////////////////////////////////////////////
// alt_get_width_pred
//
template<typename BidiIterT>
struct alt_get_width_pred
{
state_type<BidiIterT> *state_;
std::size_t *width_;
alt_get_width_pred(state_type<BidiIterT> *state, std::size_t *width)
: state_(state)
, width_(width)
{
}
template<typename XprT>
void operator ()(XprT const &xpr) const
{
if(*this->width_ != unknown_width())
{
std::size_t that_width = get_pointer(xpr)->get_width(this->state_);
if(*this->width_ != that_width)
{
*this->width_ = unknown_width();
}
}
}
};
///////////////////////////////////////////////////////////////////////////////
// alt_get_width
//
template<typename BidiIterT>
inline std::size_t alt_get_width
(
std::vector<shared_ptr<matchable<BidiIterT> const> > const &alternates
, state_type<BidiIterT> *state
)
{
typedef alt_get_width_pred<BidiIterT> alt_get_width_pred;
std::size_t width = alternates.front()->get_width(state);
std::for_each(alternates.begin() + 1, alternates.end(), alt_get_width_pred(state, &width));
return width;
}
template<typename BidiIterT, typename AlternatesT>
inline std::size_t alt_get_width
(
fusion::sequence_base<AlternatesT> const &alternates
, state_type<BidiIterT> *state
)
{
typedef alt_get_width_pred<BidiIterT> alt_get_width_pred;
std::size_t width = (*fusion::begin(alternates.cast())).get_width(state);
fusion::for_each
(
make_range(fusion::next(fusion::begin(alternates.cast())), fusion::end(alternates.cast()))
, alt_get_width_pred(state, &width)
);
return width;
}
///////////////////////////////////////////////////////////////////////////////
// alternate_matcher
//
template<typename AlternatesT, typename TraitsT>
struct alternate_matcher
: quant_style_auto<width_of<AlternatesT>, is_pure<AlternatesT> >
{
typedef AlternatesT alternates_type;
typedef typename TraitsT::char_type char_type;
AlternatesT alternates_;
mutable hash_peek_bitset<char_type> bset_;
explicit alternate_matcher(AlternatesT const &alternates = AlternatesT())
: alternates_(alternates)
, bset_()
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(!this->can_match_(*state.cur_, traits_cast<TraitsT>(state)))
{
return false;
}
return detail::alt_match(this->alternates_, state, next);
}
template<typename BidiIterT>
std::size_t get_width(state_type<BidiIterT> *state) const
{
return detail::alt_get_width(this->alternates_, state);
}
private:
bool can_match_(char_type ch, TraitsT const &traits) const
{
return this->bset_.test(ch, traits);
}
};
}}}
#endif

View File

@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////
// any_matcher.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_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// any_matcher
//
struct any_matcher
: quant_style_fixed_width<1>
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &state, NextT const &next)
{
if(state.eos())
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////////
// assert_bol_matcher.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_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_bol_matcher
//
template<typename TraitsT>
struct assert_bol_matcher
: assert_line_base<TraitsT>
{
assert_bol_matcher(TraitsT const &traits)
: assert_line_base<TraitsT>(traits)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.bos())
{
if(!state.flags_.match_bol_)
{
return false;
}
}
else if(!this->is_line_break(state))
{
return false;
}
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// assert_bos_matcher.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_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_bos_matcher
// match the beginning of the sequence (\A)
struct assert_bos_matcher
: quant_style_assertion
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &state, NextT const &next)
{
return state.bos() && next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////////
// assert_eol_matcher.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_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_eol_matcher
//
template<typename TraitsT>
struct assert_eol_matcher
: assert_line_base<TraitsT>
{
assert_eol_matcher(TraitsT const &traits)
: assert_line_base<TraitsT>(traits)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos())
{
if(!state.flags_.match_eol_)
{
return false;
}
}
else if((state.bos() && !state.flags_.match_prev_avail_) || !this->is_line_break(state))
{
return false;
}
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// assert_eos_matcher.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_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_eos_matcher
// match the end of the sequence (\Z)
struct assert_eos_matcher
: quant_style_assertion
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &state, NextT const &next)
{
return state.eos() && next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////
// assert_line_base.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_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_line_base
//
template<typename TraitsT>
struct assert_line_base
: quant_style_assertion
{
typedef typename TraitsT::char_type char_type;
typedef typename TraitsT::char_class_type char_class_type;
protected:
assert_line_base(TraitsT const &traits)
: newline_(lookup_classname(traits, "newline"))
, nl_(traits.widen('\n'))
, cr_(traits.widen('\r'))
{
}
template<typename BidiIterT>
bool is_line_break(state_type<BidiIterT> &state) const
{
BOOST_ASSERT(!state.bos() || state.flags_.match_prev_avail_);
BidiIterT tmp = state.cur_;
char_type ch = *--tmp;
if(traits_cast<TraitsT>(state).isctype(ch, this->newline_))
{
// there is no line-break between \r and \n
if(this->cr_ != ch || state.eos() || this->nl_ != *state.cur_)
{
return true;
}
}
return false;
}
private:
char_class_type newline_;
char_type nl_, cr_;
};
}}}
#endif

View File

@@ -0,0 +1,112 @@
///////////////////////////////////////////////////////////////////////////////
// assert_word_matcher.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_CORE_MATCHER_ASSERT_WORD_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_WORD_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// word_boundary
//
template<bool IsBoundaryT>
struct word_boundary
{
template<typename BidiIterT>
static bool eval(bool prevword, bool thisword, state_type<BidiIterT> &state)
{
if((state.flags_.match_not_bow_ && state.bos()) || (state.flags_.match_not_eow_ && state.eos()))
{
return !IsBoundaryT;
}
return IsBoundaryT == (prevword != thisword);
}
};
///////////////////////////////////////////////////////////////////////////////
// word_begin
//
struct word_begin
{
template<typename BidiIterT>
static bool eval(bool prevword, bool thisword, state_type<BidiIterT> &state)
{
if(state.flags_.match_not_bow_ && state.bos())
{
return false;
}
return !prevword && thisword;
}
};
///////////////////////////////////////////////////////////////////////////////
// word_end
//
struct word_end
{
template<typename BidiIterT>
static bool eval(bool prevword, bool thisword, state_type<BidiIterT> &state)
{
if(state.flags_.match_not_eow_ && state.eos())
{
return false;
}
return prevword && !thisword;
}
};
///////////////////////////////////////////////////////////////////////////////
// assert_word_matcher
//
template<typename CondT, typename TraitsT>
struct assert_word_matcher
: quant_style_assertion
{
typedef typename TraitsT::char_type char_type;
assert_word_matcher(TraitsT const &traits)
: word_(lookup_classname(traits, "w"))
{
BOOST_ASSERT(0 != this->word_);
}
bool is_word(TraitsT const &traits, char_type ch) const
{
return traits.isctype(traits.translate(ch), this->word_);
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
BidiIterT cur = state.cur_;
bool const thisword = !state.eos() && this->is_word(traits_cast<TraitsT>(state), *cur);
bool const prevword = (!state.bos() || state.flags_.match_prev_avail_)
&& this->is_word(traits_cast<TraitsT>(state), *--cur);
return CondT::eval(prevword, thisword, state) && next.match(state);
}
typename TraitsT::char_class_type word_;
};
}}}
#endif

View File

@@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////////
// charset_matcher.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_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// charset_matcher
//
template<typename TraitsT, bool ICaseT, typename CharSetT>
struct charset_matcher
: quant_style_fixed_width<1>
{
typedef typename TraitsT::char_type char_type;
typedef TraitsT traits_type;
typedef mpl::bool_<ICaseT> icase_type;
charset_matcher(CharSetT const &charset = CharSetT())
: charset_(charset)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos() || !this->charset_.test(*state.cur_, traits_cast<TraitsT>(state), icase_type()))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
CharSetT charset_;
};
}}}
#endif

View File

@@ -0,0 +1,66 @@
///////////////////////////////////////////////////////////////////////////////
// end_matcher.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_CORE_MATCHER_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/sub_match_impl.hpp>
#include <boost/xpressive/detail/core/flow_control.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// end_matcher
//
struct end_matcher
: quant_style_assertion
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &state, NextT const &)
{
BidiIterT const tmp = state.cur_;
sub_match_impl<BidiIterT> &s0 = state.sub_match(0);
BOOST_ASSERT(!s0.matched);
// SPECIAL: if there is a match context on the context stack, then
// this pattern has been nested within another. pop that context and
// continue executing.
if(state.context_.prev_context_)
{
if(!pop_context_match(state))
{
return false;
}
}
else if(state.flags_.match_all_ && !state.eos() ||
state.flags_.match_not_null_ && state.cur_ == s0.begin_)
{
return false;
}
// record the end of sub-match zero
s0.first = s0.begin_;
s0.second = tmp;
s0.matched = true;
return true;
}
};
}}}
#endif

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// epsilon_matcher.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_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// epsilon_matcher
//
struct epsilon_matcher
: quant_style_assertion
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &state, NextT const &next)
{
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////
// keeper_matcher.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_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/static/is_pure.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// keeper_matcher
// XprT can be either a static_xpression, or a shared_ptr<matchable>
template<typename XprT>
struct keeper_matcher
: quant_style_auto<width_of<XprT>, is_pure<XprT> >
{
keeper_matcher(XprT const &xpr, bool do_save = !is_pure<XprT>::value)
: xpr_(xpr)
, do_save_(do_save)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// Note that if is_pure<XprT>::value is true, the compiler can tell which
// branch to take.
return is_pure<XprT>::value || !this->do_save_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::true_) const
{
BidiIterT const tmp = state.cur_;
// matching xpr is guaranteed to not produce side-effects, don't bother saving state
if(!get_pointer(this->xpr_)->match(state))
{
return false;
}
else if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::false_) const
{
BidiIterT const tmp = state.cur_;
// matching xpr could produce side-effects, save state
memento<BidiIterT> mem = save_sub_matches(state);
if(!get_pointer(this->xpr_)->match(state))
{
reclaim_sub_matches(mem, state);
return false;
}
else if(next.match(state))
{
reclaim_sub_matches(mem, state);
return true;
}
restore_sub_matches(mem, state);
state.cur_ = tmp;
return false;
}
XprT xpr_;
bool do_save_; // true if matching xpr_ could modify the sub-matches
};
}}}
#endif

View File

@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
// literal_matcher.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_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// literal_matcher
//
template<typename TraitsT, bool ICaseT, bool NotT>
struct literal_matcher
: quant_style_fixed_width<1>
{
typedef typename TraitsT::char_type char_type;
typedef mpl::bool_<NotT> not_type;
typedef mpl::bool_<ICaseT> icase_type;
char_type ch_;
literal_matcher(char_type ch, TraitsT const &traits)
: ch_(detail::translate(ch, traits, icase_type()))
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos() || NotT ==
(detail::translate(*state.cur_, traits_cast<TraitsT>(state), icase_type()) == this->ch_))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,78 @@
///////////////////////////////////////////////////////////////////////////////
// logical_newline_matcher.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_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
//////////////////////////////////////////////////////////////////////////
// logical_newline_matcher
//
template<typename TraitsT>
struct logical_newline_matcher
: quant_style_variable_width
{
typedef typename TraitsT::char_type char_type;
typedef typename TraitsT::char_class_type char_class_type;
logical_newline_matcher(TraitsT const &traits)
: newline_(lookup_classname(traits, "newline"))
, nl_(traits.widen('\n'))
, cr_(traits.widen('\r'))
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos())
{
return false;
}
char_type ch = *state.cur_;
if(traits_cast<TraitsT>(state).isctype(ch, this->newline_))
{
++state.cur_;
if(this->cr_ == ch && !state.eos() && this->nl_ == *state.cur_)
{
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
}
else if(next.match(state))
{
return true;
}
--state.cur_;
}
return false;
}
private:
char_class_type newline_;
char_type nl_, cr_;
};
}}}
#endif

View File

@@ -0,0 +1,144 @@
///////////////////////////////////////////////////////////////////////////////
// lookahead_matcher.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_CORE_MATCHER_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/static/is_pure.hpp>
#include <boost/xpressive/detail/utility/save_restore.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// lookahead_matcher
// XprT can be either a static_xpression, or a shared_ptr<matchable>
//
template<typename XprT>
struct lookahead_matcher
: quant_style<quant_none, mpl::size_t<0>, is_pure<XprT> >
{
lookahead_matcher(XprT const &xpr, bool no = false, bool do_save = !is_pure<XprT>::value)
: xpr_(xpr)
, not_(no)
, do_save_(do_save)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// Note that if is_pure<XprT>::value is true, the compiler can optimize this.
return is_pure<XprT>::value || !this->do_save_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::true_) const
{
BidiIterT const tmp = state.cur_;
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
restore partial_match = save(state.found_partial_match_);
ignore_unused(&partial_match);
if(get_pointer(this->xpr_)->match(state))
{
state.cur_ = tmp;
return false;
}
else if(next.match(state))
{
return true;
}
}
else
{
if(!get_pointer(this->xpr_)->match(state))
{
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
return true;
}
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::false_) const
{
BidiIterT const tmp = state.cur_;
// matching xpr could produce side-effects, save state
memento<BidiIterT> mem = save_sub_matches(state);
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
restore partial_match = save(state.found_partial_match_);
ignore_unused(&partial_match);
if(get_pointer(this->xpr_)->match(state))
{
restore_sub_matches(mem, state);
state.cur_ = tmp;
return false;
}
else if(next.match(state))
{
reclaim_sub_matches(mem, state);
return true;
}
reclaim_sub_matches(mem, state);
}
else
{
if(!get_pointer(this->xpr_)->match(state))
{
reclaim_sub_matches(mem, state);
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
reclaim_sub_matches(mem, state);
return true;
}
restore_sub_matches(mem, state);
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
XprT xpr_;
bool not_;
bool do_save_; // true if matching xpr_ could modify the sub-matches
};
}}}
#endif

View File

@@ -0,0 +1,175 @@
///////////////////////////////////////////////////////////////////////////////
// lookbehind_matcher.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_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
#include <boost/xpressive/detail/utility/save_restore.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// get_width
//
template<typename XprT>
inline std::size_t get_width(XprT const &xpr)
{
return xpr.get_width(static_cast<state_type<char const *>*>(0));
}
template<typename BidiIterT>
inline std::size_t get_width(shared_ptr<matchable<BidiIterT> const> const &xpr)
{
return xpr->get_width(0);
}
///////////////////////////////////////////////////////////////////////////////
// lookbehind_matcher
// XprT can be either a static_xpression, or a shared_ptr<matchable>
template<typename XprT>
struct lookbehind_matcher
: quant_style<quant_none, mpl::size_t<0>, is_pure<XprT> >
{
lookbehind_matcher(XprT const &xpr, bool no = false, bool do_save = !is_pure<XprT>::value)
: xpr_(xpr)
, not_(no)
, do_save_(do_save)
, width_(detail::get_width(xpr))
{
detail::ensure(this->width_ != unknown_width(), regex_constants::error_badlookbehind,
"Variable-width look-behind assertions are not supported");
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// Note that if is_pure<XprT>::value is true, the compiler can optimize this.
return is_pure<XprT>::value || !this->do_save_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::true_) const
{
typedef typename iterator_difference<BidiIterT>::type difference_type;
BidiIterT const tmp = state.cur_;
if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
{
state.cur_ = tmp;
return this->not_ ? next.match(state) : false;
}
if(this->not_)
{
if(get_pointer(this->xpr_)->match(state))
{
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
return true;
}
}
else
{
if(!get_pointer(this->xpr_)->match(state))
{
state.cur_ = tmp;
return false;
}
BOOST_ASSERT(state.cur_ == tmp);
if(next.match(state))
{
return true;
}
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::false_) const
{
typedef typename iterator_difference<BidiIterT>::type difference_type;
BidiIterT const tmp = state.cur_;
if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
{
state.cur_ = tmp;
return this->not_ ? next.match(state) : false;
}
// matching xpr could produce side-effects, save state
memento<BidiIterT> mem = save_sub_matches(state);
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
restore partial_match = save(state.found_partial_match_);
ignore_unused(&partial_match);
if(get_pointer(this->xpr_)->match(state))
{
restore_sub_matches(mem, state);
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
reclaim_sub_matches(mem, state);
return true;
}
reclaim_sub_matches(mem, state);
}
else
{
if(!get_pointer(this->xpr_)->match(state))
{
state.cur_ = tmp;
reclaim_sub_matches(mem, state);
return false;
}
BOOST_ASSERT(state.cur_ == tmp);
if(next.match(state))
{
reclaim_sub_matches(mem, state);
return true;
}
restore_sub_matches(mem, state);
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
XprT xpr_;
bool not_;
bool do_save_; // true if matching xpr_ could modify the sub-matches
std::size_t width_;
};
}}}
#endif

View File

@@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////
// mark_begin_matcher.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_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// mark_begin_matcher
//
struct mark_begin_matcher
: quant_style<quant_fixed_width, mpl::size_t<0>, mpl::false_>
{
int mark_number_; // signed because it could be negative
mark_begin_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
BidiIterT old_begin = br.begin_;
br.begin_ = state.cur_;
if(next.match(state))
{
return true;
}
br.begin_ = old_begin;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,64 @@
///////////////////////////////////////////////////////////////////////////////
// mark_end_matcher.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_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// mark_end_matcher
//
struct mark_end_matcher
: quant_style<quant_none, mpl::size_t<0>, mpl::false_>
{
int mark_number_;
mark_end_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
BidiIterT old_first = br.first;
BidiIterT old_second = br.second;
bool old_matched = br.matched;
br.first = br.begin_;
br.second = state.cur_;
br.matched = true;
if(next.match(state))
{
return true;
}
br.first = old_first;
br.second = old_second;
br.matched = old_matched;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,86 @@
///////////////////////////////////////////////////////////////////////////////
// mark_matcher.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_CORE_MATCHER_MARK_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// mark_matcher
//
template<typename TraitsT, bool ICaseT>
struct mark_matcher
: quant_style_fixed_unknown_width
{
typedef mpl::bool_<ICaseT> icase_type;
int mark_number_;
mark_matcher(int mark_number, TraitsT const &)
: mark_number_(mark_number)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
BOOST_ASSERT(this->mark_number_ < static_cast<int>(state.mark_count_));
sub_match_impl<BidiIterT> const &br = state.sub_match(this->mark_number_);
if(!br.matched)
{
return false;
}
BidiIterT const tmp = state.cur_;
for(BidiIterT begin = br.first, end = br.second; begin != end; ++begin, ++state.cur_)
{
if(state.eos()
|| detail::translate(*state.cur_, traits_cast<TraitsT>(state), icase_type())
!= detail::translate(*begin, traits_cast<TraitsT>(state), icase_type()))
{
state.cur_ = tmp;
return false;
}
}
if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
template<typename BidiIterT>
std::size_t get_width(state_type<BidiIterT> *state) const
{
if(0 == state)
{
return unknown_width();
}
sub_match_impl<BidiIterT> &br = state->sub_match(this->mark_number_);
return br.matched ? static_cast<std::size_t>(std::distance(br.first, br.second)) : 1U;
}
};
}}}
#endif

View File

@@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// posix_charset_matcher.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_CORE_MATCHER_POSIX_CHARSET_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_POSIX_CHARSET_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// posix_charset_matcher
//
template<typename TraitsT, bool ICaseT>
struct posix_charset_matcher
: quant_style_fixed_width<1>
{
typedef TraitsT traits_type;
typedef mpl::bool_<ICaseT> icase_type;
typedef typename TraitsT::char_class_type char_class_type;
posix_charset_matcher(char_class_type m, bool no)
: not_(no)
, mask_(m)
{
BOOST_ASSERT(0 != this->mask_);
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos() || this->not_ == traits_cast<TraitsT>(state).isctype(
detail::translate(*state.cur_, traits_cast<TraitsT>(state), icase_type()), this->mask_))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
bool not_;
char_class_type mask_;
};
}}}
#endif

View File

@@ -0,0 +1,76 @@
///////////////////////////////////////////////////////////////////////////////
// range_matcher.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_CORE_MATCHER_RANGE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_RANGE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// range_matcher
//
template<typename TraitsT, bool ICaseT>
struct range_matcher
: quant_style_fixed_width<1>
{
typedef typename TraitsT::char_type char_type;
typedef mpl::bool_<ICaseT> icase_type;
char_type ch_min_;
char_type ch_max_;
bool not_;
range_matcher(char_type ch_min, char_type ch_max, bool no, TraitsT const &)
: ch_min_(ch_min)
, ch_max_(ch_max)
, not_(no)
{
}
bool in_range(TraitsT const &traits, char_type ch, mpl::false_) const // case-sensitive
{
return traits.in_range(this->ch_min_, this->ch_max_, ch);
}
bool in_range(TraitsT const &traits, char_type ch, mpl::true_) const // case-insensitive
{
return traits.in_range_nocase(this->ch_min_, this->ch_max_, ch);
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos() || this->not_ ==
this->in_range(traits_cast<TraitsT>(state), *state.cur_, icase_type()))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// regex_byref_matcher.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_CORE_MATCHER_REGEX_BYREF_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_BYREF_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/core/adaptor.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex_byref_matcher
//
template<typename BidiIterT>
struct regex_byref_matcher
: quant_style<quant_variable_width, unknown_width, mpl::false_>
{
// avoid cyclic references by holding a weak_ptr to the
// regex_impl struct
weak_ptr<regex_impl<BidiIterT> > wimpl_;
// the basic_regex object holds a ref-count to this regex_impl, so
// we don't have to worry about it going away.
regex_impl<BidiIterT> const *pimpl_;
regex_byref_matcher(shared_ptr<regex_impl<BidiIterT> > const &impl)
: wimpl_(impl)
, pimpl_(impl.get())
{
BOOST_ASSERT(this->pimpl_);
}
template<typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// regex_matcher is used for embeding a dynamic regex in a static regex. As such,
// NextT will always point to a static regex.
BOOST_MPL_ASSERT((is_static_xpression<NextT>));
BOOST_ASSERT(this->pimpl_ == this->wimpl_.lock().get());
ensure(this->pimpl_->xpr_, regex_constants::error_badref, "bad regex reference");
// wrap the static xpression in a matchable interface
xpression_adaptor<NextT const &, BidiIterT> adaptor(next);
return push_context_match(*this->pimpl_, state, adaptor);
}
};
}}}
#endif

View File

@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
// regex_matcher.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_CORE_MATCHER_REGEX_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_MATCHER_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/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/adaptor.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex_matcher
//
template<typename BidiIterT>
struct regex_matcher
: quant_style<quant_variable_width, unknown_width, mpl::false_>
{
regex_impl<BidiIterT> impl_;
regex_matcher(shared_ptr<regex_impl<BidiIterT> > const &impl)
: impl_()
{
this->impl_.xpr_ = impl->xpr_;
this->impl_.traits_ = impl->traits_;
this->impl_.mark_count_ = impl->mark_count_;
this->impl_.hidden_mark_count_ = impl->hidden_mark_count_;
ensure(this->impl_.xpr_, regex_constants::error_badref, "bad regex reference");
}
template<typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// regex_matcher is used for embeding a dynamic regex in a static regex. As such,
// NextT will always point to a static regex.
BOOST_MPL_ASSERT((is_static_xpression<NextT>));
// wrap the static xpression in a matchable interface
xpression_adaptor<NextT const &, BidiIterT> adaptor(next);
return push_context_match(this->impl_, state, adaptor);
}
};
}}}
#endif

View File

@@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher.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_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
//
// Note: here is the variable-width xpression quantifier. It always
// matches at least once, so if the min is 0, it is the responsibility
// of the parser to make it alternate with an epsilon matcher.
//
///////////////////////////////////////////////////////////////////////////////
// repeat_begin_matcher
//
struct repeat_begin_matcher
: quant_style<quant_variable_width, unknown_width, mpl::false_>
{
int mark_number_;
repeat_begin_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
unsigned int old_repeat_count = br.repeat_count_;
bool old_zero_width = br.zero_width_;
br.repeat_count_ = 1;
br.zero_width_ = false;
// "push" next onto the stack, so it can be "popped" in
// repeat_end_matcher and used to loop back.
if(next.BOOST_NESTED_TEMPLATE push_match<NextT>(state))
{
return true;
}
br.repeat_count_ = old_repeat_count;
br.zero_width_ = old_zero_width;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher.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_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher
//
template<bool GreedyT>
struct repeat_end_matcher
: quant_style<quant_none, mpl::size_t<0>, mpl::false_>
{
typedef mpl::bool_<GreedyT> greedy_type;
int mark_number_;
unsigned int min_, max_;
mutable xpression_base const *back_;
repeat_end_matcher(int mark_number, unsigned int min, unsigned int max)
: mark_number_(mark_number)
, min_(min)
, max_(max)
, back_(0)
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
// prevent repeated zero-width sub-matches from causing infinite recursion
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
if(br.zero_width_ && br.begin_ == state.cur_)
{
return next.skip_match(state);
}
bool old_zero_width = br.zero_width_;
br.zero_width_ = (br.begin_ == state.cur_);
if(this->match_(state, next, greedy_type()))
{
return true;
}
br.zero_width_ = old_zero_width;
return false;
}
// greedy, variable-width quantifier
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::true_) const
{
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
if(this->max_ > br.repeat_count_)
{
++br.repeat_count_;
// loop back to the expression "pushed" in repeat_begin_matcher::match
if(next.top_match(state, this->back_))
{
return true;
}
else if(--br.repeat_count_ < this->min_)
{
return false;
}
}
// looping finished, continue matching the rest of the pattern
return next.skip_match(state);
}
// non-greedy, variable-width quantifier
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, mpl::false_) const
{
sub_match_impl<BidiIterT> &br = state.sub_match(this->mark_number_);
if(this->min_ <= br.repeat_count_)
{
if(next.skip_match(state))
{
return true;
}
}
if(this->max_ > br.repeat_count_)
{
++br.repeat_count_;
if(next.top_match(state, this->back_))
{
return true;
}
--br.repeat_count_;
}
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,138 @@
///////////////////////////////////////////////////////////////////////////////
// set.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_SET_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_SET_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <algorithm>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// set_matcher
//
template<typename TraitsT, int SizeT>
struct set_matcher
: quant_style_fixed_width<1>
{
typedef typename TraitsT::char_type char_type;
char_type set_[ SizeT ? SizeT : 1 ];
bool not_;
bool icase_;
typedef set_matcher<TraitsT, SizeT + 1> next_type;
friend struct set_matcher<TraitsT, SizeT - 1>;
set_matcher(TraitsT const &)
: set_()
, not_(false)
, icase_(false)
{
}
set_matcher(char_type ch, TraitsT const &traits)
: set_()
, not_(false)
, icase_(false)
{
BOOST_MPL_ASSERT_RELATION(1, ==, SizeT);
this->set_[0] = traits.translate(ch);
}
void complement()
{
this->not_ = !this->not_;
}
void nocase(TraitsT const &traits)
{
this->icase_ = true;
for(int i = 0; i < SizeT; ++i)
{
this->set_[i] = traits.translate_nocase(this->set_[i]);
}
}
next_type push_back(char_type ch, TraitsT const &traits) const
{
return next_type(*this, ch, traits);
}
char_type const *begin() const
{
return this->set_;
}
char_type const *end() const
{
return this->set_ + SizeT;
}
bool in_set(TraitsT const &traits, char_type ch) const
{
ch = this->icase_ ? traits.translate_nocase(ch) : traits.translate(ch);
if(1 == SizeT)
{
return this->set_[0] == ch;
}
else
{
return this->end() != std::find(this->begin(), this->end(), ch);
}
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
if(state.eos() || this->not_ == this->in_set(traits_cast<TraitsT>(state), *state.cur_))
{
return false;
}
if(++state.cur_, next.match(state))
{
return true;
}
return --state.cur_, false;
}
private:
set_matcher(set_matcher<TraitsT, SizeT - 1> const &that, char_type ch, TraitsT const &traits)
: set_()
, not_(false)
, icase_(that.icase_)
{
std::copy(that.begin(), that.end(), this->set_);
this->set_[ SizeT - 1 ] = traits.translate(ch);
}
};
///////////////////////////////////////////////////////////////////////////////
// set_initializer
struct set_initializer
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,214 @@
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_matcher.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_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/static/type_traits.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_traits
//
struct greedy_slow_tag {};
struct greedy_fast_tag {};
struct non_greedy_tag {};
typedef static_xpression<any_matcher, true_xpression> any_sxpr;
typedef matcher_wrapper<any_matcher> any_dxpr;
template<typename XprT, typename GreedyT, typename RandomT>
struct simple_repeat_traits
{
typedef typename mpl::if_<GreedyT, greedy_slow_tag, non_greedy_tag>::type tag_type;
};
template<>
struct simple_repeat_traits<any_sxpr, mpl::true_, mpl::true_>
{
typedef greedy_fast_tag tag_type;
};
template<>
struct simple_repeat_traits<any_dxpr, mpl::true_, mpl::true_>
{
typedef greedy_fast_tag tag_type;
};
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_matcher
//
template<typename XprT, bool GreedyT>
struct simple_repeat_matcher
: quant_style_variable_width
{
typedef XprT xpr_type;
typedef mpl::bool_<GreedyT> greedy_type;
XprT xpr_;
unsigned int min_, max_;
simple_repeat_matcher(XprT const &xpr, unsigned int min, unsigned int max)
: xpr_(xpr)
, min_(min)
, max_(max)
{
// it is the job of the parser to make sure this never happens
BOOST_ASSERT(min <= max);
BOOST_ASSERT(0 != max);
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
typedef mpl::bool_<is_random<BidiIterT>::value> is_rand;
typedef typename simple_repeat_traits<XprT, greedy_type, is_rand>::tag_type tag_type;
return this->match_(state, next, tag_type());
}
// greedy, fixed-width quantifier
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, greedy_slow_tag) const
{
int const diff = -static_cast<int>(this->xpr_.get_width(&state));
BOOST_ASSERT(diff != -static_cast<int>(unknown_width()));
unsigned int matches = 0;
BidiIterT const tmp = state.cur_;
if(0 == diff)
{
return this->xpr_.match(state) && next.match(state);
}
// greedily match as much as we can
while(matches < this->max_ && this->xpr_.match(state))
{
++matches;
}
if(this->min_ > matches)
{
state.cur_ = tmp;
return false;
}
// try matching the rest of the pattern, and back off if necessary
for(; ; --matches, std::advance(state.cur_, diff))
{
if(next.match(state))
{
return true;
}
else if(this->min_ == matches)
{
state.cur_ = tmp;
return false;
}
}
}
// non-greedy fixed-width quantification
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, non_greedy_tag) const
{
BidiIterT const tmp = state.cur_;
unsigned int matches = 0;
if(0 == this->xpr_.get_width(&state))
{
return this->xpr_.match(state) && next.match(state);
}
for(; matches < this->min_; ++matches)
{
if(!this->xpr_.match(state))
{
state.cur_ = tmp;
return false;
}
}
do
{
if(next.match(state))
{
return true;
}
}
while(matches++ < this->max_ && this->xpr_.match(state));
state.cur_ = tmp;
return false;
}
// when greedily matching any character, skip to the end instead of iterating there.
template<typename BidiIterT, typename NextT>
bool match_(state_type<BidiIterT> &state, NextT const &next, greedy_fast_tag) const
{
BidiIterT const tmp = state.cur_;
std::size_t const diff_to_end = static_cast<std::size_t>(state.end_ - tmp);
// is there enough room?
if(this->min_ > diff_to_end)
{
return false;
}
BidiIterT const min_iter = tmp + this->min_;
state.cur_ += (std::min)((std::size_t)this->max_, diff_to_end);
for(;; --state.cur_)
{
if(next.match(state))
{
return true;
}
else if(min_iter == state.cur_)
{
state.cur_ = tmp;
return false;
}
}
}
template<typename BidiIterT>
std::size_t get_width(state_type<BidiIterT> *state) const
{
if(this->min_ != this->max_)
{
return unknown_width();
}
return this->min_ * this->xpr_.get_width(state);
}
};
// BUGBUG can all non-greedy quantification be done with the fixed width quantifier?
// BUGBUG matchers are chained together using static_xpression so that matchers to
// the left can invoke matchers to the right. This is so that if the left matcher
// succeeds but the right matcher fails, the left matcher is given the opportunity
// to try something else. This is how backtracking works. However, if the left matcher
// can succeed only one way (as with any_matcher, for example), it does not need
// backtracking. In this case, leaving its stack frame active is a waste of stack
// space. Can something be done?
}}}
#endif

View File

@@ -0,0 +1,87 @@
///////////////////////////////////////////////////////////////////////////////
// string_matcher.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_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// string_matcher
//
template<typename TraitsT, bool ICaseT>
struct string_matcher
: quant_style_fixed_unknown_width
{
typedef typename TraitsT::char_type char_type;
typedef mpl::bool_<ICaseT> icase_type;
std::basic_string<char_type> str_;
char_type const *end_;
string_matcher(std::basic_string<char_type> const &str, TraitsT const &traits)
: str_(str)
, end_(str_.data() + str_.size())
{
for(typename std::basic_string<char_type>::size_type i = 0; i < this->str_.size(); ++i)
{
this->str_[i] = detail::translate(this->str_[i], traits, icase_type());
}
}
string_matcher(string_matcher<TraitsT, ICaseT> const &that)
: str_(that.str_)
, end_(str_.data() + str_.size())
{
}
template<typename BidiIterT, typename NextT>
bool match(state_type<BidiIterT> &state, NextT const &next) const
{
BidiIterT const tmp = state.cur_;
char_type const *begin = this->str_.data();
for(; begin != this->end_; ++begin, ++state.cur_)
{
if(state.eos() ||
(detail::translate(*state.cur_, traits_cast<TraitsT>(state), icase_type()) != *begin))
{
state.cur_ = tmp;
return false;
}
}
if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
template<typename BidiIterT>
std::size_t get_width(state_type<BidiIterT> *) const
{
return this->str_.size();
}
};
}}}
#endif

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// true_matcher.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_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// true_matcher
//
struct true_matcher
: quant_style_assertion
{
template<typename BidiIterT, typename NextT>
static bool match(state_type<BidiIterT> &, NextT const &)
{
return true;
}
};
}}}
#endif

View File

@@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////
// matchers.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_CORE_MATCHERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHERS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/alternate_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/any_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_word_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/charset_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/epsilon_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/keeper_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/literal_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/lookahead_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/range_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/regex_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/set_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/string_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/true_matcher.hpp>
#endif

View File

@@ -0,0 +1,197 @@
///////////////////////////////////////////////////////////////////////////////
// peeker.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_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>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// peek_next
// tell whether or not to keep looking for a peek optimization
template<typename MatcherT>
struct peek_next
: mpl::equal_to<typename MatcherT::width, mpl::size_t<0> >
{
};
template<>
struct peek_next<mark_begin_matcher>
: mpl::true_
{
};
template<>
struct peek_next<repeat_begin_matcher>
: mpl::true_
{
};
///////////////////////////////////////////////////////////////////////////////
// xpression_peeker
//
template<typename CharT>
struct xpression_peeker
{
template<typename TraitsT>
explicit xpression_peeker(hash_peek_bitset<CharT> *bset, TraitsT const &traits)
: bset_(bset)
, str_(0)
, str_icase_(false)
, line_start_(false)
, traits_(0)
, traits_type_(0)
{
this->set_traits(traits);
}
///////////////////////////////////////////////////////////////////////////////
// accessors
std::pair<std::basic_string<CharT> const *, bool> get_string() const
{
return std::make_pair(this->str_, this->str_icase_);
}
bool line_start() const
{
return this->line_start_;
}
///////////////////////////////////////////////////////////////////////////////
// modifiers
void fail()
{
this->bset_->set_all();
}
template<typename XprT>
peek_next<XprT> peek(XprT const &xpr)
{
if(!peek_next<XprT>::value)
{
this->fail(); // fail, we're done
}
return peek_next<XprT>();
}
template<typename TraitsT>
mpl::true_ peek(assert_bol_matcher<TraitsT> const &xpr)
{
this->line_start_ = true;
return mpl::true_();
}
template<typename TraitsT, bool ICaseT>
mpl::false_ peek(literal_matcher<TraitsT, ICaseT, false> const &xpr)
{
this->bset_->set_char(xpr.ch_, ICaseT, this->get_traits_<TraitsT>());
return mpl::false_();
}
template<typename TraitsT, bool ICaseT>
mpl::false_ peek(string_matcher<TraitsT, ICaseT> const &xpr)
{
this->bset_->set_char(xpr.str_[0], ICaseT, this->get_traits_<TraitsT>());
this->str_ = &xpr.str_;
this->str_icase_ = ICaseT;
return mpl::false_();
}
template<typename AlternatesT, typename TraitsT>
mpl::false_ peek(alternate_matcher<AlternatesT, TraitsT> const &xpr)
{
BOOST_ASSERT(0 != xpr.bset_.count());
this->bset_->set_bitset(xpr.bset_);
return mpl::false_();
}
template<typename TraitsT, bool ICaseT>
mpl::false_ peek(posix_charset_matcher<TraitsT, ICaseT> const &xpr)
{
this->bset_->set_class(xpr.mask_, xpr.not_, ICaseT, this->get_traits_<TraitsT>());
return mpl::false_();
}
template<typename DummyT = void>
struct is_char_8bit : mpl::bool_<1 == sizeof(CharT)> {};
template<bool ICaseT, typename TraitsT>
typename enable_if<is_char_8bit<TraitsT>, mpl::false_>::type
peek(charset_matcher<TraitsT, ICaseT, basic_chset<CharT> > const &xpr)
{
BOOST_ASSERT(0 != xpr.charset_.base().count());
this->bset_->set_charset(xpr.charset_, ICaseT);
return mpl::false_();
}
template<typename TraitsT, bool ICaseT>
mpl::false_ peek(range_matcher<TraitsT, ICaseT> const &xpr)
{
this->bset_->set_range(xpr.ch_min_, xpr.ch_max_, xpr.not_, ICaseT, this->get_traits_<TraitsT>());
return mpl::false_();
}
template<typename XprT, bool GreedyT>
mpl::false_ peek(simple_repeat_matcher<XprT, GreedyT> const &xpr)
{
0 != xpr.min_ ? xpr.xpr_.peek(*this) : this->fail(); // could be a union of xpr and next
return mpl::false_();
}
template<typename TraitsT>
void set_traits(TraitsT const &traits)
{
if(0 == this->traits_)
{
this->traits_ = &traits;
this->traits_type_ = &typeid(TraitsT);
}
else if(*this->traits_type_ != typeid(TraitsT) || this->get_traits_<TraitsT>() != traits)
{
this->fail(); // traits mis-match! set all and bail
}
}
private:
template<typename TraitsT>
TraitsT const &get_traits_() const
{
BOOST_ASSERT(!!(*this->traits_type_ == typeid(TraitsT)));
return *static_cast<TraitsT const *>(this->traits_);
}
hash_peek_bitset<CharT> *bset_;
std::basic_string<CharT> const *str_;
bool str_icase_;
bool line_start_;
void const *traits_;
std::type_info const *traits_type_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,157 @@
///////////////////////////////////////////////////////////////////////////////
// quant_style.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_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#if defined(NDEBUG) & defined(BOOST_XPR_DEBUG_STACK)
# undef BOOST_XPR_DEBUG_STACK
#endif
#ifdef BOOST_XPR_DEBUG_STACK
# define BOOST_XPR_DEBUG_STACK_ASSERT BOOST_ASSERT
#else
# define BOOST_XPR_DEBUG_STACK_ASSERT(x) static_cast<void>(0)
#endif
namespace boost { namespace xpressive { namespace detail
{
//////////////////////////////////////////////////////////////////////////
// xpression_base
//
struct xpression_base
{
#ifdef BOOST_XPR_DEBUG_STACK
virtual ~xpression_base()
{
}
#endif
};
///////////////////////////////////////////////////////////////////////////////
// is_xpr
//
template<typename T>
struct is_xpr
: is_base_and_derived<xpression_base, T>
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_enum
//
enum quant_enum
{
quant_none,
quant_auto,
quant_fixed_width,
quant_variable_width
};
///////////////////////////////////////////////////////////////////////////////
// quant_style
//
template<quant_enum QuantStyleT, typename WidthT = unknown_width, typename PureT = mpl::true_>
struct quant_style
: xpression_base
{
typedef mpl::int_<QuantStyleT> quant; // Which quantification strategy to use?
typedef WidthT width; // how many characters this matcher consumes
typedef PureT pure; // whether this matcher has observable side-effects
template<typename BidiIterT>
static std::size_t get_width(state_type<BidiIterT> *)
{
return WidthT::value;
}
};
///////////////////////////////////////////////////////////////////////////////
// quant_style_none
// this sub-expression cannot be quantified
typedef quant_style<quant_none> quant_style_none;
///////////////////////////////////////////////////////////////////////////////
// quant_style_fixed_unknown_width
// this sub-expression is fixed width for the purpose of quantification, but
// the width cannot be determined at compile time. An example would be the
// string_matcher or the mark_matcher.
typedef quant_style<quant_fixed_width> quant_style_fixed_unknown_width;
///////////////////////////////////////////////////////////////////////////////
// quant_style_variable_width
// this sub-expression can match a variable number of characters
typedef quant_style<quant_variable_width> quant_style_variable_width;
///////////////////////////////////////////////////////////////////////////////
// quant_style_fixed_width
// for when the sub-expression has a fixed width that is known at compile time
template<std::size_t WidthT>
struct quant_style_fixed_width
: quant_style<quant_fixed_width, mpl::size_t<WidthT> >
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_style_assertion
// a zero-width assertion.
struct quant_style_assertion
: quant_style<quant_none, mpl::size_t<0> >
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_style_auto
// automatically pick the quantification style based on width and purity
template<typename WidthT, typename PureT>
struct quant_style_auto
: quant_style<quant_auto, WidthT, PureT>
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_type
//
template<typename MatcherT, typename QuantStyleT = typename MatcherT::quant>
struct quant_type
: QuantStyleT
{
};
///////////////////////////////////////////////////////////////////////////////
// when the quant_type is auto, determine the quant type from the width and purity
template<typename MatcherT>
struct quant_type<MatcherT, mpl::int_<quant_auto> >
: mpl::if_
<
mpl::and_
<
mpl::not_equal_to<typename MatcherT::width, unknown_width>
, typename MatcherT::pure
>
, mpl::int_<quant_fixed_width>
, mpl::int_<quant_variable_width>
>::type
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,89 @@
///////////////////////////////////////////////////////////////////////////////
// regex_impl.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_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/utility/tracking_ptr.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// finder
//
template<typename BidiIterT>
struct finder
{
virtual ~finder() {}
virtual bool operator ()(state_type<BidiIterT> &state) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// regex_impl
//
template<typename BidiIterT>
struct regex_impl
: enable_reference_tracking<regex_impl<BidiIterT> >
{
typedef typename iterator_value<BidiIterT>::type char_type;
regex_impl()
: xpr_()
, traits_()
, finder_()
, mark_count_(0)
, hidden_mark_count_(0)
{
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
++instances;
#endif
}
~regex_impl()
{
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
--instances;
#endif
}
void swap(regex_impl<BidiIterT> &that)
{
enable_reference_tracking<regex_impl<BidiIterT> >::swap(that);
this->xpr_.swap(that.xpr_);
this->traits_.swap(that.traits_);
this->finder_.swap(that.finder_);
std::swap(this->mark_count_, that.mark_count_);
std::swap(this->hidden_mark_count_, that.hidden_mark_count_);
}
shared_ptr<matchable<BidiIterT> const> xpr_;
shared_ptr<void const> traits_;
shared_ptr<finder<BidiIterT> > finder_;
std::size_t mark_count_;
std::size_t hidden_mark_count_;
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
static int instances;
#endif
};
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
template<typename BidiIterT>
int regex_impl<BidiIterT>::instances = 0;
#endif
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,131 @@
///////////////////////////////////////////////////////////////////////////////
// results_cache.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_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <list>
#include <boost/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/access.hpp>
#include <boost/xpressive/match_results.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// nested_results
// BUGBUG by using std::list, it makes construction of of an empty nested_results
// incur a dynamic allocation. As a result, construction an empty match_results is
// likewise not free. FIXME.
template<typename BidiIterT>
struct nested_results
: private std::list<match_results<BidiIterT> >
{
friend struct results_cache<BidiIterT>;
friend struct match_results<BidiIterT>;
typedef std::list<match_results<BidiIterT> > base_type;
using base_type::iterator;
using base_type::const_iterator;
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB , == 1)
// old Dinkumware doesn't expose pointer typedefs
typedef base_type::value_type *pointer;
typedef base_type::value_type const *const_pointer;
#else
using base_type::pointer;
using base_type::const_pointer;
#endif
using base_type::reference;
using base_type::const_reference;
using base_type::size_type;
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::empty;
using base_type::front;
using base_type::back;
};
///////////////////////////////////////////////////////////////////////////////
// results_cache
//
// cache storage for reclaimed match_results structs
template<typename BidiIterT>
struct results_cache
{
typedef core_access<BidiIterT> access;
match_results<BidiIterT> &append_new(nested_results<BidiIterT> &out)
{
if(this->cache_.empty())
{
out.push_back(match_results<BidiIterT>());
}
else
{
BOOST_ASSERT(access::get_nested_results(this->cache_.back()).empty());
out.splice(out.end(), this->cache_, --this->cache_.end());
}
return out.back();
}
// move the last match_results struct into the cache
void reclaim_last(nested_results<BidiIterT> &out)
{
BOOST_ASSERT(!out.empty());
// first, reclaim any nested results
nested_results<BidiIterT> &nested = access::get_nested_results(out.back());
if(!nested.empty())
{
this->reclaim_all(nested);
}
// then, reclaim the last match_results
this->cache_.splice(this->cache_.end(), out, --out.end());
}
// move the last n match_results structs into the cache
void reclaim_last_n(nested_results<BidiIterT> &out, std::size_t count)
{
for(; 0 != count; --count)
{
this->reclaim_last(out);
}
}
void reclaim_all(nested_results<BidiIterT> &out)
{
typedef typename nested_results<BidiIterT>::iterator iter_type;
// first, recursively reclaim all the nested results
for(iter_type begin = out.begin(); begin != out.end(); ++begin)
{
nested_results<BidiIterT> &nested = access::get_nested_results(*begin);
if(!nested.empty())
{
this->reclaim_all(nested);
}
}
// next, reclaim the results themselves
this->cache_.splice(this->cache_.end(), out);
}
private:
nested_results<BidiIterT> cache_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,334 @@
///////////////////////////////////////////////////////////////////////////////
// state.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_CORE_STATE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/access.hpp>
#include <boost/xpressive/detail/core/action_state.hpp>
#include <boost/xpressive/detail/core/sub_match_vector.hpp>
#include <boost/xpressive/detail/utility/sequence_stack.hpp>
#include <boost/xpressive/basic_regex.hpp>
#include <boost/xpressive/regex_constants.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// match_context
//
template<typename BidiIterT>
struct match_context
{
// pointer to the current match results, passed to actions as a parameter.
match_results<BidiIterT> *results_ptr_;
// The previous match context, if this match_context corresponds to a nested regex invocation
match_context<BidiIterT> *prev_context_;
// If this is a nested match, the "next" sub-expression to execute after the nested match
matchable<BidiIterT> const *next_ptr_;
// A pointer to the current traits object
void const *traits_;
};
///////////////////////////////////////////////////////////////////////////////
// match_flags
//
struct match_flags
{
bool match_all_;
bool match_prev_avail_;
bool match_bol_;
bool match_eol_;
bool match_not_bow_;
bool match_not_eow_;
bool match_not_null_;
bool match_continuous_;
bool match_partial_;
explicit match_flags(regex_constants::match_flag_type flags)
: match_all_(false)
, match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
, match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
, match_eol_(0 == (flags & regex_constants::match_not_eol))
, match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
, match_not_eow_(0 != (flags & regex_constants::match_not_eow))
, match_not_null_(0 != (flags & regex_constants::match_not_null))
, match_continuous_(0 != (flags & regex_constants::match_continuous))
, match_partial_(0 != (flags & regex_constants::match_partial))
{
}
};
///////////////////////////////////////////////////////////////////////////////
// state_type
//
template<typename BidiIterT>
struct state_type
{
typedef core_access<BidiIterT> access;
typedef match_context<BidiIterT> match_context;
typedef results_extras<BidiIterT> results_extras;
typedef regex_impl<BidiIterT> regex_impl;
typedef matchable<BidiIterT> matchable;
typedef basic_regex<BidiIterT> basic_regex;
typedef match_results<BidiIterT> match_results;
typedef sub_match_impl<BidiIterT> sub_match_impl;
BidiIterT cur_;
sub_match_impl *sub_matches_;
std::size_t mark_count_;
BidiIterT begin_;
BidiIterT end_;
match_flags flags_;
bool found_partial_match_;
match_context context_;
results_extras &extras_;
action_state action_state_;
///////////////////////////////////////////////////////////////////////////////
//
state_type
(
BidiIterT begin
, BidiIterT end
, match_results &what
, basic_regex const &rex
, regex_constants::match_flag_type flags
)
: cur_(begin)
, sub_matches_(0)
, mark_count_(0)
, begin_(begin)
, end_(end)
, flags_(flags)
, found_partial_match_(false)
, context_() // zero-initializes the fields of context_
, extras_(core_access<BidiIterT>::get_extras(what))
, action_state_(core_access<BidiIterT>::get_action_state(what))
{
// reclaim any cached memory in the match_results struct
this->extras_.sub_match_stack_.unwind();
// initialize the context_ struct
this->init_(*access::get_regex_impl(rex), what);
// move all the nested match_results structs into the match_results cache
this->extras_.results_cache_.reclaim_all(access::get_nested_results(what));
}
///////////////////////////////////////////////////////////////////////////////
// reset
void reset(match_results &what, basic_regex const &rex)
{
this->context_.prev_context_ = 0;
this->found_partial_match_ = false;
this->extras_.sub_match_stack_.unwind();
this->init_(*access::get_regex_impl(rex), what);
this->extras_.results_cache_.reclaim_all(access::get_nested_results(what));
}
///////////////////////////////////////////////////////////////////////////////
// push_context
// called to prepare the state object for a regex match
match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
{
// save state
match_context context = this->context_;
// create a new nested match_results for this regex
nested_results<BidiIterT> &nested = access::get_nested_results(*context.results_ptr_);
match_results &what = this->extras_.results_cache_.append_new(nested);
// (re)initialize the match context
this->init_(impl, what);
// create a linked list of match_context structs
this->context_.prev_context_ = &prev;
this->context_.next_ptr_ = &next;
// record the start of the zero-th sub-match
this->sub_matches_[0].begin_ = this->cur_;
return context;
}
///////////////////////////////////////////////////////////////////////////////
// pop_context
// called after a nested match failed to restore the context
void pop_context(regex_impl const &impl, bool success)
{
match_context &context = *this->context_.prev_context_;
if(!success)
{
match_results &what = *context.results_ptr_;
this->uninit_(impl, what);
// send the match_results struct back to the cache
nested_results<BidiIterT> &nested = access::get_nested_results(what);
this->extras_.results_cache_.reclaim_last(nested);
}
// restore the state
this->context_ = context;
match_results &results = *this->context_.results_ptr_;
this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
this->mark_count_ = results.size();
}
///////////////////////////////////////////////////////////////////////////////
// swap_context
void swap_context(match_context &context)
{
std::swap(this->context_, context);
match_results &results = *this->context_.results_ptr_;
this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
this->mark_count_ = results.size();
}
// beginning of buffer
bool bos() const
{
return this->cur_ == this->begin_;
}
// end of buffer
bool eos()
{
return this->cur_ == this->end_ && this->found_partial_match();
}
// fetch the n-th sub_match
sub_match_impl &sub_match(int n)
{
return this->sub_matches_[n];
}
// called when a partial match has succeeded
void set_partial_match()
{
sub_match_impl &sub0 = this->sub_match(0);
sub0.first = sub0.begin_;
sub0.second = this->end_;
sub0.matched = false;
}
template<typename TraitsT>
TraitsT const &get_traits() const
{
return *static_cast<TraitsT const *>(this->context_.traits_);
}
private:
void init_(regex_impl const &impl, match_results &what)
{
regex_id_type const id = impl.xpr_.get();
std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
// initialize the context and the sub_match vector
this->context_.results_ptr_ = &what;
this->context_.traits_ = impl.traits_.get();
this->mark_count_ = impl.mark_count_ + 1;
this->sub_matches_ = this->extras_.sub_match_stack_.push_sequence(total_mark_count);
this->sub_matches_ += impl.hidden_mark_count_;
// initialize the match_results struct
access::init_match_results(what, id, this->sub_matches_, this->mark_count_);
}
void uninit_(regex_impl const &impl, match_results &what)
{
extras_.sub_match_stack_.unwind_to(
access::get_sub_matches(access::get_sub_match_vector(what)) + impl.hidden_mark_count_
);
}
bool found_partial_match()
{
this->found_partial_match_ = true;
return true;
}
};
///////////////////////////////////////////////////////////////////////////////
// memento
//
template<typename BidiIterT>
struct memento
{
sub_match_impl<BidiIterT> *old_sub_matches_;
std::size_t nested_results_count_;
};
///////////////////////////////////////////////////////////////////////////////
// save_sub_matches
//
template<typename BidiIterT>
inline memento<BidiIterT> save_sub_matches(state_type<BidiIterT> &state)
{
memento<BidiIterT> mem =
{
state.extras_.sub_match_stack_.push_sequence(state.mark_count_, no_fill)
, state.context_.results_ptr_->nested_results().size()
};
std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
return mem;
}
///////////////////////////////////////////////////////////////////////////////
// restore_sub_matches
//
template<typename BidiIterT>
inline void restore_sub_matches(memento<BidiIterT> const &mem, state_type<BidiIterT> &state)
{
typedef core_access<BidiIterT> access;
nested_results<BidiIterT> &nested = access::get_nested_results(*state.context_.results_ptr_);
std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
state.extras_.results_cache_.reclaim_last_n(nested, count);
std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
state.extras_.sub_match_stack_.unwind_to(mem.old_sub_matches_);
}
///////////////////////////////////////////////////////////////////////////////
// reclaim_sub_matches
//
template<typename BidiIterT>
inline void reclaim_sub_matches(memento<BidiIterT> const &mem, state_type<BidiIterT> &state)
{
std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
if(count == 0)
{
state.extras_.sub_match_stack_.unwind_to(mem.old_sub_matches_);
}
// else we have we must orphan this block of backrefs because we are using the stack
// space above it.
}
///////////////////////////////////////////////////////////////////////////////
// traits_cast
//
template<typename TraitsT, typename BidiIterT>
inline TraitsT const &traits_cast(state_type<BidiIterT> const &state)
{
return state.template get_traits<TraitsT>();
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,43 @@
///////////////////////////////////////////////////////////////////////////////
// sub_match_impl.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_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/sub_match.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// sub_match_impl
//
template<typename BidiIterT>
struct sub_match_impl
: sub_match<BidiIterT>
{
unsigned int repeat_count_;
BidiIterT begin_;
bool zero_width_;
sub_match_impl()
: sub_match<BidiIterT>()
, repeat_count_(0)
, begin_()
, zero_width_(false)
{
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,171 @@
///////////////////////////////////////////////////////////////////////////////
// sub_match_vector.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_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/noncopyable.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/sub_match_impl.hpp>
namespace boost { namespace xpressive { namespace detail
{
#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
//////////////////////////////////////////////////////////////////////////
// sub_match_iterator
//
template<typename ValueT, typename MainIterT>
struct sub_match_iterator
: iterator_adaptor
<
sub_match_iterator<ValueT, MainIterT>
, MainIterT
, ValueT
, std::random_access_iterator_tag
>
{
typedef iterator_adaptor
<
sub_match_iterator<ValueT, MainIterT>
, MainIterT
, ValueT
, std::random_access_iterator_tag
> base_t;
sub_match_iterator(MainIterT baseiter)
: base_t(baseiter)
{
}
};
#endif
//////////////////////////////////////////////////////////////////////////
// sub_match_vector
//
template<typename BidiIterT>
struct sub_match_vector
: private noncopyable
{
private:
struct dummy { int i_; };
typedef int dummy::*bool_type;
public:
typedef sub_match<BidiIterT> value_type;
typedef std::size_t size_type;
typedef value_type const &const_reference;
typedef const_reference reference;
typedef typename iterator_difference<BidiIterT>::type difference_type;
typedef typename iterator_value<BidiIterT>::type char_type;
typedef std::basic_string<char_type> string_type;
#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
typedef sub_match_iterator
<
value_type const
, sub_match_impl<BidiIterT> const *
> const_iterator;
#else
typedef iterator_adaptor
<
sub_match_impl<BidiIterT> const *
, default_iterator_policies
, value_type
, value_type const &
, value_type const *
> const_iterator;
#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
typedef const_iterator iterator;
sub_match_vector()
: size_(0)
, sub_matches_(0)
{
}
const_reference operator [](size_type index) const
{
static value_type const s_null;
return (index >= this->size_)
? s_null
: *static_cast<value_type const *>(&this->sub_matches_[ index ]);
}
size_type size() const
{
return this->size_;
}
bool empty() const
{
return 0 == this->size();
}
const_iterator begin() const
{
return const_iterator(this->sub_matches_);
}
const_iterator end() const
{
return const_iterator(this->sub_matches_ + this->size_);
}
operator bool_type() const
{
return (!this->empty() && (*this)[0].matched) ? &dummy::i_ : 0;
}
bool operator !() const
{
return this->empty() || !(*this)[0].matched;
}
void swap(sub_match_vector<BidiIterT> &that)
{
std::swap(this->size_, that.size_);
std::swap(this->sub_matches_, that.sub_matches_);
}
private:
friend struct detail::core_access<BidiIterT>;
void init_(sub_match_impl<BidiIterT> *sub_matches, size_type size)
{
this->size_ = size;
this->sub_matches_ = sub_matches;
}
void init_(sub_match_impl<BidiIterT> *sub_matches, size_type size, sub_match_vector<BidiIterT> const &that)
{
BOOST_ASSERT(size == that.size_);
this->size_ = size;
this->sub_matches_ = sub_matches;
std::copy(that.sub_matches_, that.sub_matches_ + that.size_, this->sub_matches_);
}
size_type size_;
sub_match_impl<BidiIterT> *sub_matches_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,324 @@
///////////////////////////////////////////////////////////////////////////////
// detail_fwd.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_DETAIL_FWD_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DETAIL_FWD_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <climits> // for INT_MAX
#include <boost/mpl/bool.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/xpressive/xpressive_fwd.hpp>
namespace boost { namespace xpressive { namespace detail
{
typedef unsigned int uint_t;
template<uint_t MinT, uint_t MaxT>
struct generic_quant_tag;
struct modifier_tag;
typedef mpl::size_t<INT_MAX / 2 - 1> unknown_width;
///////////////////////////////////////////////////////////////////////////////
// placeholders
//
template<typename CharT, bool NotT = false>
struct literal_placeholder;
template<typename CharT>
struct string_placeholder;
struct mark_placeholder;
template<typename BidiIterT, bool ByRefT>
struct regex_placeholder;
struct posix_charset_placeholder;
template<typename CondT>
struct assert_word_placeholder;
template<typename CharT>
struct range_placeholder;
struct assert_bol_placeholder;
struct assert_eol_placeholder;
struct logical_newline_placeholder;
struct self_placeholder;
///////////////////////////////////////////////////////////////////////////////
// matchers
//
struct end_matcher;
struct assert_bos_matcher;
struct assert_eos_matcher;
template<typename TraitsT>
struct assert_bol_matcher;
template<typename TraitsT>
struct assert_eol_matcher;
template<typename CondT, typename TraitsT>
struct assert_word_matcher;
struct true_matcher;
template<typename AlternatesT, typename TraitsT>
struct alternate_matcher;
struct alternate_end_matcher;
template<typename TraitsT, bool ICaseT>
struct posix_charset_matcher;
template<typename BidiIterT>
struct alternates_factory;
template<typename BidiIterT>
struct sequence;
template<typename TraitsT, bool ICaseT>
struct mark_matcher;
struct mark_begin_matcher;
struct mark_end_matcher;
template<typename BidiIterT>
struct regex_matcher;
template<typename BidiIterT>
struct regex_byref_matcher;
template<typename TraitsT>
struct compound_charset;
template<typename TraitsT, bool ICaseT, typename CharSetT = compound_charset<TraitsT> >
struct charset_matcher;
template<typename TraitsT, bool ICaseT>
struct range_matcher;
template<typename TraitsT, int SizeT>
struct set_matcher;
template<typename XprT, bool GreedyT>
struct simple_repeat_matcher;
struct repeat_begin_matcher;
template<bool GreedyT>
struct repeat_end_matcher;
template<typename TraitsT, bool ICaseT, bool NotT>
struct literal_matcher;
template<typename TraitsT, bool ICaseT>
struct string_matcher;
template<typename ActionT>
struct action_matcher;
template<typename XprT>
struct as_xpr_type;
template<typename XprT>
struct is_modifiable;
template<typename AlternatesT>
struct alternates_list;
template<typename ModifierT>
struct modifier_op;
template<typename LeftT, typename RightT>
struct modifier_sequencer;
struct icase_modifier;
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct xpression_visitor;
template<typename BidiIterT>
struct regex_impl;
template<typename BidiIterT>
struct regex_matcher;
struct epsilon_matcher;
typedef proto::unary_op<epsilon_matcher, proto::noop_tag> epsilon_type;
template<typename BidiIterT>
struct nested_results;
template<typename BidiIterT>
struct regex_id_filter_predicate;
template<typename XprT>
struct keeper_matcher;
template<typename XprT>
struct lookahead_matcher;
template<typename XprT>
struct lookbehind_matcher;
template<typename CondT>
struct assert_word_placeholder;
template<bool IsBoundaryT>
struct word_boundary;
template<typename BidiIterT, typename MatcherT>
sequence<BidiIterT> make_dynamic_xpression(MatcherT const &matcher);
template<typename CharT>
struct xpression_linker;
template<typename CharT>
struct xpression_peeker;
typedef proto::unary_op<mark_placeholder, proto::noop_tag> mark_tag;
struct any_matcher;
template<typename TraitsT>
struct logical_newline_matcher;
typedef proto::unary_op<logical_newline_placeholder, proto::noop_tag> logical_newline_xpression;
struct set_initializer;
typedef proto::unary_op<set_initializer, proto::noop_tag> set_initializer_type;
struct seq_tag;
template<bool PositiveT>
struct lookahead_tag;
template<bool PositiveT>
struct lookbehind_tag;
struct keeper_tag;
template<typename LocaleT>
struct locale_modifier;
template<typename MatcherT>
struct matcher_wrapper;
template<typename LocaleT, typename BidiIterT>
struct regex_traits_type;
///////////////////////////////////////////////////////////////////////////////
// Misc.
struct no_next;
template<typename BidiIterT>
struct core_access;
template<typename BidiIterT>
struct state_type;
template<typename BidiIterT>
struct matchable;
template<typename MatcherT, typename BidiIterT>
struct dynamic_xpression;
template<typename MatcherT, typename NextT>
struct static_xpression;
typedef static_xpression<end_matcher, no_next> end_xpression;
typedef static_xpression<alternate_end_matcher, no_next> alternate_end_xpression;
typedef static_xpression<true_matcher, no_next> true_xpression;
template<typename MatcherT, typename NextT = end_xpression>
struct static_xpression;
template<typename TopT, typename NextT>
struct stacked_xpression;
template<typename XprT>
struct is_static_xpression;
template<typename BidiIterT>
struct sub_match_impl;
template<typename BidiIterT>
struct results_cache;
template<typename T>
struct sequence_stack;
template<typename BidiIterT>
struct results_extras;
template<typename BidiIterT>
struct match_context;
template<typename BidiIterT>
struct sub_match_vector;
struct action_state;
template<typename TraitsT, typename BidiIterT>
TraitsT const &traits_cast(state_type<BidiIterT> const &state);
template<typename CharT>
struct basic_chset;
template<typename BidiIterT>
struct memento;
template<typename CharT, typename TraitsT>
void set_char(compound_charset<TraitsT> &chset, CharT ch, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_range(compound_charset<TraitsT> &chset, CharT from, CharT to, TraitsT const &traits, bool icase);
template<typename TraitsT>
void set_class(compound_charset<TraitsT> &chset, typename TraitsT::char_class_type char_class, bool no, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_char(basic_chset<CharT> &chset, CharT ch, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_range(basic_chset<CharT> &chset, CharT from, CharT to, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_class(basic_chset<CharT> &chset, typename TraitsT::char_class_type char_class, bool no, TraitsT const &traits, bool icase);
}}} // namespace boost::xpressive::detail
/// INTERNAL ONLY
namespace boost { namespace xpressive
{
/// INTERNAL ONLY
template<typename TraitsT, std::size_t N>
typename TraitsT::char_class_type
lookup_classname(TraitsT const &traits, char const (&cname)[N], bool icase = false);
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,429 @@
///////////////////////////////////////////////////////////////////////////////
// dynamic.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_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <list>
#include <utility>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/core/icase.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// invalid_xpression
//
template<typename BidiIterT>
struct invalid_xpression
: matchable<BidiIterT>
{
bool match(state_type<BidiIterT> &) const
{
BOOST_ASSERT(false);
return false;
}
std::size_t get_width(state_type<BidiIterT> *) const
{
return 0;
}
static void noop(matchable<BidiIterT> const *)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// get_invalid_xpression
//
template<typename BidiIterT>
inline shared_ptr<matchable<BidiIterT> const> const &get_invalid_xpression()
{
static invalid_xpression<BidiIterT> const invalid_xpr;
static shared_ptr<matchable<BidiIterT> const> const invalid_ptr
(
static_cast<matchable<BidiIterT> const *>(&invalid_xpr)
, &invalid_xpression<BidiIterT>::noop
);
return invalid_ptr;
}
///////////////////////////////////////////////////////////////////////////////
// dynamic_xpression
//
template<typename MatcherT, typename BidiIterT>
struct dynamic_xpression
: MatcherT
, matchable<BidiIterT>
{
typedef typename iterator_value<BidiIterT>::type char_type;
shared_ptr<matchable<BidiIterT> const> next_;
dynamic_xpression(MatcherT const &matcher = MatcherT())
: MatcherT(matcher)
, next_(get_invalid_xpression<BidiIterT>())
{
}
bool match(state_type<BidiIterT> &state) const
{
return this->MatcherT::match(state, *this->next_);
}
std::size_t get_width(state_type<BidiIterT> *state) const
{
std::size_t this_width = this->MatcherT::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;
}
void link(xpression_linker<char_type> &linker) const
{
linker.link(*static_cast<MatcherT const *>(this), this->next_.get());
this->next_->link(linker);
}
void peek(xpression_peeker<char_type> &peeker) const
{
this->peek_next_(peeker.peek(*static_cast<MatcherT const *>(this)), peeker);
}
sequence<BidiIterT> quantify
(
quant_spec const &spec
, std::size_t &hidden_mark_count
, sequence<BidiIterT> seq
, alternates_factory<BidiIterT> const &factory
) const
{
return this->quantify_(spec, hidden_mark_count, seq, quant_type<MatcherT>(), factory, this);
}
bool is_quantifiable() const
{
return quant_type<MatcherT>::value != (int)quant_none;
}
private:
void peek_next_(mpl::true_, xpression_peeker<char_type> &peeker) const
{
this->next_->peek(peeker);
}
void peek_next_(mpl::false_, xpression_peeker<char_type> &) const
{
// no-op
}
sequence<BidiIterT> quantify_
(
quant_spec const &
, std::size_t &
, sequence<BidiIterT>
, mpl::int_<quant_none>
, alternates_factory<BidiIterT> const &
, void const *
) const;
sequence<BidiIterT> quantify_
(
quant_spec const &
, std::size_t &
, sequence<BidiIterT>
, mpl::int_<quant_fixed_width>
, alternates_factory<BidiIterT> const &
, void const *
) const;
sequence<BidiIterT> quantify_
(
quant_spec const &
, std::size_t &
, sequence<BidiIterT>
, mpl::int_<quant_variable_width>
, alternates_factory<BidiIterT> const &
, void const *
) const;
sequence<BidiIterT> quantify_
(
quant_spec const &
, std::size_t &
, sequence<BidiIterT>
, mpl::int_<quant_fixed_width>
, alternates_factory<BidiIterT> const &
, mark_begin_matcher const *
) const;
};
///////////////////////////////////////////////////////////////////////////////
// make_dynamic_xpression
//
template<typename BidiIterT, typename MatcherT>
inline sequence<BidiIterT> make_dynamic_xpression(MatcherT const &matcher)
{
typedef dynamic_xpression<MatcherT, BidiIterT> xpression_type;
std::auto_ptr<xpression_type> xpr(new xpression_type(matcher));
sequence<BidiIterT> seq;
seq.second = &xpr->next_;
seq.first = xpr;
return seq;
}
///////////////////////////////////////////////////////////////////////////////
// alternates_factory
//
template<typename BidiIterT>
struct alternates_factory
{
typedef std::vector<shared_ptr<matchable<BidiIterT> const> > alternates_vector;
virtual ~alternates_factory() {}
virtual std::pair<sequence<BidiIterT>, alternates_vector *>
operator ()() const = 0;
};
template<typename BidiIterT, typename TraitsT>
struct alternates_factory_impl
: alternates_factory<BidiIterT>
{
typedef typename alternates_factory<BidiIterT>::alternates_vector alternates_vector;
std::pair<sequence<BidiIterT>, alternates_vector *>
operator ()() const
{
typedef alternate_matcher<alternates_vector, TraitsT> alternate_matcher;
typedef dynamic_xpression<alternate_matcher, BidiIterT> alternate_xpression;
shared_ptr<alternate_xpression> alt_xpr(new alternate_xpression);
sequence<BidiIterT> seq(alt_xpr, &alt_xpr->next_);
return std::make_pair(seq, &alt_xpr->alternates_);
}
};
///////////////////////////////////////////////////////////////////////////////
// alternates_to_matchable
//
template<typename BidiIterT>
inline sequence<BidiIterT> alternates_to_matchable
(
std::list<sequence<BidiIterT> > const &alternates
, alternates_factory<BidiIterT> const &factory
)
{
BOOST_ASSERT(0 != alternates.size());
// If there is only 1 alternate, just return it.
if(1 == alternates.size())
{
return alternates.front();
}
typedef std::vector<shared_ptr<matchable<BidiIterT> const> > alternates_vector;
std::pair<sequence<BidiIterT>, alternates_vector *> result = factory();
// through the wonders of reference counting, all alternates can share an end_alternate
typedef dynamic_xpression<alternate_end_matcher, BidiIterT> alternate_end_xpression;
shared_ptr<alternate_end_xpression> end_alt_xpr(new alternate_end_xpression);
// terminate each alternate with an alternate_end_matcher
result.second->reserve(alternates.size());
typedef std::list<sequence<BidiIterT> > alternates_list;
typename alternates_list::const_iterator begin = alternates.begin(), end = alternates.end();
for(; begin != end; ++begin)
{
if(!begin->is_empty())
{
result.second->push_back(begin->first);
*begin->second = end_alt_xpr;
}
else
{
result.second->push_back(end_alt_xpr);
}
}
return result.first;
}
///////////////////////////////////////////////////////////////////////////////
// matcher_wrapper
//
template<typename MatcherT>
struct matcher_wrapper
: MatcherT
{
matcher_wrapper(MatcherT const &matcher = MatcherT())
: MatcherT(matcher)
{
}
template<typename BidiIterT>
bool match(state_type<BidiIterT> &state) const
{
return this->MatcherT::match(state, matcher_wrapper<true_matcher>());
}
template<typename CharT>
void link(xpression_linker<CharT> &linker) const
{
linker.link(*static_cast<MatcherT const *>(this), 0);
}
template<typename CharT>
void peek(xpression_peeker<CharT> &peeker) const
{
peeker.peek(*static_cast<MatcherT const *>(this));
}
};
//////////////////////////////////////////////////////////////////////////
// dynamic_xpression::quantify_
//
// unquantifiable
template<typename MatcherT, typename BidiIterT>
inline sequence<BidiIterT> dynamic_xpression<MatcherT, BidiIterT>::quantify_
(
quant_spec const &
, std::size_t &
, sequence<BidiIterT>
, mpl::int_<quant_none>
, alternates_factory<BidiIterT> const &
, void const *
) const
{
BOOST_ASSERT(false); // should never get here
throw regex_error(regex_constants::error_badrepeat, "expression cannot be quantified");
}
// fixed-width matchers
template<typename MatcherT, typename BidiIterT>
inline sequence<BidiIterT> dynamic_xpression<MatcherT, BidiIterT>::quantify_
(
quant_spec const &spec
, std::size_t &hidden_mark_count
, sequence<BidiIterT> seq
, mpl::int_<quant_fixed_width>
, alternates_factory<BidiIterT> const &factory
, void const *
) const
{
if(this->next_ != get_invalid_xpression<BidiIterT>())
{
return this->quantify_(spec, hidden_mark_count, seq, mpl::int_<quant_variable_width>(), factory, this);
}
typedef matcher_wrapper<MatcherT> xpr_type;
if(spec.greedy_)
{
simple_repeat_matcher<xpr_type, true> quant(*this, spec.min_, spec.max_);
return make_dynamic_xpression<BidiIterT>(quant);
}
else
{
simple_repeat_matcher<xpr_type, false> quant(*this, spec.min_, spec.max_);
return make_dynamic_xpression<BidiIterT>(quant);
}
}
// variable-width, no mark
template<typename MatcherT, typename BidiIterT>
inline sequence<BidiIterT> dynamic_xpression<MatcherT, BidiIterT>::quantify_
(
quant_spec const &spec
, std::size_t &hidden_mark_count
, sequence<BidiIterT> seq
, mpl::int_<quant_variable_width>
, alternates_factory<BidiIterT> const &factory
, void const *
) const
{
// create a hidden mark so this expression can be quantified
int mark_nbr = -static_cast<int>(++hidden_mark_count);
mark_begin_matcher mark_begin(mark_nbr);
mark_end_matcher mark_end(mark_nbr);
sequence<BidiIterT> new_seq = make_dynamic_xpression<BidiIterT>(mark_begin);
new_seq += seq;
new_seq += make_dynamic_xpression<BidiIterT>(mark_end);
return new_seq.first->quantify(spec, hidden_mark_count, new_seq, factory);
}
// variable-width with mark
template<typename MatcherT, typename BidiIterT>
inline sequence<BidiIterT> dynamic_xpression<MatcherT, BidiIterT>::quantify_
(
quant_spec const &spec
, std::size_t &
, sequence<BidiIterT> seq
, mpl::int_<quant_fixed_width>
, alternates_factory<BidiIterT> const &factory
, mark_begin_matcher const *
) const
{
BOOST_ASSERT(spec.max_); // we should never get here if max is 0
// only bother creating a quantifier if max is greater than one
if(1 < spec.max_)
{
int mark_number = this->mark_number_;
unsigned int min = spec.min_ ? spec.min_ : 1U;
detail::sequence<BidiIterT> seq_quant;
// TODO: statically bind the repeat_begin_matcher to the mark_begin for better perf
seq_quant += make_dynamic_xpression<BidiIterT>(repeat_begin_matcher(mark_number));
// TODO: statically bind the mark_end to the quantifier_end for better perf
if(spec.greedy_)
{
repeat_end_matcher<true> end_quant(mark_number, min, spec.max_);
seq += make_dynamic_xpression<BidiIterT>(end_quant);
}
else
{
repeat_end_matcher<false> end_quant(mark_number, min, spec.max_);
seq += make_dynamic_xpression<BidiIterT>(end_quant);
}
seq_quant += seq;
seq = seq_quant;
}
// if min is 0, the quant must be made alternate with an empty matcher.
if(0 == spec.min_)
{
std::list<sequence<BidiIterT> > alts(2);
(spec.greedy_ ? alts.front() : alts.back()) = seq;
seq = alternates_to_matchable(alts, factory);
}
return seq;
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,155 @@
///////////////////////////////////////////////////////////////////////////////
// matchable.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_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <utility>
#include <boost/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/regex_error.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<typename BidiIterT>
struct matchable;
///////////////////////////////////////////////////////////////////////////////
// sequence
//
template<typename BidiIterT>
struct sequence
: std::pair
<
shared_ptr<matchable<BidiIterT> const>
, shared_ptr<matchable<BidiIterT> const> *
>
{
typedef shared_ptr<matchable<BidiIterT> const> matchable_ptr_t;
typedef std::pair<matchable_ptr_t, matchable_ptr_t *> base_t;
explicit sequence(matchable_ptr_t head = matchable_ptr_t(), matchable_ptr_t *tail_ptr = 0)
: base_t(head, tail_ptr)
{
}
bool is_empty() const
{
return !this->first;
}
sequence &operator +=(sequence that)
{
if(is_empty())
{
*this = that;
}
else if(!that.is_empty())
{
*this->second = that.first;
this->second = that.second;
}
return *this;
}
};
//////////////////////////////////////////////////////////////////////////
// quant_spec
//
struct quant_spec
{
unsigned int min_;
unsigned int max_;
bool greedy_;
};
///////////////////////////////////////////////////////////////////////////////
// matchable
//
template<typename BidiIterT>
struct matchable
: xpression_base
{
typedef typename iterator_value<BidiIterT>::type char_type;
virtual ~matchable() {}
virtual bool match(state_type<BidiIterT> &state) const = 0;
virtual std::size_t get_width(state_type<BidiIterT> *state) const = 0;
virtual void link(xpression_linker<char_type> &linker) const {}
virtual void peek(xpression_peeker<char_type> &peeker) const
{
peeker.fail();
}
virtual sequence<BidiIterT> quantify
(
quant_spec const &spec
, std::size_t &hidden_mark_count
, sequence<BidiIterT> seq
, alternates_factory<BidiIterT> const &factory
) const
{
throw regex_error(regex_constants::error_badrepeat, "expression cannot be quantified");
}
virtual bool is_quantifiable() const
{
BOOST_ASSERT(false);
throw regex_error(regex_constants::error_internal, "internal error, sorry!");
}
///////////////////////////////////////////////////////////////////////////////////////////////
// The following 4 functions (push_match, top_match, pop_match and skip_match) are
// used to implement looping and branching across the matchers. Call push_match to record
// a position. Then, another matcher further down the xpression chain has the
// option to call either top_match, pop_match or skip_match. top_match and pop_match will
// jump back to the place recorded by push_match, whereas skip_match will skip the jump and
// pass execution down the xpression chain. top_match will leave the xpression on top of the
// stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for
// statically bound xpressions and one for dynamically bound xpressions.
//
template<typename TopT>
bool push_match(state_type<BidiIterT> &state) const
{
BOOST_MPL_ASSERT((is_same<TopT, matchable<BidiIterT> >));
return this->match(state);
}
static bool top_match(state_type<BidiIterT> &state, xpression_base const *top)
{
return static_cast<matchable<BidiIterT> const *>(top)->match(state);
}
static bool pop_match(state_type<BidiIterT> &state, xpression_base const *top)
{
return static_cast<matchable<BidiIterT> const *>(top)->match(state);
}
bool skip_match(state_type<BidiIterT> &state) const
{
return this->match(state);
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////////
// parse_charset.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_DYNAMIC_PARSE_CHARSET_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSE_CHARSET_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/integer.hpp>
#include <boost/numeric/conversion/converter.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
#include <boost/xpressive/detail/utility/literals.hpp>
#include <boost/xpressive/detail/utility/chset/chset.hpp>
#include <boost/xpressive/regex_constants.hpp>
namespace boost { namespace xpressive { namespace detail
{
enum escape_type
{
escape_char
, escape_mark
, escape_class
};
///////////////////////////////////////////////////////////////////////////////
// escape_value
//
template<typename CharT, typename ClassT>
struct escape_value
{
CharT ch_;
int mark_nbr_;
ClassT class_;
escape_type type_;
};
///////////////////////////////////////////////////////////////////////////////
// char_overflow_handler
//
struct char_overflow_handler
{
void operator ()(numeric::range_check_result result) const // throw(regex_error)
{
if(numeric::cInRange != result)
{
throw regex_error(regex_constants::error_escape,
"character escape too large to fit in target character type");
}
}
};
///////////////////////////////////////////////////////////////////////////////
// parse_escape
//
template<typename FwdIterT, typename CompilerTraitsT>
escape_value<typename iterator_value<FwdIterT>::type, typename CompilerTraitsT::regex_traits::char_class_type>
parse_escape(FwdIterT &begin, FwdIterT end, CompilerTraitsT &traits)
{
using namespace regex_constants;
typedef typename iterator_value<FwdIterT>::type char_type;
typedef typename CompilerTraitsT::regex_traits regex_traits;
typedef typename regex_traits::char_class_type char_class_type;
// define an unsigned type the same size as char_type
typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
ensure(begin != end, error_escape, "unexpected end of pattern found");
numeric::converter<int, uchar_t, converstion_traits, char_overflow_handler> converter;
escape_value<char_type,char_class_type> esc = { 0, 0, 0, escape_char };
bool const icase = (0 != (regex_constants::icase_ & traits.flags()));
regex_traits const &rxtraits = traits.traits();
FwdIterT tmp;
esc.class_ = rxtraits.lookup_classname(begin, begin + 1, icase);
if(0 != esc.class_)
{
esc.type_ = escape_class;
return esc;
}
if(-1 != rxtraits.value(*begin, 8))
{
esc.ch_ = converter(toi(begin, end, rxtraits, 8, 0777));
return esc;
}
switch(*begin)
{
// bell character
case BOOST_XPR_CHAR_(char_type, 'a'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\a');
++begin;
break;
// escape character
case BOOST_XPR_CHAR_(char_type, 'e'):
esc.ch_ = converter(27);
++begin;
break;
// control character
case BOOST_XPR_CHAR_(char_type, 'c'):
ensure(++begin != end, error_escape, "unexpected end of pattern found");
ensure
(
rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *begin)
|| rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *begin)
, error_escape
, "invalid escape control letter; must be one of a-z or A-Z"
);
// Convert to character according to ECMA-262, section 15.10.2.10:
esc.ch_ = converter(*begin % 32);
++begin;
break;
// formfeed character
case BOOST_XPR_CHAR_(char_type, 'f'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\f');
++begin;
break;
// newline
case BOOST_XPR_CHAR_(char_type, 'n'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\n');
++begin;
break;
// return
case BOOST_XPR_CHAR_(char_type, 'r'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\r');
++begin;
break;
// horizontal tab
case BOOST_XPR_CHAR_(char_type, 't'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\t');
++begin;
break;
// vertical tab
case BOOST_XPR_CHAR_(char_type, 'v'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\v');
++begin;
break;
// hex escape sequence
case BOOST_XPR_CHAR_(char_type, 'x'):
ensure(++begin != end, error_escape, "unexpected end of pattern found");
tmp = begin;
esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xff));
ensure(2 == std::distance(tmp, begin), error_escape, "invalid hex escape : "
"must be \\x HexDigit HexDigit");
break;
// Unicode escape sequence
case BOOST_XPR_CHAR_(char_type, 'u'):
ensure(++begin != end, error_escape, "unexpected end of pattern found");
tmp = begin;
esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xffff));
ensure(4 == std::distance(tmp, begin), error_escape, "invalid Unicode escape : "
"must be \\u HexDigit HexDigit HexDigit HexDigit");
break;
// backslash
case BOOST_XPR_CHAR_(char_type, '\\'):
//esc.ch_ = BOOST_XPR_CHAR_(char_type, '\\');
//++begin;
//break;
// all other escaped characters represent themselves
default:
esc.ch_ = *begin;
++begin;
break;
}
return esc;
}
//////////////////////////////////////////////////////////////////////////
// parse_charset
//
template<typename FwdIterT, typename RegexTraitsT, typename CompilerTraitsT>
inline void parse_charset
(
FwdIterT &begin
, FwdIterT end
, compound_charset<RegexTraitsT> &chset
, CompilerTraitsT &traits
)
{
using namespace regex_constants;
typedef typename RegexTraitsT::char_type char_type;
typedef typename RegexTraitsT::char_class_type char_class_type;
BOOST_ASSERT(begin != end);
RegexTraitsT const &rxtraits = traits.traits();
bool const icase = (0 != (regex_constants::icase_ & traits.flags()));
FwdIterT iprev = FwdIterT();
escape_value<char_type, char_class_type> esc = {0, 0, 0, escape_char};
bool invert = false;
// check to see if we have an inverse charset
if(begin != end && token_charset_invert == traits.get_charset_token(iprev = begin, end))
{
begin = iprev;
invert = true;
}
// skip the end token if-and-only-if it is the first token in the charset
if(begin != end && token_charset_end == traits.get_charset_token(iprev = begin, end))
{
for(; begin != iprev; ++begin)
{
chset.set_char(*begin, rxtraits, icase);
}
}
compiler_token_type tok;
char_type ch_prev = char_type(), ch_next = char_type();
bool have_prev = false;
ensure(begin != end, error_brack, "unexpected end of pattern found");
// remember the current position and grab the next token
iprev = begin;
tok = traits.get_charset_token(begin, end);
do
{
ensure(begin != end, error_brack, "unexpected end of pattern found");
if(token_charset_hyphen == tok && have_prev)
{
// remember the current position
FwdIterT iprev2 = begin;
have_prev = false;
// ch_prev is lower bound of a range
switch(traits.get_charset_token(begin, end))
{
case token_charset_hyphen:
case token_charset_invert:
begin = iprev2; // un-get these tokens and fall through
case token_literal:
ch_next = *begin++;
detail::ensure(ch_prev <= ch_next, error_range, "invalid charset range");
chset.set_range(ch_prev, ch_next, rxtraits, icase);
continue;
case token_charset_backspace:
ch_next = char_type(8); // backspace
detail::ensure(ch_prev <= ch_next, error_range, "invalid charset range");
chset.set_range(ch_prev, ch_next, rxtraits, icase);
continue;
case token_escape:
esc = parse_escape(begin, end, traits);
if(escape_char == esc.type_)
{
detail::ensure(ch_prev <= esc.ch_, error_range, "invalid charset range");
chset.set_range(ch_prev, esc.ch_, rxtraits, icase);
continue;
}
case token_charset_end: // fall through
default: // not a range.
begin = iprev; // backup to hyphen token
chset.set_char(ch_prev, rxtraits, icase);
chset.set_char(*begin++, rxtraits, icase);
continue;
}
}
if(have_prev)
{
chset.set_char(ch_prev, rxtraits, icase);
have_prev = false;
}
switch(tok)
{
case token_charset_hyphen:
case token_charset_invert:
case token_charset_end:
case token_posix_charset_end:
begin = iprev; // un-get these tokens
ch_prev = *begin++;
have_prev = true;
continue;
case token_charset_backspace:
ch_prev = char_type(8); // backspace
have_prev = true;
continue;
case token_posix_charset_begin:
{
FwdIterT tmp = begin, start = begin;
bool invert = (token_charset_invert == traits.get_charset_token(tmp, end));
if(invert)
{
begin = start = tmp;
}
while(token_literal == (tok = traits.get_charset_token(begin, end)))
{
tmp = ++begin;
ensure(begin != end, error_brack, "unexpected end of pattern found");
}
if(token_posix_charset_end == tok)
{
char_class_type chclass = rxtraits.lookup_classname(start, tmp, icase);
ensure(0 != chclass, error_ctype, "unknown class name");
chset.set_class(chclass, invert, icase);
continue;
}
begin = iprev; // un-get this token
ch_prev = *begin++;
have_prev = true;
}
continue;
case token_escape:
esc = parse_escape(begin, end, traits);
if(escape_char == esc.type_)
{
ch_prev = esc.ch_;
have_prev = true;
}
else if(escape_class == esc.type_)
{
char_class_type upper_ = lookup_classname(rxtraits, "upper");
BOOST_ASSERT(0 != upper_);
chset.set_class(esc.class_, rxtraits.isctype(*begin++, upper_), icase);
}
else
{
BOOST_ASSERT(false);
}
continue;
default:
ch_prev = *begin++;
have_prev = true;
continue;
}
}
while(ensure((iprev = begin) != end, error_brack, "unexpected end of pattern found"),
token_charset_end != (tok = traits.get_charset_token(begin, end)));
if(have_prev)
{
chset.set_char(ch_prev, rxtraits, icase);
}
if(invert)
{
chset.inverse();
}
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,358 @@
///////////////////////////////////////////////////////////////////////////////
/// \file parser.hpp
/// Contains the definition of regex_compiler, a factory for building regex objects
/// from strings.
//
// 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_DYNAMIC_PARSER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/dynamic/dynamic.hpp>
// The Regular Expression grammar, in pseudo BNF:
//
// expression = alternates ;
//
// alternates = sequence, *('|', sequence) ;
//
// sequence = quant, *(quant) ;
//
// quant = atom, [*+?] ;
//
// atom = literal |
// '.' |
// '\' any |
// '(' expression ')' ;
//
// literal = not a meta-character ;
//
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// make_char_xpression
//
template<typename BidiIterT, typename CharT, typename TraitsT>
inline sequence<BidiIterT> make_char_xpression
(
CharT ch
, regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
if(0 != (regex_constants::icase_ & flags))
{
literal_matcher<TraitsT, true, false> matcher(ch, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
else
{
literal_matcher<TraitsT, false, false> matcher(ch, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_any_xpression
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_any_xpression
(
regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
using namespace regex_constants;
typedef typename iterator_value<BidiIterT>::type char_type;
typedef set_matcher<TraitsT, 2> set_matcher;
typedef literal_matcher<TraitsT, false, true> literal_matcher;
char_type const newline = traits.widen('\n');
set_matcher s(traits);
s.set_[0] = newline;
s.set_[1] = 0;
s.complement();
switch(((int)not_dot_newline | not_dot_null) & flags)
{
case not_dot_null:
return make_dynamic_xpression<BidiIterT>(literal_matcher(char_type(0), traits));
case not_dot_newline:
return make_dynamic_xpression<BidiIterT>(literal_matcher(newline, traits));
case (int)not_dot_newline | not_dot_null:
return make_dynamic_xpression<BidiIterT>(s);
default:
return make_dynamic_xpression<BidiIterT>(any_matcher());
}
}
///////////////////////////////////////////////////////////////////////////////
// make_literal_xpression
//
template<typename BidiIterT, typename CharT, typename TraitsT>
inline sequence<BidiIterT> make_literal_xpression
(
std::basic_string<CharT> const &literal
, regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
BOOST_ASSERT(0 != literal.size());
if(1 == literal.size())
{
return make_char_xpression<BidiIterT>(literal[0], flags, traits);
}
typedef typename iterator_value<BidiIterT>::type char_type;
BOOST_MPL_ASSERT((is_same<char_type, CharT>));
if(0 != (regex_constants::icase_ & flags))
{
string_matcher<TraitsT, true> matcher(literal, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
else
{
string_matcher<TraitsT, false> matcher(literal, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_backref_xpression
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_backref_xpression
(
int mark_nbr
, regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
typedef typename iterator_value<BidiIterT>::type char_type;
if(0 != (regex_constants::icase_ & flags))
{
return make_dynamic_xpression<BidiIterT>
(
mark_matcher<TraitsT, true>(mark_nbr, traits)
);
}
else
{
return make_dynamic_xpression<BidiIterT>
(
mark_matcher<TraitsT, false>(mark_nbr, traits)
);
}
}
///////////////////////////////////////////////////////////////////////////////
// merge_charset
//
template<typename CharT, typename TraitsT>
inline void merge_charset
(
basic_chset<CharT> &basic
, compound_charset<TraitsT> const &compound
, TraitsT const &traits
)
{
if(0 != compound.posix_yes())
{
typename TraitsT::char_class_type mask = compound.posix_yes();
for(int i = 0; i <= UCHAR_MAX; ++i)
{
if(traits.isctype((CharT)i, mask))
{
basic.set((CharT)i);
}
}
}
if(!compound.posix_no().empty())
{
for(std::size_t j = 0; j < compound.posix_no().size(); ++j)
{
typename TraitsT::char_class_type mask = compound.posix_no()[j];
for(int i = 0; i <= UCHAR_MAX; ++i)
{
if(!traits.isctype((CharT)i, mask))
{
basic.set((CharT)i);
}
}
}
}
if(compound.is_inverted())
{
basic.inverse();
}
}
///////////////////////////////////////////////////////////////////////////////
// make_charset_xpression
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_charset_xpression
(
compound_charset<TraitsT> &chset
, TraitsT const &traits
, regex_constants::syntax_option_type flags
)
{
typedef typename TraitsT::char_type char_type;
bool const icase = (0 != (regex_constants::icase_ & flags));
// don't care about compile speed -- fold eveything into a bitset<256>
if(1 == sizeof(char_type) && 0 != (regex_constants::optimize & flags))
{
typedef basic_chset<char_type> charset_type;
charset_type charset(chset.basic_chset());
if(icase)
{
charset_matcher<TraitsT, true, charset_type> matcher(charset);
merge_charset(matcher.charset_, chset, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
else
{
charset_matcher<TraitsT, false, charset_type> matcher(charset);
merge_charset(matcher.charset_, chset, traits);
return make_dynamic_xpression<BidiIterT>(matcher);
}
}
// special case to make [[:digit:]] fast
else if(chset.basic_chset().empty() && chset.posix_no().empty())
{
BOOST_ASSERT(0 != chset.posix_yes());
if(icase)
{
posix_charset_matcher<TraitsT, true> matcher(chset.posix_yes(), chset.is_inverted());
return make_dynamic_xpression<BidiIterT>(matcher);
}
else
{
posix_charset_matcher<TraitsT, false> matcher(chset.posix_yes(), chset.is_inverted());
return make_dynamic_xpression<BidiIterT>(matcher);
}
}
// default, slow
else
{
if(icase)
{
charset_matcher<TraitsT, true> matcher(chset);
return make_dynamic_xpression<BidiIterT>(matcher);
}
else
{
charset_matcher<TraitsT, false> matcher(chset);
return make_dynamic_xpression<BidiIterT>(matcher);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// make_posix_charset_xpression
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_posix_charset_xpression
(
typename TraitsT::char_class_type m
, bool no
, regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
typedef typename iterator_value<BidiIterT>::type char_type;
bool const icase = (0 != (regex_constants::icase_ & flags));
if(icase)
{
posix_charset_matcher<TraitsT, true> charset(m, no);
return make_dynamic_xpression<BidiIterT>(charset);
}
else
{
posix_charset_matcher<TraitsT, false> charset(m, no);
return make_dynamic_xpression<BidiIterT>(charset);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_begin_line
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_assert_begin_line
(
regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
if(0 != (regex_constants::single_line & flags))
{
return detail::make_dynamic_xpression<BidiIterT>(detail::assert_bos_matcher());
}
else
{
detail::assert_bol_matcher<TraitsT> matcher(traits);
return detail::make_dynamic_xpression<BidiIterT>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_end_line
//
template<typename BidiIterT, typename TraitsT>
inline sequence<BidiIterT> make_assert_end_line
(
regex_constants::syntax_option_type flags
, TraitsT const &traits
)
{
if(0 != (regex_constants::single_line & flags))
{
return detail::make_dynamic_xpression<BidiIterT>(detail::assert_eos_matcher());
}
else
{
detail::assert_eol_matcher<TraitsT> matcher(traits);
return detail::make_dynamic_xpression<BidiIterT>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_word
//
template<typename BidiIterT, typename CondT, typename TraitsT>
inline sequence<BidiIterT> make_assert_word(CondT, TraitsT const &traits)
{
typedef typename iterator_value<BidiIterT>::type char_type;
return detail::make_dynamic_xpression<BidiIterT>
(
detail::assert_word_matcher<CondT, TraitsT>(traits)
);
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,72 @@
///////////////////////////////////////////////////////////////////////////////
// parser_enum.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_DYNAMIC_PARSER_ENUM_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_ENUM_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
namespace boost { namespace xpressive { namespace regex_constants
{
///////////////////////////////////////////////////////////////////////////////
// compiler_token_type
//
enum compiler_token_type
{
token_literal,
token_any, // .
token_escape, //
token_group_begin, // (
token_group_end, // )
token_alternate, // |
token_invalid_quantifier, // {
token_charset_begin, // [
token_charset_end, // ]
token_charset_invert, // ^
token_charset_hyphen, // -
token_charset_backspace, // \b
token_posix_charset_begin, // [:
token_posix_charset_end, // :]
token_quote_meta_begin, // \Q
token_quote_meta_end, // \E
token_no_mark, // ?:
token_positive_lookahead, // ?=
token_negative_lookahead, // ?!
token_positive_lookbehind, // ?<=
token_negative_lookbehind, // ?<!
token_independent_sub_expression, // ?>
token_comment, // ?#
token_assert_begin_sequence, // \A
token_assert_end_sequence, // \Z
token_assert_begin_line, // ^
token_assert_end_line, // $
token_assert_word_begin, // \<
token_assert_word_end, // \>
token_assert_word_boundary, // \b
token_assert_not_word_boundary, // \B
token_escape_newline, // \n
token_escape_escape, // \e
token_escape_formfeed, // \f
token_escape_horizontal_tab, // \t
token_escape_vertical_tab, // \v
token_escape_bell, // \a
token_escape_control, // \c
token_end_of_pattern
};
}}} // namespace boost::xpressive::regex_constants
#endif

View File

@@ -0,0 +1,400 @@
///////////////////////////////////////////////////////////////////////////////
// detail/dynamic/parser_traits.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_DYNAMIC_PARSER_TRAITS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_TRAITS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <climits>
#include <boost/assert.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
#include <boost/xpressive/detail/utility/literals.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
namespace boost { namespace xpressive
{
///////////////////////////////////////////////////////////////////////////////
// compiler_traits
// this works for char and wchar_t. it must be specialized for anything else.
//
template<typename RegexTraitsT>
struct compiler_traits
{
typedef typename RegexTraitsT::char_type char_type;
typedef std::basic_string<char_type> string_type;
typedef typename string_type::const_iterator iterator_type;
typedef RegexTraitsT regex_traits;
typedef typename RegexTraitsT::locale_type locale_type;
///////////////////////////////////////////////////////////////////////////////
// constructor
explicit compiler_traits(RegexTraitsT const &traits = RegexTraitsT())
: traits_(traits)
, flags_(regex_constants::ECMAScript)
, space_(lookup_classname(traits_, "space"))
{
BOOST_ASSERT(0 != this->space_);
}
///////////////////////////////////////////////////////////////////////////////
// flags
regex_constants::syntax_option_type flags() const
{
return this->flags_;
}
///////////////////////////////////////////////////////////////////////////////
// flags
void flags(regex_constants::syntax_option_type flags)
{
this->flags_ = flags;
}
///////////////////////////////////////////////////////////////////////////////
// traits
regex_traits &traits()
{
return this->traits_;
}
regex_traits const &traits() const
{
return this->traits_;
}
///////////////////////////////////////////////////////////////////////////////
// imbue
locale_type imbue(locale_type const &loc)
{
locale_type oldloc = this->traits().imbue(loc);
this->space_ = lookup_classname(this->traits(), "space");
BOOST_ASSERT(0 != this->space_);
return oldloc;
}
///////////////////////////////////////////////////////////////////////////////
// getloc
locale_type getloc() const
{
return this->traits().getloc();
}
///////////////////////////////////////////////////////////////////////////////
// get_token
// get a token and advance the iterator
regex_constants::compiler_token_type get_token(iterator_type &begin, iterator_type end)
{
using namespace regex_constants;
if(this->eat_ws_(begin, end) == end)
{
return regex_constants::token_end_of_pattern;
}
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '\\'): return this->get_escape_token(++begin, end);
case BOOST_XPR_CHAR_(char_type, '.'): ++begin; return token_any;
case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_assert_begin_line;
case BOOST_XPR_CHAR_(char_type, '$'): ++begin; return token_assert_end_line;
case BOOST_XPR_CHAR_(char_type, '('): ++begin; return token_group_begin;
case BOOST_XPR_CHAR_(char_type, ')'): ++begin; return token_group_end;
case BOOST_XPR_CHAR_(char_type, '|'): ++begin; return token_alternate;
case BOOST_XPR_CHAR_(char_type, '['): ++begin; return token_charset_begin;
case BOOST_XPR_CHAR_(char_type, ']'): ++begin; return token_charset_end;
case BOOST_XPR_CHAR_(char_type, '*'):
case BOOST_XPR_CHAR_(char_type, '+'):
case BOOST_XPR_CHAR_(char_type, '?'):
return token_invalid_quantifier;
case BOOST_XPR_CHAR_(char_type, '{'):
default:
return token_literal;
}
}
///////////////////////////////////////////////////////////////////////////////
// get_quant_spec
bool get_quant_spec(iterator_type &begin, iterator_type end, detail::quant_spec &spec)
{
using namespace regex_constants;
iterator_type old_begin;
if(this->eat_ws_(begin, end) == end)
{
return false;
}
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '*'):
spec.min_ = 0;
spec.max_ = (std::numeric_limits<unsigned int>::max)();
break;
case BOOST_XPR_CHAR_(char_type, '+'):
spec.min_ = 1;
spec.max_ = (std::numeric_limits<unsigned int>::max)();
break;
case BOOST_XPR_CHAR_(char_type, '?'):
spec.min_ = 0;
spec.max_ = 1;
break;
case BOOST_XPR_CHAR_(char_type, '{'):
old_begin = this->eat_ws_(++begin, end);
spec.min_ = spec.max_ = detail::toi(begin, end, this->traits());
detail::ensure
(
begin != old_begin && begin != end, error_brace, "invalid quantifier"
);
if(*begin == BOOST_XPR_CHAR_(char_type, ','))
{
old_begin = this->eat_ws_(++begin, end);
spec.max_ = detail::toi(begin, end, this->traits());
detail::ensure
(
begin != end && BOOST_XPR_CHAR_(char_type, '}') == *begin
, error_brace, "invalid quantifier"
);
if(begin == old_begin)
{
spec.max_ = (std::numeric_limits<unsigned int>::max)();
}
else
{
detail::ensure
(
spec.min_ <= spec.max_, error_badbrace, "invalid quantification range"
);
}
}
else
{
detail::ensure
(
BOOST_XPR_CHAR_(char_type, '}') == *begin, error_brace, "invalid quantifier"
);
}
break;
default:
return false;
}
spec.greedy_ = true;
if(this->eat_ws_(++begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
{
++begin;
spec.greedy_ = false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////
// get_group_type
regex_constants::compiler_token_type get_group_type(iterator_type &begin, iterator_type end)
{
using namespace regex_constants;
if(this->eat_ws_(begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
{
this->eat_ws_(++begin, end);
detail::ensure(begin != end, error_paren, "incomplete extension");
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, ':'): ++begin; return token_no_mark;
case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_independent_sub_expression;
case BOOST_XPR_CHAR_(char_type, '#'): ++begin; return token_comment;
case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookahead;
case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookahead;
case BOOST_XPR_CHAR_(char_type, '<'):
this->eat_ws_(++begin, end);
detail::ensure(begin != end, error_paren, "incomplete extension");
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookbehind;
case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookbehind;
default:
throw regex_error(error_badbrace, "unrecognized extension");
}
case BOOST_XPR_CHAR_(char_type, 'i'):
case BOOST_XPR_CHAR_(char_type, 'm'):
case BOOST_XPR_CHAR_(char_type, 's'):
case BOOST_XPR_CHAR_(char_type, 'x'):
case BOOST_XPR_CHAR_(char_type, '-'):
return this->parse_mods_(begin, end);
default:
throw regex_error(error_badbrace, "unrecognized extension");
}
}
return token_literal;
}
//////////////////////////////////////////////////////////////////////////
// get_charset_token
// NOTE: white-space is *never* ignored in a charset.
regex_constants::compiler_token_type get_charset_token(iterator_type &begin, iterator_type end)
{
using namespace regex_constants;
BOOST_ASSERT(begin != end);
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_charset_invert;
case BOOST_XPR_CHAR_(char_type, '-'): ++begin; return token_charset_hyphen;
case BOOST_XPR_CHAR_(char_type, ']'): ++begin; return token_charset_end;
case BOOST_XPR_CHAR_(char_type, '['):
{
iterator_type next = begin; ++next;
if(next != end && *next == BOOST_XPR_CHAR_(char_type, ':'))
{
begin = ++next;
return token_posix_charset_begin;
}
}
break;
case BOOST_XPR_CHAR_(char_type, ':'):
{
iterator_type next = begin; ++next;
if(next != end && *next == BOOST_XPR_CHAR_(char_type, ']'))
{
begin = ++next;
return token_posix_charset_end;
}
}
break;
case BOOST_XPR_CHAR_(char_type, '\\'):
if(++begin != end)
{
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_charset_backspace;
default:;
}
}
return token_escape;
default:;
}
return token_literal;
}
//////////////////////////////////////////////////////////////////////////
// get_escape_token
regex_constants::compiler_token_type get_escape_token(iterator_type &begin, iterator_type end)
{
using namespace regex_constants;
if(begin != end)
{
switch(*begin)
{
//case BOOST_XPR_CHAR_(char_type, 'a'): ++begin; return token_escape_bell;
//case BOOST_XPR_CHAR_(char_type, 'c'): ++begin; return token_escape_control;
//case BOOST_XPR_CHAR_(char_type, 'e'): ++begin; return token_escape_escape;
//case BOOST_XPR_CHAR_(char_type, 'f'): ++begin; return token_escape_formfeed;
//case BOOST_XPR_CHAR_(char_type, 'n'): ++begin; return token_escape_newline;
//case BOOST_XPR_CHAR_(char_type, 't'): ++begin; return token_escape_horizontal_tab;
//case BOOST_XPR_CHAR_(char_type, 'v'): ++begin; return token_escape_vertical_tab;
case BOOST_XPR_CHAR_(char_type, 'A'): ++begin; return token_assert_begin_sequence;
case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_assert_word_boundary;
case BOOST_XPR_CHAR_(char_type, 'B'): ++begin; return token_assert_not_word_boundary;
case BOOST_XPR_CHAR_(char_type, 'E'): ++begin; return token_quote_meta_end;
case BOOST_XPR_CHAR_(char_type, 'Q'): ++begin; return token_quote_meta_begin;
case BOOST_XPR_CHAR_(char_type, 'Z'): ++begin; return token_assert_end_sequence;
// Non-standard extension to ECMAScript syntax
case BOOST_XPR_CHAR_(char_type, '<'): ++begin; return token_assert_word_begin;
case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_assert_word_end;
default:; // fall-through
}
}
return token_escape;
}
private:
//////////////////////////////////////////////////////////////////////////
// parse_mods_
regex_constants::compiler_token_type parse_mods_(iterator_type &begin, iterator_type end)
{
using namespace regex_constants;
bool set = true;
do switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, 'i'): this->flag_(set, icase_); break;
case BOOST_XPR_CHAR_(char_type, 'm'): this->flag_(!set, single_line); break;
case BOOST_XPR_CHAR_(char_type, 's'): this->flag_(!set, not_dot_newline); break;
case BOOST_XPR_CHAR_(char_type, 'x'): this->flag_(set, ignore_white_space); break;
case BOOST_XPR_CHAR_(char_type, ':'): ++begin; // fall-through
case BOOST_XPR_CHAR_(char_type, ')'): return token_no_mark;
case BOOST_XPR_CHAR_(char_type, '-'): if(!(set = !set)) break; // else fall-through
default: throw regex_error(error_paren, "unknown pattern modifier");
}
while(detail::ensure(++begin != end, error_paren, "incomplete extension"), true);
BOOST_UNREACHABLE_RETURN(token_no_mark);
}
///////////////////////////////////////////////////////////////////////////////
// flag_
void flag_(bool set, regex_constants::syntax_option_type flag)
{
this->flags_ = set ? (this->flags_ | flag) : (this->flags_ & ~flag);
}
///////////////////////////////////////////////////////////////////////////
// is_space_
bool is_space_(char_type ch) const
{
return this->traits().isctype(ch, this->space_);
}
///////////////////////////////////////////////////////////////////////////////
// eat_ws_
iterator_type &eat_ws_(iterator_type &begin, iterator_type end)
{
if(0 != (regex_constants::ignore_white_space & this->flags()))
{
while(end != begin && (BOOST_XPR_CHAR_(char_type, '#') == *begin || this->is_space_(*begin)))
{
if(BOOST_XPR_CHAR_(char_type, '#') == *begin++)
{
while(end != begin && BOOST_XPR_CHAR_(char_type, '\n') != *begin++) {}
}
else
{
for(; end != begin && this->is_space_(*begin); ++begin) {}
}
}
}
return begin;
}
regex_traits traits_;
regex_constants::syntax_option_type flags_;
typename regex_traits::char_class_type space_;
};
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,185 @@
///////////////////////////////////////////////////////////////////////////////
// as_xpr.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_AS_XPR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_AS_XPR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/ref.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/remove_bounds.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/static/placeholders.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<typename T>
struct wrap { wrap(T); };
///////////////////////////////////////////////////////////////////////////////
// is_string_literal
//
template<typename T>
struct is_string_literal
: mpl::or_
<
is_convertible<T, wrap<char const *> >
, is_convertible<T, wrap<wchar_t const *> >
>
{
};
///////////////////////////////////////////////////////////////////////////////
// string_generator
//
template<typename StringT>
struct string_placeholder_generator
{
typedef typename remove_cv
<
typename mpl::eval_if
<
is_array<StringT>
, remove_bounds<StringT>
, remove_pointer<StringT>
>::type
>::type char_type;
typedef string_placeholder<char_type> type;
};
///////////////////////////////////////////////////////////////////////////////
// as_matcher
template<typename MatcherT, bool IsXprT = is_xpr<MatcherT>::value>
struct as_matcher_type
{
typedef MatcherT type;
static type const &call(MatcherT const &matcher)
{
return matcher;
}
};
template<typename LiteralT>
struct as_matcher_type<LiteralT, false>
{
typedef typename mpl::eval_if
<
is_string_literal<LiteralT>
, string_placeholder_generator<LiteralT>
, mpl::identity<literal_placeholder<LiteralT, false> >
>::type type;
static type call(LiteralT const &literal)
{
return type(literal);
}
};
template<typename BidiIterT>
struct as_matcher_type<basic_regex<BidiIterT>, false>
{
typedef regex_placeholder<BidiIterT, false> type;
static type call(basic_regex<BidiIterT> const &rex)
{
typedef core_access<BidiIterT> access;
shared_ptr<regex_impl<BidiIterT> > impl = access::get_regex_impl(rex);
return type(impl);
}
};
template<typename BidiIterT>
struct as_matcher_type<reference_wrapper<basic_regex<BidiIterT> const>, false>
{
typedef regex_placeholder<BidiIterT, false> type;
static type call(reference_wrapper<basic_regex<BidiIterT> const> const &rex)
{
typedef core_access<BidiIterT> access;
shared_ptr<regex_impl<BidiIterT> > impl = access::get_regex_impl(rex.get());
return type(impl);
}
};
///////////////////////////////////////////////////////////////////////////////
// matcher_generator
//
template<typename MatcherT>
struct matcher_generator
{
typedef proto::unary_op
<
typename as_matcher_type<MatcherT>::type
, proto::noop_tag
> type;
};
///////////////////////////////////////////////////////////////////////////////
// as_xpr_type
//
template<typename XprT>
struct as_xpr_type
{
typedef typename mpl::eval_if
<
proto::is_op<XprT>
, mpl::identity<XprT>
, matcher_generator<XprT>
>::type type;
};
}}} // namespace boost::xpressive::detail
namespace boost { namespace xpressive
{
///////////////////////////////////////////////////////////////////////////////
// as_xpr (from a literal to an xpression)
//
template<typename XprT>
inline typename enable_if
<
proto::is_op<XprT>
, XprT const &
>::type
as_xpr(XprT const &xpr)
{
return xpr;
}
template<typename XprT>
inline typename lazy_disable_if
<
proto::is_op<XprT>
, detail::as_xpr_type<XprT>
>::type
as_xpr(XprT const &xpr)
{
return proto::noop(detail::as_matcher_type<XprT>::call(xpr));
}
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,249 @@
///////////////////////////////////////////////////////////////////////////////
// is_pure.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_IS_PURE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_IS_PURE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/as_xpr.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// use_simple_repeat
//
template<typename XprT>
struct use_simple_repeat;
///////////////////////////////////////////////////////////////////////////////
// is_pure
//
template<typename XprT>
struct is_pure;
template<>
struct is_pure<no_next>
: mpl::true_
{
};
template<typename MatcherT>
struct is_pure<proto::unary_op<MatcherT, proto::noop_tag> >
: as_matcher_type<MatcherT>::type::pure
{
};
template<typename LeftT, typename RightT>
struct is_pure<proto::binary_op<LeftT, RightT, proto::right_shift_tag> >
: mpl::and_<is_pure<LeftT>, is_pure<RightT> >
{
};
template<typename LeftT, typename RightT>
struct is_pure<proto::binary_op<LeftT, RightT, proto::bitor_tag> >
: mpl::and_<is_pure<LeftT>, is_pure<RightT> >
{
};
template<typename RightT>
struct is_pure<proto::binary_op<mark_tag, RightT, proto::assign_tag> >
: mpl::false_
{
};
template<typename RightT>
struct is_pure<proto::binary_op<set_initializer_type, RightT, proto::assign_tag> >
: mpl::true_
{
};
template<typename ModifierT, typename XprT>
struct is_pure<proto::binary_op<ModifierT, XprT, modifier_tag> >
: is_pure<XprT>
{
};
template<typename XprT, bool PositiveT>
struct is_pure<proto::unary_op<XprT, lookahead_tag<PositiveT> > >
: is_pure<XprT>
{
};
template<typename XprT, bool PositiveT>
struct is_pure<proto::unary_op<XprT, lookbehind_tag<PositiveT> > >
: is_pure<XprT>
{
};
template<typename XprT>
struct is_pure<proto::unary_op<XprT, keeper_tag> >
: is_pure<XprT>
{
};
template<typename MatcherT, typename NextT>
struct is_pure<static_xpression<MatcherT, NextT> >
: mpl::and_<typename MatcherT::pure, is_pure<NextT> >::type
{
};
template<typename BidiIterT>
struct is_pure<shared_ptr<matchable<BidiIterT> const> >
: mpl::false_
{
};
template<typename BidiIterT>
struct is_pure<std::vector<shared_ptr<matchable<BidiIterT> const> > >
: mpl::false_
{
};
//template<typename BidiIterT>
//struct is_pure<basic_regex<BidiIterT> >
// : mpl::false_
//{
//};
template<typename BidiIterT>
struct is_pure<proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag> >
: mpl::false_
{
};
template<typename BidiIterT>
struct is_pure<proto::unary_op<reference_wrapper<basic_regex<BidiIterT> const>, proto::noop_tag> >
: mpl::false_
{
};
// when complementing a set or an assertion, the purity is that of the set (true) or the assertion
template<typename OpT>
struct is_pure<proto::unary_op<OpT, proto::complement_tag> >
: is_pure<OpT>
{
};
// The comma is used in list-initialized sets, which are pure
template<typename LeftT, typename RightT>
struct is_pure<proto::binary_op<LeftT, RightT, proto::comma_tag> >
: mpl::true_
{
};
// The subscript operator[] is used for sets, as in set['a' | range('b','h')]
// It is also used for actions, which by definition have side-effects and thus are impure
template<typename LeftT, typename RightT>
struct is_pure<proto::binary_op<LeftT, RightT, proto::subscript_tag> >
: is_same<LeftT, set_initializer_type>
{
// If LeftT is "set" then make sure that RightT is pure
BOOST_MPL_ASSERT
((
mpl::or_
<
mpl::not_<is_same<LeftT, set_initializer_type> >
, is_pure<RightT>
>
));
};
// Quantified expressions are pure IFF they use the simple_repeat_matcher
template<typename OpT>
struct is_pure<proto::unary_op<OpT, proto::unary_plus_tag> >
: use_simple_repeat<OpT>
{
};
template<typename OpT>
struct is_pure<proto::unary_op<OpT, proto::unary_star_tag> >
: use_simple_repeat<OpT>
{
};
template<typename OpT>
struct is_pure<proto::unary_op<OpT, proto::logical_not_tag> >
: use_simple_repeat<OpT>
{
};
template<typename OpT, uint_t MinT, uint_t MaxT>
struct is_pure<proto::unary_op<OpT, generic_quant_tag<MinT, MaxT> > >
: use_simple_repeat<OpT>
{
};
template<typename OpT>
struct is_pure<proto::unary_op<OpT, proto::unary_minus_tag> >
: is_pure<OpT>
{
};
template<typename AlternatesT>
struct is_pure<alternates_list<AlternatesT> >
: mpl::fold
<
mpl::transform_view<AlternatesT, is_pure<mpl::_1> >
, mpl::true_
, mpl::and_<mpl::_1, mpl::_2>
>::type
{
};
///////////////////////////////////////////////////////////////////////////////
// use_simple_repeat
// BUGBUG this doesn't handle +(_ >> s1) correctly, right?
template<typename XprT>
struct use_simple_repeat
: mpl::and_<mpl::not_equal_to<width_of<XprT>, unknown_width>, is_pure<XprT> >
{
// should never try to quantify something of 0-width
BOOST_MPL_ASSERT((mpl::not_equal_to<width_of<XprT>, mpl::size_t<0> >));
};
template<typename MatcherT>
struct use_simple_repeat<proto::unary_op<MatcherT, proto::noop_tag> >
: mpl::and_
<
mpl::equal_to
<
quant_type<typename as_matcher_type<MatcherT>::type>
, mpl::int_<quant_fixed_width>
>
, typename as_matcher_type<MatcherT>::type::pure
>
{
BOOST_MPL_ASSERT_RELATION(0, !=, as_matcher_type<MatcherT>::type::width::value);
};
template<typename OpT, typename ArgT>
struct is_pure<proto::op_proxy<OpT, ArgT> >
: is_pure<OpT>
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////
// modifier.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_MODIFIER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_MODIFIER_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/regex_constants.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// modifier
template<typename ModifierT>
struct modifier_op
{
typedef regex_constants::syntax_option_type opt_type;
template<typename XprT>
struct apply
{
typedef proto::binary_op<ModifierT, typename as_xpr_type<XprT>::type, modifier_tag> type;
};
template<typename XprT>
typename apply<XprT>::type
operator ()(XprT const &xpr) const
{
return proto::make_op<modifier_tag>(this->mod_, as_xpr(xpr));
}
operator opt_type() const
{
return this->opt_;
}
ModifierT mod_;
opt_type opt_;
};
}}}
#endif

View File

@@ -0,0 +1,162 @@
///////////////////////////////////////////////////////////////////////////////
// placeholders.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_PLACEHOLDERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PLACEHOLDERS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// literal_placeholder
//
template<typename CharT, bool NotT>
struct literal_placeholder
: quant_style_fixed_width<1>
{
typedef mpl::bool_<NotT> not_type;
CharT ch_;
literal_placeholder(CharT ch)
: ch_(ch)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// string_placeholder
//
template<typename CharT>
struct string_placeholder
: quant_style_fixed_unknown_width
{
std::basic_string<CharT> str_;
string_placeholder(std::basic_string<CharT> const &str)
: str_(str)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// mark_placeholder
//
struct mark_placeholder
: quant_style_fixed_unknown_width
{
int mark_number_;
mark_placeholder(int mark_number)
: mark_number_(mark_number)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// regex_placeholder
//
template<typename BidiIterT, bool ByRefT>
struct regex_placeholder
: quant_style<quant_variable_width, unknown_width, mpl::false_>
{
shared_ptr<regex_impl<BidiIterT> > impl_;
regex_placeholder(shared_ptr<regex_impl<BidiIterT> > const &impl)
: impl_(impl)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// posix_charset_placeholder
//
struct posix_charset_placeholder
: quant_style_fixed_width<1>
{
char const *name_;
bool not_;
posix_charset_placeholder(char const *name)
: name_(name)
, not_(false)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// assert_word_placeholder
//
template<typename CondT>
struct assert_word_placeholder
: quant_style_assertion
{
};
///////////////////////////////////////////////////////////////////////////////
// range_placeholder
//
template<typename CharT>
struct range_placeholder
: quant_style_fixed_width<1>
{
CharT ch_min_;
CharT ch_max_;
bool not_;
range_placeholder(CharT ch_min, CharT ch_max)
: ch_min_(ch_min)
, ch_max_(ch_max)
, not_(false)
{
}
};
///////////////////////////////////////////////////////////////////////////////
// assert_bol_placeholder
//
struct assert_bol_placeholder
: quant_style_assertion
{
};
///////////////////////////////////////////////////////////////////////////////
// assert_eol_placeholder
//
struct assert_eol_placeholder
: quant_style_assertion
{
};
///////////////////////////////////////////////////////////////////////////////
// logical_newline_placeholder
//
struct logical_newline_placeholder
: quant_style_variable_width
{
};
///////////////////////////////////////////////////////////////////////////////
// self_placeholder
//
struct self_placeholder
: quant_style<quant_variable_width, unknown_width, mpl::false_>
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////////////////
// alt_compilers.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_PRODUCTIONS_ALT_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_ALT_COMPILERS_HPP_EAN_10_04_2005
#include <boost/spirit/fusion/sequence/cons.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alt_branch
// Describes how to construct an alternate xpression
struct alt_branch
{
typedef boost::fusion::nil state_type;
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef static_xpression
<
alternate_matcher<alternates_list<OpT>, typename VisitorT::traits_type>
, StateT
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef alternate_matcher<alternates_list<OpT>, typename VisitorT::traits_type> alt_matcher;
return make_static_xpression(alt_matcher(op), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// alt_list_branch
struct alt_list_branch
{
typedef alternate_end_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef boost::fusion::cons<OpT, StateT> type;
};
template<typename OpT, typename StateT>
static boost::fusion::cons<OpT, StateT>
call(OpT const &op, StateT const &state, dont_care)
{
return boost::fusion::make_cons(op, state);
}
};
}}}
namespace boost { namespace proto
{
// production for alternates in sequence
template<>
struct compiler<bitor_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::alt_branch, xpressive::detail::alt_tag>
{
};
// handle alternates with the alt branch compiler
template<typename OpTagT>
struct compiler<OpTagT, xpressive::detail::alt_tag>
: branch_compiler<xpressive::detail::alt_list_branch, xpressive::detail::seq_tag>
{
};
// production for alternates in alternate
template<>
struct compiler<bitor_tag, xpressive::detail::alt_tag>
: fold_compiler<bitor_tag, xpressive::detail::alt_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,137 @@
///////////////////////////////////////////////////////////////////////////////
// charset_transforms.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_PRODUCTIONS_CHARSET_TRANSFORMS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_CHARSET_TRANSFORMS_HPP_EAN_10_04_2005
#include <boost/mpl/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// charset_state
//
template<typename CharSetT, typename TraitsT>
struct charset_state
{
typedef TraitsT traits_type;
typedef typename CharSetT::char_type char_type;
typedef typename CharSetT::icase_type icase_type;
explicit charset_state(CharSetT &charset, traits_type const &traits)
: charset_(charset)
, traits_(traits)
{
}
template<bool NotT>
void set(literal_matcher<traits_type, icase_type::value, NotT> const &ch) const
{
// BUGBUG fixme!
BOOST_MPL_ASSERT_NOT((mpl::bool_<NotT>));
set_char(this->charset_.charset_, ch.ch_, this->traits_, icase_type());
}
void set(range_matcher<traits_type, icase_type::value> const &rg) const
{
// BUGBUG fixme!
BOOST_ASSERT(!rg.not_);
set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->traits_, icase_type());
}
template<int SizeT>
void set(set_matcher<traits_type, SizeT> const &set_) const
{
// BUGBUG fixme!
BOOST_ASSERT(!set_.not_);
for(int i=0; i<SizeT; ++i)
{
set_char(this->charset_.charset_, set_.set_[i], this->traits_, icase_type::value);
}
}
void set(posix_charset_matcher<traits_type, icase_type::value> const &posix) const
{
set_class(this->charset_.charset_, posix.mask_, posix.not_, this->traits_, icase_type::value);
}
template<typename UnknownT>
void set(UnknownT const &) const
{
// If this assert fires, it means that you have put something in a set[] that doesn't
// belong there. For instance, set["hello"]. Legal members of sets are characters,
// character ranges, list-initialized sets such as (set='a','b','c') and posix-style
// character sets such as digit and ~alpha.
BOOST_MPL_ASSERT((never_true<UnknownT>));
}
private:
CharSetT &charset_;
traits_type const &traits_;
};
template<typename CharSetT, typename TraitsT>
charset_state<CharSetT, TraitsT> make_charset_state(CharSetT &charset, TraitsT const &traits)
{
return charset_state<CharSetT, TraitsT>(charset, traits);
}
///////////////////////////////////////////////////////////////////////////////
//
struct charset_transform
{
template<typename, typename, typename VisitorT>
struct apply
{
typedef typename VisitorT::char_type char_type;
// if sizeof(char_type)==1, merge everything into a basic_chset
// BUGBUG this is not optimal.
typedef typename mpl::if_
<
mpl::equal_to<mpl::sizeof_<char_type>, mpl::size_t<1> >
, basic_chset<char_type>
, compound_charset<typename VisitorT::traits_type>
>::type charset_type;
typedef charset_matcher
<
typename VisitorT::traits_type
, VisitorT::icase_type::value
, charset_type
> matcher_type;
typedef proto::unary_op<matcher_type, proto::noop_tag> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, bool complement = false)
{
typedef typename apply<OpT, StateT, VisitorT>::matcher_type matcher_type;
matcher_type matcher;
// Walks the tree and fills in the charset
proto::compile(proto::right(op), make_charset_state(matcher, visitor.traits()), visitor, set_tag());
if(complement)
{
matcher.charset_.inverse();
}
return proto::noop(matcher);
}
};
}}}
#endif

View File

@@ -0,0 +1,251 @@
////////////////////////////////////////////////////////////////////////////
// complement_compiler.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_PRODUCTIONS_COMPLEMENT_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_COMPLEMENT_COMPILER_HPP_EAN_10_04_2005
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/charset_transforms.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// complement
// the result of applying operator~ to various expressions
template<typename OpT, typename VisitorT>
struct complement
{
// If your compile breaks here, then you are applying the complement operator ~
// to something that does not support it. For instance, ~(_ >> 'a') will trigger this
// assertion because the sub-expression (_ >> 'a') has no complement.
BOOST_MPL_ASSERT((never_true<OpT>));
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, bool NotT, typename VisitorT>
struct complement<proto::unary_op<literal_placeholder<CharT, NotT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<literal_placeholder<CharT, !NotT>, proto::noop_tag> type;
static type const call(proto::unary_op<literal_placeholder<CharT, NotT>, proto::noop_tag> const &op, VisitorT &)
{
literal_placeholder<CharT, !NotT> literal = proto::arg(op).ch_;
return proto::noop(literal);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, typename VisitorT>
struct complement<proto::unary_op<CharT, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<literal_placeholder<CharT, true>, proto::noop_tag> type;
static type const call(proto::unary_op<CharT, proto::noop_tag> const &op, VisitorT &)
{
literal_placeholder<CharT, true> literal = proto::arg(op);
return proto::noop(literal);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename TraitsT, int SizeT, typename VisitorT>
struct complement<proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag> type;
static type const call(proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag> const &op, VisitorT &)
{
set_matcher<TraitsT, SizeT> set = proto::arg(op);
set.complement();
return proto::noop(set);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<proto::unary_op<posix_charset_placeholder, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<posix_charset_placeholder, proto::noop_tag> type;
static type const call(proto::unary_op<posix_charset_placeholder, proto::noop_tag> const &op, VisitorT &)
{
posix_charset_placeholder posix = proto::arg(op);
posix.not_ = !posix.not_;
return proto::noop(posix);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::binary_op<set_initializer_type, OpT, proto::subscript_tag>, VisitorT>
{
typedef typename charset_transform::BOOST_NESTED_TEMPLATE apply
<
proto::binary_op<set_initializer_type, OpT, proto::subscript_tag>
, dont_care
, VisitorT
>::type type;
static type call(proto::binary_op<set_initializer_type, OpT, proto::subscript_tag> const &op, VisitorT &visitor)
{
return charset_transform::call(op, dont_care(), visitor, true);
}
};
///////////////////////////////////////////////////////////////////////////////
// for complementing a list-initialized set, as in ~(set= 'a','b','c')
template<typename LeftT, typename RightT, typename VisitorT>
struct complement<proto::binary_op<LeftT, RightT, proto::comma_tag>, VisitorT>
{
// First, convert the parse tree into a set_matcher
typedef typename proto::compiler<proto::comma_tag, lst_tag>::BOOST_NESTED_TEMPLATE apply
<
proto::binary_op<LeftT, RightT, proto::comma_tag>
, dont_care
, VisitorT
>::type set_matcher;
typedef proto::unary_op<set_matcher, proto::noop_tag> type;
static type const call(proto::binary_op<LeftT, RightT, proto::comma_tag> const &op, VisitorT &visitor)
{
set_matcher set(proto::compile(op, dont_care(), visitor, lst_tag()));
set.complement();
return proto::noop(set);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::unary_op<OpT, lookahead_tag<true> >, VisitorT>
{
typedef proto::unary_op<OpT, lookahead_tag<false> > type;
static type call(proto::unary_op<OpT, lookahead_tag<true> > const &op, VisitorT &)
{
return proto::make_op<lookahead_tag<false> >(proto::arg(op));
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::unary_op<OpT, lookbehind_tag<true> >, VisitorT>
{
typedef proto::unary_op<OpT, lookbehind_tag<false> > type;
static type call(proto::unary_op<OpT, lookbehind_tag<true> > const &op, VisitorT &)
{
return proto::make_op<lookbehind_tag<false> >(proto::arg(op));
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<proto::unary_op<assert_word_placeholder<word_boundary<true> >, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<assert_word_placeholder<word_boundary<false> >, proto::noop_tag> type;
static type call(proto::unary_op<assert_word_placeholder<word_boundary<true> >, proto::noop_tag> const &, VisitorT &)
{
return proto::noop(assert_word_placeholder<word_boundary<false> >());
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<logical_newline_xpression, VisitorT>
{
typedef proto::binary_op
<
proto::unary_op<logical_newline_xpression, lookahead_tag<false> >
, proto::unary_op<any_matcher, proto::noop_tag>
, proto::right_shift_tag
> type;
static type call(logical_newline_xpression const &op, VisitorT &)
{
return proto::make_op<lookahead_tag<false> >(op) >> proto::noop(any_matcher());
}
};
///////////////////////////////////////////////////////////////////////////////
// complementing a complement is a no-op
template<typename ArgT, typename VisitorT>
struct complement<proto::unary_op<ArgT, proto::complement_tag>, VisitorT>
{
typedef ArgT type;
static ArgT const &call(proto::unary_op<ArgT, proto::complement_tag> const &op, VisitorT &)
{
return proto::arg(op);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, typename VisitorT>
struct complement<proto::unary_op<range_placeholder<CharT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<range_placeholder<CharT>, proto::noop_tag> type;
static type const call(proto::unary_op<range_placeholder<CharT>, proto::noop_tag> const &op, VisitorT &)
{
range_placeholder<CharT> rng = proto::arg(op);
rng.not_ = !rng.not_;
return proto::noop(rng);
}
};
///////////////////////////////////////////////////////////////////////////////
// complement_transform
struct complement_transform
{
template<typename OpT, typename, typename VisitorT>
struct apply
{
typedef typename complement<typename proto::arg_type<OpT>::type, VisitorT>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename complement<typename proto::arg_type<OpT>::type, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor)
{
return complement<typename proto::arg_type<OpT>::type, VisitorT>::call(proto::arg(op), visitor);
}
};
}}}
namespace boost { namespace proto
{
template<>
struct compiler<complement_tag, xpressive::detail::seq_tag>
: transform_compiler<xpressive::detail::complement_transform, xpressive::detail::seq_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////
// domain_tags.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_PRODUCTIONS_DOMAIN_TAGS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_DOMAIN_TAGS_HPP_EAN_10_04_2005
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex domain tags
struct seq_tag {};
struct alt_tag {};
struct lst_tag {};
struct set_tag {};
struct ind_tag {};
}}}
#endif

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// independent_compiler.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_PRODUCTIONS_INDEPENDENT_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_INDEPENDENT_COMPILER_HPP_EAN_10_04_2005
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<bool PositiveT>
struct lookahead_tag : proto::unary_tag {};
template<bool PositiveT>
struct lookbehind_tag : proto::unary_tag {};
struct keeper_tag : proto::unary_tag {};
///////////////////////////////////////////////////////////////////////////////
// lookahead_branch
template<bool PositiveT>
struct lookahead_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<lookahead_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<lookahead_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(lookahead_matcher<OpT>(op, !PositiveT), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// lookbehind_branch
template<bool PositiveT>
struct lookbehind_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<lookbehind_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<lookbehind_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(lookbehind_matcher<OpT>(op, !PositiveT), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// keeper_branch
struct keeper_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<keeper_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<keeper_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(keeper_matcher<OpT>(op), state);
}
};
}}}
namespace boost { namespace proto {
template<bool PositiveT>
struct compiler<xpressive::detail::lookahead_tag<PositiveT>, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::lookahead_branch<PositiveT>, xpressive::detail::ind_tag>
{
};
template<bool PositiveT>
struct compiler<xpressive::detail::lookbehind_tag<PositiveT>, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::lookbehind_branch<PositiveT>, xpressive::detail::ind_tag>
{
};
template<>
struct compiler<xpressive::detail::keeper_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::keeper_branch, xpressive::detail::ind_tag>
{
};
template<typename OpTagT>
struct compiler<OpTagT, xpressive::detail::ind_tag>
: transform_compiler<arg_transform, xpressive::detail::seq_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,73 @@
////////////////////////////////////////////////////////////////////////////
// marker_compiler.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_PRODUCTIONS_MARKER_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MARKER_COMPILER_HPP_EAN_10_04_2005
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/marker_transform.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// marker_assign_transform
struct marker_assign_transform
: proto::compose_transforms<proto::right_transform, marker_transform>
{
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
return marker_transform::call(proto::right(op), state, visitor, proto::arg(proto::left(op)).mark_number_);
}
};
///////////////////////////////////////////////////////////////////////////////
// is_marker_predicate
struct is_marker_predicate
{
template<typename OpT, typename, typename>
struct apply
: is_same<typename proto::left_type<OpT>::type, mark_tag>
{
};
};
///////////////////////////////////////////////////////////////////////////////
// assign_compiler
// could be (s1= 'a') or (set= 'a')
struct assign_compiler
: proto::conditional_compiler
<
is_marker_predicate
, proto::transform_compiler<marker_assign_transform, seq_tag>
, proto::branch_compiler<list_branch, lst_tag>
>
{
};
}}}
namespace boost { namespace proto {
template<>
struct compiler<assign_tag, xpressive::detail::seq_tag>
: xpressive::detail::assign_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////
// marker_transform.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_PRODUCTIONS_MARKER_TRANSFORM_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MARKER_TRANSFORM_HPP_EAN_10_04_2005
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// is_marker
template<typename OpT>
struct is_marker
: mpl::false_
{};
template<typename OpT>
struct is_marker
<
proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, OpT
, proto::right_shift_tag
>
>
: mpl::true_
{};
///////////////////////////////////////////////////////////////////////////////
// mark_number
template<typename OpT, typename VisitorT>
int mark_number
(
proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, OpT
, proto::right_shift_tag
> const &op
, VisitorT &
)
{
return proto::arg(proto::left(op)).mark_number_;
}
template<typename ArgT, typename VisitorT>
int mark_number(ArgT const &, VisitorT &visitor)
{
return visitor.get_hidden_mark();
}
///////////////////////////////////////////////////////////////////////////////
// marker_transform
// Insert mark tags before and after the expression
struct marker_transform
{
template<typename OpT, typename, typename>
struct apply
{
typedef proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, proto::binary_op
<
OpT
, proto::unary_op<mark_end_matcher, proto::noop_tag>
, proto::right_shift_tag
>
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor, int mark_nbr = -1)
{
return proto::noop(mark_begin_matcher(mark_nbr))
>> (op >> proto::noop(mark_end_matcher(mark_nbr)));
}
};
}}}
#endif

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////////
// modify_compiler.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_PRODUCTIONS_MODIFY_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MODIFY_COMPILER_HPP_EAN_10_04_2005
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex operator tags
struct modifier_tag
: proto::binary_tag
{
};
///////////////////////////////////////////////////////////////////////////////
// modify_compiler
struct modify_compiler
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename proto::left_type<OpT>::type modifier_type;
typedef typename modifier_type::BOOST_NESTED_TEMPLATE apply<VisitorT>::type visitor_type;
typedef typename proto::right_type<OpT>::type op_type;
typedef typename proto::compiler<typename proto::tag_type<op_type>::type, seq_tag>::
BOOST_NESTED_TEMPLATE apply
<
op_type
, StateT
, visitor_type
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename apply<OpT, StateT, VisitorT>::visitor_type new_visitor_type;
new_visitor_type new_visitor(proto::left(op).call(visitor));
new_visitor.swap(visitor);
struct local // for swapping state back after proto::compile returns
{ ~local() { v->swap(*nv); }
VisitorT *const v; new_visitor_type *const nv;
} const undo = { &visitor, &new_visitor };
ignore_unused(&undo);
return proto::compile(proto::right(op), state, new_visitor, seq_tag());
}
};
}}}
namespace boost { namespace proto
{
// production for modifiers
template<>
struct compiler<xpressive::detail::modifier_tag, xpressive::detail::seq_tag>
: xpressive::detail::modify_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////
// noop_compiler.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_PRODUCTIONS_NOOP_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_NOOP_COMPILER_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex compiler productions
struct noop_compiler
{
///////////////////////////////////////////////////////////////////////////////
// transformation that happens to leaf nodes in the parse tree
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename as_matcher_type<typename proto::arg_type<OpT>::type>::type matcher1;
typedef typename VisitorT::BOOST_NESTED_TEMPLATE apply<matcher1>::type matcher2;
typedef static_xpression<matcher2, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename proto::arg_type<OpT>::type arg_type;
return make_static_xpression(visitor.call(as_matcher_type<arg_type>::call(proto::arg(op))), state);
}
};
}}}
namespace boost { namespace proto
{
// production for terminals in sequence
template<>
struct compiler<noop_tag, xpressive::detail::seq_tag>
: xpressive::detail::noop_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,108 @@
///////////////////////////////////////////////////////////////////////////////
// productions.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_PRODUCTIONS_PRODUCTIONS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_PRODUCTIONS_HPP_EAN_10_04_2005
#include <boost/ref.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/visitor.hpp>
#include <boost/xpressive/detail/static/productions/quant_compilers.hpp>
#include <boost/xpressive/detail/static/productions/alt_compilers.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/noop_compiler.hpp>
#include <boost/xpressive/detail/static/productions/modify_compiler.hpp>
#include <boost/xpressive/detail/static/productions/complement_compiler.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
#include <boost/xpressive/detail/static/productions/marker_compiler.hpp>
#include <boost/xpressive/detail/static/productions/charset_transforms.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
//
struct is_set_initializer_predicate
{
template<typename OpT, typename, typename>
struct apply
{
typedef typename is_same<typename proto::left_type<OpT>::type, set_initializer_type>::type type;
};
};
///////////////////////////////////////////////////////////////////////////////
//
struct action_transform
{
template<typename OpT, typename, typename>
struct apply
{
typedef proto::binary_op
<
typename proto::left_type<OpT>::type
, typename proto::right_type<OpT>::type
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::left(op) >> proto::right(op);
}
};
///////////////////////////////////////////////////////////////////////////////
// subscript_compiler
struct subscript_compiler
: proto::conditional_compiler
<
is_set_initializer_predicate
, proto::transform_compiler<charset_transform, seq_tag>
, proto::transform_compiler<action_transform, seq_tag>
>
{
};
}}}
///////////////////////////////////////////////////////////////////////////////
// misc regex compiler productions
namespace boost { namespace proto
{
template<typename BidiIterT>
struct value_type<xpressive::basic_regex<BidiIterT> >
{
// store regex objects in the parse tree by reference
typedef reference_wrapper<xpressive::basic_regex<BidiIterT> const> type;
};
// production for sequences in sequence
template<>
struct compiler<right_shift_tag, xpressive::detail::seq_tag>
: fold_compiler<right_shift_tag, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<subscript_tag, xpressive::detail::seq_tag>
: xpressive::detail::subscript_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,169 @@
///////////////////////////////////////////////////////////////////////////////
// quant_compilers.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_PRODUCTIONS_QUANT_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_COMPILERS_HPP_EAN_10_04_2005
#include <limits.h>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/detail/static/productions/quant_traits.hpp>
#include <boost/xpressive/detail/static/productions/quant_transforms.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_compiler
: proto::conditional_compiler
<
use_simple_repeat_predicate
, proto::branch_compiler<simple_repeat_branch<GreedyT, MinT, MaxT>, ind_tag>
, proto::transform_compiler<plus_transform<GreedyT, MinT, MaxT>, seq_tag>
>
{
};
template<bool GreedyT = true, uint_t MaxT = UINT_MAX-1>
struct star_compiler
: proto::conditional_compiler
<
use_simple_repeat_predicate
, proto::branch_compiler<simple_repeat_branch<GreedyT, 0, MaxT>, ind_tag>
, proto::transform_compiler<star_transform<GreedyT, MaxT>, seq_tag>
>
{
};
template<bool GreedyT = true>
struct optional_compiler
: proto::transform_compiler<optional_transform<GreedyT>, seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// generic_quant_compiler
template<bool GreedyT, uint_t MinT, uint_t MaxT>
struct generic_quant_compiler
: plus_compiler<GreedyT, MinT, MaxT>
{
};
template<bool GreedyT, uint_t MaxT>
struct generic_quant_compiler<GreedyT, 0, MaxT>
: star_compiler<GreedyT, MaxT>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 0, 1>
: optional_compiler<GreedyT>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 1, 1>
: proto::transform_compiler<proto::arg_transform, seq_tag>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 0, 0>
: proto::transform_compiler<epsilon_transform, seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// non_greedy_compiler
//
struct non_greedy_compiler
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
// Did you apply operator- to something that wasn't a quantifier?
BOOST_MPL_ASSERT((is_greedy_quant<typename proto::arg_type<OpT>::type>));
typedef typename proto::tag_type<typename proto::arg_type<OpT>::type>::type tag_type;
typedef typename min_type<tag_type>::type min_type;
typedef typename max_type<tag_type>::type max_type;
typedef generic_quant_compiler
<
false
, min_type::value
, max_type::value
> compiler_type;
typedef typename compiler_type::BOOST_NESTED_TEMPLATE apply
<
typename proto::arg_type<OpT>::type
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename apply<OpT, StateT, VisitorT>::compiler_type compiler_type;
return compiler_type::call(proto::arg(op), state, visitor);
}
};
}}}
namespace boost { namespace proto
{
// production for one or more quant
template<>
struct compiler<unary_plus_tag, xpressive::detail::seq_tag>
: xpressive::detail::plus_compiler<>
{
};
// production for zero or more quant
template<>
struct compiler<unary_star_tag, xpressive::detail::seq_tag>
: xpressive::detail::star_compiler<>
{
};
// production for optional
template<>
struct compiler<logical_not_tag, xpressive::detail::seq_tag>
: xpressive::detail::optional_compiler<>
{
};
// production for generic quantifiers
template<unsigned int MinT, unsigned int MaxT>
struct compiler<xpressive::detail::generic_quant_tag<MinT, MaxT>, xpressive::detail::seq_tag>
: xpressive::detail::generic_quant_compiler<true, MinT, MaxT>
{
};
// production for non-greedy quantifiers
template<>
struct compiler<unary_minus_tag, xpressive::detail::seq_tag>
: xpressive::detail::non_greedy_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////
// quant_traits.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_PRODUCTIONS_QUANT_TRAITS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_TRAITS_HPP_EAN_10_04_2005
#include <boost/mpl/or.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
#include <boost/xpressive/detail/static/is_pure.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4307) // '+' : integral constant overflow
#endif
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// generic_quant_tag
template<uint_t MinT, uint_t MaxT>
struct generic_quant_tag
: proto::unary_tag
{
typedef mpl::integral_c<uint_t, MinT> min_type;
typedef mpl::integral_c<uint_t, MaxT> max_type;
};
///////////////////////////////////////////////////////////////////////////////
// min_type / max_type
template<typename TagT>
struct min_type : TagT::min_type {};
template<>
struct min_type<proto::unary_plus_tag> : mpl::integral_c<uint_t, 1> {};
template<>
struct min_type<proto::unary_star_tag> : mpl::integral_c<uint_t, 0> {};
template<>
struct min_type<proto::logical_not_tag> : mpl::integral_c<uint_t, 0> {};
template<typename TagT>
struct max_type : TagT::max_type {};
template<>
struct max_type<proto::unary_plus_tag> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::unary_star_tag> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::logical_not_tag> : mpl::integral_c<uint_t, 1> {};
struct use_simple_repeat_predicate
{
template<typename OpT, typename, typename>
struct apply
{
typedef typename use_simple_repeat<typename proto::arg_type<OpT>::type>::type type;
};
};
///////////////////////////////////////////////////////////////////////////////
// is_greedy_quant
template<typename XprT>
struct is_greedy_quant
: mpl::false_
{
};
template<typename OpT, typename TagT>
struct is_greedy_quant<proto::unary_op<OpT, TagT> >
: mpl::or_
<
is_same<TagT, proto::unary_plus_tag>
, is_same<TagT, proto::unary_star_tag>
, is_same<TagT, proto::logical_not_tag>
>
{
};
template<typename OpT, uint_t MinT, uint_t MaxT>
struct is_greedy_quant<proto::unary_op<OpT, generic_quant_tag<MinT, MaxT> > >
: mpl::true_
{
};
}}}
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,263 @@
///////////////////////////////////////////////////////////////////////////////
// quant_transforms.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_PRODUCTIONS_QUANT_TRANSFORMS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_TRANSFORMS_HPP_EAN_10_04_2005
#include <limits.h>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/static/productions/quant_traits.hpp>
#include <boost/xpressive/detail/static/productions/marker_transform.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// plus_no_mark_transform
// Unary plus becomes a quantifier by wrapping arg in begin/end quantifiers
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_no_mark_transform
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
proto::binary_op
<
proto::unary_op<repeat_begin_matcher, proto::noop_tag>
, typename proto::arg_type<OpT>::type // skip the "plus" node
, proto::right_shift_tag
>
, proto::unary_op<repeat_end_matcher<GreedyT>, proto::noop_tag>
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &, int mark_number = -1, uint_t min = MinT, uint_t max = MaxT)
{
return proto::noop(repeat_begin_matcher(mark_number))
>> proto::arg(op)
>> proto::noop(repeat_end_matcher<GreedyT>(mark_number, min, max));
}
};
///////////////////////////////////////////////////////////////////////////////
// plus_mark_transform
// compose the quant and mark transforms
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_mark_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef typename marker_transform::apply
<
typename proto::arg_type<OpT>::type
, StateT
, VisitorT
>::type marker_type;
typedef typename plus_no_mark_transform<GreedyT, MinT, MaxT>::BOOST_NESTED_TEMPLATE apply
<
proto::unary_op<marker_type, typename proto::tag_type<OpT>::type>
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, int mark_number = -1, uint_t min = MinT, uint_t max = MaxT)
{
return plus_no_mark_transform<GreedyT, MinT, MaxT>::call
(
proto::make_op<typename proto::tag_type<OpT>::type>
(
marker_transform::call(proto::arg(op), state, visitor, mark_number)
)
, state
, visitor
, mark_number
, min
, max
);
}
};
///////////////////////////////////////////////////////////////////////////////
// optional_transform
// An optional expression gets the following transformation:
template<bool GreedyT>
struct optional_transform
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
typename proto::arg_type<OpT>::type
, proto::unary_op<epsilon_matcher, proto::noop_tag>
, proto::bitor_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::arg(op) | proto::noop(epsilon_matcher());
}
};
///////////////////////////////////////////////////////////////////////////////
// non-greedy optional transform
template<>
struct optional_transform<false>
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
proto::unary_op<epsilon_matcher, proto::noop_tag>
, typename proto::arg_type<OpT>::type
, proto::bitor_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::noop(epsilon_matcher()) | proto::arg(op);
}
};
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_branch
template<bool GreedyT = true, uint_t MinT = 0, uint_t MaxT = UINT_MAX-1>
struct simple_repeat_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<OpT> >));
typedef static_xpression<simple_repeat_matcher<OpT, GreedyT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &, uint_t min = MinT, uint_t max = MaxT)
{
return make_static_xpression(simple_repeat_matcher<OpT, GreedyT>(op, min, max), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// plus_transform
// Optimization: don't insert a hidden mark if we already have a visible one
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename mpl::if_
<
is_marker<typename proto::arg_type<OpT>::type>
, plus_no_mark_transform<GreedyT, MinT, MaxT>
, plus_mark_transform<GreedyT, MinT, MaxT>
>::type transform;
typedef typename transform::BOOST_NESTED_TEMPLATE apply<OpT, StateT, VisitorT>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, uint_t min = MinT, uint_t max = MaxT)
{
return apply<OpT, StateT, VisitorT>::transform::call(op, state, visitor, mark_number(proto::arg(op), visitor), min, max);
}
};
///////////////////////////////////////////////////////////////////////////////
// star_transform
template<bool GreedyT = true, uint_t MaxT = UINT_MAX-1>
struct star_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename plus_transform<GreedyT, 1, MaxT>::BOOST_NESTED_TEMPLATE apply
<
OpT
, StateT
, VisitorT
>::type plus_type;
typedef typename optional_transform<GreedyT>::BOOST_NESTED_TEMPLATE apply
<
proto::unary_op<plus_type, proto::unary_plus_tag>
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, uint_t max = MaxT)
{
return optional_transform<GreedyT>::call
(
+plus_transform<GreedyT, 1, MaxT>::call(op, state, visitor, 1, max)
, state
, visitor
);
}
};
///////////////////////////////////////////////////////////////////////////////
// epsilon_transform
struct epsilon_transform
{
template<typename, typename, typename>
struct apply
{
typedef proto::unary_op<epsilon_matcher, proto::noop_tag> type;
};
static proto::unary_op<epsilon_matcher, proto::noop_tag>
call(dont_care, dont_care, dont_care)
{
return proto::noop(epsilon_matcher());
}
};
}}}
#endif

View File

@@ -0,0 +1,171 @@
////////////////////////////////////////////////////////////////////////////
// set_compilers.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_PRODUCTIONS_SET_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_SET_COMPILERS_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// set_branch
//
struct set_branch
{
typedef no_next state_type;
template<typename, typename StateT, typename>
struct apply
{
typedef StateT type;
};
template<typename OpT, typename StateT, typename VisitorT>
static StateT const &call(OpT const &op, StateT const &state, VisitorT &visitor)
{
return state.set(set_branch::get_matcher(op)), state;
}
private:
template<typename MatcherT>
static MatcherT const &get_matcher(static_xpression<MatcherT, no_next> const &xpr)
{
return xpr;
}
};
///////////////////////////////////////////////////////////////////////////////
// list_branch
struct list_branch
{
typedef int state_type; // not used
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<OpT, StateT> type;
};
template<typename OpT, typename StateT>
static static_xpression<OpT, StateT>
call(OpT const &op, StateT const &state, dont_care)
{
return make_static_xpression(op, state);
}
};
///////////////////////////////////////////////////////////////////////////////
// list_noop_compiler
struct list_noop_compiler
{
template<typename, typename StateT, typename>
struct apply
{
typedef typename StateT::next_type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename StateT::next_type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename VisitorT::char_type char_type;
char_type ch = char_cast<char_type>(proto::arg(op), visitor.traits());
return state.push_back(ch, visitor.traits());
}
};
///////////////////////////////////////////////////////////////////////////////
// list_assign_compiler
struct list_assign_compiler
{
template<typename OpT, typename, typename VisitorT>
struct apply
{
typedef typename VisitorT::traits_type traits_type;
typedef set_matcher<traits_type, 1> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor)
{
typedef typename VisitorT::char_type char_type;
char_type ch = char_cast<char_type>(proto::arg(proto::right(op)), visitor.traits());
return typename apply<OpT, StateT, VisitorT>::type(ch, visitor.traits());
}
};
}}}
namespace boost { namespace proto
{
///////////////////////////////////////////////////////////////////////////////
// compilers for sets such as set['a' | range('a','z')]
template<>
struct compiler<bitor_tag, xpressive::detail::set_tag>
: fold_compiler<bitor_tag, xpressive::detail::set_tag>
{
};
template<>
struct compiler<noop_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<complement_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<comma_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// compilers for list-initialized sets such as (set='a','b','c')
template<>
struct compiler<comma_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::list_branch, xpressive::detail::lst_tag>
{
};
template<>
struct compiler<comma_tag, xpressive::detail::lst_tag>
: fold_compiler<comma_tag, xpressive::detail::lst_tag, false>
{
};
template<>
struct compiler<noop_tag, xpressive::detail::lst_tag>
: xpressive::detail::list_noop_compiler
{
};
template<>
struct compiler<assign_tag, xpressive::detail::lst_tag>
: xpressive::detail::list_assign_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,199 @@
///////////////////////////////////////////////////////////////////////////////
// transmogrify.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_PRODUCTIONS_TRANSMOGRIFY_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_TRANSMOGRIFY_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/static/placeholders.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// transmogrify
//
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename MatcherT>
struct transmogrify
{
typedef MatcherT type;
static type const &call(MatcherT const &m, dont_care)
{
return m;
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_bol_placeholder>
{
typedef assert_bol_matcher<TraitsT> type;
template<typename VisitorT>
static type call(assert_bol_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_eol_placeholder>
{
typedef assert_eol_matcher<TraitsT> type;
template<typename VisitorT>
static type call(assert_eol_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, logical_newline_placeholder>
{
typedef logical_newline_matcher<TraitsT> type;
template<typename VisitorT>
static type call(logical_newline_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT, bool NotT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, literal_placeholder<CharT, NotT> >
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef literal_matcher<TraitsT, ICaseT::value, NotT> type;
template<typename VisitorT>
static type call(literal_placeholder<CharT, NotT> const &m, VisitorT &visitor)
{
char_type ch = char_cast<char_type>(m.ch_, visitor.traits());
return type(ch, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, range_placeholder<CharT> >
{
// By design, we don't widen character ranges.
typedef typename iterator_value<BidiIterT>::type char_type;
BOOST_MPL_ASSERT((is_same<CharT, char_type>));
typedef range_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(range_placeholder<CharT> const &m, VisitorT &visitor)
{
return type(m.ch_min_, m.ch_max_, m.not_, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, string_placeholder<CharT> >
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef string_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(string_placeholder<CharT> const &m, VisitorT &visitor)
{
return type(string_cast<char_type>(m.str_, visitor.traits()), visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, mark_placeholder>
{
typedef mark_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(mark_placeholder const &m, VisitorT &visitor)
{
return type(m.mark_number_, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, posix_charset_placeholder>
{
typedef posix_charset_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(posix_charset_placeholder const &m, VisitorT &visitor)
{
char const *name_end = m.name_ + std::strlen(m.name_);
return type(visitor.traits().lookup_classname(m.name_, name_end, ICaseT::value), m.not_);
}
};
template<typename BidiIterT, typename TraitsT, int SizeT>
struct transmogrify<BidiIterT, mpl::true_, TraitsT, set_matcher<TraitsT, SizeT> >
{
typedef set_matcher<TraitsT, SizeT> type;
template<typename VisitorT>
static type call(set_matcher<TraitsT, SizeT> m, VisitorT &visitor)
{
m.nocase(visitor.traits());
return m;
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CondT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_word_placeholder<CondT> >
{
typedef assert_word_matcher<CondT, TraitsT> type;
template<typename VisitorT>
static type call(dont_care, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, bool ByRefT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, regex_placeholder<BidiIterT, ByRefT> >
{
typedef typename mpl::if_c
<
ByRefT
, regex_byref_matcher<BidiIterT>
, regex_matcher<BidiIterT>
>::type type;
static type call(regex_placeholder<BidiIterT, ByRefT> const &m, dont_care)
{
return type(m.impl_);
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, self_placeholder>
{
typedef regex_byref_matcher<BidiIterT> type;
template<typename VisitorT>
static type call(self_placeholder, VisitorT &visitor)
{
return type(visitor.self());
}
};
}}}
#endif

View File

@@ -0,0 +1,142 @@
///////////////////////////////////////////////////////////////////////////////
// visitor.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_PRODUCTIONS_VISITOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_VISITOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/static/productions/transmogrify.hpp>
#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
//
template<typename BidiIterT>
struct xpression_visitor_base
{
explicit xpression_visitor_base(shared_ptr<regex_impl<BidiIterT> > const &self)
: impl_()
, self_(self)
{
}
void swap(xpression_visitor_base &that)
{
this->impl_.swap(that.impl_);
this->self_.swap(that.self_);
}
int get_hidden_mark()
{
return -(int)(++this->impl_.hidden_mark_count_);
}
void mark_number(int mark_number)
{
if(0 < mark_number)
{
this->impl_.mark_count_ =
(std::max)(this->impl_.mark_count_, (std::size_t)mark_number);
}
}
shared_ptr<regex_impl<BidiIterT> > &self()
{
return this->self_;
}
regex_impl<BidiIterT> &impl()
{
return this->impl_;
}
protected:
template<typename MatcherT>
void visit_(MatcherT const &)
{
// no-op
}
template<bool ByRefT>
void visit_(regex_placeholder<BidiIterT, ByRefT> const &rex)
{
// when visiting an embeded regex, track the references
this->impl_.track_reference(rex.impl_);
}
void visit_(mark_placeholder const &backref)
{
// keep track of the largest mark number found
this->mark_number(backref.mark_number_);
}
void visit_(mark_begin_matcher const &mark_begin)
{
// keep track of the largest mark number found
this->mark_number(mark_begin.mark_number_);
}
private:
regex_impl<BidiIterT> impl_;
shared_ptr<regex_impl<BidiIterT> > self_;
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct xpression_visitor
: xpression_visitor_base<BidiIterT>
{
typedef BidiIterT iterator_type;
typedef ICaseT icase_type;
typedef TraitsT traits_type;
typedef typename boost::iterator_value<BidiIterT>::type char_type;
explicit xpression_visitor(TraitsT const &tr, shared_ptr<regex_impl<BidiIterT> > const &self)
: xpression_visitor_base<BidiIterT>(self)
, traits_(tr)
{
}
template<typename MatcherT>
struct apply
{
typedef typename transmogrify<BidiIterT, ICaseT, TraitsT, MatcherT>::type type;
};
template<typename MatcherT>
typename apply<MatcherT>::type
call(MatcherT const &matcher)
{
this->visit_(matcher);
return transmogrify<BidiIterT, ICaseT, TraitsT, MatcherT>::call(matcher, *this);
}
TraitsT const &traits() const
{
return this->traits_;
}
private:
TraitsT traits_;
};
}}}
#endif

View File

@@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////////////////
// alt_compilers.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_PRODUCTIONS_ALT_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_ALT_COMPILERS_HPP_EAN_10_04_2005
#include <boost/spirit/fusion/sequence/cons.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alt_branch
// Describes how to construct an alternate xpression
struct alt_branch
{
typedef boost::fusion::nil state_type;
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef static_xpression
<
alternate_matcher<alternates_list<OpT>, typename VisitorT::traits_type>
, StateT
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef alternate_matcher<alternates_list<OpT>, typename VisitorT::traits_type> alt_matcher;
return make_static_xpression(alt_matcher(op), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// alt_list_branch
struct alt_list_branch
{
typedef alternate_end_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef boost::fusion::cons<OpT, StateT> type;
};
template<typename OpT, typename StateT>
static boost::fusion::cons<OpT, StateT>
call(OpT const &op, StateT const &state, dont_care)
{
return boost::fusion::make_cons(op, state);
}
};
}}}
namespace boost { namespace proto
{
// production for alternates in sequence
template<>
struct compiler<bitor_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::alt_branch, xpressive::detail::alt_tag>
{
};
// handle alternates with the alt branch compiler
template<typename OpTagT>
struct compiler<OpTagT, xpressive::detail::alt_tag>
: branch_compiler<xpressive::detail::alt_list_branch, xpressive::detail::seq_tag>
{
};
// production for alternates in alternate
template<>
struct compiler<bitor_tag, xpressive::detail::alt_tag>
: fold_compiler<bitor_tag, xpressive::detail::alt_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,137 @@
///////////////////////////////////////////////////////////////////////////////
// charset_transforms.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_PRODUCTIONS_CHARSET_TRANSFORMS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_CHARSET_TRANSFORMS_HPP_EAN_10_04_2005
#include <boost/mpl/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// charset_state
//
template<typename CharSetT, typename TraitsT>
struct charset_state
{
typedef TraitsT traits_type;
typedef typename CharSetT::char_type char_type;
typedef typename CharSetT::icase_type icase_type;
explicit charset_state(CharSetT &charset, traits_type const &traits)
: charset_(charset)
, traits_(traits)
{
}
template<bool NotT>
void set(literal_matcher<traits_type, icase_type::value, NotT> const &ch) const
{
// BUGBUG fixme!
BOOST_MPL_ASSERT_NOT((mpl::bool_<NotT>));
set_char(this->charset_.charset_, ch.ch_, this->traits_, icase_type());
}
void set(range_matcher<traits_type, icase_type::value> const &rg) const
{
// BUGBUG fixme!
BOOST_ASSERT(!rg.not_);
set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->traits_, icase_type());
}
template<int SizeT>
void set(set_matcher<traits_type, SizeT> const &set_) const
{
// BUGBUG fixme!
BOOST_ASSERT(!set_.not_);
for(int i=0; i<SizeT; ++i)
{
set_char(this->charset_.charset_, set_.set_[i], this->traits_, icase_type::value);
}
}
void set(posix_charset_matcher<traits_type, icase_type::value> const &posix) const
{
set_class(this->charset_.charset_, posix.mask_, posix.not_, this->traits_, icase_type::value);
}
template<typename UnknownT>
void set(UnknownT const &) const
{
// If this assert fires, it means that you have put something in a set[] that doesn't
// belong there. For instance, set["hello"]. Legal members of sets are characters,
// character ranges, list-initialized sets such as (set='a','b','c') and posix-style
// character sets such as digit and ~alpha.
BOOST_MPL_ASSERT((never_true<UnknownT>));
}
private:
CharSetT &charset_;
traits_type const &traits_;
};
template<typename CharSetT, typename TraitsT>
charset_state<CharSetT, TraitsT> make_charset_state(CharSetT &charset, TraitsT const &traits)
{
return charset_state<CharSetT, TraitsT>(charset, traits);
}
///////////////////////////////////////////////////////////////////////////////
//
struct charset_transform
{
template<typename, typename, typename VisitorT>
struct apply
{
typedef typename VisitorT::char_type char_type;
// if sizeof(char_type)==1, merge everything into a basic_chset
// BUGBUG this is not optimal.
typedef typename mpl::if_
<
mpl::equal_to<mpl::sizeof_<char_type>, mpl::size_t<1> >
, basic_chset<char_type>
, compound_charset<typename VisitorT::traits_type>
>::type charset_type;
typedef charset_matcher
<
typename VisitorT::traits_type
, VisitorT::icase_type::value
, charset_type
> matcher_type;
typedef proto::unary_op<matcher_type, proto::noop_tag> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, bool complement = false)
{
typedef typename apply<OpT, StateT, VisitorT>::matcher_type matcher_type;
matcher_type matcher;
// Walks the tree and fills in the charset
proto::compile(proto::right(op), make_charset_state(matcher, visitor.traits()), visitor, set_tag());
if(complement)
{
matcher.charset_.inverse();
}
return proto::noop(matcher);
}
};
}}}
#endif

View File

@@ -0,0 +1,251 @@
////////////////////////////////////////////////////////////////////////////
// complement_compiler.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_PRODUCTIONS_COMPLEMENT_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_COMPLEMENT_COMPILER_HPP_EAN_10_04_2005
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/charset_transforms.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// complement
// the result of applying operator~ to various expressions
template<typename OpT, typename VisitorT>
struct complement
{
// If your compile breaks here, then you are applying the complement operator ~
// to something that does not support it. For instance, ~(_ >> 'a') will trigger this
// assertion because the sub-expression (_ >> 'a') has no complement.
BOOST_MPL_ASSERT((never_true<OpT>));
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, bool NotT, typename VisitorT>
struct complement<proto::unary_op<literal_placeholder<CharT, NotT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<literal_placeholder<CharT, !NotT>, proto::noop_tag> type;
static type const call(proto::unary_op<literal_placeholder<CharT, NotT>, proto::noop_tag> const &op, VisitorT &)
{
literal_placeholder<CharT, !NotT> literal = proto::arg(op).ch_;
return proto::noop(literal);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, typename VisitorT>
struct complement<proto::unary_op<CharT, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<literal_placeholder<CharT, true>, proto::noop_tag> type;
static type const call(proto::unary_op<CharT, proto::noop_tag> const &op, VisitorT &)
{
literal_placeholder<CharT, true> literal = proto::arg(op);
return proto::noop(literal);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename TraitsT, int SizeT, typename VisitorT>
struct complement<proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag> type;
static type const call(proto::unary_op<set_matcher<TraitsT, SizeT>, proto::noop_tag> const &op, VisitorT &)
{
set_matcher<TraitsT, SizeT> set = proto::arg(op);
set.complement();
return proto::noop(set);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<proto::unary_op<posix_charset_placeholder, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<posix_charset_placeholder, proto::noop_tag> type;
static type const call(proto::unary_op<posix_charset_placeholder, proto::noop_tag> const &op, VisitorT &)
{
posix_charset_placeholder posix = proto::arg(op);
posix.not_ = !posix.not_;
return proto::noop(posix);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::binary_op<set_initializer_type, OpT, proto::subscript_tag>, VisitorT>
{
typedef typename charset_transform::BOOST_NESTED_TEMPLATE apply
<
proto::binary_op<set_initializer_type, OpT, proto::subscript_tag>
, dont_care
, VisitorT
>::type type;
static type call(proto::binary_op<set_initializer_type, OpT, proto::subscript_tag> const &op, VisitorT &visitor)
{
return charset_transform::call(op, dont_care(), visitor, true);
}
};
///////////////////////////////////////////////////////////////////////////////
// for complementing a list-initialized set, as in ~(set= 'a','b','c')
template<typename LeftT, typename RightT, typename VisitorT>
struct complement<proto::binary_op<LeftT, RightT, proto::comma_tag>, VisitorT>
{
// First, convert the parse tree into a set_matcher
typedef typename proto::compiler<proto::comma_tag, lst_tag>::BOOST_NESTED_TEMPLATE apply
<
proto::binary_op<LeftT, RightT, proto::comma_tag>
, dont_care
, VisitorT
>::type set_matcher;
typedef proto::unary_op<set_matcher, proto::noop_tag> type;
static type const call(proto::binary_op<LeftT, RightT, proto::comma_tag> const &op, VisitorT &visitor)
{
set_matcher set(proto::compile(op, dont_care(), visitor, lst_tag()));
set.complement();
return proto::noop(set);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::unary_op<OpT, lookahead_tag<true> >, VisitorT>
{
typedef proto::unary_op<OpT, lookahead_tag<false> > type;
static type call(proto::unary_op<OpT, lookahead_tag<true> > const &op, VisitorT &)
{
return proto::make_op<lookahead_tag<false> >(proto::arg(op));
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename OpT, typename VisitorT>
struct complement<proto::unary_op<OpT, lookbehind_tag<true> >, VisitorT>
{
typedef proto::unary_op<OpT, lookbehind_tag<false> > type;
static type call(proto::unary_op<OpT, lookbehind_tag<true> > const &op, VisitorT &)
{
return proto::make_op<lookbehind_tag<false> >(proto::arg(op));
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<proto::unary_op<assert_word_placeholder<word_boundary<true> >, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<assert_word_placeholder<word_boundary<false> >, proto::noop_tag> type;
static type call(proto::unary_op<assert_word_placeholder<word_boundary<true> >, proto::noop_tag> const &, VisitorT &)
{
return proto::noop(assert_word_placeholder<word_boundary<false> >());
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename VisitorT>
struct complement<logical_newline_xpression, VisitorT>
{
typedef proto::binary_op
<
proto::unary_op<logical_newline_xpression, lookahead_tag<false> >
, proto::unary_op<any_matcher, proto::noop_tag>
, proto::right_shift_tag
> type;
static type call(logical_newline_xpression const &op, VisitorT &)
{
return proto::make_op<lookahead_tag<false> >(op) >> proto::noop(any_matcher());
}
};
///////////////////////////////////////////////////////////////////////////////
// complementing a complement is a no-op
template<typename ArgT, typename VisitorT>
struct complement<proto::unary_op<ArgT, proto::complement_tag>, VisitorT>
{
typedef ArgT type;
static ArgT const &call(proto::unary_op<ArgT, proto::complement_tag> const &op, VisitorT &)
{
return proto::arg(op);
}
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename CharT, typename VisitorT>
struct complement<proto::unary_op<range_placeholder<CharT>, proto::noop_tag>, VisitorT>
{
typedef proto::unary_op<range_placeholder<CharT>, proto::noop_tag> type;
static type const call(proto::unary_op<range_placeholder<CharT>, proto::noop_tag> const &op, VisitorT &)
{
range_placeholder<CharT> rng = proto::arg(op);
rng.not_ = !rng.not_;
return proto::noop(rng);
}
};
///////////////////////////////////////////////////////////////////////////////
// complement_transform
struct complement_transform
{
template<typename OpT, typename, typename VisitorT>
struct apply
{
typedef typename complement<typename proto::arg_type<OpT>::type, VisitorT>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename complement<typename proto::arg_type<OpT>::type, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor)
{
return complement<typename proto::arg_type<OpT>::type, VisitorT>::call(proto::arg(op), visitor);
}
};
}}}
namespace boost { namespace proto
{
template<>
struct compiler<complement_tag, xpressive::detail::seq_tag>
: transform_compiler<xpressive::detail::complement_transform, xpressive::detail::seq_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////
// domain_tags.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_PRODUCTIONS_DOMAIN_TAGS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_DOMAIN_TAGS_HPP_EAN_10_04_2005
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex domain tags
struct seq_tag {};
struct alt_tag {};
struct lst_tag {};
struct set_tag {};
struct ind_tag {};
}}}
#endif

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// independent_compiler.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_PRODUCTIONS_INDEPENDENT_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_INDEPENDENT_COMPILER_HPP_EAN_10_04_2005
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<bool PositiveT>
struct lookahead_tag : proto::unary_tag {};
template<bool PositiveT>
struct lookbehind_tag : proto::unary_tag {};
struct keeper_tag : proto::unary_tag {};
///////////////////////////////////////////////////////////////////////////////
// lookahead_branch
template<bool PositiveT>
struct lookahead_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<lookahead_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<lookahead_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(lookahead_matcher<OpT>(op, !PositiveT), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// lookbehind_branch
template<bool PositiveT>
struct lookbehind_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<lookbehind_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<lookbehind_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(lookbehind_matcher<OpT>(op, !PositiveT), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// keeper_branch
struct keeper_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<keeper_matcher<OpT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static static_xpression<keeper_matcher<OpT>, StateT>
call(OpT const &op, StateT const &state, VisitorT &)
{
return make_static_xpression(keeper_matcher<OpT>(op), state);
}
};
}}}
namespace boost { namespace proto {
template<bool PositiveT>
struct compiler<xpressive::detail::lookahead_tag<PositiveT>, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::lookahead_branch<PositiveT>, xpressive::detail::ind_tag>
{
};
template<bool PositiveT>
struct compiler<xpressive::detail::lookbehind_tag<PositiveT>, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::lookbehind_branch<PositiveT>, xpressive::detail::ind_tag>
{
};
template<>
struct compiler<xpressive::detail::keeper_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::keeper_branch, xpressive::detail::ind_tag>
{
};
template<typename OpTagT>
struct compiler<OpTagT, xpressive::detail::ind_tag>
: transform_compiler<arg_transform, xpressive::detail::seq_tag>
{
};
}}
#endif

View File

@@ -0,0 +1,73 @@
////////////////////////////////////////////////////////////////////////////
// marker_compiler.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_PRODUCTIONS_MARKER_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MARKER_COMPILER_HPP_EAN_10_04_2005
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/marker_transform.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// marker_assign_transform
struct marker_assign_transform
: proto::compose_transforms<proto::right_transform, marker_transform>
{
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
return marker_transform::call(proto::right(op), state, visitor, proto::arg(proto::left(op)).mark_number_);
}
};
///////////////////////////////////////////////////////////////////////////////
// is_marker_predicate
struct is_marker_predicate
{
template<typename OpT, typename, typename>
struct apply
: is_same<typename proto::left_type<OpT>::type, mark_tag>
{
};
};
///////////////////////////////////////////////////////////////////////////////
// assign_compiler
// could be (s1= 'a') or (set= 'a')
struct assign_compiler
: proto::conditional_compiler
<
is_marker_predicate
, proto::transform_compiler<marker_assign_transform, seq_tag>
, proto::branch_compiler<list_branch, lst_tag>
>
{
};
}}}
namespace boost { namespace proto {
template<>
struct compiler<assign_tag, xpressive::detail::seq_tag>
: xpressive::detail::assign_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////
// marker_transform.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_PRODUCTIONS_MARKER_TRANSFORM_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MARKER_TRANSFORM_HPP_EAN_10_04_2005
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// is_marker
template<typename OpT>
struct is_marker
: mpl::false_
{};
template<typename OpT>
struct is_marker
<
proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, OpT
, proto::right_shift_tag
>
>
: mpl::true_
{};
///////////////////////////////////////////////////////////////////////////////
// mark_number
template<typename OpT, typename VisitorT>
int mark_number
(
proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, OpT
, proto::right_shift_tag
> const &op
, VisitorT &
)
{
return proto::arg(proto::left(op)).mark_number_;
}
template<typename ArgT, typename VisitorT>
int mark_number(ArgT const &, VisitorT &visitor)
{
return visitor.get_hidden_mark();
}
///////////////////////////////////////////////////////////////////////////////
// marker_transform
// Insert mark tags before and after the expression
struct marker_transform
{
template<typename OpT, typename, typename>
struct apply
{
typedef proto::binary_op
<
proto::unary_op<mark_begin_matcher, proto::noop_tag>
, proto::binary_op
<
OpT
, proto::unary_op<mark_end_matcher, proto::noop_tag>
, proto::right_shift_tag
>
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor, int mark_nbr = -1)
{
return proto::noop(mark_begin_matcher(mark_nbr))
>> (op >> proto::noop(mark_end_matcher(mark_nbr)));
}
};
}}}
#endif

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////////
// modify_compiler.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_PRODUCTIONS_MODIFY_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_MODIFY_COMPILER_HPP_EAN_10_04_2005
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex operator tags
struct modifier_tag
: proto::binary_tag
{
};
///////////////////////////////////////////////////////////////////////////////
// modify_compiler
struct modify_compiler
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename proto::left_type<OpT>::type modifier_type;
typedef typename modifier_type::BOOST_NESTED_TEMPLATE apply<VisitorT>::type visitor_type;
typedef typename proto::right_type<OpT>::type op_type;
typedef typename proto::compiler<typename proto::tag_type<op_type>::type, seq_tag>::
BOOST_NESTED_TEMPLATE apply
<
op_type
, StateT
, visitor_type
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename apply<OpT, StateT, VisitorT>::visitor_type new_visitor_type;
new_visitor_type new_visitor(proto::left(op).call(visitor));
new_visitor.swap(visitor);
struct local // for swapping state back after proto::compile returns
{ ~local() { v->swap(*nv); }
VisitorT *const v; new_visitor_type *const nv;
} const undo = { &visitor, &new_visitor };
ignore_unused(&undo);
return proto::compile(proto::right(op), state, new_visitor, seq_tag());
}
};
}}}
namespace boost { namespace proto
{
// production for modifiers
template<>
struct compiler<xpressive::detail::modifier_tag, xpressive::detail::seq_tag>
: xpressive::detail::modify_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////
// noop_compiler.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_PRODUCTIONS_NOOP_COMPILER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_NOOP_COMPILER_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex compiler productions
struct noop_compiler
{
///////////////////////////////////////////////////////////////////////////////
// transformation that happens to leaf nodes in the parse tree
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename as_matcher_type<typename proto::arg_type<OpT>::type>::type matcher1;
typedef typename VisitorT::BOOST_NESTED_TEMPLATE apply<matcher1>::type matcher2;
typedef static_xpression<matcher2, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename proto::arg_type<OpT>::type arg_type;
return make_static_xpression(visitor.call(as_matcher_type<arg_type>::call(proto::arg(op))), state);
}
};
}}}
namespace boost { namespace proto
{
// production for terminals in sequence
template<>
struct compiler<noop_tag, xpressive::detail::seq_tag>
: xpressive::detail::noop_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,108 @@
///////////////////////////////////////////////////////////////////////////////
// productions.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_PRODUCTIONS_PRODUCTIONS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_PRODUCTIONS_HPP_EAN_10_04_2005
#include <boost/ref.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
#include <boost/xpressive/detail/static/productions/visitor.hpp>
#include <boost/xpressive/detail/static/productions/quant_compilers.hpp>
#include <boost/xpressive/detail/static/productions/alt_compilers.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/noop_compiler.hpp>
#include <boost/xpressive/detail/static/productions/modify_compiler.hpp>
#include <boost/xpressive/detail/static/productions/complement_compiler.hpp>
#include <boost/xpressive/detail/static/productions/set_compilers.hpp>
#include <boost/xpressive/detail/static/productions/marker_compiler.hpp>
#include <boost/xpressive/detail/static/productions/charset_transforms.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
//
struct is_set_initializer_predicate
{
template<typename OpT, typename, typename>
struct apply
{
typedef typename is_same<typename proto::left_type<OpT>::type, set_initializer_type>::type type;
};
};
///////////////////////////////////////////////////////////////////////////////
//
struct action_transform
{
template<typename OpT, typename, typename>
struct apply
{
typedef proto::binary_op
<
typename proto::left_type<OpT>::type
, typename proto::right_type<OpT>::type
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::left(op) >> proto::right(op);
}
};
///////////////////////////////////////////////////////////////////////////////
// subscript_compiler
struct subscript_compiler
: proto::conditional_compiler
<
is_set_initializer_predicate
, proto::transform_compiler<charset_transform, seq_tag>
, proto::transform_compiler<action_transform, seq_tag>
>
{
};
}}}
///////////////////////////////////////////////////////////////////////////////
// misc regex compiler productions
namespace boost { namespace proto
{
template<typename BidiIterT>
struct value_type<xpressive::basic_regex<BidiIterT> >
{
// store regex objects in the parse tree by reference
typedef reference_wrapper<xpressive::basic_regex<BidiIterT> const> type;
};
// production for sequences in sequence
template<>
struct compiler<right_shift_tag, xpressive::detail::seq_tag>
: fold_compiler<right_shift_tag, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<subscript_tag, xpressive::detail::seq_tag>
: xpressive::detail::subscript_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,169 @@
///////////////////////////////////////////////////////////////////////////////
// quant_compilers.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_PRODUCTIONS_QUANT_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_COMPILERS_HPP_EAN_10_04_2005
#include <limits.h>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/proto/compiler/transform.hpp>
#include <boost/xpressive/proto/compiler/conditional.hpp>
#include <boost/xpressive/detail/static/productions/quant_traits.hpp>
#include <boost/xpressive/detail/static/productions/quant_transforms.hpp>
#include <boost/xpressive/detail/static/productions/independent_compiler.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_compiler
: proto::conditional_compiler
<
use_simple_repeat_predicate
, proto::branch_compiler<simple_repeat_branch<GreedyT, MinT, MaxT>, ind_tag>
, proto::transform_compiler<plus_transform<GreedyT, MinT, MaxT>, seq_tag>
>
{
};
template<bool GreedyT = true, uint_t MaxT = UINT_MAX-1>
struct star_compiler
: proto::conditional_compiler
<
use_simple_repeat_predicate
, proto::branch_compiler<simple_repeat_branch<GreedyT, 0, MaxT>, ind_tag>
, proto::transform_compiler<star_transform<GreedyT, MaxT>, seq_tag>
>
{
};
template<bool GreedyT = true>
struct optional_compiler
: proto::transform_compiler<optional_transform<GreedyT>, seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// generic_quant_compiler
template<bool GreedyT, uint_t MinT, uint_t MaxT>
struct generic_quant_compiler
: plus_compiler<GreedyT, MinT, MaxT>
{
};
template<bool GreedyT, uint_t MaxT>
struct generic_quant_compiler<GreedyT, 0, MaxT>
: star_compiler<GreedyT, MaxT>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 0, 1>
: optional_compiler<GreedyT>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 1, 1>
: proto::transform_compiler<proto::arg_transform, seq_tag>
{
};
template<bool GreedyT>
struct generic_quant_compiler<GreedyT, 0, 0>
: proto::transform_compiler<epsilon_transform, seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// non_greedy_compiler
//
struct non_greedy_compiler
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
// Did you apply operator- to something that wasn't a quantifier?
BOOST_MPL_ASSERT((is_greedy_quant<typename proto::arg_type<OpT>::type>));
typedef typename proto::tag_type<typename proto::arg_type<OpT>::type>::type tag_type;
typedef typename min_type<tag_type>::type min_type;
typedef typename max_type<tag_type>::type max_type;
typedef generic_quant_compiler
<
false
, min_type::value
, max_type::value
> compiler_type;
typedef typename compiler_type::BOOST_NESTED_TEMPLATE apply
<
typename proto::arg_type<OpT>::type
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename apply<OpT, StateT, VisitorT>::compiler_type compiler_type;
return compiler_type::call(proto::arg(op), state, visitor);
}
};
}}}
namespace boost { namespace proto
{
// production for one or more quant
template<>
struct compiler<unary_plus_tag, xpressive::detail::seq_tag>
: xpressive::detail::plus_compiler<>
{
};
// production for zero or more quant
template<>
struct compiler<unary_star_tag, xpressive::detail::seq_tag>
: xpressive::detail::star_compiler<>
{
};
// production for optional
template<>
struct compiler<logical_not_tag, xpressive::detail::seq_tag>
: xpressive::detail::optional_compiler<>
{
};
// production for generic quantifiers
template<unsigned int MinT, unsigned int MaxT>
struct compiler<xpressive::detail::generic_quant_tag<MinT, MaxT>, xpressive::detail::seq_tag>
: xpressive::detail::generic_quant_compiler<true, MinT, MaxT>
{
};
// production for non-greedy quantifiers
template<>
struct compiler<unary_minus_tag, xpressive::detail::seq_tag>
: xpressive::detail::non_greedy_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////
// quant_traits.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_PRODUCTIONS_QUANT_TRAITS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_TRAITS_HPP_EAN_10_04_2005
#include <boost/mpl/or.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
#include <boost/xpressive/detail/static/is_pure.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4307) // '+' : integral constant overflow
#endif
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// generic_quant_tag
template<uint_t MinT, uint_t MaxT>
struct generic_quant_tag
: proto::unary_tag
{
typedef mpl::integral_c<uint_t, MinT> min_type;
typedef mpl::integral_c<uint_t, MaxT> max_type;
};
///////////////////////////////////////////////////////////////////////////////
// min_type / max_type
template<typename TagT>
struct min_type : TagT::min_type {};
template<>
struct min_type<proto::unary_plus_tag> : mpl::integral_c<uint_t, 1> {};
template<>
struct min_type<proto::unary_star_tag> : mpl::integral_c<uint_t, 0> {};
template<>
struct min_type<proto::logical_not_tag> : mpl::integral_c<uint_t, 0> {};
template<typename TagT>
struct max_type : TagT::max_type {};
template<>
struct max_type<proto::unary_plus_tag> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::unary_star_tag> : mpl::integral_c<uint_t, UINT_MAX-1> {};
template<>
struct max_type<proto::logical_not_tag> : mpl::integral_c<uint_t, 1> {};
struct use_simple_repeat_predicate
{
template<typename OpT, typename, typename>
struct apply
{
typedef typename use_simple_repeat<typename proto::arg_type<OpT>::type>::type type;
};
};
///////////////////////////////////////////////////////////////////////////////
// is_greedy_quant
template<typename XprT>
struct is_greedy_quant
: mpl::false_
{
};
template<typename OpT, typename TagT>
struct is_greedy_quant<proto::unary_op<OpT, TagT> >
: mpl::or_
<
is_same<TagT, proto::unary_plus_tag>
, is_same<TagT, proto::unary_star_tag>
, is_same<TagT, proto::logical_not_tag>
>
{
};
template<typename OpT, uint_t MinT, uint_t MaxT>
struct is_greedy_quant<proto::unary_op<OpT, generic_quant_tag<MinT, MaxT> > >
: mpl::true_
{
};
}}}
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,263 @@
///////////////////////////////////////////////////////////////////////////////
// quant_transforms.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_PRODUCTIONS_QUANT_TRANSFORMS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_QUANT_TRANSFORMS_HPP_EAN_10_04_2005
#include <limits.h>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/width_of.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/static/productions/quant_traits.hpp>
#include <boost/xpressive/detail/static/productions/marker_transform.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// plus_no_mark_transform
// Unary plus becomes a quantifier by wrapping arg in begin/end quantifiers
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_no_mark_transform
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
proto::binary_op
<
proto::unary_op<repeat_begin_matcher, proto::noop_tag>
, typename proto::arg_type<OpT>::type // skip the "plus" node
, proto::right_shift_tag
>
, proto::unary_op<repeat_end_matcher<GreedyT>, proto::noop_tag>
, proto::right_shift_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &, int mark_number = -1, uint_t min = MinT, uint_t max = MaxT)
{
return proto::noop(repeat_begin_matcher(mark_number))
>> proto::arg(op)
>> proto::noop(repeat_end_matcher<GreedyT>(mark_number, min, max));
}
};
///////////////////////////////////////////////////////////////////////////////
// plus_mark_transform
// compose the quant and mark transforms
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_mark_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef typename marker_transform::apply
<
typename proto::arg_type<OpT>::type
, StateT
, VisitorT
>::type marker_type;
typedef typename plus_no_mark_transform<GreedyT, MinT, MaxT>::BOOST_NESTED_TEMPLATE apply
<
proto::unary_op<marker_type, typename proto::tag_type<OpT>::type>
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, int mark_number = -1, uint_t min = MinT, uint_t max = MaxT)
{
return plus_no_mark_transform<GreedyT, MinT, MaxT>::call
(
proto::make_op<typename proto::tag_type<OpT>::type>
(
marker_transform::call(proto::arg(op), state, visitor, mark_number)
)
, state
, visitor
, mark_number
, min
, max
);
}
};
///////////////////////////////////////////////////////////////////////////////
// optional_transform
// An optional expression gets the following transformation:
template<bool GreedyT>
struct optional_transform
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
typename proto::arg_type<OpT>::type
, proto::unary_op<epsilon_matcher, proto::noop_tag>
, proto::bitor_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::arg(op) | proto::noop(epsilon_matcher());
}
};
///////////////////////////////////////////////////////////////////////////////
// non-greedy optional transform
template<>
struct optional_transform<false>
{
template<typename OpT, typename, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<typename proto::arg_type<OpT>::type> >));
typedef proto::binary_op
<
proto::unary_op<epsilon_matcher, proto::noop_tag>
, typename proto::arg_type<OpT>::type
, proto::bitor_tag
> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &)
{
return proto::noop(epsilon_matcher()) | proto::arg(op);
}
};
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_branch
template<bool GreedyT = true, uint_t MinT = 0, uint_t MaxT = UINT_MAX-1>
struct simple_repeat_branch
{
typedef true_xpression state_type;
template<typename OpT, typename StateT, typename>
struct apply
{
BOOST_MPL_ASSERT((mpl::not_equal_to<mpl::size_t<0>, width_of<OpT> >));
typedef static_xpression<simple_repeat_matcher<OpT, GreedyT>, StateT> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &, uint_t min = MinT, uint_t max = MaxT)
{
return make_static_xpression(simple_repeat_matcher<OpT, GreedyT>(op, min, max), state);
}
};
///////////////////////////////////////////////////////////////////////////////
// plus_transform
// Optimization: don't insert a hidden mark if we already have a visible one
template<bool GreedyT = true, uint_t MinT = 1, uint_t MaxT = UINT_MAX-1>
struct plus_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename mpl::if_
<
is_marker<typename proto::arg_type<OpT>::type>
, plus_no_mark_transform<GreedyT, MinT, MaxT>
, plus_mark_transform<GreedyT, MinT, MaxT>
>::type transform;
typedef typename transform::BOOST_NESTED_TEMPLATE apply<OpT, StateT, VisitorT>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, uint_t min = MinT, uint_t max = MaxT)
{
return apply<OpT, StateT, VisitorT>::transform::call(op, state, visitor, mark_number(proto::arg(op), visitor), min, max);
}
};
///////////////////////////////////////////////////////////////////////////////
// star_transform
template<bool GreedyT = true, uint_t MaxT = UINT_MAX-1>
struct star_transform
{
template<typename OpT, typename StateT, typename VisitorT>
struct apply
{
typedef typename plus_transform<GreedyT, 1, MaxT>::BOOST_NESTED_TEMPLATE apply
<
OpT
, StateT
, VisitorT
>::type plus_type;
typedef typename optional_transform<GreedyT>::BOOST_NESTED_TEMPLATE apply
<
proto::unary_op<plus_type, proto::unary_plus_tag>
, StateT
, VisitorT
>::type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &state, VisitorT &visitor, uint_t max = MaxT)
{
return optional_transform<GreedyT>::call
(
+plus_transform<GreedyT, 1, MaxT>::call(op, state, visitor, 1, max)
, state
, visitor
);
}
};
///////////////////////////////////////////////////////////////////////////////
// epsilon_transform
struct epsilon_transform
{
template<typename, typename, typename>
struct apply
{
typedef proto::unary_op<epsilon_matcher, proto::noop_tag> type;
};
static proto::unary_op<epsilon_matcher, proto::noop_tag>
call(dont_care, dont_care, dont_care)
{
return proto::noop(epsilon_matcher());
}
};
}}}
#endif

View File

@@ -0,0 +1,171 @@
////////////////////////////////////////////////////////////////////////////
// set_compilers.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_PRODUCTIONS_SET_COMPILERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_SET_COMPILERS_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/compiler/fold.hpp>
#include <boost/xpressive/proto/compiler/branch.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
#include <boost/xpressive/detail/static/productions/domain_tags.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// set_branch
//
struct set_branch
{
typedef no_next state_type;
template<typename, typename StateT, typename>
struct apply
{
typedef StateT type;
};
template<typename OpT, typename StateT, typename VisitorT>
static StateT const &call(OpT const &op, StateT const &state, VisitorT &visitor)
{
return state.set(set_branch::get_matcher(op)), state;
}
private:
template<typename MatcherT>
static MatcherT const &get_matcher(static_xpression<MatcherT, no_next> const &xpr)
{
return xpr;
}
};
///////////////////////////////////////////////////////////////////////////////
// list_branch
struct list_branch
{
typedef int state_type; // not used
template<typename OpT, typename StateT, typename>
struct apply
{
typedef static_xpression<OpT, StateT> type;
};
template<typename OpT, typename StateT>
static static_xpression<OpT, StateT>
call(OpT const &op, StateT const &state, dont_care)
{
return make_static_xpression(op, state);
}
};
///////////////////////////////////////////////////////////////////////////////
// list_noop_compiler
struct list_noop_compiler
{
template<typename, typename StateT, typename>
struct apply
{
typedef typename StateT::next_type type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename StateT::next_type
call(OpT const &op, StateT const &state, VisitorT &visitor)
{
typedef typename VisitorT::char_type char_type;
char_type ch = char_cast<char_type>(proto::arg(op), visitor.traits());
return state.push_back(ch, visitor.traits());
}
};
///////////////////////////////////////////////////////////////////////////////
// list_assign_compiler
struct list_assign_compiler
{
template<typename OpT, typename, typename VisitorT>
struct apply
{
typedef typename VisitorT::traits_type traits_type;
typedef set_matcher<traits_type, 1> type;
};
template<typename OpT, typename StateT, typename VisitorT>
static typename apply<OpT, StateT, VisitorT>::type
call(OpT const &op, StateT const &, VisitorT &visitor)
{
typedef typename VisitorT::char_type char_type;
char_type ch = char_cast<char_type>(proto::arg(proto::right(op)), visitor.traits());
return typename apply<OpT, StateT, VisitorT>::type(ch, visitor.traits());
}
};
}}}
namespace boost { namespace proto
{
///////////////////////////////////////////////////////////////////////////////
// compilers for sets such as set['a' | range('a','z')]
template<>
struct compiler<bitor_tag, xpressive::detail::set_tag>
: fold_compiler<bitor_tag, xpressive::detail::set_tag>
{
};
template<>
struct compiler<noop_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<complement_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
template<>
struct compiler<comma_tag, xpressive::detail::set_tag>
: branch_compiler<xpressive::detail::set_branch, xpressive::detail::seq_tag>
{
};
///////////////////////////////////////////////////////////////////////////////
// compilers for list-initialized sets such as (set='a','b','c')
template<>
struct compiler<comma_tag, xpressive::detail::seq_tag>
: branch_compiler<xpressive::detail::list_branch, xpressive::detail::lst_tag>
{
};
template<>
struct compiler<comma_tag, xpressive::detail::lst_tag>
: fold_compiler<comma_tag, xpressive::detail::lst_tag, false>
{
};
template<>
struct compiler<noop_tag, xpressive::detail::lst_tag>
: xpressive::detail::list_noop_compiler
{
};
template<>
struct compiler<assign_tag, xpressive::detail::lst_tag>
: xpressive::detail::list_assign_compiler
{
};
}}
#endif

View File

@@ -0,0 +1,199 @@
///////////////////////////////////////////////////////////////////////////////
// transmogrify.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_PRODUCTIONS_TRANSMOGRIFY_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_TRANSMOGRIFY_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/static/placeholders.hpp>
#include <boost/xpressive/detail/utility/dont_care.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// transmogrify
//
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename MatcherT>
struct transmogrify
{
typedef MatcherT type;
static type const &call(MatcherT const &m, dont_care)
{
return m;
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_bol_placeholder>
{
typedef assert_bol_matcher<TraitsT> type;
template<typename VisitorT>
static type call(assert_bol_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_eol_placeholder>
{
typedef assert_eol_matcher<TraitsT> type;
template<typename VisitorT>
static type call(assert_eol_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, logical_newline_placeholder>
{
typedef logical_newline_matcher<TraitsT> type;
template<typename VisitorT>
static type call(logical_newline_placeholder, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT, bool NotT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, literal_placeholder<CharT, NotT> >
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef literal_matcher<TraitsT, ICaseT::value, NotT> type;
template<typename VisitorT>
static type call(literal_placeholder<CharT, NotT> const &m, VisitorT &visitor)
{
char_type ch = char_cast<char_type>(m.ch_, visitor.traits());
return type(ch, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, range_placeholder<CharT> >
{
// By design, we don't widen character ranges.
typedef typename iterator_value<BidiIterT>::type char_type;
BOOST_MPL_ASSERT((is_same<CharT, char_type>));
typedef range_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(range_placeholder<CharT> const &m, VisitorT &visitor)
{
return type(m.ch_min_, m.ch_max_, m.not_, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CharT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, string_placeholder<CharT> >
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef string_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(string_placeholder<CharT> const &m, VisitorT &visitor)
{
return type(string_cast<char_type>(m.str_, visitor.traits()), visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, mark_placeholder>
{
typedef mark_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(mark_placeholder const &m, VisitorT &visitor)
{
return type(m.mark_number_, visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, posix_charset_placeholder>
{
typedef posix_charset_matcher<TraitsT, ICaseT::value> type;
template<typename VisitorT>
static type call(posix_charset_placeholder const &m, VisitorT &visitor)
{
char const *name_end = m.name_ + std::strlen(m.name_);
return type(visitor.traits().lookup_classname(m.name_, name_end, ICaseT::value), m.not_);
}
};
template<typename BidiIterT, typename TraitsT, int SizeT>
struct transmogrify<BidiIterT, mpl::true_, TraitsT, set_matcher<TraitsT, SizeT> >
{
typedef set_matcher<TraitsT, SizeT> type;
template<typename VisitorT>
static type call(set_matcher<TraitsT, SizeT> m, VisitorT &visitor)
{
m.nocase(visitor.traits());
return m;
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, typename CondT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, assert_word_placeholder<CondT> >
{
typedef assert_word_matcher<CondT, TraitsT> type;
template<typename VisitorT>
static type call(dont_care, VisitorT &visitor)
{
return type(visitor.traits());
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT, bool ByRefT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, regex_placeholder<BidiIterT, ByRefT> >
{
typedef typename mpl::if_c
<
ByRefT
, regex_byref_matcher<BidiIterT>
, regex_matcher<BidiIterT>
>::type type;
static type call(regex_placeholder<BidiIterT, ByRefT> const &m, dont_care)
{
return type(m.impl_);
}
};
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct transmogrify<BidiIterT, ICaseT, TraitsT, self_placeholder>
{
typedef regex_byref_matcher<BidiIterT> type;
template<typename VisitorT>
static type call(self_placeholder, VisitorT &visitor)
{
return type(visitor.self());
}
};
}}}
#endif

View File

@@ -0,0 +1,142 @@
///////////////////////////////////////////////////////////////////////////////
// visitor.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_PRODUCTIONS_VISITOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_PRODUCTIONS_VISITOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/static/productions/transmogrify.hpp>
#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
//
template<typename BidiIterT>
struct xpression_visitor_base
{
explicit xpression_visitor_base(shared_ptr<regex_impl<BidiIterT> > const &self)
: impl_()
, self_(self)
{
}
void swap(xpression_visitor_base &that)
{
this->impl_.swap(that.impl_);
this->self_.swap(that.self_);
}
int get_hidden_mark()
{
return -(int)(++this->impl_.hidden_mark_count_);
}
void mark_number(int mark_number)
{
if(0 < mark_number)
{
this->impl_.mark_count_ =
(std::max)(this->impl_.mark_count_, (std::size_t)mark_number);
}
}
shared_ptr<regex_impl<BidiIterT> > &self()
{
return this->self_;
}
regex_impl<BidiIterT> &impl()
{
return this->impl_;
}
protected:
template<typename MatcherT>
void visit_(MatcherT const &)
{
// no-op
}
template<bool ByRefT>
void visit_(regex_placeholder<BidiIterT, ByRefT> const &rex)
{
// when visiting an embeded regex, track the references
this->impl_.track_reference(rex.impl_);
}
void visit_(mark_placeholder const &backref)
{
// keep track of the largest mark number found
this->mark_number(backref.mark_number_);
}
void visit_(mark_begin_matcher const &mark_begin)
{
// keep track of the largest mark number found
this->mark_number(mark_begin.mark_number_);
}
private:
regex_impl<BidiIterT> impl_;
shared_ptr<regex_impl<BidiIterT> > self_;
};
///////////////////////////////////////////////////////////////////////////////
//
template<typename BidiIterT, typename ICaseT, typename TraitsT>
struct xpression_visitor
: xpression_visitor_base<BidiIterT>
{
typedef BidiIterT iterator_type;
typedef ICaseT icase_type;
typedef TraitsT traits_type;
typedef typename boost::iterator_value<BidiIterT>::type char_type;
explicit xpression_visitor(TraitsT const &tr, shared_ptr<regex_impl<BidiIterT> > const &self)
: xpression_visitor_base<BidiIterT>(self)
, traits_(tr)
{
}
template<typename MatcherT>
struct apply
{
typedef typename transmogrify<BidiIterT, ICaseT, TraitsT, MatcherT>::type type;
};
template<typename MatcherT>
typename apply<MatcherT>::type
call(MatcherT const &matcher)
{
this->visit_(matcher);
return transmogrify<BidiIterT, ICaseT, TraitsT, MatcherT>::call(matcher, *this);
}
TraitsT const &traits() const
{
return this->traits_;
}
private:
TraitsT traits_;
};
}}}
#endif

View File

@@ -0,0 +1,164 @@
///////////////////////////////////////////////////////////////////////////////
// regex_operators.hpp
//
// Copyright 2005 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_REGEX_OPERATORS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_REGEX_OPERATORS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/utility/enable_if.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/basic_regex.hpp>
namespace boost { namespace xpressive
{
///////////////////////////////////////////////////////////////////////////////
// operator +
template<typename BidiIterT>
inline proto::unary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_plus_tag
>
operator +(basic_regex<BidiIterT> const &regex)
{
return +proto::noop(regex);
}
///////////////////////////////////////////////////////////////////////////////
// operator *
template<typename BidiIterT>
inline proto::unary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_star_tag
>
operator *(basic_regex<BidiIterT> const &regex)
{
return *proto::noop(regex);
}
///////////////////////////////////////////////////////////////////////////////
// operator !
template<typename BidiIterT>
inline proto::unary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::logical_not_tag
>
operator !(basic_regex<BidiIterT> const &regex)
{
return !proto::noop(regex);
}
///////////////////////////////////////////////////////////////////////////////
// operator >>
template<typename RightT, typename BidiIterT>
inline typename disable_if
<
proto::is_op<RightT>
, proto::binary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_op<RightT, proto::noop_tag>
, proto::right_shift_tag
>
>::type
operator >>(basic_regex<BidiIterT> const &regex, RightT const &right)
{
return proto::noop(regex) >> proto::noop(right);
}
///////////////////////////////////////////////////////////////////////////////
// operator >>
template<typename BidiIterT, typename LeftT>
inline typename disable_if
<
proto::is_op<LeftT>
, proto::binary_op
<
proto::unary_op<LeftT, proto::noop_tag>
, proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::right_shift_tag
>
>::type
operator >>(LeftT const &left, basic_regex<BidiIterT> const &regex)
{
return proto::noop(left) >> proto::noop(regex);
}
///////////////////////////////////////////////////////////////////////////////
// operator >>
template<typename BidiIterT>
inline proto::binary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::right_shift_tag
>
operator >>(basic_regex<BidiIterT> const &left, basic_regex<BidiIterT> const &right)
{
return proto::noop(left) >> proto::noop(right);
}
///////////////////////////////////////////////////////////////////////////////
// operator |
template<typename RightT, typename BidiIterT>
inline typename disable_if
<
proto::is_op<RightT>
, proto::binary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_op<RightT, proto::noop_tag>
, proto::bitor_tag
>
>::type
operator |(basic_regex<BidiIterT> const &regex, RightT const &right)
{
return proto::noop(regex) | proto::noop(right);
}
///////////////////////////////////////////////////////////////////////////////
// operator |
template<typename BidiIterT, typename LeftT>
inline typename disable_if
<
proto::is_op<LeftT>
, proto::binary_op
<
proto::unary_op<LeftT, proto::noop_tag>
, proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::bitor_tag
>
>::type
operator |(LeftT const &left, basic_regex<BidiIterT> const &regex)
{
return proto::noop(left) | proto::noop(regex);
}
///////////////////////////////////////////////////////////////////////////////
// operator |
template<typename BidiIterT>
inline proto::binary_op
<
proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag>
, proto::bitor_tag
>
operator |(basic_regex<BidiIterT> const &left, basic_regex<BidiIterT> const &right)
{
return proto::noop(left) | proto::noop(right);
}
}}
#endif

View File

@@ -0,0 +1,289 @@
///////////////////////////////////////////////////////////////////////////////
// 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:
// set[ a + b - c ]
// set[ a ] + set[ b ] - set[ c ]
// -set[ a + b + c ] (set negation)
// must support indirect repeat counts {$n,$m}
// must support logical newline and intelligent negation of logical newline
// add ws to eat whitespace (make *_ws illegal)
// a{n} -> a[n]
// a{n,m} -> a[n][m]
// a{n,m}? -> -a[n][m] // yuk, breaks quantifier up.
// 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 TopT>
struct top_type
{
typedef TopT type;
};
///////////////////////////////////////////////////////////////////////////////
// top_type
//
template<typename TopT, typename NextT>
struct top_type<stacked_xpression<TopT, NextT> >
{
typedef NextT type;
};
#endif
///////////////////////////////////////////////////////////////////////////////
// stacked_xpression
//
template<typename TopT, typename NextT>
struct stacked_xpression
: NextT
{
// match
// delegates to NextT
template<typename BidiIterT>
bool match(state_type<BidiIterT> &state) const
{
return this->NextT::BOOST_NESTED_TEMPLATE push_match<TopT>(state);
}
// top_match
// jump back to the xpression on top of the xpression stack,
// and keep the xpression on the stack.
template<typename BidiIterT>
static bool top_match(state_type<BidiIterT> &state, xpression_base const *top)
{
BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<TopT>::type));
return static_cast<TopT const *>(top)->
BOOST_NESTED_TEMPLATE push_match<TopT>(state);
}
// pop_match
// jump back to the xpression on top of the xpression stack,
// pop the xpression off the stack.
template<typename BidiIterT>
static bool pop_match(state_type<BidiIterT> &state, xpression_base const *top)
{
BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<TopT>::type));
return static_cast<TopT const *>(top)->match(state);
}
// skip_match
// pop the xpression off the top of the stack and ignore it; call
// match on next.
template<typename BidiIterT>
bool skip_match(state_type<BidiIterT> &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 TopT::skip_impl(*static_cast<NextT const *>(this), state);
}
//protected:
// skip_impl
// implementation of skip_match.
template<typename ThatT, typename BidiIterT>
static bool skip_impl(ThatT const &that, state_type<BidiIterT> &state)
{
return that.BOOST_NESTED_TEMPLATE push_match<TopT>(state);
}
};
///////////////////////////////////////////////////////////////////////////////
// stacked_xpression_cast
//
template<typename TopT, typename NextT>
inline stacked_xpression<TopT, NextT> const &stacked_xpression_cast(NextT 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<TopT, NextT>), ==, sizeof(NextT));
return *static_cast<stacked_xpression<TopT, NextT> const *>(&next);
}
///////////////////////////////////////////////////////////////////////////////
// static_xpression
//
template<typename MatcherT, typename NextT>
struct static_xpression
: MatcherT
{
NextT next_;
static_xpression(MatcherT const &matcher = MatcherT(), NextT const &next = NextT())
: MatcherT(matcher)
, next_(next)
{
}
// match
// delegates to the MatcherT
template<typename BidiIterT>
bool match(state_type<BidiIterT> &state) const
{
return this->MatcherT::match(state, this->next_);
}
// push_match
// call match on this, but also push "TopT" onto the xpression
// stack so we know what we are jumping back to later.
template<typename TopT, typename BidiIterT>
bool push_match(state_type<BidiIterT> &state) const
{
return this->MatcherT::match(state, stacked_xpression_cast<TopT>(this->next_));
}
// skip_impl
// implementation of skip_match, called from stacked_xpression::skip_match
template<typename ThatT, typename BidiIterT>
static bool skip_impl(ThatT const &that, state_type<BidiIterT> &state)
{
return that.match(state);
}
// for linking a compiled regular xpression
template<typename CharT>
void link(xpression_linker<CharT> &linker) const
{
linker.link(*static_cast<MatcherT const *>(this), &this->next_);
this->next_.link(linker);
}
// for building a lead-follow
template<typename CharT>
void peek(xpression_peeker<CharT> &peeker) const
{
this->peek_next_(peeker.peek(*static_cast<MatcherT const *>(this)), peeker);
}
// for getting xpression width
template<typename BidiIterT>
std::size_t get_width(state_type<BidiIterT> *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->MatcherT::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
template<typename CharT>
void peek_next_(mpl::true_, xpression_peeker<CharT> &peeker) const
{
this->next_.peek(peeker);
}
template<typename CharT>
static void peek_next_(mpl::false_, xpression_peeker<CharT> &)
{
// no-op
}
using MatcherT::width;
using MatcherT::pure;
};
// syntactic sugar so this xpression can be treated the same as
// (a smart pointer to) a dynamic xpression from templates
template<typename MatcherT, typename NextT>
inline static_xpression<MatcherT, NextT> const *
get_pointer(static_xpression<MatcherT, NextT> const &xpr)
{
return &xpr;
}
///////////////////////////////////////////////////////////////////////////////
// make_static_xpression
//
template<typename MatcherT>
inline static_xpression<MatcherT> const
make_static_xpression(MatcherT const &matcher)
{
return static_xpression<MatcherT>(matcher);
}
template<typename MatcherT, typename NextT>
inline static_xpression<MatcherT, NextT> const
make_static_xpression(MatcherT const &matcher, NextT const &next)
{
return static_xpression<MatcherT, NextT>(matcher, next);
}
///////////////////////////////////////////////////////////////////////////////
// no_next
//
struct no_next
: xpression_base
{
template<typename CharT>
void link(xpression_linker<CharT> &linker) const
{
}
template<typename CharT>
void peek(xpression_peeker<CharT> &peeker) const
{
peeker.fail();
}
template<typename BidiIterT>
static std::size_t get_width(state_type<BidiIterT> *)
{
return 0;
}
};
///////////////////////////////////////////////////////////////////////////////
// alternates_list
//
template<typename AlternatesT>
struct alternates_list
: AlternatesT
{
alternates_list(AlternatesT const &alternates)
: AlternatesT(alternates)
{
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////////////
// type_traits.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_TYPE_TRAITS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_TYPE_TRAITS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/ref.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// is_static_xpression
//
template<typename T>
struct is_static_xpression
: mpl::false_
{
};
template<typename MatcherT, typename NextT>
struct is_static_xpression<static_xpression<MatcherT, NextT> >
: mpl::true_
{
};
template<typename TopT, typename NextT>
struct is_static_xpression<stacked_xpression<TopT, NextT> >
: mpl::true_
{
};
///////////////////////////////////////////////////////////////////////////////
// is_regex
//
template<typename XprT>
struct is_regex
: mpl::false_
{
};
template<typename BidiIterT>
struct is_regex<basic_regex<BidiIterT> >
: mpl::true_
{
};
template<typename BidiIterT>
struct is_regex<reference_wrapper<basic_regex<BidiIterT> > >
: mpl::true_
{
};
///////////////////////////////////////////////////////////////////////////////
// is_modifiable
//
template<typename XprT>
struct is_modifiable
: mpl::not_<is_regex<XprT> >
{
};
//////////////////////////////////////////////////////////////////////////
// is_random
//
template<typename BidiIterT>
struct is_random
: is_convertible
<
typename iterator_category<BidiIterT>::type
, std::random_access_iterator_tag
>
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,267 @@
///////////////////////////////////////////////////////////////////////////////
// width_of.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_WIDTH_OF_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/times.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/static/as_xpr.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// add_width
template<typename X, typename Y>
struct add_width
: mpl::eval_if
<
mpl::or_
<
mpl::equal_to<X, unknown_width>
, mpl::equal_to<Y, unknown_width>
>
, mpl::identity<unknown_width>
, mpl::plus<X, Y>
>::type
{
};
///////////////////////////////////////////////////////////////////////////////
// mult_width
template<typename X, typename Y>
struct mult_width
: mpl::eval_if
<
mpl::or_
<
mpl::equal_to<X, unknown_width>
, mpl::equal_to<Y, unknown_width>
>
, mpl::identity<unknown_width>
, mpl::times<X, Y>
>::type
{
};
///////////////////////////////////////////////////////////////////////////////
// equal_width
template<typename X, typename Y>
struct equal_width
: mpl::if_
<
mpl::equal_to<X, Y>
, X
, unknown_width
>::type
{
};
///////////////////////////////////////////////////////////////////////////////
// width_of
//
template<typename XprT>
struct width_of;
template<>
struct width_of<no_next>
: mpl::size_t<0>
{
};
template<typename MatcherT>
struct width_of<proto::unary_op<MatcherT, proto::noop_tag> >
: as_matcher_type<MatcherT>::type::width
{
};
template<typename LeftT, typename RightT>
struct width_of<proto::binary_op<LeftT, RightT, proto::right_shift_tag> >
: add_width<width_of<LeftT>, width_of<RightT> >
{
};
template<typename LeftT, typename RightT>
struct width_of<proto::binary_op<LeftT, RightT, proto::bitor_tag> >
: equal_width<width_of<LeftT>, width_of<RightT> >
{
};
template<typename RightT>
struct width_of<proto::binary_op<mark_tag, RightT, proto::assign_tag> >
: width_of<RightT>
{
};
template<typename RightT>
struct width_of<proto::binary_op<set_initializer_type, RightT, proto::assign_tag> >
: mpl::size_t<1>
{
};
template<typename ModifierT, typename XprT>
struct width_of<proto::binary_op<ModifierT, XprT, modifier_tag> >
: width_of<XprT>
{
};
template<typename XprT, bool PositiveT>
struct width_of<proto::unary_op<XprT, lookahead_tag<PositiveT> > >
: mpl::size_t<0>
{
};
template<typename XprT, bool PositiveT>
struct width_of<proto::unary_op<XprT, lookbehind_tag<PositiveT> > >
: mpl::size_t<0>
{
};
template<typename XprT>
struct width_of<proto::unary_op<XprT, keeper_tag> >
: width_of<XprT>
{
};
template<typename MatcherT, typename NextT>
struct width_of<static_xpression<MatcherT, NextT> >
: add_width<typename MatcherT::width, width_of<NextT> >
{
};
template<typename BidiIterT>
struct width_of<shared_ptr<matchable<BidiIterT> const> >
: unknown_width
{
};
template<typename BidiIterT>
struct width_of<std::vector<shared_ptr<matchable<BidiIterT> const> > >
: unknown_width
{
};
template<typename BidiIterT>
struct width_of<proto::unary_op<basic_regex<BidiIterT>, proto::noop_tag> >
: unknown_width
{
};
template<typename BidiIterT>
struct width_of<proto::unary_op<reference_wrapper<basic_regex<BidiIterT> const>, proto::noop_tag> >
: unknown_width
{
};
template<typename OpT>
struct width_of<proto::unary_op<OpT, proto::unary_plus_tag> >
: unknown_width
{
};
template<typename OpT>
struct width_of<proto::unary_op<OpT, proto::unary_star_tag> >
: unknown_width
{
};
template<typename OpT>
struct width_of<proto::unary_op<OpT, proto::logical_not_tag> >
: unknown_width
{
};
template<typename OpT, uint_t MinT, uint_t MaxT>
struct width_of<proto::unary_op<OpT, generic_quant_tag<MinT, MaxT> > >
: mpl::if_c<MinT==MaxT, mult_width<width_of<OpT>, mpl::size_t<MinT> >, unknown_width>::type
{
};
template<typename OpT>
struct width_of<proto::unary_op<OpT, proto::unary_minus_tag> >
: width_of<OpT>
{
};
// when complementing a set or an assertion, the width is that of the set (1) or the assertion (0)
template<typename OpT>
struct width_of<proto::unary_op<OpT, proto::complement_tag> >
: width_of<OpT>
{
};
// The comma is used in list-initialized sets, and the width of sets are 1
template<typename LeftT, typename RightT>
struct width_of<proto::binary_op<LeftT, RightT, proto::comma_tag> >
: mpl::size_t<1>
{
};
// The subscript operator[] is used for sets, as in set['a' | range('b','h')],
// or for actions as in (any >> expr)[ action ]
template<typename LeftT, typename RightT>
struct width_of<proto::binary_op<LeftT, RightT, proto::subscript_tag> >
: mpl::if_<is_same<LeftT, set_initializer_type>, mpl::size_t<1>, width_of<LeftT> >::type
{
// If LeftT is "set" then make sure that RightT has a width_of 1
BOOST_MPL_ASSERT
((
mpl::or_
<
mpl::not_<is_same<LeftT, set_initializer_type> >
, mpl::equal_to<width_of<RightT>, mpl::size_t<1> >
>
));
};
// The width of a list of alternates is N if all the alternates have width N, otherwise unknown_width
template<typename WidthsT>
struct alt_width_of
: mpl::fold
<
WidthsT
, typename mpl::front<WidthsT>::type
, equal_width<mpl::_1, mpl::_2>
>::type
{
};
template<typename AlternatesT>
struct width_of<alternates_list<AlternatesT> >
: alt_width_of<mpl::transform_view<AlternatesT, width_of<mpl::_1> > >
{
};
template<typename OpT, typename ArgT>
struct width_of<proto::op_proxy<OpT, ArgT> >
: width_of<OpT>
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////////
// algorithm.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_UTILITY_ALGORITHM_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_UTILITY_ALGORITHM_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <climits>
#include <algorithm>
#include <boost/iterator/iterator_traits.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// any
//
template<typename InIterT, typename PredT>
inline bool any(InIterT begin, InIterT end, PredT pred)
{
return end != std::find_if(begin, end, pred);
}
///////////////////////////////////////////////////////////////////////////////
// find_nth_if
//
template<typename FwdIterT, typename DiffT, typename PredT>
FwdIterT find_nth_if(FwdIterT begin, FwdIterT end, DiffT count, PredT pred)
{
for(; begin != end; ++begin)
{
if(pred(*begin) && 0 == count--)
{
return begin;
}
}
return end;
}
///////////////////////////////////////////////////////////////////////////////
// toi
//
template<typename InIterT, typename TraitsT>
int toi(InIterT &begin, InIterT end, TraitsT const &traits, int radix = 10, int max = INT_MAX)
{
int i = 0, c = 0;
for(; begin != end && -1 != (c = traits.value(*begin, radix)); ++begin)
{
if(max < ((i *= radix) += c))
return i / radix;
}
return i;
}
///////////////////////////////////////////////////////////////////////////////
// advance_to
//
template<typename BidiIterT, typename DiffT>
inline bool advance_to_impl(BidiIterT & iter, DiffT diff, BidiIterT end, std::bidirectional_iterator_tag)
{
for(; 0 < diff && iter != end; --diff)
++iter;
for(; 0 > diff && iter != end; ++diff)
--iter;
return 0 == diff;
}
template<typename RandIterT, typename DiffT>
inline bool advance_to_impl(RandIterT & iter, DiffT diff, RandIterT end, std::random_access_iterator_tag)
{
if(0 < diff)
{
if((end - iter) < diff)
return false;
}
else if(0 > diff)
{
if((iter - end) < -diff)
return false;
}
iter += diff;
return true;
}
template<typename IterT, typename DiffT>
inline bool advance_to(IterT & iter, DiffT diff, IterT end)
{
return detail::advance_to_impl(iter, diff, end, typename iterator_category<IterT>::type());
}
}}}
#endif

View File

@@ -0,0 +1,204 @@
///////////////////////////////////////////////////////////////////////////////
/// \file boyer_moore.hpp
/// Contains the boyer-moore implementation. Note: this is *not* a general-
/// purpose boyer-moore implementation. It truncates the search string at
/// 256 characters, but it is sufficient for the needs of xpressive.
//
// 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_BOYER_MOORE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_BOYER_MOORE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <climits> // for UCHAR_MAX
#include <cstddef> // for std::ptrdiff_t
#include <utility> // for std::max
#include <vector>
#include <boost/mpl/bool.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
namespace boost { namespace xpressive { namespace detail
{
/////////////////////////////////////////////////////////////////////////////////
//// case_fold
//template<typename TraitsT>
//struct case_fold
// : is_convertible<
// typename TraitsT::version_tag *
// , regex_traits_version_1_case_fold_tag *
// >
//{
//};
///////////////////////////////////////////////////////////////////////////////
// boyer_moore
//
template<typename BidiIterT, typename TraitsT> //, bool CaseFoldT = case_fold<TraitsT>::value>
struct boyer_moore
{
typedef typename iterator_value<BidiIterT>::type char_type;
typedef TraitsT traits_type;
typedef is_convertible<
typename TraitsT::version_tag *
, regex_traits_version_1_case_fold_tag *
> case_fold;
typedef typename TraitsT::string_type string_type;
// initialize the Boyer-Moore search data structure, using the
// search sub-sequence to prime the pump.
boyer_moore(char_type const *begin, char_type const *end, TraitsT const &traits, bool icase)
: begin_(begin)
, last_(begin)
, fold_()
, find_fun_(
icase
? (case_fold() ? &boyer_moore::find_nocase_fold_ : &boyer_moore::find_nocase_)
: &boyer_moore::find_
)
{
std::ptrdiff_t const uchar_max = UCHAR_MAX;
std::ptrdiff_t diff = std::distance(begin, end);
this->length_ = static_cast<unsigned char>((std::min)(diff, uchar_max));
std::fill_n(this->offsets_, uchar_max + 1, this->length_);
--this->length_;
icase ? this->init_(traits, case_fold()) : this->init_(traits, mpl::false_());
}
BidiIterT find(BidiIterT begin, BidiIterT end, TraitsT const &traits) const
{
return (this->*this->find_fun_)(begin, end, traits);
}
private:
void init_(TraitsT const &traits, mpl::false_)
{
for(unsigned char offset = this->length_; offset; --offset, ++this->last_)
{
this->offsets_[traits.hash(*this->last_)] = offset;
}
}
void init_(TraitsT const &traits, mpl::true_)
{
this->fold_.reserve(this->length_ + 1);
for(unsigned char offset = this->length_; offset; --offset, ++this->last_)
{
this->fold_.push_back(traits.fold_case(*this->last_));
for(typename string_type::const_iterator beg = this->fold_.back().begin(), end = this->fold_.back().end();
beg != end; ++beg)
{
this->offsets_[traits.hash(*beg)] = offset;
}
}
this->fold_.push_back(traits.fold_case(*this->last_));
}
// case-sensitive Boyer-Moore search
BidiIterT find_(BidiIterT begin, BidiIterT end, TraitsT const &traits) const
{
typedef typename boost::iterator_difference<BidiIterT>::type diff_type;
diff_type const endpos = std::distance(begin, end);
diff_type offset = static_cast<diff_type>(this->length_);
for(diff_type curpos = offset; curpos < endpos; curpos += offset)
{
std::advance(begin, offset);
char_type const *pat_tmp = this->last_;
BidiIterT str_tmp = begin;
for(; traits.translate(*str_tmp) == *pat_tmp; --pat_tmp, --str_tmp)
{
if(pat_tmp == this->begin_)
{
return str_tmp;
}
}
offset = this->offsets_[traits.hash(traits.translate(*begin))];
}
return end;
}
// case-insensitive Boyer-Moore search
BidiIterT find_nocase_(BidiIterT begin, BidiIterT end, TraitsT const &traits) const
{
typedef typename boost::iterator_difference<BidiIterT>::type diff_type;
diff_type const endpos = std::distance(begin, end);
diff_type offset = static_cast<diff_type>(this->length_);
for(diff_type curpos = offset; curpos < endpos; curpos += offset)
{
std::advance(begin, offset);
char_type const *pat_tmp = this->last_;
BidiIterT str_tmp = begin;
for(; traits.translate_nocase(*str_tmp) == *pat_tmp; --pat_tmp, --str_tmp)
{
if(pat_tmp == this->begin_)
{
return str_tmp;
}
}
offset = this->offsets_[traits.hash(traits.translate_nocase(*begin))];
}
return end;
}
// case-insensitive Boyer-Moore search with case-folding
BidiIterT find_nocase_fold_(BidiIterT begin, BidiIterT end, TraitsT const &traits) const
{
typedef typename boost::iterator_difference<BidiIterT>::type diff_type;
diff_type const endpos = std::distance(begin, end);
diff_type offset = static_cast<diff_type>(this->length_);
for(diff_type curpos = offset; curpos < endpos; curpos += offset)
{
std::advance(begin, offset);
string_type const *pat_tmp = &this->fold_.back();
BidiIterT str_tmp = begin;
for(; pat_tmp->end() != std::find(pat_tmp->begin(), pat_tmp->end(), *str_tmp);
--pat_tmp, --str_tmp)
{
if(pat_tmp == &this->fold_.front())
{
return str_tmp;
}
}
offset = this->offsets_[traits.hash(*begin)];
}
return end;
}
private:
char_type const *begin_;
char_type const *last_;
std::vector<string_type> fold_;
BidiIterT (boyer_moore::*const find_fun_)(BidiIterT, BidiIterT, TraitsT const &) const;
unsigned char length_;
unsigned char offsets_[UCHAR_MAX + 1];
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,150 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2001-2003 Daniel Nuffer
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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_SPIRIT_BASIC_CHSET_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_HPP_EAN_10_04_2005
///////////////////////////////////////////////////////////////////////////////
#include <bitset>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/utility/chset/range_run.ipp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////
//
// basic_chset: basic character set implementation using range_run
//
///////////////////////////////////////////////////////////////////////////
template<typename CharT>
struct basic_chset
{
basic_chset();
basic_chset(basic_chset const &arg);
bool empty() const;
void set(CharT from, CharT to);
template<typename TraitsT>
void set(CharT from, CharT to, TraitsT const &traits);
void set(CharT c);
template<typename TraitsT>
void set(CharT c, TraitsT const &traits);
void clear(CharT from, CharT to);
template<typename TraitsT>
void clear(CharT from, CharT to, TraitsT const &traits);
void clear(CharT c);
template<typename TraitsT>
void clear(CharT c, TraitsT const &traits);
void clear();
template<typename TraitsT>
bool test(CharT v, TraitsT const &traits, mpl::false_) const; // case-sensitive
template<typename TraitsT>
bool test(CharT v, TraitsT const &traits, mpl::true_) const; // case-insensitive
void inverse();
void swap(basic_chset& x);
basic_chset &operator |=(basic_chset const &x);
basic_chset &operator &=(basic_chset const &x);
basic_chset &operator -=(basic_chset const &x);
basic_chset &operator ^=(basic_chset const &x);
private:
range_run<CharT> rr_;
};
#if(CHAR_BIT == 8)
///////////////////////////////////////////////////////////////////////////
//
// basic_chset: specializations for 8 bit chars using std::bitset
//
///////////////////////////////////////////////////////////////////////////
template<typename CharT>
struct basic_chset_8bit
{
basic_chset_8bit();
basic_chset_8bit(basic_chset_8bit const &arg);
bool empty() const;
void set(CharT from, CharT to);
template<typename TraitsT>
void set(CharT from, CharT to, TraitsT const &traits);
void set(CharT c);
template<typename TraitsT>
void set(CharT c, TraitsT const &traits);
void clear(CharT from, CharT to);
template<typename TraitsT>
void clear(CharT from, CharT to, TraitsT const &traits);
void clear(CharT c);
template<typename TraitsT>
void clear(CharT c, TraitsT const &traits);
void clear();
template<typename TraitsT>
bool test(CharT v, TraitsT const &traits, mpl::false_) const; // case-sensitive
template<typename TraitsT>
bool test(CharT v, TraitsT const &traits, mpl::true_) const; // case-insensitive
void inverse();
void swap(basic_chset_8bit& x);
basic_chset_8bit &operator |=(basic_chset_8bit const &x);
basic_chset_8bit &operator &=(basic_chset_8bit const &x);
basic_chset_8bit &operator -=(basic_chset_8bit const &x);
basic_chset_8bit &operator ^=(basic_chset_8bit const &x);
std::bitset<256> const &base() const;
private:
std::bitset<256> bset_; // BUGBUG range-checking slows this down
};
/////////////////////////////////
template<>
struct basic_chset<char>
: basic_chset_8bit<char>
{
};
/////////////////////////////////
template<>
struct basic_chset<signed char>
: basic_chset_8bit<signed char>
{
};
/////////////////////////////////
template<>
struct basic_chset<unsigned char>
: basic_chset_8bit<unsigned char>
{
};
#endif
///////////////////////////////////////////////////////////////////////////////
// helpers
template<typename CharT, typename TraitsT>
void set_char(basic_chset<CharT> &chset, CharT ch, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_range(basic_chset<CharT> &chset, CharT from, CharT to, TraitsT const &traits, bool icase);
template<typename CharT, typename TraitsT>
void set_class(basic_chset<CharT> &chset, typename TraitsT::char_class_type char_class, bool no, TraitsT const &traits, bool icase);
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,409 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2001-2003 Daniel Nuffer
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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_SPIRIT_BASIC_CHSET_IPP
#define BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_IPP
///////////////////////////////////////////////////////////////////////////////
#include <bitset>
#include <boost/xpressive/detail/utility/chset/basic_chset.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
//
// basic_chset: character set implementation
//
///////////////////////////////////////////////////////////////////////////////
template<typename CharT>
inline basic_chset<CharT>::basic_chset()
{
}
//////////////////////////////////
template<typename CharT>
inline basic_chset<CharT>::basic_chset(basic_chset const &arg)
: rr_(arg.rr_)
{
}
//////////////////////////////////
template<typename CharT>
inline bool basic_chset<CharT>::empty() const
{
return this->rr_.empty();
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline bool basic_chset<CharT>::test(CharT v, TraitsT const &, mpl::false_) const // case-sensitive
{
return this->rr_.test(v);
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline bool basic_chset<CharT>::test(CharT v, TraitsT const &traits, mpl::true_) const // case-insensitive
{
return this->rr_.test(v, traits);
}
//////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::set(CharT from, CharT to)
{
this->rr_.set(range<CharT>(from, to));
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset<CharT>::set(CharT from, CharT to, TraitsT const &)
{
this->rr_.set(range<CharT>(from, to));
}
//////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::set(CharT c)
{
this->rr_.set(range<CharT>(c, c));
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset<CharT>::set(CharT c, TraitsT const &)
{
this->rr_.set(range<CharT>(c, c));
}
//////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::clear(CharT c)
{
this->rr_.clear(range<CharT>(c, c));
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset<CharT>::clear(CharT c, TraitsT const &)
{
this->rr_.clear(range<CharT>(c, c));
}
//////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::clear(CharT from, CharT to)
{
this->rr_.clear(range<CharT>(from, to));
}
//////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset<CharT>::clear(CharT from, CharT to, TraitsT const &)
{
this->rr_.clear(range<CharT>(from, to));
}
//////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::clear()
{
this->rr_.clear();
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::inverse()
{
// BUGBUG is this right? Does this handle icase correctly?
basic_chset<CharT> inv;
inv.set((std::numeric_limits<CharT>::min)(), (std::numeric_limits<CharT>::max)());
inv -= *this;
this->swap(inv);
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset<CharT>::swap(basic_chset<CharT> &that)
{
this->rr_.swap(that.rr_);
}
/////////////////////////////////
template<typename CharT>
inline basic_chset<CharT> &
basic_chset<CharT>::operator |=(basic_chset<CharT> const &that)
{
typedef typename range_run<CharT>::const_iterator const_iterator;
for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
{
this->rr_.set(*iter);
}
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset<CharT> &
basic_chset<CharT>::operator &=(basic_chset<CharT> const &that)
{
basic_chset<CharT> inv;
inv.set((std::numeric_limits<CharT>::min)(), (std::numeric_limits<CharT>::max)());
inv -= that;
*this -= inv;
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset<CharT> &
basic_chset<CharT>::operator -=(basic_chset<CharT> const &that)
{
typedef typename range_run<CharT>::const_iterator const_iterator;
for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
{
this->rr_.clear(*iter);
}
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset<CharT> &
basic_chset<CharT>::operator ^=(basic_chset<CharT> const &that)
{
basic_chset bma = that;
bma -= *this;
*this -= that;
*this |= bma;
return *this;
}
#if(CHAR_BIT == 8)
///////////////////////////////////////////////////////////////////////////////
//
// basic_chset: specializations for 8 bit chars using std::bitset
//
///////////////////////////////////////////////////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT>::basic_chset_8bit()
{
}
/////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT>::basic_chset_8bit(basic_chset_8bit<CharT> const &arg)
: bset_(arg.bset_)
{
}
/////////////////////////////////
template<typename CharT>
inline bool basic_chset_8bit<CharT>::empty() const
{
return !this->bset_.any();
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline bool basic_chset_8bit<CharT>::test(CharT v, TraitsT const &, mpl::false_) const // case-sensitive
{
return this->bset_.test((unsigned char)v);
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline bool basic_chset_8bit<CharT>::test(CharT v, TraitsT const &traits, mpl::true_) const // case-insensitive
{
return this->bset_.test((unsigned char)traits.translate_nocase(v));
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::set(CharT from, CharT to)
{
for(int i = from; i <= to; ++i)
{
this->bset_.set((unsigned char)i);
}
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset_8bit<CharT>::set(CharT from, CharT to, TraitsT const &traits)
{
for(int i = from; i <= to; ++i)
{
this->bset_.set((unsigned char)traits.translate_nocase((CharT)i));
}
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::set(CharT c)
{
this->bset_.set((unsigned char)c);
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset_8bit<CharT>::set(CharT c, TraitsT const &traits)
{
this->bset_.set((unsigned char)traits.translate_nocase(c));
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::clear(CharT from, CharT to)
{
for(int i = from; i <= to; ++i)
{
this->bset_.reset((unsigned char)i);
}
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset_8bit<CharT>::clear(CharT from, CharT to, TraitsT const &traits)
{
for(int i = from; i <= to; ++i)
{
this->bset_.reset((unsigned char)traits.translate_nocase((CharT)i));
}
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::clear(CharT c)
{
this->bset_.reset((unsigned char)c);
}
/////////////////////////////////
template<typename CharT>
template<typename TraitsT>
inline void basic_chset_8bit<CharT>::clear(CharT c, TraitsT const &traits)
{
this->bset_.reset((unsigned char)traits.tranlsate_nocase(c));
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::clear()
{
this->bset_.reset();
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::inverse()
{
this->bset_.flip();
}
/////////////////////////////////
template<typename CharT>
inline void basic_chset_8bit<CharT>::swap(basic_chset_8bit<CharT> &that)
{
std::swap(this->bset_, that.bset_);
}
/////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT> &
basic_chset_8bit<CharT>::operator |=(basic_chset_8bit<CharT> const &that)
{
this->bset_ |= that.bset_;
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT> &
basic_chset_8bit<CharT>::operator &=(basic_chset_8bit<CharT> const &that)
{
this->bset_ &= that.bset_;
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT> &
basic_chset_8bit<CharT>::operator -=(basic_chset_8bit<CharT> const &that)
{
this->bset_ &= ~that.bset_;
return *this;
}
/////////////////////////////////
template<typename CharT>
inline basic_chset_8bit<CharT> &
basic_chset_8bit<CharT>::operator ^=(basic_chset_8bit<CharT> const &that)
{
this->bset_ ^= that.bset_;
return *this;
}
template<typename CharT>
inline std::bitset<256> const &
basic_chset_8bit<CharT>::base() const
{
return this->bset_;
}
#endif // if(CHAR_BIT == 8)
///////////////////////////////////////////////////////////////////////////////
// helpers
template<typename CharT, typename TraitsT>
inline void set_char(basic_chset<CharT> &chset, CharT ch, TraitsT const &traits, bool icase)
{
icase ? chset.set(ch, traits) : chset.set(ch);
}
template<typename CharT, typename TraitsT>
inline void set_range(basic_chset<CharT> &chset, CharT from, CharT to, TraitsT const &traits, bool icase)
{
icase ? chset.set(from, to, traits) : chset.set(from, to);
}
template<typename CharT, typename TraitsT>
inline void set_class(basic_chset<CharT> &chset, typename TraitsT::char_class_type char_class, bool no, TraitsT const &traits, bool icase)
{
BOOST_MPL_ASSERT_RELATION(1, ==, sizeof(CharT));
for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
{
typedef typename std::char_traits<CharT>::int_type int_type;
CharT ch = std::char_traits<CharT>::to_char_type(static_cast<int_type>(i));
if(no != traits.isctype(ch, char_class))
{
chset.set(ch);
}
}
}
}}} // namespace boost::xpressive::detail
#endif

Some files were not shown because too many files have changed in this diff Show More