/////////////////////////////////////////////////////////////////////////////// | |
// as_set.hpp | |
// | |
// Copyright 2008 Eric Niebler. Distributed under the Boost | |
// Software License, Version 1.0. (See accompanying file | |
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007 | |
#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007 | |
// MS compatible compilers support #pragma once | |
#if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
# pragma once | |
#endif | |
#include <boost/mpl/assert.hpp> | |
#include <boost/proto/core.hpp> | |
#include <boost/xpressive/detail/detail_fwd.hpp> | |
#include <boost/xpressive/detail/static/static.hpp> | |
#include <boost/xpressive/detail/utility/chset/chset.hpp> | |
#include <boost/xpressive/detail/utility/traits_utils.hpp> | |
namespace boost { namespace xpressive { namespace grammar_detail | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// CharLiteral | |
template<typename Char> | |
struct CharLiteral | |
: or_< | |
terminal<char> | |
, terminal<Char> | |
> | |
{}; | |
template<> | |
struct CharLiteral<char> | |
: terminal<char> | |
{}; | |
/////////////////////////////////////////////////////////////////////////// | |
// ListSet | |
// matches expressions like (set= 'a','b','c') | |
// calculates the size of the set | |
template<typename Char> | |
struct ListSet | |
: or_< | |
when< | |
comma<ListSet<Char>, CharLiteral<Char> > | |
, make<mpl::next<call<ListSet<Char>(_left)> > > // TODO make a custom transform for this... | |
> | |
, when< | |
assign<detail::set_initializer_type, CharLiteral<Char> > | |
, make<mpl::int_<1> > | |
> | |
> | |
{}; | |
template<typename Char, typename Traits> | |
void fill_list_set(Char *&, detail::set_initializer_type, Traits const &) | |
{} | |
template<typename Char, typename Expr, typename Traits> | |
void fill_list_set(Char *&buffer, Expr const &expr, Traits const &traits) | |
{ | |
fill_list_set(buffer, proto::left(expr), traits); | |
*buffer++ = traits.translate(detail::char_cast<Char>(proto::value(proto::right(expr)), traits)); | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// as_list_set_matcher | |
template<typename Char, typename Callable = proto::callable> | |
struct as_list_set_matcher : proto::transform<as_list_set_matcher<Char, Callable> > | |
{ | |
template<typename Expr, typename State, typename Data> | |
struct impl : proto::transform_impl<Expr, State, Data> | |
{ | |
typedef typename impl::data data_type; | |
typedef | |
detail::set_matcher< | |
typename data_type::traits_type | |
, typename ListSet<Char>::template impl<Expr, State, Data>::result_type | |
> | |
result_type; | |
result_type operator ()( | |
typename impl::expr_param expr | |
, typename impl::state_param | |
, typename impl::data_param data | |
) const | |
{ | |
result_type set; | |
typedef typename impl::data data_type; | |
typename data_type::char_type *buffer = set.set_; | |
fill_list_set(buffer, expr, data.traits()); | |
return set; | |
} | |
}; | |
}; | |
/////////////////////////////////////////////////////////////////////////////// | |
// merge_charset | |
// | |
template<typename Grammar, typename CharSet, typename Data> | |
struct merge_charset | |
{ | |
typedef typename Data::traits_type traits_type; | |
typedef typename CharSet::char_type char_type; | |
typedef typename CharSet::icase_type icase_type; | |
merge_charset(CharSet &charset, Data &data) | |
: charset_(charset) | |
, visitor_(data) | |
{} | |
template<typename Expr> | |
void operator ()(Expr const &expr) const | |
{ | |
this->call_(expr, typename Expr::proto_tag()); | |
} | |
private: | |
merge_charset &operator =(merge_charset const &); | |
template<typename Expr, typename Tag> | |
void call_(Expr const &expr, Tag) const | |
{ | |
this->set_( | |
typename Grammar::template impl<Expr const &, detail::end_xpression, Data &>()( | |
expr | |
, detail::end_xpression() | |
, this->visitor_ | |
) | |
); | |
} | |
template<typename Expr> | |
void call_(Expr const &expr, tag::bitwise_or) const | |
{ | |
(*this)(proto::left(expr)); | |
(*this)(proto::right(expr)); | |
} | |
template<typename Not> | |
void set_(detail::literal_matcher<traits_type, icase_type, Not> const &ch) const | |
{ | |
// BUGBUG fixme! | |
BOOST_MPL_ASSERT_NOT((Not)); | |
set_char(this->charset_.charset_, ch.ch_, this->visitor_.traits(), icase_type()); | |
} | |
void set_(detail::range_matcher<traits_type, icase_type> const &rg) const | |
{ | |
// BUGBUG fixme! | |
BOOST_ASSERT(!rg.not_); | |
set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->visitor_.traits(), icase_type()); | |
} | |
template<typename Size> | |
void set_(detail::set_matcher<traits_type, Size> const &set_) const | |
{ | |
// BUGBUG fixme! | |
BOOST_ASSERT(!set_.not_); | |
for(int i = 0; i < Size::value; ++i) | |
{ | |
set_char(this->charset_.charset_, set_.set_[i], this->visitor_.traits(), icase_type()); | |
} | |
} | |
void set_(detail::posix_charset_matcher<traits_type> const &posix) const | |
{ | |
set_class(this->charset_.charset_, posix.mask_, posix.not_, this->visitor_.traits()); | |
} | |
CharSet &charset_; | |
Data &visitor_; | |
}; | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
template<typename Grammar, typename Callable = proto::callable> | |
struct as_set_matcher : proto::transform<as_set_matcher<Grammar, Callable> > | |
{ | |
template<typename Expr, typename State, typename Data> | |
struct impl : proto::transform_impl<Expr, State, Data> | |
{ | |
typedef typename impl::data data_type; | |
typedef typename data_type::char_type char_type; | |
// if sizeof(char_type)==1, merge everything into a basic_chset | |
// BUGBUG this is not optimal. | |
typedef | |
typename mpl::if_c< | |
detail::is_narrow_char<char_type>::value | |
, detail::basic_chset<char_type> | |
, detail::compound_charset<typename data_type::traits_type> | |
>::type | |
charset_type; | |
typedef | |
detail::charset_matcher< | |
typename data_type::traits_type | |
, typename data_type::icase_type | |
, charset_type | |
> | |
result_type; | |
result_type operator ()( | |
typename impl::expr_param expr | |
, typename impl::state_param | |
, typename impl::data_param data | |
) const | |
{ | |
result_type matcher; | |
merge_charset<Grammar, result_type, typename impl::data> merge(matcher, data); | |
merge(expr); // Walks the tree and fills in the charset | |
return matcher; | |
} | |
}; | |
}; | |
}}} | |
#endif |