]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // matchable.hpp | |
3 | // | |
4 | // Copyright 2008 Eric Niebler. Distributed under the Boost | |
5 | // Software License, Version 1.0. (See accompanying file | |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005 | |
9 | #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005 | |
10 | ||
11 | // MS compatible compilers support #pragma once | |
12 | #if defined(_MSC_VER) | |
13 | # pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/assert.hpp> | |
17 | #include <boost/mpl/assert.hpp> | |
18 | #include <boost/intrusive_ptr.hpp> | |
19 | #include <boost/throw_exception.hpp> | |
20 | #include <boost/type_traits/is_same.hpp> | |
21 | #include <boost/xpressive/detail/core/quant_style.hpp> | |
22 | #include <boost/xpressive/detail/utility/counted_base.hpp> | |
23 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
24 | #include <boost/xpressive/detail/dynamic/sequence.hpp> | |
25 | #include <boost/xpressive/regex_error.hpp> | |
26 | ||
27 | namespace boost { namespace xpressive { namespace detail | |
28 | { | |
29 | ||
30 | ////////////////////////////////////////////////////////////////////////// | |
31 | // quant_spec | |
32 | struct quant_spec | |
33 | { | |
34 | unsigned int min_; | |
35 | unsigned int max_; | |
36 | bool greedy_; | |
37 | std::size_t *hidden_mark_count_; | |
38 | }; | |
39 | ||
40 | /////////////////////////////////////////////////////////////////////////////// | |
41 | // matchable | |
42 | template<typename BidiIter> | |
43 | struct matchable | |
44 | { | |
45 | typedef BidiIter iterator_type; | |
46 | typedef typename iterator_value<iterator_type>::type char_type; | |
47 | virtual ~matchable() {} | |
48 | virtual bool match(match_state<BidiIter> &state) const = 0; | |
49 | }; | |
50 | ||
51 | /////////////////////////////////////////////////////////////////////////////// | |
52 | // matchable_ex | |
53 | template<typename BidiIter> | |
54 | struct matchable_ex | |
55 | : matchable<BidiIter> | |
56 | , counted_base<matchable_ex<BidiIter> > | |
57 | { | |
58 | typedef BidiIter iterator_type; | |
59 | typedef typename iterator_value<iterator_type>::type char_type; | |
60 | ||
61 | virtual void link(xpression_linker<char_type> &) const | |
62 | { | |
63 | } | |
64 | ||
65 | virtual void peek(xpression_peeker<char_type> &peeker) const | |
66 | { | |
67 | peeker.fail(); | |
68 | } | |
69 | ||
70 | virtual void repeat(quant_spec const &, sequence<BidiIter> &) const | |
71 | { | |
72 | BOOST_THROW_EXCEPTION( | |
73 | regex_error(regex_constants::error_badrepeat, "expression cannot be quantified") | |
74 | ); | |
75 | } | |
76 | ||
77 | /////////////////////////////////////////////////////////////////////////////////////////////// | |
78 | // The following 4 functions (push_match, top_match, pop_match and skip_match) are | |
79 | // used to implement looping and branching across the matchers. Call push_match to record | |
80 | // a position. Then, another matcher further down the xpression chain has the | |
81 | // option to call either top_match, pop_match or skip_match. top_match and pop_match will | |
82 | // jump back to the place recorded by push_match, whereas skip_match will skip the jump and | |
83 | // pass execution down the xpression chain. top_match will leave the xpression on top of the | |
84 | // stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for | |
85 | // statically bound xpressions and one for dynamically bound xpressions. | |
86 | // | |
87 | ||
88 | template<typename Top> | |
89 | bool push_match(match_state<BidiIter> &state) const | |
90 | { | |
91 | BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >)); | |
92 | return this->match(state); | |
93 | } | |
94 | ||
95 | static bool top_match(match_state<BidiIter> &state, void const *top) | |
96 | { | |
97 | return static_cast<matchable_ex<BidiIter> const *>(top)->match(state); | |
98 | } | |
99 | ||
100 | static bool pop_match(match_state<BidiIter> &state, void const *top) | |
101 | { | |
102 | return static_cast<matchable_ex<BidiIter> const *>(top)->match(state); | |
103 | } | |
104 | ||
105 | bool skip_match(match_state<BidiIter> &state) const | |
106 | { | |
107 | return this->match(state); | |
108 | } | |
109 | }; | |
110 | ||
111 | /////////////////////////////////////////////////////////////////////////////// | |
112 | // shared_matchable | |
113 | template<typename BidiIter> | |
114 | struct shared_matchable | |
115 | { | |
116 | typedef BidiIter iterator_type; | |
117 | typedef typename iterator_value<BidiIter>::type char_type; | |
118 | typedef intrusive_ptr<matchable_ex<BidiIter> const> matchable_ptr; | |
119 | ||
120 | BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value); | |
121 | BOOST_STATIC_CONSTANT(bool, pure = false); | |
122 | ||
123 | shared_matchable(matchable_ptr const &xpr = matchable_ptr()) | |
124 | : xpr_(xpr) | |
125 | { | |
126 | } | |
127 | ||
128 | bool operator !() const | |
129 | { | |
130 | return !this->xpr_; | |
131 | } | |
132 | ||
133 | friend bool operator ==(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right) | |
134 | { | |
135 | return left.xpr_ == right.xpr_; | |
136 | } | |
137 | ||
138 | friend bool operator !=(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right) | |
139 | { | |
140 | return left.xpr_ != right.xpr_; | |
141 | } | |
142 | ||
143 | matchable_ptr const &matchable() const | |
144 | { | |
145 | return this->xpr_; | |
146 | } | |
147 | ||
148 | bool match(match_state<BidiIter> &state) const | |
149 | { | |
150 | return this->xpr_->match(state); | |
151 | } | |
152 | ||
153 | void link(xpression_linker<char_type> &linker) const | |
154 | { | |
155 | this->xpr_->link(linker); | |
156 | } | |
157 | ||
158 | void peek(xpression_peeker<char_type> &peeker) const | |
159 | { | |
160 | this->xpr_->peek(peeker); | |
161 | } | |
162 | ||
163 | // BUGBUG yuk! | |
164 | template<typename Top> | |
165 | bool push_match(match_state<BidiIter> &state) const | |
166 | { | |
167 | BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >)); | |
168 | return this->match(state); | |
169 | } | |
170 | ||
171 | private: | |
172 | matchable_ptr xpr_; | |
173 | }; | |
174 | ||
175 | }}} // namespace boost::xpressive::detail | |
176 | ||
177 | #endif |