]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/classic/dynamic/switch.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / classic / dynamic / switch.hpp
1 /*=============================================================================
2 Copyright (c) 2003 Hartmut Kaiser
3 http://spirit.sourceforge.net/
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #ifndef BOOST_SPIRIT_SWITCH_HPP
9 #define BOOST_SPIRIT_SWITCH_HPP
10
11 ///////////////////////////////////////////////////////////////////////////////
12 //
13 // The default_p parser generator template uses the following magic number
14 // as the corresponding case label value inside the generated switch()
15 // statements. If this number conflicts with your code, please pick a
16 // different one.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19 #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
20 #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
21 #endif
22
23 ///////////////////////////////////////////////////////////////////////////////
24 //
25 // Spirit predefined maximum number of possible case_p/default_p case branch
26 // parsers.
27 //
28 ///////////////////////////////////////////////////////////////////////////////
29 #if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
30 #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
31 #endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
32
33 ///////////////////////////////////////////////////////////////////////////////
34 #include <boost/static_assert.hpp>
35
36 ///////////////////////////////////////////////////////////////////////////////
37 //
38 // Ensure BOOST_SPIRIT_SELECT_LIMIT > 0
39 //
40 ///////////////////////////////////////////////////////////////////////////////
41 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
42
43 #include <boost/spirit/home/classic/namespace.hpp>
44 #include <boost/spirit/home/classic/core/config.hpp>
45 #include <boost/type_traits/is_same.hpp>
46 #include <boost/spirit/home/classic/core/parser.hpp>
47 #include <boost/spirit/home/classic/core/composite/epsilon.hpp>
48 #include <boost/spirit/home/classic/dynamic/impl/switch.ipp>
49
50 ///////////////////////////////////////////////////////////////////////////////
51 namespace boost { namespace spirit {
52
53 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
54
55 ///////////////////////////////////////////////////////////////////////////////
56 //
57 // The switch_parser allows to build switch like parsing constructs, which
58 // will have much better perfomance as comparable straight solutions.
59 //
60 // Input stream driven syntax:
61 //
62 // switch_p
63 // [
64 // case_p<'a'>
65 // (...parser to use, if the next character is 'a'...),
66 // case_p<'b'>
67 // (...parser to use, if the next character is 'b'...),
68 // default_p
69 // (...parser to use, if nothing was matched before...)
70 // ]
71 //
72 // General syntax:
73 //
74 // switch_p(...lazy expression returning the switch condition value...)
75 // [
76 // case_p<1>
77 // (...parser to use, if the switch condition value is 1...),
78 // case_p<2>
79 // (...parser to use, if the switch condition value is 2...),
80 // default_p
81 // (...parser to use, if nothing was matched before...)
82 // ]
83 //
84 // The maximum number of possible case_p branches is defined by the p constant
85 // BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
86 // defined).
87 //
88 ///////////////////////////////////////////////////////////////////////////////
89 template <typename CaseT, typename CondT = impl::get_next_token_cond>
90 struct switch_parser
91 : public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
92 {
93 typedef switch_parser<CaseT, CondT> self_t;
94 typedef unary_parser_category parser_category_t;
95 typedef unary<CaseT, parser<self_t> > base_t;
96
97 switch_parser(CaseT const &case_)
98 : base_t(case_), cond(CondT())
99 {}
100
101 switch_parser(CaseT const &case_, CondT const &cond_)
102 : base_t(case_), cond(cond_)
103 {}
104
105 template <typename ScannerT>
106 struct result
107 {
108 typedef typename match_result<ScannerT, nil_t>::type type;
109 };
110
111 template <typename ScannerT>
112 typename parser_result<self_t, ScannerT>::type
113 parse(ScannerT const& scan) const
114 {
115 return this->subject().parse(scan,
116 impl::make_cond_functor<CondT>::do_(cond));
117 }
118
119 CondT cond;
120 };
121
122 ///////////////////////////////////////////////////////////////////////////////
123 template <typename CondT>
124 struct switch_cond_parser
125 {
126 switch_cond_parser(CondT const &cond_)
127 : cond(cond_)
128 {}
129
130 template <typename ParserT>
131 switch_parser<ParserT, CondT>
132 operator[](parser<ParserT> const &p) const
133 {
134 return switch_parser<ParserT, CondT>(p.derived(), cond);
135 }
136
137 CondT const &cond;
138 };
139
140 ///////////////////////////////////////////////////////////////////////////////
141 template <int N, typename ParserT, bool IsDefault>
142 struct case_parser
143 : public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
144 {
145 typedef case_parser<N, ParserT, IsDefault> self_t;
146 typedef unary_parser_category parser_category_t;
147 typedef unary<ParserT, parser<self_t> > base_t;
148
149 typedef typename base_t::subject_t self_subject_t;
150
151 BOOST_STATIC_CONSTANT(int, value = N);
152 BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
153 BOOST_STATIC_CONSTANT(bool, is_simple = true);
154 BOOST_STATIC_CONSTANT(bool, is_epsilon = (
155 is_default && boost::is_same<self_subject_t, epsilon_parser>::value
156 ));
157
158 case_parser(parser<ParserT> const &p)
159 : base_t(p.derived())
160 {}
161
162 template <typename ScannerT>
163 struct result
164 {
165 typedef typename match_result<ScannerT, nil_t>::type type;
166 };
167
168 template <typename ScannerT, typename CondT>
169 typename parser_result<self_t, ScannerT>::type
170 parse(ScannerT const& scan, CondT const &cond) const
171 {
172 typedef impl::default_case<self_t> default_t;
173
174 if (!scan.at_end()) {
175 typedef impl::default_delegate_parse<
176 value, is_default, default_t::value> default_parse_t;
177
178 typename ScannerT::iterator_t const save(scan.first);
179 return default_parse_t::parse(cond(scan), *this,
180 *this, scan, save);
181 }
182
183 return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
184 }
185
186 template <int N1, typename ParserT1, bool IsDefault1>
187 impl::compound_case_parser<
188 self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
189 >
190 operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
191 {
192 // If the following compile time assertion fires, you've probably used
193 // more than one default_p case inside the switch_p parser construct.
194 BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
195
196 typedef case_parser<N1, ParserT1, IsDefault1> right_t;
197 return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
198 }
199 };
200
201 ///////////////////////////////////////////////////////////////////////////////
202 struct switch_parser_gen {
203
204 // This generates a switch parser, which is driven by the condition value
205 // returned by the lazy parameter expression 'cond'. This may be a parser,
206 // which result is used or a phoenix actor, which will be dereferenced to
207 // obtain the switch condition value.
208 template <typename CondT>
209 switch_cond_parser<CondT>
210 operator()(CondT const &cond) const
211 {
212 return switch_cond_parser<CondT>(cond);
213 }
214
215 // This generates a switch parser, which is driven by the next character/token
216 // found in the input stream.
217 template <typename CaseT>
218 switch_parser<CaseT>
219 operator[](parser<CaseT> const &p) const
220 {
221 return switch_parser<CaseT>(p.derived());
222 }
223 };
224
225 switch_parser_gen const switch_p = switch_parser_gen();
226
227 ///////////////////////////////////////////////////////////////////////////////
228 template <int N, typename ParserT>
229 inline case_parser<N, ParserT, false>
230 case_p(parser<ParserT> const &p)
231 {
232 return case_parser<N, ParserT, false>(p);
233 }
234
235 ///////////////////////////////////////////////////////////////////////////////
236 struct default_parser_gen
237 : public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
238 {
239 default_parser_gen()
240 : case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
241 (epsilon_p)
242 {}
243
244 template <typename ParserT>
245 case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
246 operator()(parser<ParserT> const &p) const
247 {
248 return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
249 }
250 };
251
252 default_parser_gen const default_p = default_parser_gen();
253
254 ///////////////////////////////////////////////////////////////////////////////
255 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
256
257 }} // namespace BOOST_SPIRIT_CLASSIC_NS
258
259 #endif // BOOST_SPIRIT_SWITCH_HPP