1 /*=============================================================================
2 Copyright (c) 2002 2004 2006 Joel de Guzman
3 Copyright (c) 2004 Eric Niebler
4 http://spirit.sourceforge.net/
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 =============================================================================*/
12 #include <boost/foreach.hpp>
13 #include <boost/spirit/include/classic_core.hpp>
14 #include <boost/spirit/include/classic_actor.hpp>
15 #include <boost/spirit/include/classic_loops.hpp>
16 #include <boost/spirit/include/classic_symbols.hpp>
17 #include <boost/spirit/include/classic_chset.hpp>
18 #include <boost/spirit/include/classic_numerics.hpp>
19 #include <boost/spirit/include/phoenix1_primitives.hpp>
20 #include <boost/spirit/include/phoenix1_operators.hpp>
21 #include "grammar_impl.hpp"
22 #include "actions_class.hpp"
23 #include "doc_info_tags.hpp"
24 #include "phrase_tags.hpp"
28 namespace cl = boost::spirit::classic;
32 attribute_info(value::tag_type t, cl::rule<scanner>* r)
37 cl::rule<scanner>* rule;
40 struct doc_info_grammar_local
42 struct assign_attribute_type
44 assign_attribute_type(doc_info_grammar_local& l)
48 void operator()(value::tag_type& t) const {
49 l.attribute_rule = *l.attribute_rules[t];
53 doc_info_grammar_local& l;
56 struct fallback_attribute_type
58 fallback_attribute_type(doc_info_grammar_local& l)
62 void operator()(parse_iterator, parse_iterator) const {
63 l.attribute_rule = l.doc_fallback;
64 l.attribute_tag = value::default_tag;
67 doc_info_grammar_local& l;
71 doc_info_block, doc_attribute, doc_info_attribute,
72 doc_title, doc_simple, doc_phrase, doc_fallback,
73 doc_authors, doc_author,
74 doc_copyright, doc_copyright_holder,
75 doc_source_mode, doc_biblioid, doc_compatibility_mode,
76 quickbook_version, char_;
77 cl::uint_parser<int, 10, 4, 4> doc_copyright_year;
78 cl::symbols<> doc_types;
79 cl::symbols<value::tag_type> doc_info_attributes;
80 cl::symbols<value::tag_type> doc_attributes;
81 std::map<value::tag_type, cl::rule<scanner>* > attribute_rules;
82 value::tag_type attribute_tag;
83 cl::rule<scanner> attribute_rule;
84 assign_attribute_type assign_attribute;
85 fallback_attribute_type fallback_attribute;
87 doc_info_grammar_local()
88 : assign_attribute(*this)
89 , fallback_attribute(*this)
92 bool source_mode_unset;
95 void quickbook_grammar::impl::init_doc_info()
97 doc_info_grammar_local& local = cleanup_.add(
98 new doc_info_grammar_local);
100 typedef cl::uint_parser<int, 10, 1, 2> uint2_t;
103 "book", "article", "library", "chapter", "part"
104 , "appendix", "preface", "qandadiv", "qandaset"
108 BOOST_FOREACH(value::tag_type t, doc_attributes::tags()) {
109 local.doc_attributes.add(doc_attributes::name(t), t);
110 local.doc_info_attributes.add(doc_attributes::name(t), t);
113 BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
114 local.doc_info_attributes.add(doc_info_attributes::name(t), t);
118 space [ph::var(local.source_mode_unset) = true]
119 >> *( local.doc_attribute
122 >> !local.doc_info_block
125 local.doc_info_block =
128 >> (local.doc_types >> cl::eps_p)
129 [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)]
131 >> actions.to_value(doc_info_tags::title)
132 [ *( ~cl::eps_p(blank >> (cl::ch_p('[') | ']' | cl::eol_p))
135 // Include 'blank' here so that it will be included in
140 >> !(qbk_since(106u) >> cl::eps_p(ph::var(local.source_mode_unset))
141 [cl::assign_a(actions.source_mode, "c++")]
143 >> (*( local.doc_info_attribute
145 )) [actions.values.sort()]
147 >> (+eol | cl::end_p)
148 | cl::eps_p [actions.error]
152 local.doc_attribute =
155 >> local.doc_attributes [local.assign_attribute]
157 >> actions.values.list(ph::var(local.attribute_tag))
158 [ cl::eps_p [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)]
159 >> local.attribute_rule
165 local.doc_info_attribute =
168 >> ( local.doc_info_attributes
169 [local.assign_attribute]
170 | (+(cl::alnum_p | '_' | '-'))
171 [local.fallback_attribute]
172 [actions.error("Unrecognized document attribute: '%s'.")]
175 >> actions.values.list(ph::var(local.attribute_tag))
176 [local.attribute_rule]
181 local.doc_fallback = actions.to_value() [
182 *(~cl::eps_p(']') >> local.char_)
185 // Document Attributes
187 local.quickbook_version =
188 cl::uint_p [actions.values.entry(ph::arg1)]
190 >> uint2_t() [actions.values.entry(ph::arg1)]
193 local.attribute_rules[doc_attributes::qbk_version] = &local.quickbook_version;
195 local.doc_compatibility_mode =
196 cl::uint_p [actions.values.entry(ph::arg1)]
198 >> uint2_t() [actions.values.entry(ph::arg1)]
201 local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode;
203 local.doc_source_mode =
208 ) [cl::assign_a(actions.source_mode)]
209 [ph::var(local.source_mode_unset) = false]
212 local.attribute_rules[doc_attributes::source_mode] = &local.doc_source_mode;
214 // Document Info Attributes
216 local.doc_simple = actions.to_value() [*(~cl::eps_p(']') >> local.char_)];
217 local.attribute_rules[doc_info_attributes::version] = &local.doc_simple;
218 local.attribute_rules[doc_info_attributes::id] = &local.doc_simple;
219 local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple;
220 local.attribute_rules[doc_info_attributes::category] = &local.doc_simple;
221 local.attribute_rules[doc_info_attributes::last_revision] = &local.doc_simple;
222 local.attribute_rules[doc_info_attributes::lang] = &local.doc_simple;
223 local.attribute_rules[doc_info_attributes::xmlbase] = &local.doc_simple;
225 local.doc_copyright_holder
228 | ',' >> space >> local.doc_copyright_year
233 local.doc_copyright =
234 *( +( local.doc_copyright_year
235 [actions.values.entry(ph::arg1, doc_info_tags::copyright_year)]
239 >> local.doc_copyright_year
240 [actions.values.entry(ph::arg1, doc_info_tags::copyright_year_end)]
246 >> actions.to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ]
252 local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright;
254 local.doc_phrase = actions.to_value() [ nested_phrase ];
255 local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase;
256 local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase;
261 >> actions.to_value(doc_info_tags::author_surname)
262 [*(~cl::eps_p(',') >> local.char_)]
264 >> actions.to_value(doc_info_tags::author_first)
265 [*(~cl::eps_p(']') >> local.char_)]
272 >> !(cl::ch_p(',') >> space)
276 local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors;
279 (+cl::alnum_p) [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)]
281 >> actions.to_value(doc_info_tags::biblioid_value)
282 [+(~cl::eps_p(']') >> local.char_)]
285 local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
287 local.char_ = escape | cl::anychar_p[actions.plain_char];