]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/quickbook/src/parsers.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / tools / quickbook / src / parsers.hpp
1 /*=============================================================================
2 Copyright (c) 2010-2011 Daniel James
3 Copyright (c) 2003 Martin Wille
4 http://spirit.sourceforge.net/
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9
10 // Some custom parsers for use in quickbook.
11
12 #ifndef BOOST_QUICKBOOK_PARSERS_HPP
13 #define BOOST_QUICKBOOK_PARSERS_HPP
14
15 #include <boost/spirit/include/classic_core.hpp>
16 #include <boost/spirit/include/classic_nil.hpp>
17 #include <boost/spirit/include/phoenix1_primitives.hpp>
18 #include <boost/spirit/include/phoenix1_tuples.hpp>
19 #include <boost/spirit/include/phoenix1_binders.hpp>
20 #include "fwd.hpp"
21 #include "iterator.hpp"
22
23 namespace quickbook {
24 namespace cl = boost::spirit::classic;
25
26 ///////////////////////////////////////////////////////////////////////////
27 //
28 // scoped_parser<Impl>
29 //
30 // Impl is a struct with the methods:
31 //
32 // void start();
33 // void success(parse_iterator, parse_iterator);
34 // void failure();
35 // void cleanup();
36 //
37 ///////////////////////////////////////////////////////////////////////////
38
39 template <typename Impl, typename Arguments, typename ParserT>
40 struct scoped_parser_impl
41 : public cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > >
42 {
43 typedef scoped_parser_impl<Impl, Arguments, ParserT> self_t;
44 typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > > base_t;
45
46 template <typename ScannerT>
47 struct result { typedef cl::match<> type; };
48
49 scoped_parser_impl(
50 Impl const& impl,
51 Arguments const& arguments,
52 ParserT const &p)
53 : base_t(p)
54 , impl_(impl)
55 , arguments_(arguments)
56 {}
57
58 struct scoped
59 {
60 explicit scoped(Impl const& impl)
61 : impl_(impl)
62 , in_progress_(false)
63 {}
64
65 typedef phoenix::tuple_index<0> t0;
66 typedef phoenix::tuple_index<1> t1;
67
68 bool start(phoenix::tuple<> const&)
69 {
70 in_progress_ = impl_.start();
71 return in_progress_;
72 }
73
74 template <typename Arg1>
75 bool start(phoenix::tuple<Arg1> const& x)
76 {
77 in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])();
78 return in_progress_;
79 }
80
81 template <typename Arg1, typename Arg2>
82 bool start(phoenix::tuple<Arg1, Arg2> const& x)
83 {
84 in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()], x[t1()])();
85 return in_progress_;
86 }
87
88 void success(parse_iterator f, parse_iterator l)
89 {
90 in_progress_ = false;
91 impl_.success(f, l);
92 }
93
94 void failure()
95 {
96 in_progress_ = false;
97 impl_.failure();
98 }
99
100 ~scoped()
101 {
102 if (in_progress_) impl_.failure();
103 impl_.cleanup();
104 }
105
106 Impl impl_;
107 bool in_progress_;
108 };
109
110 template <typename ScannerT>
111 typename result<ScannerT>::type parse(ScannerT const &scan) const
112 {
113 typedef typename ScannerT::iterator_t iterator_t;
114 iterator_t save = scan.first;
115
116 scoped scope(impl_);
117 if (!scope.start(arguments_))
118 return scan.no_match();
119
120 typename cl::parser_result<ParserT, ScannerT>::type r
121 = this->subject().parse(scan);
122
123 bool success = scope.impl_.result(r, scan);
124
125 if (success) {
126 scope.success(save, scan.first);
127
128 if (r) {
129 return scan.create_match(r.length(), cl::nil_t(), save, scan.first);
130 }
131 else {
132 return scan.create_match(scan.first.base() - save.base(), cl::nil_t(), save, scan.first);
133 }
134 }
135 else {
136 scope.failure();
137 return scan.no_match();
138 }
139 }
140
141 Impl impl_;
142 Arguments arguments_;
143 };
144
145 template <typename Impl, typename Arguments>
146 struct scoped_parser_gen
147 {
148 explicit scoped_parser_gen(Impl impl, Arguments const& arguments)
149 : impl_(impl), arguments_(arguments) {}
150
151 template<typename ParserT>
152 scoped_parser_impl
153 <
154 Impl,
155 Arguments,
156 typename cl::as_parser<ParserT>::type
157 >
158 operator[](ParserT const &p) const
159 {
160 typedef cl::as_parser<ParserT> as_parser_t;
161 typedef typename as_parser_t::type parser_t;
162
163 return scoped_parser_impl<Impl, Arguments, parser_t>
164 (impl_, arguments_, p);
165 }
166
167 Impl impl_;
168 Arguments arguments_;
169 };
170
171 template <typename Impl>
172 struct scoped_parser
173 {
174 scoped_parser(Impl const& impl)
175 : impl_(impl) {}
176
177 scoped_parser_gen<Impl, phoenix::tuple<> >
178 operator()() const
179 {
180 typedef phoenix::tuple<> tuple;
181 return scoped_parser_gen<Impl, tuple>(impl_, tuple());
182 }
183
184 template <typename Arg1>
185 scoped_parser_gen<Impl, phoenix::tuple<Arg1> >
186 operator()(Arg1 x1) const
187 {
188 typedef phoenix::tuple<Arg1> tuple;
189 return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1));
190 }
191
192 template <typename Arg1, typename Arg2>
193 scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> >
194 operator()(Arg1 x1, Arg2 x2) const
195 {
196 typedef phoenix::tuple<Arg1, Arg2> tuple;
197 return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2));
198 }
199
200 Impl impl_;
201
202 private:
203 scoped_parser& operator=(scoped_parser const&);
204 };
205
206 ///////////////////////////////////////////////////////////////////////////
207 //
208 // Lookback parser
209 //
210 // usage: lookback[body]
211 //
212 // Requires that iterator has typedef 'lookback_range' and function
213 // 'lookback' returning a 'lookback_range'.
214 //
215 ///////////////////////////////////////////////////////////////////////////
216
217 template <typename ParserT>
218 struct lookback_parser
219 : public cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > >
220 {
221 typedef lookback_parser<ParserT> self_t;
222 typedef cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > > base_t;
223
224 template <typename ScannerT>
225 struct result
226 {
227 typedef typename cl::parser_result<ParserT, ScannerT>::type type;
228 };
229
230 lookback_parser(ParserT const& p)
231 : base_t(p)
232 {}
233
234 template <typename ScannerT>
235 typename result<ScannerT>::type parse(ScannerT const &scan) const
236 {
237 typedef typename ScannerT::iterator_t::lookback_range::iterator iterator_t;
238 typedef cl::scanner<iterator_t, typename ScannerT::policies_t> scanner_t;
239
240 iterator_t begin = scan.first.lookback().begin();
241 scanner_t lookback_scan(begin, scan.first.lookback().end(), scan);
242
243 if (this->subject().parse(lookback_scan))
244 return scan.empty_match();
245 else
246 return scan.no_match();
247 }
248 };
249
250 struct lookback_gen
251 {
252 template <typename ParserT>
253 lookback_parser<ParserT> operator[](ParserT const& p) const
254 {
255 return lookback_parser<ParserT>(p);
256 }
257 };
258
259 lookback_gen const lookback = lookback_gen();
260
261 ///////////////////////////////////////////////////////////////////////////
262 //
263 // UTF-8 code point
264 //
265 // Very crude, it doesn't check that the code point is in any way valid.
266 // Just looks for the beginning of the next character. This is just for
267 // implementing some crude fixes, rather than full unicode support. I'm
268 // sure experts would be appalled.
269 //
270 ///////////////////////////////////////////////////////////////////////////
271
272 struct u8_codepoint_parser : public cl::parser<u8_codepoint_parser>
273 {
274 typedef u8_codepoint_parser self_t;
275
276 template <typename Scanner>
277 struct result
278 {
279 typedef cl::match<> type;
280 };
281
282 template <typename Scanner>
283 typename result<Scanner>::type parse(Scanner const& scan) const
284 {
285 typedef typename Scanner::iterator_t iterator_t;
286
287 if (scan.at_end()) return scan.no_match();
288
289 iterator_t save(scan.first);
290
291 do {
292 ++scan.first;
293 } while (!scan.at_end() &&
294 ((unsigned char) *scan.first & 0xc0) == 0x80);
295
296 return scan.create_match(scan.first.base() - save.base(),
297 cl::nil_t(), save, scan.first);
298 }
299 };
300
301 u8_codepoint_parser const u8_codepoint_p = u8_codepoint_parser();
302 }
303
304 #endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP