| /////////////////////////////////////////////////////////////////////////////// |
| // 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 |