summaryrefslogtreecommitdiff
path: root/boost/xpressive/detail/static/is_pure.hpp
blob: f7da4f04bbc75c2200e2f4ca14672b21893dfb60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
///////////////////////////////////////////////////////////////////////////////
// is_pure.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_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 <boost/ref.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.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>

namespace boost { namespace xpressive { namespace detail
{
    ///////////////////////////////////////////////////////////////////////////////
    // use_simple_repeat_terminal
    //
    template<typename Expr, typename Char, bool IsXpr = is_xpr<Expr>::value>
    struct use_simple_repeat_terminal
      : mpl::bool_<
            Expr::quant == quant_fixed_width
        || (Expr::width != unknown_width::value && Expr::pure)
        >
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_terminal<Expr, Char, false>
      : mpl::true_              // char literals, string literals, etc.
    {};

    template<typename BidiIter, typename Char>
    struct use_simple_repeat_terminal<tracking_ptr<regex_impl<BidiIter> >, Char, false>
      : mpl::false_             // basic_regex
    {};

    template<typename BidiIter, typename Char>
    struct use_simple_repeat_terminal<reference_wrapper<basic_regex<BidiIter> >, Char, false>
      : mpl::false_             // basic_regex
    {};

    template<typename BidiIter, typename Char>
    struct use_simple_repeat_terminal<reference_wrapper<basic_regex<BidiIter> const>, Char, false>
      : mpl::false_             // basic_regex
    {};

    ///////////////////////////////////////////////////////////////////////////////
    // use_simple_repeat_
    //
    template<typename Expr, typename Char, typename Tag = typename Expr::proto_tag>
    struct use_simple_repeat_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::terminal>
      : use_simple_repeat_terminal<typename proto::result_of::value<Expr>::type, Char>
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::shift_right>
      : mpl::and_<
            use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
          , use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
        >
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::bitwise_or>
      : mpl::and_<
            mpl::not_equal_to<unknown_width, width_of<Expr, Char> >
          , use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
          , use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
        >
    {};

    template<typename Left>
    struct use_simple_repeat_assign
    {};

    template<>
    struct use_simple_repeat_assign<mark_placeholder>
      : mpl::false_
    {};

    template<>
    struct use_simple_repeat_assign<set_initializer>
      : mpl::true_
    {};

    template<typename Nbr>
    struct use_simple_repeat_assign<attribute_placeholder<Nbr> >
      : mpl::false_
    {};

    // either (s1 = ...) or (a1 = ...) or (set = ...)
    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::assign>
      : use_simple_repeat_assign<
            typename proto::result_of::value<
                typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr
            >::type
        >
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, modifier_tag>
      : use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, lookahead_tag>
      : mpl::false_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, lookbehind_tag>
      : mpl::false_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, keeper_tag>
      : mpl::false_
    {};

    // when complementing a set or an assertion, the purity is that of the set (true) or the assertion
    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::complement>
      : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
    {};

    // The comma is used in list-initialized sets, which are pure
    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::comma>
      : 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 Expr, typename Char, typename Left>
    struct use_simple_repeat_subscript
      : mpl::false_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_subscript<Expr, Char, set_initializer_type>
      : mpl::true_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::subscript>
      : use_simple_repeat_subscript<Expr, Char, typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr>
    {};

    // Quantified expressions are variable-width and cannot use the simple quantifier
    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::unary_plus>
      : mpl::false_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::dereference>
      : mpl::false_
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::logical_not>
      : mpl::false_
    {};

    template<typename Expr, typename Char, uint_t Min, uint_t Max>
    struct use_simple_repeat_<Expr, Char, generic_quant_tag<Min, Max> >
      : mpl::false_
    {};

    template<typename Expr, typename Char, uint_t Count>
    struct use_simple_repeat_<Expr, Char, generic_quant_tag<Count, Count> >
      : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
    {};

    template<typename Expr, typename Char>
    struct use_simple_repeat_<Expr, Char, proto::tag::negate>
      : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
    {};

    ///////////////////////////////////////////////////////////////////////////////
    // use_simple_repeat
    //
    template<typename Expr, typename Char>
    struct use_simple_repeat
      : use_simple_repeat_<Expr, Char>
    {
        // should never try to repeat something of 0-width
        BOOST_MPL_ASSERT_RELATION(0, !=, (width_of<Expr, Char>::value));
    };

    template<typename Expr, typename Char>
    struct use_simple_repeat<Expr &, Char>
      : use_simple_repeat_<Expr, Char>
    {
        // should never try to repeat something of 0-width
        BOOST_MPL_ASSERT_RELATION(0, !=, (width_of<Expr, Char>::value));
    };

}}} // namespace boost::xpressive::detail

#endif