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_chset.hpp>
14 #include <boost/spirit/include/classic_core.hpp>
15 #include <boost/spirit/include/classic_loops.hpp>
16 #include <boost/spirit/include/classic_numerics.hpp>
17 #include <boost/spirit/include/classic_symbols.hpp>
18 #include <boost/spirit/include/phoenix1_operators.hpp>
19 #include <boost/spirit/include/phoenix1_primitives.hpp>
20 #include "actions.hpp"
21 #include "doc_info_tags.hpp"
22 #include "grammar_impl.hpp"
23 #include "phrase_tags.hpp"
28 namespace cl
= boost::spirit::classic
;
32 attribute_info(value::tag_type t
, cl::rule
<scanner
>* r
)
38 cl::rule
<scanner
>* rule
;
41 struct doc_info_grammar_local
43 struct assign_attribute_type
45 assign_attribute_type(doc_info_grammar_local
& l_
) : l(l_
) {}
47 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_
) : l(l_
) {}
60 void operator()(parse_iterator
, parse_iterator
) const
62 l
.attribute_rule
= l
.doc_fallback
;
63 l
.attribute_tag
= value::default_tag
;
66 doc_info_grammar_local
& l
;
69 cl::rule
<scanner
> doc_info_block
, doc_attribute
, doc_info_attribute
,
70 doc_info_escaped_attributes
, doc_title
, doc_simple
, doc_phrase
,
71 doc_fallback
, doc_authors
, doc_author
, doc_copyright
,
72 doc_copyright_holder
, doc_source_mode
, doc_biblioid
,
73 doc_compatibility_mode
, quickbook_version
, macro
, char_
;
74 cl::uint_parser
<int, 10, 4, 4> doc_copyright_year
;
75 cl::symbols
<> doc_types
;
76 cl::symbols
<value::tag_type
> doc_info_attributes
;
77 cl::symbols
<value::tag_type
> doc_attributes
;
78 std::map
<value::tag_type
, cl::rule
<scanner
>*> attribute_rules
;
79 value::tag_type attribute_tag
;
80 cl::rule
<scanner
> attribute_rule
;
81 assign_attribute_type assign_attribute
;
82 fallback_attribute_type fallback_attribute
;
84 doc_info_grammar_local()
85 : assign_attribute(*this), fallback_attribute(*this)
89 bool source_mode_unset
;
92 void quickbook_grammar::impl::init_doc_info()
94 doc_info_grammar_local
& local
=
95 cleanup_
.add(new doc_info_grammar_local
);
97 typedef cl::uint_parser
<int, 10, 1, 2> uint2_t
;
99 local
.doc_types
= "book", "article", "library", "chapter", "part",
100 "appendix", "preface", "qandadiv", "qandaset", "reference", "set";
102 BOOST_FOREACH (value::tag_type t
, doc_attributes::tags()) {
103 local
.doc_attributes
.add(doc_attributes::name(t
), t
);
104 local
.doc_info_attributes
.add(doc_attributes::name(t
), t
);
107 BOOST_FOREACH (value::tag_type t
, doc_info_attributes::tags()) {
108 local
.doc_info_attributes
.add(doc_info_attributes::name(t
), t
);
112 error_action
error(state
);
113 plain_char_action
plain_char(state
);
114 do_macro_action
do_macro(state
);
115 scoped_parser
<to_value_scoped_action
> to_value(state
);
116 member_action_value
<quickbook::state
, source_mode_type
>
117 change_source_mode(state
, &state::change_source_mode
);
118 member_action_fixed_value
<quickbook::state
, source_mode_type
>
120 state
, &state::change_source_mode
, source_mode_tags::cpp
);
125 cl::eps_p
[ph::var(local
.source_mode_unset
) = true]
127 >> local
.doc_attribute
130 >> local
.doc_info_block
135 local
.doc_info_block
=
138 >> (local
.doc_types
>> cl::eps_p
)
139 [state
.values
.entry(ph::arg1
, ph::arg2
, doc_info_tags::type
)]
141 >> to_value(doc_info_tags::title
)
142 [ *( ~cl::eps_p(blank
>> (cl::ch_p('[') | ']' | cl::eol_p
))
145 // Include 'blank' here so that it will be included in
150 >> !(qbk_ver(106u) >> cl::eps_p(ph::var(local
.source_mode_unset
))
151 [default_source_mode
]
153 >> ( *( ( local
.doc_info_attribute
154 | local
.doc_info_escaped_attributes
158 ) [state
.values
.sort()]
165 local
.doc_attribute
=
168 >> local
.doc_attributes
[local
.assign_attribute
]
170 >> state
.values
.list(ph::var(local
.attribute_tag
))
171 [ cl::eps_p
[state
.values
.entry(ph::arg1
, ph::arg2
, doc_info_tags::before_docinfo
)]
172 >> local
.attribute_rule
178 local
.doc_info_attribute
=
181 >> ( local
.doc_info_attributes
182 [local
.assign_attribute
]
183 | (+(cl::alnum_p
| '_' | '-'))
184 [local
.fallback_attribute
]
185 [error("Unrecognized document attribute: '%s'.")]
188 >> state
.values
.list(ph::var(local
.attribute_tag
))
189 [local
.attribute_rule
]
194 local
.doc_fallback
= to_value() [
195 *(~cl::eps_p(']') >> local
.char_
)
198 local
.doc_info_escaped_attributes
=
200 >> (*(cl::anychar_p
- "'''")) [state
.values
.entry(ph::arg1
, ph::arg2
, doc_info_tags::escaped_attribute
)]
201 >> ( cl::str_p("'''")
202 | cl::eps_p
[error("Unclosed boostbook escape.")]
206 // Document Attributes
208 local
.quickbook_version
=
209 cl::uint_p
[state
.values
.entry(ph::arg1
)]
211 >> uint2_t() [state
.values
.entry(ph::arg1
)]
214 local
.attribute_rules
[doc_attributes::qbk_version
] = &local
.quickbook_version
;
216 local
.doc_compatibility_mode
=
217 cl::uint_p
[state
.values
.entry(ph::arg1
)]
219 >> uint2_t() [state
.values
.entry(ph::arg1
)]
222 local
.attribute_rules
[doc_attributes::compatibility_mode
] = &local
.doc_compatibility_mode
;
224 local
.doc_source_mode
= source_modes
226 [ph::var(local
.source_mode_unset
) = false]
229 local
.attribute_rules
[doc_attributes::source_mode
] = &local
.doc_source_mode
;
231 // Document Info Attributes
233 local
.doc_simple
= to_value() [*(~cl::eps_p(']') >> local
.char_
)];
234 local
.attribute_rules
[doc_info_attributes::version
] = &local
.doc_simple
;
235 local
.attribute_rules
[doc_info_attributes::id
] = &local
.doc_simple
;
236 local
.attribute_rules
[doc_info_attributes::dirname
] = &local
.doc_simple
;
237 local
.attribute_rules
[doc_info_attributes::category
] = &local
.doc_simple
;
238 local
.attribute_rules
[doc_info_attributes::last_revision
] = &local
.doc_simple
;
239 local
.attribute_rules
[doc_info_attributes::lang
] = &local
.doc_simple
;
240 local
.attribute_rules
[doc_info_attributes::xmlbase
] = &local
.doc_simple
;
242 local
.doc_copyright_holder
245 | ',' >> space
>> local
.doc_copyright_year
250 local
.doc_copyright
=
251 *( +( local
.doc_copyright_year
252 [state
.values
.entry(ph::arg1
, doc_info_tags::copyright_year
)]
256 >> local
.doc_copyright_year
257 [state
.values
.entry(ph::arg1
, doc_info_tags::copyright_year_end
)]
263 >> to_value(doc_info_tags::copyright_name
) [ local
.doc_copyright_holder
]
269 local
.attribute_rules
[doc_info_attributes::copyright
] = &local
.doc_copyright
;
271 local
.doc_phrase
= to_value() [ nested_phrase
];
272 local
.attribute_rules
[doc_info_attributes::purpose
] = &local
.doc_phrase
;
273 local
.attribute_rules
[doc_info_attributes::license
] = &local
.doc_phrase
;
278 >> to_value(doc_info_tags::author_surname
)
279 [*(~cl::eps_p(',') >> local
.char_
)]
281 >> to_value(doc_info_tags::author_first
)
282 [*(~cl::eps_p(']') >> local
.char_
)]
289 >> !(cl::ch_p(',') >> space
)
293 local
.attribute_rules
[doc_info_attributes::authors
] = &local
.doc_authors
;
296 (+cl::alnum_p
) [state
.values
.entry(ph::arg1
, ph::arg2
, doc_info_tags::biblioid_class
)]
298 >> to_value(doc_info_tags::biblioid_value
)
299 [+(~cl::eps_p(']') >> local
.char_
)]
302 local
.attribute_rules
[doc_info_attributes::biblioid
] = &local
.doc_biblioid
;
307 | cl::anychar_p
[plain_char
];
313 >> ~cl::eps_p(cl::alpha_p
| '_')
314 // must not be followed by alpha or underscore
316 & macro_identifier
// must be a valid macro for the current version
318 >> state
.macro
[do_macro
]