1 /*=============================================================================
2     Copyright (c) 2002 2004  2006Joel 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 
11 #include <boost/spirit/include/classic_assign_actor.hpp>
12 #include <boost/spirit/include/classic_clear_actor.hpp>
13 #include <boost/spirit/include/classic_if.hpp>
14 #include <boost/spirit/include/phoenix1_casts.hpp>
15 #include <boost/spirit/include/phoenix1_primitives.hpp>
16 #include "actions.hpp"
17 #include "block_tags.hpp"
18 #include "grammar_impl.hpp"
19 #include "state.hpp"
20 #include "template_tags.hpp"
21 #include "utils.hpp"
22 
23 namespace quickbook
24 {
25     namespace cl = boost::spirit::classic;
26     namespace ph = phoenix;
27 
28     struct block_element_grammar_local
29     {
30         cl::rule<scanner> heading, inner_block, inner_phrase, def_macro, table,
31             table_title, table_row, variablelist, varlistentry, varlistterm,
32             list, cell, preformatted, begin_section, end_section, xinclude,
33             include, include_filename, template_, template_id,
34             template_formal_arg, template_body, identifier, import, element_id,
35             same_line;
36     };
37 
init_block_elements()38     void quickbook_grammar::impl::init_block_elements()
39     {
40         block_element_grammar_local& local =
41             cleanup_.add(new block_element_grammar_local);
42 
43         // Actions
44         error_action error(state);
45         element_id_warning_action element_id_warning(state);
46         raw_char_action raw_char(state);
47         explicit_list_action explicit_list(state);
48         scoped_parser<to_value_scoped_action> to_value(state);
49 
50         // clang-format off
51 
52         local.element_id =
53             !(  ':'
54             >>  (   qbk_ver(107u)
55                 >>  to_value(general_tags::element_id) [attribute_value_1_7]
56                 |   qbk_ver(0, 107u)
57                 >>  !(qbk_ver(105u) >> space)
58                 >>  (+(cl::alnum_p | '_'))      [state.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
59                 |   cl::eps_p                   [element_id_warning]
60                 )
61             )
62             ;
63 
64         elements.add
65             ("section", element_info(element_info::section_block, &local.begin_section, block_tags::begin_section))
66             ("endsect", element_info(element_info::section_block, &local.end_section, block_tags::end_section))
67             ;
68 
69         local.begin_section =
70                 space
71             >>  local.element_id
72             >>  space
73             >>  local.inner_phrase
74             ;
75 
76         local.end_section =
77                 space
78             >>  local.element_id
79             ;
80 
81         local.heading
82             =   space
83             >>  !(qbk_ver(106u) >> local.element_id)
84             >>  space
85             >>  local.inner_phrase
86             ;
87 
88         elements.add
89             ("heading", element_info(element_info::conditional_or_block, &local.heading, block_tags::generic_heading))
90             ("h1", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading1))
91             ("h2", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading2))
92             ("h3", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading3))
93             ("h4", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading4))
94             ("h5", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading5))
95             ("h6", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading6))
96             ;
97 
98         elements.add
99             ("blurb", element_info(element_info::nested_block, &local.inner_block, block_tags::blurb))
100             (":", element_info(element_info::nested_block, &local.inner_block, block_tags::blockquote))
101             ("warning", element_info(element_info::nested_block, &local.inner_block, block_tags::warning))
102             ("caution", element_info(element_info::nested_block, &local.inner_block, block_tags::caution))
103             ("important", element_info(element_info::nested_block, &local.inner_block, block_tags::important))
104             ("note", element_info(element_info::nested_block, &local.inner_block, block_tags::note))
105             ("tip", element_info(element_info::nested_block, &local.inner_block, block_tags::tip))
106             ;
107 
108         elements.add
109             ("block", element_info(element_info::nested_block, &local.inner_phrase, block_tags::block, 106u))
110             ;
111 
112         elements.add
113             ("pre", element_info(element_info::nested_block, &local.preformatted, block_tags::preformatted))
114             ;
115 
116         local.preformatted =
117                 ( qbk_ver(0, 106) >> space
118                 | qbk_ver(106) >> blank >> !eol
119                 )
120             >>  to_value()
121                 [
122                     inside_preformatted
123                 ]
124             ;
125 
126         elements.add
127             ("def", element_info(element_info::conditional_or_block, &local.def_macro, block_tags::macro_definition))
128             ;
129 
130         local.def_macro =
131                space
132             >> macro_identifier                 [state.values.entry(ph::arg1, ph::arg2)]
133             >> blank
134             >> local.inner_phrase
135             ;
136 
137         local.identifier =
138             (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
139             ;
140 
141         local.template_id =
142             local.identifier | (cl::punct_p - (cl::ch_p('[') | ']'))
143             ;
144 
145         elements.add
146             ("template", element_info(element_info::conditional_or_block, &local.template_, block_tags::template_definition))
147             ;
148 
149         local.template_ =
150                space
151             >> local.template_id                [state.values.entry(ph::arg1, ph::arg2)]
152             >> state.values.list()[
153             !(
154                 space >> '['
155                 >> *(
156                         space
157                     >>  local.template_id       [state.values.entry(ph::arg1, ph::arg2)]
158                     )
159                 >> space >> ']'
160             )
161             ]
162             >>  (   cl::eps_p(*cl::blank_p >> cl::eol_p)
163                 >>  local.template_body         [state.values.entry(ph::arg1, ph::arg2, template_tags::block)]
164                 |   local.template_body         [state.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
165                 )
166             ;
167 
168         local.template_body =
169                 qbk_ver(106u)
170             >>  *(~cl::eps_p(']') >> skip_entity)
171             |   qbk_ver(0,106u)
172             >>  *(('[' >> local.template_body >> ']') | (cl::anychar_p - ']'))
173             >> cl::eps_p(space >> ']')
174             >> space
175             ;
176 
177         elements.add
178             ("variablelist", element_info(element_info::nested_block, &local.variablelist, block_tags::variable_list))
179             ;
180 
181         local.variablelist =
182                 (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
183             >>  local.table_title
184             >>  *local.varlistentry
185             ;
186 
187         local.varlistentry =
188             space
189             >>  cl::ch_p('[')
190             >>  state.values.list()
191             [
192                 (
193                     local.varlistterm
194                     >>  (   +local.cell
195                         |   cl::eps_p           [error]
196                         )
197                     >>  cl::ch_p(']')
198                     >>  space
199                 )
200                 | cl::eps_p                     [error]
201             ]
202             ;
203 
204         local.varlistterm =
205             space
206             >>  cl::ch_p('[')
207             >>  local.inner_phrase
208             >>  (   cl::ch_p(']')
209                 >>  space
210                 |   cl::eps_p                   [error]
211                 )
212             ;
213 
214         elements.add
215             ("table", element_info(element_info::nested_block, &local.table, block_tags::table))
216             ;
217 
218         local.same_line = *cl::blank_p >> !(comment >> space);
219 
220         local.table =
221                 local.same_line
222             >>  !(qbk_ver(105u) >> local.element_id)
223             >>  local.same_line
224             >>  local.table_title
225             >>  *local.table_row
226             ;
227 
228         local.table_row =
229             space
230             >>  cl::ch_p('[')
231             >>
232             (
233                 (
234                     state.values.list(table_tags::row)
235                     [   *local.cell
236                     ]
237                     >>  cl::ch_p(']')
238                     >>  space
239                 )
240                 | cl::eps_p                     [error]
241             )
242             ;
243 
244         local.table_title =
245                 qbk_ver(0, 106)
246             >>  (*(cl::anychar_p - eol))        [state.values.entry(ph::arg1, ph::arg2, table_tags::title)]
247             >>  (+eol)
248             |   qbk_ver(106)
249             >>  to_value(table_tags::title)
250                 [
251                     table_title_phrase
252                 ]
253             >>  space
254             ;
255 
256         elements.add
257             ("ordered_list", element_info(element_info::nested_block, &local.list, block_tags::ordered_list, 106))
258             ("itemized_list", element_info(element_info::nested_block, &local.list, block_tags::itemized_list, 106))
259             ;
260 
261         local.list =
262             *(  cl::eps_p                       [explicit_list]
263             >>  local.cell
264             )
265             ;
266 
267         local.cell =
268                 space
269             >>  cl::ch_p('[')
270             >>  (   local.inner_block
271                 >>  cl::ch_p(']')
272                 >>  space
273                 |   cl::eps_p                   [error]
274                 )
275             ;
276 
277         elements.add
278             ("xinclude", element_info(element_info::conditional_or_block, &local.xinclude, block_tags::xinclude))
279             ("import", element_info(element_info::conditional_or_block, &local.import, block_tags::import))
280             ("include", element_info(element_info::conditional_or_block, &local.include, block_tags::include))
281             ;
282 
283         local.xinclude =
284                space
285             >> local.include_filename
286             ;
287 
288         local.import =
289                space
290             >> local.include_filename
291             ;
292 
293         local.include =
294                space
295             >>
296            !(
297                 ':'
298                 >> (*((cl::alnum_p | '_') - cl::space_p))
299                                                 [state.values.entry(ph::arg1, ph::arg2, general_tags::include_id)]
300                 >> space
301             )
302             >> local.include_filename
303             ;
304 
305         local.include_filename =
306                 qbk_ver(0, 106u)
307             >>  (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
308             |   qbk_ver(106u, 107u)
309             >>  to_value()
310                 [   *(  raw_escape
311                     |   (cl::anychar_p - phrase_end)
312                                                 [raw_char]
313                     )
314                 ]
315             |   qbk_ver(107u)
316             >>  to_value() [ attribute_value_1_7 ]
317             ;
318 
319         local.inner_block =
320             to_value()
321             [
322                 inside_paragraph
323             ]
324             ;
325 
326         local.inner_phrase =
327             to_value()
328             [
329                 paragraph_phrase
330             ]
331             ;
332 
333         // clang-format on
334     }
335 }
336