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 11 #include <boost/spirit/include/classic_assign_actor.hpp> 12 #include <boost/spirit/include/classic_clear_actor.hpp> 13 #include <boost/spirit/include/classic_core.hpp> 14 #include <boost/spirit/include/classic_if.hpp> 15 #include <boost/spirit/include/phoenix1_casts.hpp> 16 #include <boost/spirit/include/phoenix1_primitives.hpp> 17 #include "actions.hpp" 18 #include "for.hpp" 19 #include "grammar_impl.hpp" 20 #include "phrase_tags.hpp" 21 #include "state.hpp" 22 #include "utils.hpp" 23 24 namespace quickbook 25 { 26 namespace cl = boost::spirit::classic; 27 28 struct phrase_element_grammar_local 29 { 30 cl::rule<scanner> image, anchor, link, empty, cond_phrase, inner_phrase, 31 role, source_mode; 32 }; 33 init_phrase_elements()34 void quickbook_grammar::impl::init_phrase_elements() 35 { 36 phrase_element_grammar_local& local = 37 cleanup_.add(new phrase_element_grammar_local); 38 39 error_action error(state); 40 raw_char_action raw_char(state); 41 scoped_parser<cond_phrase_push> scoped_cond_phrase(state); 42 scoped_parser<to_value_scoped_action> to_value(state); 43 44 // clang-format off 45 46 elements.add 47 ("?", element_info(element_info::phrase, &local.cond_phrase)) 48 ; 49 50 local.cond_phrase = 51 ( !(qbk_ver(107u) >> "!") ) [state.values.entry(ph::arg1, ph::arg2)] 52 >> blank 53 >> macro_identifier [state.values.entry(ph::arg1, ph::arg2)] 54 >> scoped_cond_phrase() [extended_phrase] 55 ; 56 57 elements.add 58 ("$", element_info(element_info::phrase, &local.image, phrase_tags::image)) 59 ; 60 61 // Note that the attribute values here are encoded in plain text not 62 // boostbook. 63 local.image = 64 qbk_ver(105u) 65 >> blank 66 >> ( qbk_ver(0, 106u) 67 >> (+( 68 *cl::space_p 69 >> +(cl::anychar_p - (cl::space_p | phrase_end | '[')) 70 )) [state.values.entry(ph::arg1, ph::arg2)] 71 | qbk_ver(106u) 72 >> to_value() 73 [ +( raw_escape 74 | (+cl::space_p >> ~cl::eps_p(phrase_end | '[')) 75 [raw_char] 76 | (cl::anychar_p - (cl::space_p | phrase_end | '[')) 77 [raw_char] 78 ) 79 ] 80 ) 81 >> hard_space 82 >> *state.values.list() 83 [ '[' 84 >> (*(cl::alnum_p | '_')) 85 [state.values.entry(ph::arg1, ph::arg2)] 86 >> space 87 >> ( qbk_ver(0, 106u) 88 >> (*(cl::anychar_p - (phrase_end | '['))) 89 [state.values.entry(ph::arg1, ph::arg2)] 90 | qbk_ver(106u) 91 >> to_value() 92 [ *( raw_escape 93 | (cl::anychar_p - (phrase_end | '[')) 94 [raw_char] 95 ) 96 ] 97 ) 98 >> ']' 99 >> space 100 ] 101 >> cl::eps_p(']') 102 | qbk_ver(0, 105u) 103 >> blank 104 >> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)] 105 >> cl::eps_p(']') 106 ; 107 108 elements.add 109 ("@", element_info(element_info::phrase, &local.link, phrase_tags::url)) 110 ("link", element_info(element_info::phrase, &local.link, phrase_tags::link)) 111 ("funcref", element_info(element_info::phrase, &local.link, phrase_tags::funcref)) 112 ("classref", element_info(element_info::phrase, &local.link, phrase_tags::classref)) 113 ("memberref", element_info(element_info::phrase, &local.link, phrase_tags::memberref)) 114 ("enumref", element_info(element_info::phrase, &local.link, phrase_tags::enumref)) 115 ("macroref", element_info(element_info::phrase, &local.link, phrase_tags::macroref)) 116 ("headerref", element_info(element_info::phrase, &local.link, phrase_tags::headerref)) 117 ("conceptref", element_info(element_info::phrase, &local.link, phrase_tags::conceptref)) 118 ("globalref", element_info(element_info::phrase, &local.link, phrase_tags::globalref)) 119 ; 120 121 local.link = 122 space 123 >> ( qbk_ver(0, 106u) 124 >> (*(cl::anychar_p - (']' | space))) 125 [state.values.entry(ph::arg1, ph::arg2)] 126 | qbk_ver(106u, 107u) 127 >> to_value() 128 [ *( raw_escape 129 | (cl::anychar_p - (cl::ch_p('[') | ']' | space)) 130 [raw_char] 131 ) 132 ] 133 >> !( ~cl::eps_p(comment) 134 >> cl::eps_p('[') [error("Open bracket in link value.")] 135 ) 136 | qbk_ver(107u) 137 >> to_value() [attribute_value_1_7] 138 ) 139 >> hard_space 140 >> local.inner_phrase 141 ; 142 143 elements.add 144 ("#", element_info(element_info::maybe_block, &local.anchor, phrase_tags::anchor)) 145 ; 146 147 local.anchor = 148 blank 149 >> ( qbk_ver(0, 106u) 150 >> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)] 151 | qbk_ver(106u, 107u) 152 >> to_value() 153 [ *( raw_escape 154 | (cl::anychar_p - phrase_end) 155 [raw_char] 156 ) 157 ] 158 | qbk_ver(107u) 159 >> to_value() [attribute_value_1_7] 160 ) 161 ; 162 163 elements.add 164 ("*", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::bold)) 165 ("'", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::italic)) 166 ("_", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::underline)) 167 ("^", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::teletype)) 168 ("-", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::strikethrough)) 169 ("\"", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::quote)) 170 ("~", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::replaceable)) 171 ("footnote", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::footnote)) 172 ; 173 174 elements.add("!", element_info(element_info::maybe_block, &local.source_mode, code_tags::next_source_mode, 107u)) 175 ; 176 177 local.source_mode = 178 cl::eps_p [state.values.entry(ph::arg1, ph::arg2)] 179 >> source_modes [state.values.entry(ph::arg1)]; 180 181 QUICKBOOK_FOR(int tag, source_mode_tags::tags()) { 182 source_modes.add(source_mode_tags::name(tag), tag); 183 elements.add(source_mode_tags::name(tag), 184 element_info(element_info::phrase, &local.empty, tag)); 185 } 186 187 elements.add 188 ("role", element_info(element_info::phrase, &local.role, phrase_tags::role, 106u)) 189 ; 190 191 local.role 192 = space 193 >> ( qbk_ver(0, 107u) 194 >> (+(cl::alnum_p | '_')) [state.values.entry(ph::arg1, ph::arg2)] 195 | qbk_ver(107u) 196 >> to_value() [attribute_value_1_7] 197 ) 198 >> hard_space 199 >> local.inner_phrase 200 ; 201 202 local.empty = cl::eps_p; 203 204 local.inner_phrase = 205 blank 206 >> to_value() [ paragraph_phrase ] 207 ; 208 209 // clang-format on 210 } 211 } 212