1 /*=============================================================================
2     Copyright (c) 2002 2004 2006 Joel de Guzman
3     Copyright (c) 2004 Eric Niebler
4     http://spirit.sourceforge.net/
5 
6     Use, modification and distribution is subject to the Boost Software
7     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8     http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #if !defined(BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP)
11 #define BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
12 
13 #include <string>
14 #include <vector>
15 #include <boost/spirit/include/classic_parser.hpp>
16 #include "fwd.hpp"
17 #include "iterator.hpp"
18 #include "scoped.hpp"
19 #include "utils.hpp"
20 #include "values.hpp"
21 
22 namespace quickbook
23 {
24     namespace cl = boost::spirit::classic;
25 
26     // Match if quickbook version is within range
27     struct quickbook_range : cl::parser<quickbook_range>
28     {
quickbook_rangequickbook::quickbook_range29         explicit quickbook_range(unsigned lower_, unsigned upper_)
30             : lower(lower_), upper(upper_)
31         {
32         }
33 
34         bool in_range() const;
35 
36         template <typename ScannerT>
parsequickbook::quickbook_range37         typename cl::parser_result<quickbook_range, ScannerT>::type parse(
38             ScannerT const& scan) const
39         {
40             return in_range() ? scan.empty_match() : scan.no_match();
41         }
42 
43         unsigned lower, upper;
44     };
45 
qbk_ver(unsigned lower,unsigned upper=999u)46     inline quickbook_range qbk_ver(unsigned lower, unsigned upper = 999u)
47     {
48         return quickbook_range(lower, upper);
49     }
50 
51     // Match if in strict mode.
52     struct quickbook_strict : cl::parser<quickbook_strict>
53     {
quickbook_strictquickbook::quickbook_strict54         explicit quickbook_strict(
55             quickbook::state& state_, bool positive_ = true)
56             : state(state_), positive(positive_)
57         {
58         }
59 
60         bool is_strict_checking() const;
61 
62         template <typename ScannerT>
parsequickbook::quickbook_strict63         typename cl::parser_result<quickbook_range, ScannerT>::type parse(
64             ScannerT const& scan) const
65         {
66             return is_strict_checking() == positive ? scan.empty_match()
67                                                     : scan.no_match();
68         }
69 
operator ~quickbook::quickbook_strict70         quickbook_strict operator~() const
71         {
72             return quickbook_strict(state, !positive);
73         }
74 
75         quickbook::state& state;
76         bool positive;
77     };
78 
qbk_strict(quickbook::state & state,unsigned lower=999u)79     inline quickbook_strict qbk_strict(
80         quickbook::state& state, unsigned lower = 999u)
81     {
82         return quickbook_strict(state, lower);
83     }
84 
85     // Throws load_error
86     int load_snippets(
87         fs::path const& file,
88         std::vector<template_symbol>& storage,
89         std::string const& extension,
90         value::tag_type load_type);
91 
92     struct error_message_action
93     {
94         // Prints an error message to std::cerr
95 
error_message_actionquickbook::error_message_action96         explicit error_message_action(
97             quickbook::state& state_, std::string const& message_)
98             : state(state_), message(message_)
99         {
100         }
101 
102         void operator()(parse_iterator, parse_iterator) const;
103 
104         quickbook::state& state;
105         std::string message;
106     };
107 
108     struct error_action
109     {
110         // Prints an error message to std::cerr
111 
error_actionquickbook::error_action112         explicit error_action(quickbook::state& state_) : state(state_) {}
113 
114         void operator()(parse_iterator first, parse_iterator last) const;
115 
operator ()quickbook::error_action116         error_message_action operator()(std::string const& message)
117         {
118             return error_message_action(state, message);
119         }
120 
121         quickbook::state& state;
122     };
123 
124     struct element_action
125     {
element_actionquickbook::element_action126         explicit element_action(quickbook::state& state_) : state(state_) {}
127 
128         void operator()(parse_iterator, parse_iterator) const;
129 
130         quickbook::state& state;
131     };
132 
133     struct paragraph_action
134     {
135         //  implicit paragraphs
136         //  doesn't output the paragraph if it's only whitespace.
137 
paragraph_actionquickbook::paragraph_action138         explicit paragraph_action(quickbook::state& state_) : state(state_) {}
139 
140         void operator()() const;
operator ()quickbook::paragraph_action141         void operator()(parse_iterator, parse_iterator) const { (*this)(); }
142 
143         quickbook::state& state;
144     };
145 
146     struct explicit_list_action
147     {
148         //  implicit paragraphs
149         //  doesn't output the paragraph if it's only whitespace.
150 
explicit_list_actionquickbook::explicit_list_action151         explicit explicit_list_action(quickbook::state& state_) : state(state_)
152         {
153         }
154 
155         void operator()() const;
operator ()quickbook::explicit_list_action156         void operator()(parse_iterator, parse_iterator) const { (*this)(); }
157 
158         quickbook::state& state;
159     };
160 
161     struct phrase_end_action
162     {
phrase_end_actionquickbook::phrase_end_action163         explicit phrase_end_action(quickbook::state& state_) : state(state_) {}
164 
165         void operator()() const;
operator ()quickbook::phrase_end_action166         void operator()(parse_iterator, parse_iterator) const { (*this)(); }
167 
168         quickbook::state& state;
169     };
170 
171     struct simple_phrase_action
172     {
173         //  Handles simple text formats
174 
simple_phrase_actionquickbook::simple_phrase_action175         explicit simple_phrase_action(quickbook::state& state_) : state(state_)
176         {
177         }
178 
179         void operator()(char) const;
180 
181         quickbook::state& state;
182     };
183 
184     struct cond_phrase_push : scoped_action_base
185     {
cond_phrase_pushquickbook::cond_phrase_push186         cond_phrase_push(quickbook::state& x) : state(x) {}
187 
188         bool start();
189         void cleanup();
190 
191         quickbook::state& state;
192         bool saved_conditional;
193         std::vector<std::string> anchors;
194     };
195 
196     struct do_macro_action
197     {
198         // Handles macro substitutions
199 
do_macro_actionquickbook::do_macro_action200         explicit do_macro_action(quickbook::state& state_) : state(state_) {}
201 
202         void operator()(std::string const& str) const;
203         quickbook::state& state;
204     };
205 
206     struct raw_char_action
207     {
208         // Prints a space
209 
raw_char_actionquickbook::raw_char_action210         explicit raw_char_action(quickbook::state& state_) : state(state_) {}
211 
212         void operator()(char ch) const;
213         void operator()(parse_iterator first, parse_iterator last) const;
214 
215         quickbook::state& state;
216     };
217 
218     struct plain_char_action
219     {
220         // Prints a single plain char.
221         // Converts '<' to "&lt;"... etc See utils.hpp
222 
plain_char_actionquickbook::plain_char_action223         explicit plain_char_action(quickbook::state& state_) : state(state_) {}
224 
225         void operator()(char ch) const;
226         void operator()(parse_iterator first, parse_iterator last) const;
227 
228         quickbook::state& state;
229     };
230 
231     struct escape_unicode_action
232     {
escape_unicode_actionquickbook::escape_unicode_action233         explicit escape_unicode_action(quickbook::state& state_) : state(state_)
234         {
235         }
236 
237         void operator()(parse_iterator first, parse_iterator last) const;
238 
239         quickbook::state& state;
240     };
241 
242     struct break_action
243     {
break_actionquickbook::break_action244         explicit break_action(quickbook::state& state_) : state(state_) {}
245 
246         void operator()(parse_iterator f, parse_iterator) const;
247 
248         quickbook::state& state;
249     };
250 
251     struct element_id_warning_action
252     {
element_id_warning_actionquickbook::element_id_warning_action253         explicit element_id_warning_action(quickbook::state& state_)
254             : state(state_)
255         {
256         }
257 
258         void operator()(parse_iterator first, parse_iterator last) const;
259 
260         quickbook::state& state;
261     };
262 
263     // Returns the doc_type, or an empty string if there isn't one.
264     std::string pre(
265         quickbook::state& state,
266         parse_iterator pos,
267         value include_doc_id,
268         bool nested_file);
269     void post(quickbook::state& state, std::string const& doc_type);
270 
271     struct to_value_scoped_action : scoped_action_base
272     {
to_value_scoped_actionquickbook::to_value_scoped_action273         to_value_scoped_action(quickbook::state& state_) : state(state_) {}
274 
275         bool start(value::tag_type = value::default_tag);
276         void success(parse_iterator, parse_iterator);
277         void cleanup();
278 
279         quickbook::state& state;
280         std::vector<std::string> saved_anchors;
281         value::tag_type tag;
282     };
283 
284     // member_action
285     //
286     // Action for calling a member function taking two parse iterators.
287 
288     template <typename T> struct member_action
289     {
290         typedef void (T::*member_function)(parse_iterator, parse_iterator);
291 
292         T& l;
293         member_function mf;
294 
member_actionquickbook::member_action295         explicit member_action(T& l_, member_function mf_) : l(l_), mf(mf_) {}
296 
operator ()quickbook::member_action297         void operator()(parse_iterator first, parse_iterator last) const
298         {
299             (l.*mf)(first, last);
300         }
301     };
302 
303     // member_action1
304     //
305     // Action for calling a member function taking two parse iterators and a
306     // value.
307 
308     template <typename T, typename Arg1> struct member_action1
309     {
310         typedef void (T::*member_function)(
311             parse_iterator, parse_iterator, Arg1);
312 
313         T& l;
314         member_function mf;
315 
member_action1quickbook::member_action1316         explicit member_action1(T& l_, member_function mf_) : l(l_), mf(mf_) {}
317 
318         struct impl
319         {
320             member_action1 a;
321             Arg1 value;
322 
implquickbook::member_action1::impl323             explicit impl(member_action1& a_, Arg1 value_)
324                 : a(a_), value(value_)
325             {
326             }
327 
operator ()quickbook::member_action1::impl328             void operator()(parse_iterator first, parse_iterator last) const
329             {
330                 (a.l.*a.mf)(first, last, value);
331             }
332         };
333 
operator ()quickbook::member_action1334         impl operator()(Arg1 a1) { return impl(*this, a1); }
335     };
336 
337     // member_action_value
338     //
339     // Action for calling a unary member function.
340 
341     template <typename T, typename Value> struct member_action_value
342     {
343         typedef void (T::*member_function)(Value);
344 
345         T& l;
346         member_function mf;
347 
member_action_valuequickbook::member_action_value348         explicit member_action_value(T& l_, member_function mf_)
349             : l(l_), mf(mf_)
350         {
351         }
352 
operator ()quickbook::member_action_value353         void operator()(Value v) const { (l.*mf)(v); }
354     };
355 
356     // member_action_value
357     //
358     // Action for calling a unary member function with a fixed value.
359 
360     template <typename T, typename Value> struct member_action_fixed_value
361     {
362         typedef void (T::*member_function)(Value);
363 
364         T& l;
365         member_function mf;
366         Value v;
367 
member_action_fixed_valuequickbook::member_action_fixed_value368         explicit member_action_fixed_value(T& l_, member_function mf_, Value v_)
369             : l(l_), mf(mf_), v(v_)
370         {
371         }
372 
operator ()quickbook::member_action_fixed_value373         void operator()() const { (l.*mf)(v); }
374 
operator ()quickbook::member_action_fixed_value375         void operator()(parse_iterator, parse_iterator) const { (l.*mf)(v); }
376     };
377 }
378 
379 #endif // BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
380