]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 <map> | |
12 | #include <boost/foreach.hpp> | |
13 | #include <boost/spirit/include/classic_core.hpp> | |
14 | #include <boost/spirit/include/classic_loops.hpp> | |
15 | #include <boost/spirit/include/classic_symbols.hpp> | |
16 | #include <boost/spirit/include/classic_chset.hpp> | |
17 | #include <boost/spirit/include/classic_numerics.hpp> | |
18 | #include <boost/spirit/include/phoenix1_primitives.hpp> | |
19 | #include <boost/spirit/include/phoenix1_operators.hpp> | |
20 | #include "grammar_impl.hpp" | |
21 | #include "state.hpp" | |
22 | #include "actions.hpp" | |
23 | #include "doc_info_tags.hpp" | |
24 | #include "phrase_tags.hpp" | |
25 | ||
26 | namespace quickbook | |
27 | { | |
28 | namespace cl = boost::spirit::classic; | |
29 | ||
30 | struct attribute_info | |
31 | { | |
32 | attribute_info(value::tag_type t, cl::rule<scanner>* r) | |
33 | : tag(t), rule(r) | |
34 | {} | |
35 | ||
36 | value::tag_type tag; | |
37 | cl::rule<scanner>* rule; | |
38 | }; | |
39 | ||
40 | struct doc_info_grammar_local | |
41 | { | |
42 | struct assign_attribute_type | |
43 | { | |
b32b8144 FG |
44 | assign_attribute_type(doc_info_grammar_local& l_) |
45 | : l(l_) | |
7c673cae FG |
46 | {} |
47 | ||
48 | void operator()(value::tag_type& t) const { | |
49 | l.attribute_rule = *l.attribute_rules[t]; | |
50 | l.attribute_tag = t; | |
51 | } | |
52 | ||
53 | doc_info_grammar_local& l; | |
54 | }; | |
55 | ||
56 | struct fallback_attribute_type | |
57 | { | |
b32b8144 FG |
58 | fallback_attribute_type(doc_info_grammar_local& l_) |
59 | : l(l_) | |
7c673cae FG |
60 | {} |
61 | ||
62 | void operator()(parse_iterator, parse_iterator) const { | |
63 | l.attribute_rule = l.doc_fallback; | |
64 | l.attribute_tag = value::default_tag; | |
65 | } | |
66 | ||
67 | doc_info_grammar_local& l; | |
68 | }; | |
69 | ||
70 | cl::rule<scanner> | |
71 | doc_info_block, doc_attribute, doc_info_attribute, | |
72 | doc_info_escaped_attributes, | |
73 | doc_title, doc_simple, doc_phrase, doc_fallback, | |
74 | doc_authors, doc_author, | |
75 | doc_copyright, doc_copyright_holder, | |
76 | doc_source_mode, doc_biblioid, doc_compatibility_mode, | |
77 | quickbook_version, macro, char_; | |
78 | cl::uint_parser<int, 10, 4, 4> doc_copyright_year; | |
79 | cl::symbols<> doc_types; | |
80 | cl::symbols<value::tag_type> doc_info_attributes; | |
81 | cl::symbols<value::tag_type> doc_attributes; | |
82 | std::map<value::tag_type, cl::rule<scanner>* > attribute_rules; | |
83 | value::tag_type attribute_tag; | |
84 | cl::rule<scanner> attribute_rule; | |
85 | assign_attribute_type assign_attribute; | |
86 | fallback_attribute_type fallback_attribute; | |
87 | ||
88 | doc_info_grammar_local() | |
89 | : assign_attribute(*this) | |
90 | , fallback_attribute(*this) | |
91 | {} | |
92 | ||
93 | bool source_mode_unset; | |
94 | }; | |
95 | ||
96 | void quickbook_grammar::impl::init_doc_info() | |
97 | { | |
98 | doc_info_grammar_local& local = cleanup_.add( | |
99 | new doc_info_grammar_local); | |
100 | ||
101 | typedef cl::uint_parser<int, 10, 1, 2> uint2_t; | |
102 | ||
103 | local.doc_types = | |
104 | "book", "article", "library", "chapter", "part" | |
105 | , "appendix", "preface", "qandadiv", "qandaset" | |
106 | , "reference", "set" | |
107 | ; | |
108 | ||
109 | BOOST_FOREACH(value::tag_type t, doc_attributes::tags()) { | |
110 | local.doc_attributes.add(doc_attributes::name(t), t); | |
111 | local.doc_info_attributes.add(doc_attributes::name(t), t); | |
112 | } | |
113 | ||
114 | BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) { | |
115 | local.doc_info_attributes.add(doc_info_attributes::name(t), t); | |
116 | } | |
117 | ||
118 | // Actions | |
119 | error_action error(state); | |
120 | plain_char_action plain_char(state); | |
121 | do_macro_action do_macro(state); | |
122 | scoped_parser<to_value_scoped_action> to_value(state); | |
123 | member_action_value<quickbook::state, source_mode_type> change_source_mode( | |
124 | state, &state::change_source_mode); | |
125 | member_action_fixed_value<quickbook::state, source_mode_type> default_source_mode( | |
126 | state, &state::change_source_mode, source_mode_tags::cpp); | |
127 | ||
128 | doc_info_details = | |
129 | cl::eps_p [ph::var(local.source_mode_unset) = true] | |
130 | >> *( space | |
131 | >> local.doc_attribute | |
132 | ) | |
133 | >> !( space | |
134 | >> local.doc_info_block | |
135 | ) | |
136 | >> *eol | |
137 | ; | |
138 | ||
139 | local.doc_info_block = | |
140 | '[' | |
141 | >> space | |
142 | >> (local.doc_types >> cl::eps_p) | |
143 | [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)] | |
144 | >> hard_space | |
145 | >> to_value(doc_info_tags::title) | |
146 | [ *( ~cl::eps_p(blank >> (cl::ch_p('[') | ']' | cl::eol_p)) | |
147 | >> local.char_ | |
148 | ) | |
149 | // Include 'blank' here so that it will be included in | |
150 | // id generation. | |
151 | >> blank | |
152 | ] | |
153 | >> space | |
154 | >> !(qbk_ver(106u) >> cl::eps_p(ph::var(local.source_mode_unset)) | |
155 | [default_source_mode] | |
156 | ) | |
157 | >> ( *( ( local.doc_info_attribute | |
158 | | local.doc_info_escaped_attributes | |
159 | ) | |
160 | >> space | |
161 | ) | |
162 | ) [state.values.sort()] | |
163 | >> ( ']' | |
164 | >> (eol | cl::end_p) | |
165 | | cl::eps_p [error] | |
166 | ) | |
167 | ; | |
168 | ||
169 | local.doc_attribute = | |
170 | '[' | |
171 | >> space | |
172 | >> local.doc_attributes [local.assign_attribute] | |
173 | >> hard_space | |
174 | >> state.values.list(ph::var(local.attribute_tag)) | |
175 | [ cl::eps_p [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)] | |
176 | >> local.attribute_rule | |
177 | ] | |
178 | >> space | |
179 | >> ']' | |
180 | ; | |
181 | ||
182 | local.doc_info_attribute = | |
183 | '[' | |
184 | >> space | |
185 | >> ( local.doc_info_attributes | |
186 | [local.assign_attribute] | |
187 | | (+(cl::alnum_p | '_' | '-')) | |
188 | [local.fallback_attribute] | |
189 | [error("Unrecognized document attribute: '%s'.")] | |
190 | ) | |
191 | >> hard_space | |
192 | >> state.values.list(ph::var(local.attribute_tag)) | |
193 | [local.attribute_rule] | |
194 | >> space | |
195 | >> ']' | |
196 | ; | |
197 | ||
198 | local.doc_fallback = to_value() [ | |
199 | *(~cl::eps_p(']') >> local.char_) | |
200 | ]; | |
201 | ||
202 | local.doc_info_escaped_attributes = | |
203 | ("'''" >> !eol) | |
204 | >> (*(cl::anychar_p - "'''")) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::escaped_attribute)] | |
205 | >> ( cl::str_p("'''") | |
206 | | cl::eps_p [error("Unclosed boostbook escape.")] | |
207 | ) | |
208 | ; | |
209 | ||
210 | // Document Attributes | |
211 | ||
212 | local.quickbook_version = | |
213 | cl::uint_p [state.values.entry(ph::arg1)] | |
214 | >> '.' | |
215 | >> uint2_t() [state.values.entry(ph::arg1)] | |
216 | ; | |
217 | ||
218 | local.attribute_rules[doc_attributes::qbk_version] = &local.quickbook_version; | |
219 | ||
220 | local.doc_compatibility_mode = | |
221 | cl::uint_p [state.values.entry(ph::arg1)] | |
222 | >> '.' | |
223 | >> uint2_t() [state.values.entry(ph::arg1)] | |
224 | ; | |
225 | ||
226 | local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode; | |
227 | ||
228 | local.doc_source_mode = source_modes | |
229 | [change_source_mode] | |
230 | [ph::var(local.source_mode_unset) = false] | |
231 | ; | |
232 | ||
233 | local.attribute_rules[doc_attributes::source_mode] = &local.doc_source_mode; | |
234 | ||
235 | // Document Info Attributes | |
236 | ||
237 | local.doc_simple = to_value() [*(~cl::eps_p(']') >> local.char_)]; | |
238 | local.attribute_rules[doc_info_attributes::version] = &local.doc_simple; | |
239 | local.attribute_rules[doc_info_attributes::id] = &local.doc_simple; | |
240 | local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple; | |
241 | local.attribute_rules[doc_info_attributes::category] = &local.doc_simple; | |
242 | local.attribute_rules[doc_info_attributes::last_revision] = &local.doc_simple; | |
243 | local.attribute_rules[doc_info_attributes::lang] = &local.doc_simple; | |
244 | local.attribute_rules[doc_info_attributes::xmlbase] = &local.doc_simple; | |
245 | ||
246 | local.doc_copyright_holder | |
247 | = *( ~cl::eps_p | |
248 | ( ']' | |
249 | | ',' >> space >> local.doc_copyright_year | |
250 | ) | |
251 | >> local.char_ | |
252 | ); | |
253 | ||
254 | local.doc_copyright = | |
255 | *( +( local.doc_copyright_year | |
256 | [state.values.entry(ph::arg1, doc_info_tags::copyright_year)] | |
257 | >> space | |
258 | >> !( '-' | |
259 | >> space | |
260 | >> local.doc_copyright_year | |
261 | [state.values.entry(ph::arg1, doc_info_tags::copyright_year_end)] | |
262 | >> space | |
263 | ) | |
264 | >> !cl::ch_p(',') | |
265 | >> space | |
266 | ) | |
267 | >> to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ] | |
268 | >> !cl::ch_p(',') | |
269 | >> space | |
270 | ) | |
271 | ; | |
272 | ||
273 | local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright; | |
274 | ||
275 | local.doc_phrase = to_value() [ nested_phrase ]; | |
276 | local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase; | |
277 | local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase; | |
278 | ||
279 | local.doc_author = | |
280 | '[' | |
281 | >> space | |
282 | >> to_value(doc_info_tags::author_surname) | |
283 | [*(~cl::eps_p(',') >> local.char_)] | |
284 | >> ',' >> space | |
285 | >> to_value(doc_info_tags::author_first) | |
286 | [*(~cl::eps_p(']') >> local.char_)] | |
287 | >> ']' | |
288 | ; | |
289 | ||
290 | local.doc_authors = | |
291 | *( local.doc_author | |
292 | >> space | |
293 | >> !(cl::ch_p(',') >> space) | |
294 | ) | |
295 | ; | |
296 | ||
297 | local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors; | |
298 | ||
299 | local.doc_biblioid = | |
300 | (+cl::alnum_p) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)] | |
301 | >> hard_space | |
302 | >> to_value(doc_info_tags::biblioid_value) | |
303 | [+(~cl::eps_p(']') >> local.char_)] | |
304 | ; | |
305 | ||
306 | local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid; | |
307 | ||
308 | local.char_ = | |
309 | escape | |
310 | | local.macro | |
311 | | cl::anychar_p[plain_char]; | |
312 | ; | |
313 | ||
314 | local.macro = | |
315 | cl::eps_p | |
316 | ( ( state.macro | |
317 | >> ~cl::eps_p(cl::alpha_p | '_') | |
318 | // must not be followed by alpha or underscore | |
319 | ) | |
320 | & macro_identifier // must be a valid macro for the current version | |
321 | ) | |
322 | >> state.macro [do_macro] | |
323 | ; | |
324 | } | |
325 | } |