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