/*============================================================================= Copyright (c) 2002 2004 2006 Joel de Guzman Copyright (c) 2004 Eric Niebler http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #include #include #include #include #include #include #include #include #include "actions.hpp" #include "doc_info_tags.hpp" #include "for.hpp" #include "grammar_impl.hpp" #include "phrase_tags.hpp" #include "state.hpp" namespace quickbook { namespace cl = boost::spirit::classic; struct attribute_info { attribute_info(value::tag_type t, cl::rule* r) : tag(t), rule(r) { } value::tag_type tag; cl::rule* rule; }; struct doc_info_grammar_local { struct assign_attribute_type { assign_attribute_type(doc_info_grammar_local& l_) : l(l_) {} void operator()(value::tag_type& t) const { l.attribute_rule = *l.attribute_rules[t]; l.attribute_tag = t; } doc_info_grammar_local& l; }; struct fallback_attribute_type { fallback_attribute_type(doc_info_grammar_local& l_) : l(l_) {} void operator()(parse_iterator, parse_iterator) const { l.attribute_rule = l.doc_fallback; l.attribute_tag = value::default_tag; } doc_info_grammar_local& l; }; cl::rule doc_info_block, doc_attribute, doc_info_attribute, doc_info_escaped_attributes, doc_title, doc_simple, doc_phrase, doc_fallback, doc_authors, doc_author, doc_copyright, doc_copyright_holder, doc_source_mode, doc_biblioid, doc_compatibility_mode, quickbook_version, macro, char_; cl::uint_parser doc_copyright_year; cl::symbols<> doc_types; cl::symbols doc_info_attributes; cl::symbols doc_attributes; std::map*> attribute_rules; value::tag_type attribute_tag; cl::rule attribute_rule; assign_attribute_type assign_attribute; fallback_attribute_type fallback_attribute; doc_info_grammar_local() : assign_attribute(*this), fallback_attribute(*this) { } bool source_mode_unset; }; void quickbook_grammar::impl::init_doc_info() { doc_info_grammar_local& local = cleanup_.add(new doc_info_grammar_local); typedef cl::uint_parser uint2_t; local.doc_types = "book", "article", "library", "chapter", "part", "appendix", "preface", "qandadiv", "qandaset", "reference", "set"; QUICKBOOK_FOR (value::tag_type t, doc_attributes::tags()) { local.doc_attributes.add(doc_attributes::name(t), t); local.doc_info_attributes.add(doc_attributes::name(t), t); } QUICKBOOK_FOR (value::tag_type t, doc_info_attributes::tags()) { local.doc_info_attributes.add(doc_info_attributes::name(t), t); } // Actions error_action error(state); plain_char_action plain_char(state); do_macro_action do_macro(state); scoped_parser to_value(state); member_action_value change_source_mode(state, &state::change_source_mode); member_action_fixed_value default_source_mode( state, &state::change_source_mode, source_mode_tags::cpp); // clang-format off doc_info_details = cl::eps_p [ph::var(local.source_mode_unset) = true] >> *( space >> local.doc_attribute ) >> !( space >> local.doc_info_block ) >> *eol ; local.doc_info_block = '[' >> space >> (local.doc_types >> cl::eps_p) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)] >> hard_space >> to_value(doc_info_tags::title) [ *( ~cl::eps_p(blank >> (cl::ch_p('[') | ']' | cl::eol_p)) >> local.char_ ) // Include 'blank' here so that it will be included in // id generation. >> blank ] >> space >> !(qbk_ver(106u) >> cl::eps_p(ph::var(local.source_mode_unset)) [default_source_mode] ) >> ( *( ( local.doc_info_attribute | local.doc_info_escaped_attributes ) >> space ) ) [state.values.sort()] >> ( ']' >> (eol | cl::end_p) | cl::eps_p [error] ) ; local.doc_attribute = '[' >> space >> local.doc_attributes [local.assign_attribute] >> hard_space >> state.values.list(ph::var(local.attribute_tag)) [ cl::eps_p [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)] >> local.attribute_rule ] >> space >> ']' ; local.doc_info_attribute = '[' >> space >> ( local.doc_info_attributes [local.assign_attribute] | (+(cl::alnum_p | '_' | '-')) [local.fallback_attribute] [error("Unrecognized document attribute: '%s'.")] ) >> hard_space >> state.values.list(ph::var(local.attribute_tag)) [local.attribute_rule] >> space >> ']' ; local.doc_fallback = to_value() [ *(~cl::eps_p(']') >> local.char_) ]; local.doc_info_escaped_attributes = ("'''" >> !eol) >> (*(cl::anychar_p - "'''")) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::escaped_attribute)] >> ( cl::str_p("'''") | cl::eps_p [error("Unclosed boostbook escape.")] ) ; // Document Attributes local.quickbook_version = cl::uint_p [state.values.entry(ph::arg1)] >> '.' >> uint2_t() [state.values.entry(ph::arg1)] ; local.attribute_rules[doc_attributes::qbk_version] = &local.quickbook_version; local.doc_compatibility_mode = cl::uint_p [state.values.entry(ph::arg1)] >> '.' >> uint2_t() [state.values.entry(ph::arg1)] ; local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode; local.doc_source_mode = source_modes [change_source_mode] [ph::var(local.source_mode_unset) = false] ; local.attribute_rules[doc_attributes::source_mode] = &local.doc_source_mode; // Document Info Attributes local.doc_simple = to_value() [*(~cl::eps_p(']') >> local.char_)]; local.attribute_rules[doc_info_attributes::version] = &local.doc_simple; local.attribute_rules[doc_info_attributes::id] = &local.doc_simple; local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple; local.attribute_rules[doc_info_attributes::category] = &local.doc_simple; local.attribute_rules[doc_info_attributes::last_revision] = &local.doc_simple; local.attribute_rules[doc_info_attributes::lang] = &local.doc_simple; local.attribute_rules[doc_info_attributes::xmlbase] = &local.doc_simple; local.doc_copyright_holder = *( ~cl::eps_p ( ']' | ',' >> space >> local.doc_copyright_year ) >> local.char_ ); local.doc_copyright = *( +( local.doc_copyright_year [state.values.entry(ph::arg1, doc_info_tags::copyright_year)] >> space >> !( '-' >> space >> local.doc_copyright_year [state.values.entry(ph::arg1, doc_info_tags::copyright_year_end)] >> space ) >> !cl::ch_p(',') >> space ) >> to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ] >> !cl::ch_p(',') >> space ) ; local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright; local.doc_phrase = to_value() [ nested_phrase ]; local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase; local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase; local.doc_author = '[' >> space >> to_value(doc_info_tags::author_surname) [*(~cl::eps_p(',') >> local.char_)] >> ',' >> space >> to_value(doc_info_tags::author_first) [*(~cl::eps_p(']') >> local.char_)] >> ']' ; local.doc_authors = *( local.doc_author >> space >> !(cl::ch_p(',') >> space) ) ; local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors; local.doc_biblioid = (+cl::alnum_p) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)] >> hard_space >> to_value(doc_info_tags::biblioid_value) [+(~cl::eps_p(']') >> local.char_)] ; local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid; local.char_ = escape | local.macro | cl::anychar_p[plain_char]; ; local.macro = cl::eps_p ( ( state.macro >> ~cl::eps_p(cl::alpha_p | '_') // must not be followed by alpha or underscore ) & macro_identifier // must be a valid macro for the current version ) >> state.macro [do_macro] ; // clang-format on } }