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