1 | /*============================================================================= |
---|
2 | Copyright (c) 2002 2004 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_PHRASE_HPP) |
---|
11 | #define BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP |
---|
12 | |
---|
13 | #include "detail/utils.hpp" |
---|
14 | #include <boost/spirit/core.hpp> |
---|
15 | #include <boost/spirit/utility/confix.hpp> |
---|
16 | #include <boost/spirit/utility/chset.hpp> |
---|
17 | #include <boost/spirit/actor/assign_actor.hpp> |
---|
18 | #include <boost/spirit/dynamic/if.hpp> |
---|
19 | |
---|
20 | namespace quickbook |
---|
21 | { |
---|
22 | using namespace boost::spirit; |
---|
23 | |
---|
24 | template <typename Rule, typename Action> |
---|
25 | inline void |
---|
26 | simple_markup(Rule& simple, char mark, Action const& action, Rule const& eol) |
---|
27 | { |
---|
28 | simple = |
---|
29 | mark >> |
---|
30 | ( |
---|
31 | ( |
---|
32 | graph_p // A single char. e.g. *c* |
---|
33 | >> eps_p(mark |
---|
34 | >> (space_p | punct_p)) |
---|
35 | ) |
---|
36 | | ( graph_p >> // graph_p must follow mark |
---|
37 | *(anychar_p - |
---|
38 | ( eol // Make sure that we don't go |
---|
39 | | (graph_p >> mark) // past a single line |
---|
40 | ) |
---|
41 | ) >> graph_p // graph_p must precede mark |
---|
42 | >> eps_p(mark |
---|
43 | >> (space_p | punct_p)) // space_p or punct_p must |
---|
44 | ) // follow mark |
---|
45 | ) [action] |
---|
46 | >> mark |
---|
47 | ; |
---|
48 | } |
---|
49 | |
---|
50 | template <typename Actions> |
---|
51 | struct phrase_grammar : grammar<phrase_grammar<Actions> > |
---|
52 | { |
---|
53 | phrase_grammar(Actions& actions, bool& is_not_preformatted) |
---|
54 | : is_not_preformatted(is_not_preformatted), actions(actions) {} |
---|
55 | |
---|
56 | template <typename Scanner> |
---|
57 | struct definition |
---|
58 | { |
---|
59 | definition(phrase_grammar const& self) |
---|
60 | { |
---|
61 | using detail::var; |
---|
62 | Actions& actions = self.actions; |
---|
63 | |
---|
64 | space = |
---|
65 | *(space_p | comment) |
---|
66 | ; |
---|
67 | |
---|
68 | blank = |
---|
69 | *(blank_p | comment) |
---|
70 | ; |
---|
71 | |
---|
72 | eol = blank >> eol_p |
---|
73 | ; |
---|
74 | |
---|
75 | close_bracket = |
---|
76 | ']' | |
---|
77 | if_p(var(self.is_not_preformatted)) |
---|
78 | [ |
---|
79 | eol_p >> eol_p // Make sure that we don't go |
---|
80 | ] // past a single block, except |
---|
81 | ; // when preformatted. |
---|
82 | |
---|
83 | hard_space = |
---|
84 | (eps_p - (alnum_p | '_')) >> space // must not be followed by |
---|
85 | ; // alpha-numeric or underscore |
---|
86 | |
---|
87 | comment = |
---|
88 | "[/" >> *(anychar_p - ']') >> ']' |
---|
89 | ; |
---|
90 | |
---|
91 | common = |
---|
92 | actions.macro [actions.do_macro] |
---|
93 | | phrase_markup |
---|
94 | | code_block |
---|
95 | | inline_code |
---|
96 | | simple_format |
---|
97 | | escape |
---|
98 | | comment |
---|
99 | ; |
---|
100 | |
---|
101 | inline_code = |
---|
102 | '`' >> |
---|
103 | ( |
---|
104 | *(anychar_p - |
---|
105 | ( '`' |
---|
106 | | (eol >> eol) // Make sure that we don't go |
---|
107 | ) // past a single block |
---|
108 | ) >> eps_p('`') |
---|
109 | ) [actions.inline_code] |
---|
110 | >> '`' |
---|
111 | ; |
---|
112 | |
---|
113 | code_block = |
---|
114 | "``" >> |
---|
115 | ( |
---|
116 | *(anychar_p - "``") |
---|
117 | >> eps_p("``") |
---|
118 | ) [actions.code_block] |
---|
119 | >> "``" |
---|
120 | ; |
---|
121 | |
---|
122 | simple_format = |
---|
123 | simple_bold |
---|
124 | | simple_italic |
---|
125 | | simple_underline |
---|
126 | | simple_teletype |
---|
127 | ; |
---|
128 | |
---|
129 | simple_markup(simple_bold, |
---|
130 | '*', actions.simple_bold, eol); |
---|
131 | simple_markup(simple_italic, |
---|
132 | '/', actions.simple_italic, eol); |
---|
133 | simple_markup(simple_underline, |
---|
134 | '_', actions.simple_underline, eol); |
---|
135 | simple_markup(simple_teletype, |
---|
136 | '=', actions.simple_teletype, eol); |
---|
137 | |
---|
138 | phrase = |
---|
139 | *( common |
---|
140 | | comment |
---|
141 | | (anychar_p - |
---|
142 | close_bracket) [actions.plain_char] |
---|
143 | ) |
---|
144 | ; |
---|
145 | |
---|
146 | phrase_markup = |
---|
147 | '[' |
---|
148 | >> ( image |
---|
149 | | url |
---|
150 | | link |
---|
151 | | anchor |
---|
152 | | source_mode |
---|
153 | | funcref |
---|
154 | | classref |
---|
155 | | memberref |
---|
156 | | enumref |
---|
157 | | headerref |
---|
158 | | bold |
---|
159 | | italic |
---|
160 | | underline |
---|
161 | | teletype |
---|
162 | | strikethrough |
---|
163 | | quote |
---|
164 | | replaceable |
---|
165 | | footnote |
---|
166 | | str_p("br") [actions.break_] |
---|
167 | ) |
---|
168 | >> ']' |
---|
169 | ; |
---|
170 | |
---|
171 | escape = |
---|
172 | str_p("\\n") [actions.break_] |
---|
173 | | '\\' >> punct_p [actions.raw_char] |
---|
174 | | ( |
---|
175 | ("'''" >> !eol) [actions.escape_pre] |
---|
176 | >> *(anychar_p - "'''") [actions.raw_char] |
---|
177 | >> str_p("'''") [actions.escape_post] |
---|
178 | ) |
---|
179 | ; |
---|
180 | |
---|
181 | image = |
---|
182 | '$' >> blank |
---|
183 | >> (*(anychar_p - |
---|
184 | close_bracket)) [actions.image] |
---|
185 | ; |
---|
186 | |
---|
187 | url = |
---|
188 | '@' |
---|
189 | >> (*(anychar_p - |
---|
190 | (']' | hard_space))) [actions.url_pre] |
---|
191 | >> ( eps_p(']') |
---|
192 | | (hard_space >> phrase) |
---|
193 | ) [actions.url_post] |
---|
194 | ; |
---|
195 | |
---|
196 | link = |
---|
197 | "link" >> hard_space |
---|
198 | >> (*(anychar_p - |
---|
199 | (']' | hard_space))) [actions.link_pre] |
---|
200 | >> ( eps_p(']') |
---|
201 | | (hard_space >> phrase) |
---|
202 | ) [actions.link_post] |
---|
203 | ; |
---|
204 | |
---|
205 | anchor = |
---|
206 | '#' |
---|
207 | >> blank |
---|
208 | >> ( *(anychar_p - |
---|
209 | close_bracket) |
---|
210 | ) [actions.anchor] |
---|
211 | ; |
---|
212 | |
---|
213 | funcref = |
---|
214 | "funcref" >> hard_space |
---|
215 | >> (*(anychar_p - |
---|
216 | (']' | hard_space))) [actions.funcref_pre] |
---|
217 | >> ( eps_p(']') |
---|
218 | | (hard_space >> phrase) |
---|
219 | ) [actions.funcref_post] |
---|
220 | ; |
---|
221 | |
---|
222 | classref = |
---|
223 | "classref" >> hard_space |
---|
224 | >> (*(anychar_p - |
---|
225 | (']' | hard_space))) [actions.classref_pre] |
---|
226 | >> ( eps_p(']') |
---|
227 | | (hard_space >> phrase) |
---|
228 | ) [actions.classref_post] |
---|
229 | ; |
---|
230 | |
---|
231 | memberref = |
---|
232 | "memberref" >> hard_space |
---|
233 | >> (*(anychar_p - |
---|
234 | (']' | hard_space))) [actions.memberref_pre] |
---|
235 | >> ( eps_p(']') |
---|
236 | | (hard_space >> phrase) |
---|
237 | ) [actions.memberref_post] |
---|
238 | ; |
---|
239 | |
---|
240 | enumref = |
---|
241 | "enumref" >> hard_space |
---|
242 | >> (*(anychar_p - |
---|
243 | (']' | hard_space))) [actions.enumref_pre] |
---|
244 | >> ( eps_p(']') |
---|
245 | | (hard_space >> phrase) |
---|
246 | ) [actions.enumref_post] |
---|
247 | ; |
---|
248 | |
---|
249 | headerref = |
---|
250 | "headerref" >> hard_space |
---|
251 | >> (*(anychar_p - |
---|
252 | (']' | hard_space))) [actions.headerref_pre] |
---|
253 | >> ( eps_p(']') |
---|
254 | | (hard_space >> phrase) |
---|
255 | ) [actions.headerref_post] |
---|
256 | ; |
---|
257 | |
---|
258 | bold = |
---|
259 | ch_p('*') [actions.bold_pre] |
---|
260 | >> blank >> phrase [actions.bold_post] |
---|
261 | ; |
---|
262 | |
---|
263 | italic = |
---|
264 | ch_p('\'') [actions.italic_pre] |
---|
265 | >> blank >> phrase [actions.italic_post] |
---|
266 | ; |
---|
267 | |
---|
268 | underline = |
---|
269 | ch_p('_') [actions.underline_pre] |
---|
270 | >> blank >> phrase [actions.underline_post] |
---|
271 | ; |
---|
272 | |
---|
273 | teletype = |
---|
274 | ch_p('^') [actions.teletype_pre] |
---|
275 | >> blank >> phrase [actions.teletype_post] |
---|
276 | ; |
---|
277 | |
---|
278 | strikethrough = |
---|
279 | ch_p('-') [actions.strikethrough_pre] |
---|
280 | >> blank >> phrase [actions.strikethrough_post] |
---|
281 | ; |
---|
282 | |
---|
283 | quote = |
---|
284 | ch_p('"') [actions.quote_pre] |
---|
285 | >> blank >> phrase [actions.quote_post] |
---|
286 | ; |
---|
287 | |
---|
288 | replaceable = |
---|
289 | ch_p('~') [actions.replaceable_pre] |
---|
290 | >> blank >> phrase [actions.replaceable_post] |
---|
291 | ; |
---|
292 | |
---|
293 | source_mode = |
---|
294 | ( |
---|
295 | str_p("c++") |
---|
296 | | "python" |
---|
297 | ) [assign_a(actions.source_mode)] |
---|
298 | ; |
---|
299 | |
---|
300 | footnote = |
---|
301 | str_p("footnote") [actions.footnote_pre] |
---|
302 | >> blank >> phrase [actions.footnote_post] |
---|
303 | ; |
---|
304 | } |
---|
305 | |
---|
306 | rule<Scanner> space, blank, comment, phrase, phrase_markup, image, |
---|
307 | close_bracket, bold, italic, underline, teletype, |
---|
308 | strikethrough, escape, url, common, funcref, |
---|
309 | classref, memberref, enumref, headerref, anchor, |
---|
310 | link, hard_space, eol, inline_code, simple_format, |
---|
311 | simple_bold, simple_italic, simple_underline, |
---|
312 | simple_teletype, source_mode, |
---|
313 | quote, code_block, footnote, replaceable; |
---|
314 | |
---|
315 | rule<Scanner> const& |
---|
316 | start() const { return common; } |
---|
317 | }; |
---|
318 | |
---|
319 | bool& is_not_preformatted; |
---|
320 | Actions& actions; |
---|
321 | }; |
---|
322 | } |
---|
323 | |
---|
324 | #endif // BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP |
---|
325 | |
---|