summaryrefslogtreecommitdiff
path: root/boost/spirit/home/classic/core/match.hpp
blob: c82baa1489496f16f99099f43729b07efb7fe8fd (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
/*=============================================================================
    Copyright (c) 1998-2003 Joel de Guzman
    http://spirit.sourceforge.net/

  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)
=============================================================================*/
#if !defined(BOOST_SPIRIT_MATCH_HPP)
#define BOOST_SPIRIT_MATCH_HPP

#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/config.hpp>
#include <boost/spirit/home/classic/core/nil.hpp>
#include <boost/call_traits.hpp>
#include <boost/optional.hpp>
#include <boost/spirit/home/classic/core/assert.hpp>
#include <boost/spirit/home/classic/core/safe_bool.hpp>
#include <boost/spirit/home/classic/core/impl/match_attr_traits.ipp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/is_reference.hpp>

namespace boost { namespace spirit {

BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN

    ///////////////////////////////////////////////////////////////////////////
    //
    //  match class
    //
    //      The match holds the result of a parser. A match object evaluates
    //      to true when a successful match is found, otherwise false. The
    //      length of the match is the number of characters (or tokens) that
    //      is successfully matched. This can be queried through its length()
    //      member function. A negative value means that the match is
    //      unsucessful.
    //
    //      Each parser may have an associated attribute. This attribute is
    //      also returned back to the client on a successful parse through
    //      the match object. The match's value() member function returns the
    //      match's attribute.
    //
    //      A match attribute is valid:
    //
    //          * on a successful match
    //          * when its value is set through the value(val) member function
    //          * if it is assigned or copied from a compatible match object
    //            (e.g. match<double> from match<int>) with a valid attribute.
    //
    //      The match attribute is undefined:
    //
    //          * on an unsuccessful match
    //          * when an attempt to copy or assign from another match object
    //            with an incompatible attribute type (e.g. match<std::string>
    //            from match<int>).
    //
    //      The member function has_valid_attribute() can be queried to know if
    //      it is safe to get the match's attribute. The attribute may be set
    //      through the member function value(v) where v is the new attribute
    //      value.
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename T = nil_t>
    class match : public safe_bool<match<T> >
    {
        typedef typename
            conditional<
                is_reference<T>::value
              , T
              , typename add_reference<
                    typename add_const<T>::type
                >::type
            >::type attr_ref_t;

    public:

        typedef typename boost::optional<T> optional_type;
        typedef attr_ref_t ctor_param_t;
        typedef attr_ref_t return_t;
        typedef T attr_t;

                                match();
        explicit                match(std::size_t length);
                                match(std::size_t length, ctor_param_t val);

        bool                    operator!() const;
        std::ptrdiff_t          length() const;
        bool                    has_valid_attribute() const;
        return_t                value() const;
        void                    swap(match& other);

        template <typename T2>
        match(match<T2> const& other)
        : len(other.length()), val()
        {
            impl::match_attr_traits<T>::copy(val, other);
        }

        template <typename T2>
        match&
        operator=(match<T2> const& other)
        {
            impl::match_attr_traits<T>::assign(val, other);
            len = other.length();
            return *this;
        }

        template <typename MatchT>
        void
        concat(MatchT const& other)
        {
            BOOST_SPIRIT_ASSERT(*this && other);
            len += other.length();
        }

        template <typename ValueT>
        void
        value(ValueT const& val_)
        {
            impl::match_attr_traits<T>::set_value(val, val_, is_reference<T>());
        }

        bool operator_bool() const
        {
            return len >= 0;
        }

    private:

        std::ptrdiff_t len;
        optional_type val;
    };

    ///////////////////////////////////////////////////////////////////////////
    //
    //  match class specialization for nil_t values
    //
    ///////////////////////////////////////////////////////////////////////////
    template <>
    class match<nil_t> : public safe_bool<match<nil_t> >
    {
    public:

        typedef nil_t attr_t;
        typedef nil_t return_t;

                                match();
        explicit                match(std::size_t length);
                                match(std::size_t length, nil_t);

        bool                    operator!() const;
        bool                    has_valid_attribute() const;
        std::ptrdiff_t          length() const;
        nil_t                   value() const;
        void                    value(nil_t);
        void                    swap(match& other);

        template <typename T>
        match(match<T> const& other)
        : len(other.length()) {}

        template <typename T>
        match<>&
        operator=(match<T> const& other)
        {
            len = other.length();
            return *this;
        }

        template <typename T>
        void
        concat(match<T> const& other)
        {
            BOOST_SPIRIT_ASSERT(*this && other);
            len += other.length();
        }

        bool operator_bool() const
        {
            return len >= 0;
        }

    private:

        std::ptrdiff_t len;
    };

BOOST_SPIRIT_CLASSIC_NAMESPACE_END

}} // namespace BOOST_SPIRIT_CLASSIC_NS

#endif
#include <boost/spirit/home/classic/core/impl/match.ipp>