]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/dynamic/switch.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / dynamic / switch.hpp
CommitLineData
7c673cae
FG
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///////////////////////////////////////////////////////////////////////////////
41BOOST_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///////////////////////////////////////////////////////////////////////////////
51namespace boost { namespace spirit {
52
53BOOST_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///////////////////////////////////////////////////////////////////////////////
89template <typename CaseT, typename CondT = impl::get_next_token_cond>
90struct 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///////////////////////////////////////////////////////////////////////////////
123template <typename CondT>
124struct 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///////////////////////////////////////////////////////////////////////////////
141template <int N, typename ParserT, bool IsDefault>
142struct 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///////////////////////////////////////////////////////////////////////////////
202struct 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
225switch_parser_gen const switch_p = switch_parser_gen();
226
227///////////////////////////////////////////////////////////////////////////////
228template <int N, typename ParserT>
229inline case_parser<N, ParserT, false>
230case_p(parser<ParserT> const &p)
231{
232 return case_parser<N, ParserT, false>(p);
233}
234
235///////////////////////////////////////////////////////////////////////////////
236struct 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
252default_parser_gen const default_p = default_parser_gen();
253
254///////////////////////////////////////////////////////////////////////////////
255BOOST_SPIRIT_CLASSIC_NAMESPACE_END
256
257}} // namespace BOOST_SPIRIT_CLASSIC_NS
258
259#endif // BOOST_SPIRIT_SWITCH_HPP