• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_binders.hpp>
18 #include <boost/spirit/include/phoenix1_primitives.hpp>
19 #include <boost/spirit/include/phoenix1_tuples.hpp>
20 #include "fwd.hpp"
21 #include "iterator.hpp"
22 
23 namespace quickbook
24 {
25     namespace cl = boost::spirit::classic;
26 
27     ///////////////////////////////////////////////////////////////////////////
28     //
29     // scoped_parser<Impl>
30     //
31     // Impl is a struct with the methods:
32     //
33     // void start();
34     // void success(parse_iterator, parse_iterator);
35     // void failure();
36     // void cleanup();
37     //
38     ///////////////////////////////////////////////////////////////////////////
39 
40     template <typename Impl, typename Arguments, typename ParserT>
41     struct scoped_parser_impl
42         : public cl::unary<
43               ParserT,
44               cl::parser<scoped_parser_impl<Impl, Arguments, ParserT> > >
45     {
46         typedef scoped_parser_impl<Impl, Arguments, ParserT> self_t;
47         typedef cl::unary<
48             ParserT,
49             cl::parser<scoped_parser_impl<Impl, Arguments, ParserT> > >
50             base_t;
51 
52         template <typename ScannerT> struct result
53         {
54             typedef cl::match<> type;
55         };
56 
scoped_parser_implquickbook::scoped_parser_impl57         scoped_parser_impl(
58             Impl const& impl, Arguments const& arguments, ParserT const& p)
59             : base_t(p), impl_(impl), arguments_(arguments)
60         {
61         }
62 
63         struct scoped
64         {
scopedquickbook::scoped_parser_impl::scoped65             explicit scoped(Impl const& impl) : impl_(impl), in_progress_(false)
66             {
67             }
68 
69             typedef phoenix::tuple_index<0> t0;
70             typedef phoenix::tuple_index<1> t1;
71 
startquickbook::scoped_parser_impl::scoped72             bool start(phoenix::tuple<> const&)
73             {
74                 in_progress_ = impl_.start();
75                 return in_progress_;
76             }
77 
startquickbook::scoped_parser_impl::scoped78             template <typename Arg1> bool start(phoenix::tuple<Arg1> const& x)
79             {
80                 in_progress_ =
81                     phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])();
82                 return in_progress_;
83             }
84 
85             template <typename Arg1, typename Arg2>
startquickbook::scoped_parser_impl::scoped86             bool start(phoenix::tuple<Arg1, Arg2> const& x)
87             {
88                 in_progress_ = phoenix::bind(&Impl::start)(
89                     phoenix::var(impl_), x[t0()], x[t1()])();
90                 return in_progress_;
91             }
92 
successquickbook::scoped_parser_impl::scoped93             void success(parse_iterator f, parse_iterator l)
94             {
95                 in_progress_ = false;
96                 impl_.success(f, l);
97             }
98 
failurequickbook::scoped_parser_impl::scoped99             void failure()
100             {
101                 in_progress_ = false;
102                 impl_.failure();
103             }
104 
~scopedquickbook::scoped_parser_impl::scoped105             ~scoped()
106             {
107                 if (in_progress_) impl_.failure();
108                 impl_.cleanup();
109             }
110 
111             Impl impl_;
112             bool in_progress_;
113         };
114 
115         template <typename ScannerT>
parsequickbook::scoped_parser_impl116         typename result<ScannerT>::type parse(ScannerT const& scan) const
117         {
118             typedef typename ScannerT::iterator_t iterator_t;
119             iterator_t save = scan.first;
120 
121             scoped scope(impl_);
122             if (!scope.start(arguments_)) return scan.no_match();
123 
124             typename cl::parser_result<ParserT, ScannerT>::type r =
125                 this->subject().parse(scan);
126 
127             bool success = scope.impl_.result(r, scan);
128 
129             if (success) {
130                 scope.success(save, scan.first);
131 
132                 if (r) {
133                     return scan.create_match(
134                         r.length(), cl::nil_t(), save, scan.first);
135                 }
136                 else {
137                     return scan.create_match(
138                         scan.first.base() - save.base(), cl::nil_t(), save,
139                         scan.first);
140                 }
141             }
142             else {
143                 scope.failure();
144                 return scan.no_match();
145             }
146         }
147 
148         Impl impl_;
149         Arguments arguments_;
150     };
151 
152     template <typename Impl, typename Arguments> struct scoped_parser_gen
153     {
scoped_parser_genquickbook::scoped_parser_gen154         explicit scoped_parser_gen(Impl impl, Arguments const& arguments)
155             : impl_(impl), arguments_(arguments)
156         {
157         }
158 
159         template <typename ParserT>
160         scoped_parser_impl<
161             Impl,
162             Arguments,
163             typename cl::as_parser<ParserT>::type>
operator []quickbook::scoped_parser_gen164         operator[](ParserT const& p) const
165         {
166             typedef cl::as_parser<ParserT> as_parser_t;
167             typedef typename as_parser_t::type parser_t;
168 
169             return scoped_parser_impl<Impl, Arguments, parser_t>(
170                 impl_, arguments_, p);
171         }
172 
173         Impl impl_;
174         Arguments arguments_;
175     };
176 
177     template <typename Impl> struct scoped_parser
178     {
scoped_parserquickbook::scoped_parser179         scoped_parser(Impl const& impl) : impl_(impl) {}
180 
operator ()quickbook::scoped_parser181         scoped_parser_gen<Impl, phoenix::tuple<> > operator()() const
182         {
183             typedef phoenix::tuple<> tuple;
184             return scoped_parser_gen<Impl, tuple>(impl_, tuple());
185         }
186 
187         template <typename Arg1>
operator ()quickbook::scoped_parser188         scoped_parser_gen<Impl, phoenix::tuple<Arg1> > operator()(Arg1 x1) const
189         {
190             typedef phoenix::tuple<Arg1> tuple;
191             return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1));
192         }
193 
194         template <typename Arg1, typename Arg2>
operator ()quickbook::scoped_parser195         scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> > operator()(
196             Arg1 x1, Arg2 x2) const
197         {
198             typedef phoenix::tuple<Arg1, Arg2> tuple;
199             return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2));
200         }
201 
202         Impl impl_;
203 
204       private:
205         scoped_parser& operator=(scoped_parser const&);
206     };
207 
208     ///////////////////////////////////////////////////////////////////////////
209     //
210     // Lookback parser
211     //
212     // usage: lookback[body]
213     //
214     // Requires that iterator has typedef 'lookback_range' and function
215     // 'lookback' returning a 'lookback_range'.
216     //
217     ///////////////////////////////////////////////////////////////////////////
218 
219     template <typename ParserT>
220     struct lookback_parser
221         : public cl::unary<ParserT, cl::parser<lookback_parser<ParserT> > >
222     {
223         typedef lookback_parser<ParserT> self_t;
224         typedef cl::unary<ParserT, cl::parser<lookback_parser<ParserT> > >
225             base_t;
226 
227         template <typename ScannerT> struct result
228         {
229             typedef typename cl::parser_result<ParserT, ScannerT>::type type;
230         };
231 
lookback_parserquickbook::lookback_parser232         lookback_parser(ParserT const& p) : base_t(p) {}
233 
234         template <typename ScannerT>
parsequickbook::lookback_parser235         typename result<ScannerT>::type parse(ScannerT const& scan) const
236         {
237             typedef typename ScannerT::iterator_t::lookback_range::iterator
238                 iterator_t;
239             typedef cl::scanner<iterator_t, typename ScannerT::policies_t>
240                 scanner_t;
241 
242             iterator_t begin = scan.first.lookback().begin();
243             scanner_t lookback_scan(begin, scan.first.lookback().end(), scan);
244 
245             if (this->subject().parse(lookback_scan))
246                 return scan.empty_match();
247             else
248                 return scan.no_match();
249         }
250     };
251 
252     struct lookback_gen
253     {
254         template <typename ParserT>
operator []quickbook::lookback_gen255         lookback_parser<ParserT> operator[](ParserT const& p) const
256         {
257             return lookback_parser<ParserT>(p);
258         }
259     };
260 
261     lookback_gen const lookback = lookback_gen();
262 
263     ///////////////////////////////////////////////////////////////////////////
264     //
265     // UTF-8 code point
266     //
267     // Very crude, it doesn't check that the code point is in any way valid.
268     // Just looks for the beginning of the next character. This is just for
269     // implementing some crude fixes, rather than full unicode support. I'm
270     // sure experts would be appalled.
271     //
272     ///////////////////////////////////////////////////////////////////////////
273 
274     struct u8_codepoint_parser : public cl::parser<u8_codepoint_parser>
275     {
276         typedef u8_codepoint_parser self_t;
277 
278         template <typename Scanner> struct result
279         {
280             typedef cl::match<> type;
281         };
282 
283         template <typename Scanner>
parsequickbook::u8_codepoint_parser284         typename result<Scanner>::type parse(Scanner const& scan) const
285         {
286             typedef typename Scanner::iterator_t iterator_t;
287 
288             if (scan.at_end()) return scan.no_match();
289 
290             iterator_t save(scan.first);
291 
292             do {
293                 ++scan.first;
294             } while (!scan.at_end() &&
295                      ((unsigned char)*scan.first & 0xc0) == 0x80);
296 
297             return scan.create_match(
298                 scan.first.base() - save.base(), cl::nil_t(), save, scan.first);
299         }
300     };
301 
302     u8_codepoint_parser const u8_codepoint_p = u8_codepoint_parser();
303 }
304 
305 #endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
306