366 lines
13 KiB
C++
366 lines
13 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// 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)
|
|
# 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
|