/////////////////////////////////////////////////////////////////////////////// | |
// grammar.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_GRAMMAR_HPP_EAN_11_12_2006 | |
#define BOOST_XPRESSIVE_DETAIL_STATIC_GRAMMAR_HPP_EAN_11_12_2006 | |
// 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/proto/core.hpp> | |
#include <boost/xpressive/detail/static/is_pure.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_matcher.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_alternate.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_sequence.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_quantifier.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_marker.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_set.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_independent.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_modifier.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_inverse.hpp> | |
#include <boost/xpressive/detail/static/transforms/as_action.hpp> | |
#include <boost/xpressive/detail/detail_fwd.hpp> | |
#define BOOST_XPRESSIVE_CHECK_REGEX(Expr, Char)\ | |
BOOST_MPL_ASSERT\ | |
((\ | |
typename boost::mpl::if_c<\ | |
boost::xpressive::is_valid_regex<Expr, Char>::value\ | |
, boost::mpl::true_\ | |
, boost::xpressive::INVALID_REGULAR_EXPRESSION\ | |
>::type\ | |
)); | |
////////////////////////////////////////////////////////////////////////// | |
//**********************************************************************// | |
//* << NOTE! >> *// | |
//* *// | |
//* Whenever you change this grammar, you MUST also make corresponding *// | |
//* changes to width_of.hpp and is_pure.hpp. *// | |
//* *// | |
//**********************************************************************// | |
////////////////////////////////////////////////////////////////////////// | |
namespace boost { namespace xpressive | |
{ | |
template<typename Char> | |
struct Grammar; | |
template<typename Char> | |
struct ActionableGrammar; | |
namespace grammar_detail | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// CharLiteral | |
template<typename Char> | |
struct CharLiteral; | |
/////////////////////////////////////////////////////////////////////////// | |
// ListSet | |
template<typename Char> | |
struct ListSet; | |
/////////////////////////////////////////////////////////////////////////// | |
// as_repeat | |
template<typename Char, typename Gram, typename Greedy> | |
struct as_repeat | |
: if_< | |
make<detail::use_simple_repeat<_child, Char> > | |
, as_simple_quantifier<Gram, Greedy> | |
, as_default_quantifier<Greedy> | |
> | |
{}; | |
/////////////////////////////////////////////////////////////////////////// | |
// NonGreedyRepeatCases | |
template<typename Gram> | |
struct NonGreedyRepeatCases | |
{ | |
template<typename Tag, typename Dummy = void> | |
struct case_ | |
: not_<_> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::dereference, Dummy> | |
: dereference<Gram> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::unary_plus, Dummy> | |
: unary_plus<Gram> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::logical_not, Dummy> | |
: logical_not<Gram> | |
{}; | |
template<uint_t Min, uint_t Max, typename Dummy> | |
struct case_<detail::generic_quant_tag<Min, Max>, Dummy> | |
: unary_expr<detail::generic_quant_tag<Min, Max>, Gram> | |
{}; | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
// InvertibleCases | |
template<typename Char, typename Gram> | |
struct InvertibleCases | |
{ | |
template<typename Tag, typename Dummy = void> | |
struct case_ | |
: not_<_> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::comma, Dummy> | |
: when<ListSet<Char>, as_list_set_matcher<Char> > | |
{}; | |
template<typename Dummy> | |
struct case_<tag::assign, Dummy> | |
: when<ListSet<Char>, as_list_set_matcher<Char> > | |
{}; | |
template<typename Dummy> | |
struct case_<tag::subscript, Dummy> | |
: when<subscript<detail::set_initializer_type, Gram>, call<as_set_matcher<Gram>(_right)> > | |
{}; | |
template<typename Dummy> | |
struct case_<detail::lookahead_tag, Dummy> | |
: when< | |
unary_expr<detail::lookahead_tag, Gram> | |
, as_lookahead<Gram> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<detail::lookbehind_tag, Dummy> | |
: when< | |
unary_expr<detail::lookbehind_tag, Gram> | |
, as_lookbehind<Gram> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::terminal, Dummy> | |
: when< | |
or_< | |
CharLiteral<Char> | |
, terminal<detail::posix_charset_placeholder> | |
, terminal<detail::range_placeholder<_> > | |
, terminal<detail::logical_newline_placeholder> | |
, terminal<detail::assert_word_placeholder<detail::word_boundary<mpl::true_> > > | |
> | |
, as_matcher | |
> | |
{}; | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
// Cases | |
template<typename Char, typename Gram> | |
struct Cases | |
{ | |
template<typename Tag, typename Dummy = void> | |
struct case_ | |
: not_<_> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::terminal, Dummy> | |
: when< | |
_ | |
, in_sequence<as_matcher> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::shift_right, Dummy> | |
: when< | |
shift_right<Gram, Gram> | |
, reverse_fold<_, _state, Gram> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::bitwise_or, Dummy> | |
: when< | |
bitwise_or<Gram, Gram> | |
, in_sequence< | |
as_alternate_matcher< | |
reverse_fold_tree<_, make<fusion::nil>, in_alternate_list<Gram> > | |
> | |
> | |
> | |
{}; | |
template<typename Dummy, typename Greedy> | |
struct case_<optional_tag<Greedy> , Dummy> | |
: when< | |
unary_expr<optional_tag<Greedy>, Gram> | |
, in_sequence<call<as_optional<Gram, Greedy>(_child)> > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::dereference, Dummy> | |
: when< | |
dereference<Gram> | |
, call<Gram(as_repeat<Char, Gram, mpl::true_>)> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::unary_plus, Dummy> | |
: when< | |
unary_plus<Gram> | |
, call<Gram(as_repeat<Char, Gram, mpl::true_>)> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::logical_not, Dummy> | |
: when< | |
logical_not<Gram> | |
, call<Gram(as_repeat<Char, Gram, mpl::true_>)> | |
> | |
{}; | |
template<uint_t Min, uint_t Max, typename Dummy> | |
struct case_<detail::generic_quant_tag<Min, Max>, Dummy> | |
: when< | |
unary_expr<detail::generic_quant_tag<Min, Max>, Gram> | |
, call<Gram(as_repeat<Char, Gram, mpl::true_>)> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::negate, Dummy> | |
: when< | |
negate<switch_<NonGreedyRepeatCases<Gram> > > | |
, call<Gram(call<as_repeat<Char, Gram, mpl::false_>(_child)>)> | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::complement, Dummy> | |
: when< | |
complement<switch_<InvertibleCases<Char, Gram> > > | |
, in_sequence<call<as_inverse(call<switch_<InvertibleCases<Char, Gram> >(_child)>)> > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<detail::modifier_tag, Dummy> | |
: when<binary_expr<detail::modifier_tag, _, Gram>, as_modifier<Gram> > | |
{}; | |
template<typename Dummy> | |
struct case_<detail::lookahead_tag, Dummy> | |
: when< | |
unary_expr<detail::lookahead_tag, Gram> | |
, in_sequence<as_lookahead<Gram> > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<detail::lookbehind_tag, Dummy> | |
: when< | |
unary_expr<detail::lookbehind_tag, Gram> | |
, in_sequence<as_lookbehind<Gram> > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<detail::keeper_tag, Dummy> | |
: when< | |
unary_expr<detail::keeper_tag, Gram> | |
, in_sequence<as_keeper<Gram> > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::comma, Dummy> | |
: when<ListSet<Char>, in_sequence<as_list_set_matcher<Char> > > | |
{}; | |
template<typename Dummy> | |
struct case_<tag::assign, Dummy> | |
: or_< | |
when<assign<detail::basic_mark_tag, Gram>, call<Gram(as_marker)> > | |
, when<ListSet<Char>, in_sequence<as_list_set_matcher<Char> > > | |
> | |
{}; | |
template<typename Dummy> | |
struct case_<tag::subscript, Dummy> | |
: or_< | |
when<subscript<detail::set_initializer_type, Gram>, in_sequence<call<as_set_matcher<Gram>(_right)> > > | |
, when<subscript<ActionableGrammar<Char>, _>, call<ActionableGrammar<Char>(as_action)> > | |
> | |
{}; | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
// ActionableCases | |
template<typename Char, typename Gram> | |
struct ActionableCases | |
{ | |
template<typename Tag, typename Dummy = void> | |
struct case_ | |
: Cases<Char, Gram>::template case_<Tag> | |
{}; | |
// Only in sub-expressions with actions attached do we allow attribute assignements | |
template<typename Dummy> | |
struct case_<proto::tag::assign, Dummy> | |
: or_< | |
typename Cases<Char, Gram>::template case_<proto::tag::assign> | |
, when<proto::assign<terminal<detail::attribute_placeholder<_> >, _>, in_sequence<as_attr_matcher> > | |
> | |
{}; | |
}; | |
} // namespace detail | |
/////////////////////////////////////////////////////////////////////////// | |
// Grammar | |
template<typename Char> | |
struct Grammar | |
: proto::switch_<grammar_detail::Cases<Char, Grammar<Char> > > | |
{}; | |
template<typename Char> | |
struct ActionableGrammar | |
: proto::switch_<grammar_detail::ActionableCases<Char, ActionableGrammar<Char> > > | |
{}; | |
/////////////////////////////////////////////////////////////////////////// | |
// INVALID_REGULAR_EXPRESSION | |
struct INVALID_REGULAR_EXPRESSION | |
: mpl::false_ | |
{}; | |
/////////////////////////////////////////////////////////////////////////// | |
// is_valid_regex | |
template<typename Expr, typename Char> | |
struct is_valid_regex | |
: proto::matches<Expr, Grammar<Char> > | |
{}; | |
}} // namespace boost::xpressive | |
#endif |