Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r70177 - in trunk/tools/quickbook: . doc src test test/unit
From: dnljms_at_[hidden]
Date: 2011-03-19 07:45:52


Author: danieljames
Date: 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
New Revision: 70177
URL: http://svn.boost.org/trac/boost/changeset/70177

Log:
Quickbook: merge 'values' from quickbook-filenames branch.

Added:
   trunk/tools/quickbook/src/doc_info_tags.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/doc_info_tags.hpp
   trunk/tools/quickbook/src/table_tags.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/table_tags.hpp
   trunk/tools/quickbook/src/template_tags.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/template_tags.hpp
   trunk/tools/quickbook/src/value_tags.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/value_tags.hpp
   trunk/tools/quickbook/src/values.cpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/values.cpp
   trunk/tools/quickbook/src/values.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/values.hpp
   trunk/tools/quickbook/src/values_parse.hpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/src/values_parse.hpp
   trunk/tools/quickbook/test/unit/
      - copied from r68889, /branches/quickbook-filenames/tools/quickbook/test/unit/
   trunk/tools/quickbook/test/unit/Jamfile.v2
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/test/unit/Jamfile.v2
   trunk/tools/quickbook/test/unit/values_test.cpp
      - copied unchanged from r68889, /branches/quickbook-filenames/tools/quickbook/test/unit/values_test.cpp
Properties modified:
   trunk/tools/quickbook/ (props changed)
Text files modified:
   trunk/tools/quickbook/doc/quickbook.qbk | 4
   trunk/tools/quickbook/src/Jamfile.v2 | 1
   trunk/tools/quickbook/src/actions.cpp | 338 +++++++++++++++++++++++----------------
   trunk/tools/quickbook/src/actions.hpp | 177 ++++----------------
   trunk/tools/quickbook/src/actions_class.cpp | 69 ++------
   trunk/tools/quickbook/src/actions_class.hpp | 67 -------
   trunk/tools/quickbook/src/block_element_grammar.cpp | 119 +++++--------
   trunk/tools/quickbook/src/doc_info_actions.cpp | 290 +++++++++++++++++++--------------
   trunk/tools/quickbook/src/doc_info_grammar.cpp | 215 ++++++++++++++----------
   trunk/tools/quickbook/src/main_grammar.cpp | 50 ++--
   trunk/tools/quickbook/src/phrase_element_grammar.cpp | 15
   trunk/tools/quickbook/src/scoped_parser.hpp | 11
   trunk/tools/quickbook/test/Jamfile.v2 | 1
   13 files changed, 641 insertions(+), 716 deletions(-)

Modified: trunk/tools/quickbook/doc/quickbook.qbk
==============================================================================
--- trunk/tools/quickbook/doc/quickbook.qbk (original)
+++ trunk/tools/quickbook/doc/quickbook.qbk 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -273,6 +273,10 @@
 * Reverse deprecation of `[br]`, printing a single warning about
   generating invalid boostbook.
 * Fix handling empty category attributes.
+* Store data from the parser in a dynamic data structure.
+ This simplifies the implementation and makes it easier to parse
+ more complicated data structures.
+* Improved error messages for unknown doc info attributes.
 * Quickbook 1.6:
   * Scope source mode changes to the file they're made in.
 

Modified: trunk/tools/quickbook/src/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/src/Jamfile.v2 (original)
+++ trunk/tools/quickbook/src/Jamfile.v2 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -26,6 +26,7 @@
     actions_class.cpp
     utils.cpp
     input_path.cpp
+ values.cpp
     post_process.cpp
     collector.cpp
     template_stack.cpp

Modified: trunk/tools/quickbook/src/actions.cpp
==============================================================================
--- trunk/tools/quickbook/src/actions.cpp (original)
+++ trunk/tools/quickbook/src/actions.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -15,6 +15,8 @@
 #include <boost/filesystem/v3/fstream.hpp>
 #include <boost/range/algorithm/replace.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/range/distance.hpp>
+#include <boost/algorithm/string/replace.hpp>
 #include "quickbook.hpp"
 #include "actions.hpp"
 #include "utils.hpp"
@@ -22,6 +24,8 @@
 #include "actions_class.hpp"
 #include "grammar.hpp"
 #include "input_path.hpp"
+#include "template_tags.hpp"
+#include "table_tags.hpp"
 
 namespace quickbook
 {
@@ -74,6 +78,21 @@
         phrase << break_mark;
     }
 
+ void error_message_action::operator()(iterator first, iterator last) const
+ {
+ file_position const pos = first.get_position();
+
+ std::string value(first, last);
+ std::string formatted_message = message;
+ boost::replace_all(formatted_message, "%s", value);
+ boost::replace_all(formatted_message, "%c",
+ boost::lexical_cast<std::string>(pos.column));
+
+ detail::outerr(actions.filename, pos.line)
+ << formatted_message << std::endl;
+ ++actions.error_count;
+ }
+
     void error_action::operator()(iterator first, iterator /*last*/) const
     {
         file_position const pos = first.get_position();
@@ -82,11 +101,12 @@
         ++actions.error_count;
     }
 
- void tagged_action::operator()(std::string const& str) const
+ void tagged_action::operator()(iterator, iterator) const
     {
         if(!actions.output_pre(out)) return;
 
- out << pre << str << post;
+ value_consumer values = actions.values.get();
+ out << pre << values.consume().get_boostbook() << post;
     }
 
     void phrase_action::operator()() const
@@ -145,6 +165,8 @@
 
         std::string str;
         phrase.swap(str);
+
+ value_consumer values = actions.values.get();
 
         std::string anchor;
 
@@ -156,7 +178,7 @@
         else
         {
             std::string id =
- !element_id.empty() ? element_id :
+ values.is(general_tags::element_id) ? values.consume().get_quickbook() :
                 qbk_version_n >= 106 ? detail::make_identifier(first, last) :
                 detail::make_identifier(str.begin(), str.end());
 
@@ -185,8 +207,10 @@
         std::string str;
         phrase.swap(str);
 
+ value_consumer values = actions.values.get();
+
         std::string id =
- !element_id.empty() ? element_id :
+ values.is(general_tags::element_id) ? values.consume().get_quickbook() :
             qbk_version_n >= 106 ? detail::make_identifier(first, last) :
             detail::make_identifier(str.begin(), str.end());
 
@@ -503,33 +527,45 @@
         }
     }
 
- void attribute_action::operator()(iterator first, iterator last) const
+ void image_action::operator()(iterator, iterator) const
     {
- file_position const pos = first.get_position();
+ if(!actions.output_pre(phrase)) return;
+
+ typedef std::map<std::string, value> attribute_map;
+ attribute_map attributes;
 
- if (!attributes.insert(
- attribute_map::value_type(attribute_name, std::string(first, last))
- ).second)
+ value_consumer values = actions.values.get();
+ attributes["fileref"] = values.consume();
+
+ BOOST_FOREACH(value pair_, values)
         {
- detail::outwarn(actions.filename, pos.line)
- << "Repeated attribute: " << detail::utf8(attribute_name) << ".\n";
+ value_consumer pair = pair_;
+ value name = pair.consume();
+ value value = pair.consume();
+ assert(!pair.is());
+ if(!attributes.insert(std::make_pair(name.get_quickbook(), value)).second)
+ {
+ detail::outwarn(actions.filename, name.get_position().line)
+ << "Duplicate image attribute: " << name.get_quickbook() << std::endl;
+ }
         }
- }
 
- void image_action::operator()(iterator first, iterator) const
- {
- if(!actions.output_pre(phrase)) return;
+ // Find the file basename and extension.
+ //
+ // Not using Boost.Filesystem because I want to stay in UTF-8.
+ // Need to think about uri encoding.
         
- std::string fileref = image_fileref;
+ std::string fileref = attributes["fileref"].get_quickbook();
 
         // Check for windows paths, then convert.
         // A bit crude, but there you go.
 
         if(fileref.find('\\') != std::string::npos)
         {
- detail::outwarn(actions.filename, first.get_position().line)
- << "Image path isn't portable: "
+ detail::outwarn(actions.filename, attributes["fileref"].get_position().line)
+ << "Image path isn't portable: '"
                 << detail::utf8(fileref)
+ << "'"
                 << std::endl;
         }
 
@@ -543,10 +579,10 @@
         std::string::size_type pos;
         std::string stem,extension;
 
- pos = image_fileref.rfind('/');
+ pos = fileref.rfind('/');
         stem = pos == std::string::npos ?
- image_fileref :
- image_fileref.substr(pos + 1);
+ fileref :
+ fileref.substr(pos + 1);
 
         pos = stem.rfind('.');
         if (pos != std::string::npos)
@@ -560,12 +596,11 @@
         // TODO: IMO if there isn't an alt tag, then the description should
         // be empty or missing.
 
- attribute_map::iterator it = attributes.find("alt");
- std::string alt_text = it != attributes.end() ? it->second : stem;
+ attribute_map::iterator alt_pos = attributes.find("alt");
+ std::string alt_text = alt_pos != attributes.end() ?
+ alt_pos->second.get_quickbook() : stem;
         attributes.erase("alt");
 
- attributes.insert(attribute_map::value_type("fileref", image_fileref));
-
         if(extension == ".svg")
         {
            //
@@ -579,13 +614,15 @@
            // a tiny box with scrollbars (Firefox), or else cropped to
            // fit in a tiny box (IE7).
            //
- attributes.insert(attribute_map::value_type("format", "SVG"));
+
+ attributes.insert(attribute_map::value_type("format", qbk_value("SVG")));
+
            //
            // Image paths are relative to the html subdirectory:
            //
            // TODO: This seems wrong to me.
            //
- fs::path img = detail::generic_to_path(image_fileref);
+ fs::path img = detail::generic_to_path(fileref);
            if(img.root_path().empty())
               img = "html" / img; // relative path
 
@@ -614,8 +651,10 @@
            b = svg_text.find('\"', a + 1);
            if(a != std::string::npos)
            {
- attributes.insert(attribute_map::value_type("contentwidth",
- std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+ attributes.insert(std::make_pair(
+ "contentwidth", qbk_value(std::string(
+ svg_text.begin() + a + 1, svg_text.begin() + b))
+ ));
            }
            a = svg_text.find("height");
            a = svg_text.find('=', a);
@@ -623,8 +662,10 @@
            b = svg_text.find('\"', a + 1);
            if(a != std::string::npos)
            {
- attributes.insert(attribute_map::value_type("contentdepth",
- std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+ attributes.insert(std::make_pair(
+ "contentdepth", qbk_value(std::string(
+ svg_text.begin() + a + 1, svg_text.begin() + b))
+ ));
            }
         }
 
@@ -632,15 +673,13 @@
 
         phrase << "<imageobject><imagedata";
         
- for(attribute_map::const_iterator
- attr_first = attributes.begin(), attr_last = attributes.end();
- attr_first != attr_last; ++attr_first)
+ BOOST_FOREACH(attribute_map::value_type const& attr, attributes)
         {
- phrase << " " << attr_first->first << "=\"";
+ phrase << " " << attr.first << "=\"";
 
+ std::string value = attr.second.get_quickbook();
             for(std::string::const_iterator
- first = attr_first->second.begin(),
- last = attr_first->second.end();
+ first = value.begin(), last = value.end();
                 first != last; ++first)
             {
                 if (*first == '\\' && ++first == last) break;
@@ -679,27 +718,37 @@
         actions.phrase.pop(); // restore the phrase
     }
 
- void template_body_action::operator()(iterator first, iterator last) const
+ void template_body_action::operator()(iterator, iterator) const
     {
         if(actions.suppress) return;
+
+ value_consumer values = actions.values.get();
+ std::string identifier = values.consume().get_quickbook();
+
+ std::vector<std::string> template_values;
+ BOOST_FOREACH(value const& p, values.consume()) {
+ template_values.push_back(p.get_quickbook());
+ }
+
+ BOOST_ASSERT(values.is(template_tags::block) || values.is(template_tags::phrase));
+ value body = values.consume();
+ BOOST_ASSERT(!values.is());
+
         if (!actions.templates.add(
             template_symbol(
- actions.template_identifier,
- actions.template_info,
- std::string(first, last),
+ identifier,
+ template_values,
+ body.get_quickbook(),
                 actions.filename,
- first.get_position(),
- actions.template_block,
+ body.get_position(),
+ body.get_tag() == template_tags::block,
                 &actions.templates.top_scope())))
         {
- file_position const pos = first.get_position();
+ file_position const pos = body.get_position();
             detail::outerr(actions.filename, pos.line)
- << "Template Redefinition: " << detail::utf8(actions.template_identifier) << std::endl;
+ << "Template Redefinition: " << detail::utf8(identifier) << std::endl;
             ++actions.error_count;
         }
-
- actions.template_identifier.clear();
- actions.template_info.clear();
     }
 
     namespace
@@ -900,29 +949,36 @@
         int callout_id = 0;
     }
 
- void template_arg_action::operator()(iterator first, iterator last) const
+ void do_template_action::operator()(iterator first, iterator) const
     {
         if(actions.suppress) return;
 
- actions.template_args.push_back(
- template_body(
- std::string(first, last),
- actions.filename,
- first.get_position(),
- actions.template_block));
- }
+ file_position const pos = first.get_position();
+
+ // Get the arguments
+ value_consumer values = actions.values.get();
 
- void do_template_action::operator()(iterator first, iterator) const
- {
- if(actions.suppress) return;
+ bool template_escape = values.is(template_tags::escape);
+ if(template_escape) values.consume();
 
- // Get the arguments and clear values stored in action.
+ std::string identifier = values.consume(template_tags::identifier).get_quickbook();
 
         std::vector<template_body> args;
- std::string identifier;
- std::swap(args, actions.template_args);
- std::swap(identifier, actions.template_identifier);
- file_position const pos = first.get_position();
+
+ BOOST_FOREACH(value arg, values)
+ {
+ BOOST_ASSERT(
+ arg.get_tag() == template_tags::block ||
+ arg.get_tag() == template_tags::phrase);
+
+ args.push_back(
+ template_body(
+ arg.get_quickbook(),
+ actions.filename,
+ arg.get_position(),
+ arg.get_tag() == template_tags::block
+ ));
+ }
 
         ++actions.template_depth;
         if (actions.template_depth > actions.max_template_depth)
@@ -1022,7 +1078,7 @@
             ///////////////////////////////////
             // parse the template body:
 
- if (!parse_template(symbol->body, actions.template_escape, actions))
+ if (!parse_template(symbol->body, template_escape, actions))
             {
                 file_position const pos = first.get_position();
                 detail::outerr(actions.filename, pos.line)
@@ -1130,46 +1186,72 @@
     {
         if(actions.suppress) return;
 
+ value_consumer values = actions.values.get();
+ std::string title = values.consume(table_tags::title).get_quickbook();
+
         actions.out << "<variablelist>\n";
 
         actions.out << "<title>";
- std::string::iterator first = actions.table_title.begin();
- std::string::iterator last = actions.table_title.end();
- while (first != last)
- detail::print_char(*first++, actions.out.get());
+ detail::print_string(title, actions.out.get());
         actions.out << "</title>\n";
 
- std::string str;
- actions.phrase.swap(str);
- actions.out << str;
+ BOOST_FOREACH(value_consumer entry, values) {
+ actions.out << start_varlistentry_;
+
+ if(entry.is()) {
+ actions.out << start_varlistterm_;
+ actions.out << entry.consume().get_boostbook();
+ actions.out << end_varlistterm_;
+ }
+
+ if(entry.is()) {
+ actions.out << start_varlistitem_;
+ BOOST_FOREACH(value phrase, entry) actions.out << phrase.get_boostbook();
+ actions.out << end_varlistitem_;
+ }
+
+ actions.out << end_varlistentry_;
+ }
 
         actions.out << "</variablelist>\n";
- actions.table_span = 0;
- actions.table_header.clear();
- actions.table_title.clear();
     }
 
     void table_action::operator()(iterator, iterator) const
     {
         if(actions.suppress) return;
 
- std::string::iterator first = actions.table_title.begin();
- std::string::iterator last = actions.table_title.end();
- bool has_title = first != last;
+ value_consumer values = actions.values.get();
+
+ std::string element_id;
+ if(values.is(general_tags::element_id))
+ element_id = values.consume().get_quickbook();
+
+ std::string title = values.consume(table_tags::title).get_quickbook();
+ bool has_title = !title.empty();
         
         std::string table_id;
         if(qbk_version_n >= 105) {
- if(!actions.element_id.empty()) {
+ if(!element_id.empty()) {
                 table_id = fully_qualified_id(actions.doc_id,
- actions.qualified_section_id, actions.element_id);
+ actions.qualified_section_id, element_id);
             }
             else if(has_title) {
                 table_id = fully_qualified_id(actions.doc_id,
                     actions.qualified_section_id,
- detail::make_identifier(first, last));
+ detail::make_identifier(title.begin(), title.end()));
             }
         }
 
+ // Emulating the old behaviour which used the width of the final
+ // row for span_count.
+ int row_count = 0;
+ int span_count = 0;
+
+ BOOST_FOREACH(value row, values) {
+ ++row_count;
+ span_count = boost::distance(row);
+ }
+
         if (has_title)
         {
             actions.out << "<table frame=\"all\"";
@@ -1177,8 +1259,7 @@
                 actions.out << " id=\"" << table_id << "\"";
             actions.out << ">\n";
             actions.out << "<title>";
- while (first != last)
- detail::print_char(*first++, actions.out.get());
+ detail::print_string(title, actions.out.get());
             actions.out << "</title>";
         }
         else
@@ -1189,18 +1270,26 @@
             actions.out << ">\n";
         }
 
- actions.out << "<tgroup cols=\"" << actions.table_span << "\">\n";
+ actions.out << "<tgroup cols=\"" << span_count << "\">\n";
 
- if (!actions.table_header.empty())
+ if (row_count > 1)
         {
- actions.out << "<thead>" << actions.table_header << "</thead>\n";
+ actions.out << "<thead>" << start_row_;
+ BOOST_FOREACH(value cell, values.consume()) {
+ actions.out << start_cell_ << cell.get_boostbook() << end_cell_;
+ }
+ actions.out << end_row_ << "</thead>\n";
         }
 
         actions.out << "<tbody>\n";
 
- std::string str;
- actions.phrase.swap(str);
- actions.out << str;
+ BOOST_FOREACH(value row, values) {
+ actions.out << start_row_;
+ BOOST_FOREACH(value cell, row) {
+ actions.out << start_cell_ << cell.get_boostbook() << end_cell_;
+ }
+ actions.out << end_row_;
+ }
 
         actions.out << "</tbody>\n"
                      << "</tgroup>\n";
@@ -1213,45 +1302,17 @@
         {
             actions.out << "</informaltable>\n";
         }
-
- actions.table_span = 0;
- actions.table_header.clear();
- actions.table_title.clear();
- }
-
- void start_row_action::operator()(char) const
- {
- if (actions.suppress) return;
-
- // the first row is the header
- if (header.empty() && !phrase.str().empty())
- {
- phrase.swap(header);
- }
-
- phrase << start_row_;
- span = 0;
- }
-
- void start_row_action::operator()(iterator f, iterator) const
- {
- (*this)(*f);
- }
-
- void col_action::operator()(std::string const& contents) const
- {
- if(actions.suppress) return;
- phrase << start_cell_ << contents << end_cell_;
- ++span;
     }
 
     void begin_section_action::operator()(iterator first, iterator last) const
     {
         if(actions.suppress) return;
 
- section_id = element_id.empty() ?
- detail::make_identifier(first, last) :
- element_id;
+ value_consumer values = actions.values.get();
+
+ section_id = values.is(general_tags::element_id) ?
+ values.consume().get_quickbook() :
+ detail::make_identifier(first, last);
 
         if (section_level != 0)
             qualified_section_id += '.';
@@ -1454,7 +1515,6 @@
         fs::path filein = include_search(actions.filename.parent_path(),
             check_path(first, last, actions));
         std::string doc_type, doc_id;
- docinfo_string doc_dirname, doc_last_revision;
 
         // swap the filenames
         std::swap(actions.filename, filein);
@@ -1463,14 +1523,10 @@
         if(qbk_version_n >= 106) {
             doc_type = actions.doc_type;
             doc_id = actions.doc_id;
- doc_dirname = actions.doc_dirname;
- doc_last_revision = actions.doc_last_revision;
         }
         else {
             actions.doc_type.swap(doc_type);
             actions.doc_id.swap(doc_id);
- actions.doc_dirname.swap(doc_dirname);
- actions.doc_last_revision.swap(doc_last_revision);
         }
         
         // save the source mode and version info (only restored for 1.6+)
@@ -1505,8 +1561,6 @@
 
         actions.doc_type.swap(doc_type);
         actions.doc_id.swap(doc_id);
- actions.doc_dirname.swap(doc_dirname);
- actions.doc_last_revision.swap(doc_last_revision);
         
         if(qbk_version_n >= 106 || qbk_version_n_store >= 106)
         {
@@ -1534,11 +1588,22 @@
 
     void phrase_to_docinfo_action::operator()(iterator first, iterator last) const
     {
- if(!actions.output_pre(phrase)) return;
+ if(!actions.output_pre(actions.phrase)) return;
+
+ std::string encoded;
+ actions.phrase.swap(encoded);
+ actions.values.builder.insert(
+ qbk_bbk_value(first, last, encoded, actions.values.builder.release_tag()));
+ }
+
+ void phrase_to_value_action::operator()(iterator first, iterator last) const
+ {
+ if(!actions.output_pre(actions.phrase)) return;
 
- out.encoded.clear();
- phrase.swap(out.encoded);
- out.raw = std::string(first, last);
+ std::string value;
+ actions.phrase.swap(value);
+ actions.values.builder.insert(
+ bbk_value(value, actions.values.builder.release_tag()));
     }
     
     void inner_phrase_action_pre::operator()(iterator, iterator) const
@@ -1594,12 +1659,11 @@
         actions.out.pop();
     }
 
- std::string const& scoped_block_push::success_impl()
+ void scoped_block_push::success_impl()
     {
- // TODO: This should probably return an empty string
- // if actions.suppress is true.
         actions.inside_paragraph();
- return actions.out.str();
+ actions.values.builder.insert(
+ bbk_value(actions.out.str(), actions.values.builder.release_tag()));
     }
 
     set_no_eols_scoped::set_no_eols_scoped(quickbook::actions& actions)

Modified: trunk/tools/quickbook/src/actions.hpp
==============================================================================
--- trunk/tools/quickbook/src/actions.hpp (original)
+++ trunk/tools/quickbook/src/actions.hpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -72,7 +72,6 @@
     }
 
     typedef cl::symbols<std::string> string_symbols;
- typedef std::map<std::string, std::string> attribute_map;
 
     int load_snippets(std::string const& file, std::vector<template_symbol>& storage,
         std::string const& extension, std::string const& doc_id);
@@ -81,44 +80,27 @@
         actions& escape_actions,
         std::string const& source_mode);
 
- template <typename Derived, typename DataT = void>
     struct scoped_action_base
     {
         typedef quickbook::actions data_type;
         
- template <typename T>
- struct result
- {
- typedef cl::match<DataT> type;
- };
-
- template <typename T>
- DataT success(T const&)
- {
- return static_cast<Derived*>(this)->success_impl();
- }
-
- void failure() {
- return static_cast<Derived*>(this)->failure_impl();
- }
-
- void failure_impl() {}
+ template <typename T> void success(T const&) {}
+ void failure() {}
     };
 
- struct void_type {};
-
- template <typename Derived>
- struct scoped_action_base<Derived, void>
- : scoped_action_base<Derived, void_type>
+ struct error_message_action
     {
- template <typename T>
- void_type success(T const&)
- {
- static_cast<Derived*>(this)->success_impl();
- return void_type();
- }
-
- void success_impl() {}
+ // Prints an error message to std::cerr
+
+ error_message_action(quickbook::actions& actions, std::string const& m)
+ : actions(actions)
+ , message(m)
+ {}
+
+ void operator()(iterator, iterator) const;
+
+ quickbook::actions& actions;
+ std::string message;
     };
 
     struct error_action
@@ -130,6 +112,11 @@
 
         void operator()(iterator first, iterator /*last*/) const;
 
+ error_message_action operator()(std::string const& message)
+ {
+ return error_message_action(actions, message);
+ }
+
         quickbook::actions& actions;
     };
 
@@ -145,7 +132,7 @@
         , post(post)
         , actions(actions) {}
 
- void operator()(std::string const&) const;
+ void operator()(iterator, iterator) const;
 
         collector& out;
         std::string pre;
@@ -216,7 +203,6 @@
         header_action(
             collector& out,
             collector& phrase,
- std::string const& element_id,
             std::string const& library_id,
             std::string const& section_id,
             std::string const& qualified_section_id,
@@ -224,7 +210,6 @@
             quickbook::actions& actions)
         : out(out)
         , phrase(phrase)
- , element_id(element_id)
         , library_id(library_id)
         , section_id(section_id)
         , qualified_section_id(qualified_section_id)
@@ -235,7 +220,6 @@
 
         collector& out;
         collector& phrase;
- std::string const& element_id;
         std::string const& library_id;
         std::string const& section_id;
         std::string const& qualified_section_id;
@@ -250,7 +234,6 @@
         generic_header_action(
             collector& out,
             collector& phrase,
- std::string const& element_id,
             std::string const& library_id,
             std::string const& section_id,
             std::string const& qualified_section_id,
@@ -258,7 +241,6 @@
             quickbook::actions& actions)
         : out(out)
         , phrase(phrase)
- , element_id(element_id)
         , library_id(library_id)
         , section_id(section_id)
         , qualified_section_id(qualified_section_id)
@@ -269,7 +251,6 @@
 
         collector& out;
         collector& phrase;
- std::string const& element_id;
         std::string const& library_id;
         std::string const& section_id;
         std::string const& qualified_section_id;
@@ -318,7 +299,7 @@
         string_symbols const& macro;
     };
 
- struct cond_phrase_push : scoped_action_base<cond_phrase_push>
+ struct cond_phrase_push : scoped_action_base
     {
         cond_phrase_push(quickbook::actions&);
         ~cond_phrase_push();
@@ -519,44 +500,19 @@
         quickbook::actions& actions;
     };
 
- struct attribute_action
- {
- // Handle image attributes
-
- attribute_action(
- attribute_map& attributes
- , std::string& attribute_name
- , quickbook::actions& actions)
- : attributes(attributes)
- , attribute_name(attribute_name)
- , actions(actions) {}
-
- void operator()(iterator first, iterator last) const;
-
- attribute_map& attributes;
- std::string& attribute_name;
- quickbook::actions& actions;
- };
-
     struct image_action
     {
         // Handles inline images
 
         image_action(
             collector& phrase
- , attribute_map& attributes
- , std::string& image_fileref
           , quickbook::actions& actions)
         : phrase(phrase)
- , attributes(attributes)
- , image_fileref(image_fileref)
         , actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
 
         collector& phrase;
- attribute_map& attributes;
- std::string& image_fileref;
         quickbook::actions& actions;
     };
 
@@ -674,18 +630,6 @@
         quickbook::actions& actions;
     };
     
- struct template_arg_action
- {
- // Handles a template argument
-
- template_arg_action(quickbook::actions& actions)
- : actions(actions) {}
-
- void operator()(iterator first, iterator last) const;
-
- quickbook::actions& actions;
- };
-
     struct do_template_action
     {
         // Handles template substitutions
@@ -739,34 +683,6 @@
         quickbook::actions& actions;
     };
 
- struct start_row_action
- {
- // Handles table rows
-
- start_row_action(collector& phrase, unsigned& span, std::string& header, quickbook::actions& actions)
- : phrase(phrase), span(span), header(header), actions(actions) {}
-
- void operator()(char) const;
- void operator()(iterator f, iterator) const;
-
- collector& phrase;
- unsigned& span;
- std::string& header;
- quickbook::actions& actions;
- };
-
- struct col_action
- {
- col_action(collector& phrase, unsigned& span, quickbook::actions& actions)
- : phrase(phrase), span(span), actions(actions) {}
-
- void operator()(std::string const&) const;
-
- collector& phrase;
- unsigned& span;
- quickbook::actions& actions;
- };
-
     struct begin_section_action
     {
         // Handles begin page
@@ -778,7 +694,6 @@
           , std::string& section_id
           , int& section_level
           , std::string& qualified_section_id
- , std::string& element_id
           , quickbook::actions& actions)
         : out(out)
         , phrase(phrase)
@@ -786,7 +701,6 @@
         , section_id(section_id)
         , section_level(section_level)
         , qualified_section_id(qualified_section_id)
- , element_id(element_id)
         , actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
@@ -797,7 +711,6 @@
         std::string& section_id;
         int& section_level;
         std::string& qualified_section_id;
- std::string& element_id;
         quickbook::actions& actions;
     };
 
@@ -873,29 +786,6 @@
         quickbook::actions& actions;
     };
 
- struct docinfo_string {
- std::string raw;
- std::string encoded;
-
- docinfo_string() : raw(), encoded() {}
-
- void swap(docinfo_string& x) {
- raw.swap(x.raw);
- encoded.swap(x.encoded);
- }
-
- void clear() {
- raw.clear();
- encoded.clear();
- }
-
- bool empty() const {
- return raw.empty();
- }
-
- std::string const& get(unsigned version) const;
- };
-
     void pre(collector& out, quickbook::actions& actions, bool ignore_docinfo = false);
     void post(collector& out, quickbook::actions& actions, bool ignore_docinfo = false);
 
@@ -913,15 +803,21 @@
 
     struct phrase_to_docinfo_action
     {
- phrase_to_docinfo_action(docinfo_string& out, collector& phrase, quickbook::actions& actions)
- : out(out)
- , phrase(phrase)
- , actions(actions) {}
+ phrase_to_docinfo_action(quickbook::actions& actions)
+ : actions(actions) {}
+
+ void operator()(iterator first, iterator last) const;
+
+ quickbook::actions& actions;
+ };
+
+ struct phrase_to_value_action
+ {
+ phrase_to_value_action(quickbook::actions& actions)
+ : actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
 
- docinfo_string& out;
- collector& phrase;
         quickbook::actions& actions;
     };
 
@@ -956,16 +852,17 @@
         quickbook::actions& actions;
     };
 
- struct scoped_block_push : scoped_action_base<scoped_block_push, std::string>
+ struct scoped_block_push : scoped_action_base
     {
         scoped_block_push(quickbook::actions&);
         ~scoped_block_push();
- std::string const& success_impl();
+ template <typename T> void success(T const&) { this->success_impl(); }
+ void success_impl();
 
         quickbook::actions& actions;
     };
 
- struct set_no_eols_scoped : scoped_action_base<set_no_eols_scoped>
+ struct set_no_eols_scoped : scoped_action_base
     {
         set_no_eols_scoped(quickbook::actions&);
         ~set_no_eols_scoped();

Modified: trunk/tools/quickbook/src/actions_class.cpp
==============================================================================
--- trunk/tools/quickbook/src/actions_class.cpp (original)
+++ trunk/tools/quickbook/src/actions_class.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -23,18 +23,14 @@
     actions::actions(fs::path const& filein_, fs::path const& outdir_, string_stream& out_)
         : grammar_()
 
+ , values()
+ , phrase_value(*this)
+ , docinfo_value(*this)
+
     // header info
         , doc_type()
- , doc_title()
- , doc_version()
+ , doc_title_qbk()
         , doc_id()
- , doc_dirname()
- , doc_copyrights()
- , doc_purpose()
- , doc_categories()
- , doc_authors()
- , doc_license()
- , doc_last_revision()
         , include_doc_id()
 
     // main output stream
@@ -56,22 +52,12 @@
         , source_mode("c++")
 
     // temporary or global state
- , element_id()
- , table_title()
- , table_span(0)
- , table_header()
         , macro_id()
         , list_marks()
         , list_indent(-1)
- , template_identifier()
- , template_info()
         , template_depth(0)
- , template_escape(false)
         , templates()
         , error_count(0)
- , image_fileref()
- , attribute_name()
- , attributes()
         , anchors()
         , saved_anchors()
         , no_eols(true)
@@ -80,31 +66,18 @@
 
     // actions
         , error(*this)
- , extract_doc_title(doc_title, phrase, *this)
- , extract_doc_license(doc_license, phrase, *this)
- , extract_doc_purpose(doc_purpose, phrase, *this)
- , extract_doc_version(doc_version, phrase, *this)
- , extract_doc_id(doc_id_tmp, phrase, *this)
- , extract_doc_dirname(doc_dirname, phrase, *this)
- , extract_copyright_second(copyright.second, phrase, *this)
- , extract_name_second(name.second, phrase, *this)
- , extract_name_first(name.first, phrase, *this)
- , extract_doc_last_revision(doc_last_revision, phrase, *this)
- , extract_doc_category(doc_category, phrase, *this)
- , extract_doc_biblioid(doc_biblioid.second, phrase, *this)
- , extract_doc_lang(doc_lang, phrase, *this)
         , scoped_block(*this)
         , code(out, phrase, *this)
         , code_block(phrase, phrase, *this)
         , inline_code(phrase, *this)
         , inside_paragraph(out, phrase, paragraph_pre, paragraph_post, *this)
- , h(out, phrase, element_id, doc_id, section_id, qualified_section_id, section_level, *this)
- , h1(out, phrase, element_id, doc_id, section_id, qualified_section_id, 1, *this)
- , h2(out, phrase, element_id, doc_id, section_id, qualified_section_id, 2, *this)
- , h3(out, phrase, element_id, doc_id, section_id, qualified_section_id, 3, *this)
- , h4(out, phrase, element_id, doc_id, section_id, qualified_section_id, 4, *this)
- , h5(out, phrase, element_id, doc_id, section_id, qualified_section_id, 5, *this)
- , h6(out, phrase, element_id, doc_id, section_id, qualified_section_id, 6, *this)
+ , h(out, phrase, doc_id, section_id, qualified_section_id, section_level, *this)
+ , h1(out, phrase, doc_id, section_id, qualified_section_id, 1, *this)
+ , h2(out, phrase, doc_id, section_id, qualified_section_id, 2, *this)
+ , h3(out, phrase, doc_id, section_id, qualified_section_id, 3, *this)
+ , h4(out, phrase, doc_id, section_id, qualified_section_id, 4, *this)
+ , h5(out, phrase, doc_id, section_id, qualified_section_id, 5, *this)
+ , h6(out, phrase, doc_id, section_id, qualified_section_id, 6, *this)
         , hr(out, hr_, *this)
         , blurb(out, blurb_pre, blurb_post, *this)
         , blockquote(out, blockquote_pre, blockquote_post, *this)
@@ -119,8 +92,7 @@
         , plain_char(phrase, *this)
         , raw_char(phrase, *this)
         , escape_unicode(phrase, *this)
- , attribute(attributes, attribute_name, *this)
- , image(phrase, attributes, image_fileref, *this)
+ , image(phrase, *this)
         , cond_phrase_pre(condition, macro)
         , scoped_cond_phrase(*this)
 
@@ -169,30 +141,21 @@
         , simple_strikethrough(phrase, strikethrough_pre_, strikethrough_post_, macro, *this)
 
         , variablelist(*this)
- , start_varlistentry(phrase, start_varlistentry_, *this)
- , end_varlistentry(phrase, end_varlistentry_, *this)
- , start_varlistterm(phrase, start_varlistterm_, *this)
- , end_varlistterm(phrase, end_varlistterm_, *this)
- , varlistitem(phrase, start_varlistitem_, end_varlistitem_, *this)
 
         , break_(phrase, *this)
         , macro_identifier(*this)
         , macro_definition(*this)
         , do_macro(phrase, *this)
         , template_body(*this)
- , template_arg(*this)
         , do_template(*this)
         , url_pre(phrase, url_pre_, *this)
         , url_post(phrase, url_post_, *this)
         , link_pre(phrase, link_pre_, *this)
         , link_post(phrase, link_post_, *this)
         , table(*this)
- , start_row(phrase, table_span, table_header, *this)
- , end_row(phrase, end_row_, *this)
- , cell(phrase, table_span, *this)
         , anchor(*this)
 
- , begin_section(out, phrase, doc_id, section_id, section_level, qualified_section_id, element_id, *this)
+ , begin_section(out, phrase, doc_id, section_id, section_level, qualified_section_id, *this)
         , end_section(out, section_level, min_section_level, qualified_section_id, error_count, *this)
         , element_id_warning(*this)
         , xinclude(out, *this)
@@ -241,7 +204,8 @@
         out.push();
         phrase.push();
         list_buffer.push();
- templates.push();
+ templates.push();
+ values.builder.save();
     }
     
     // Pushing and popping the macro symbol table is pretty expensive, so
@@ -282,6 +246,7 @@
         phrase.pop();
         list_buffer.pop();
         templates.pop();
+ values.builder.restore();
     }
     
     quickbook_grammar& actions::grammar() const {

Modified: trunk/tools/quickbook/src/actions_class.hpp
==============================================================================
--- trunk/tools/quickbook/src/actions_class.hpp (original)
+++ trunk/tools/quickbook/src/actions_class.hpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -12,6 +12,7 @@
 
 #include "actions.hpp"
 #include "scoped_parser.hpp"
+#include "values_parse.hpp"
 #include <boost/tuple/tuple.hpp>
 #include <boost/scoped_ptr.hpp>
 
@@ -34,38 +35,18 @@
 
         typedef std::vector<std::string> string_list;
 
- typedef std::vector<docinfo_string> docinfo_list;
- typedef std::pair<docinfo_string, docinfo_string> author;
- typedef std::vector<author> author_list;
- typedef std::pair<string_list, docinfo_string> copyright_item;
- typedef std::vector<copyright_item> copyright_list;
- typedef std::pair<std::string, docinfo_string> biblioid_item;
- typedef std::vector<biblioid_item> biblioid_list;
         typedef std::pair<char, int> mark_type;
         static int const max_template_depth = 100;
 
+ value_parser values;
+ phrase_to_value_action phrase_value;
+ phrase_to_docinfo_action docinfo_value;
+
     // header info
         std::string doc_type;
- docinfo_string doc_title;
- docinfo_string doc_version;
+ std::string doc_title_qbk;
         std::string doc_id;
- docinfo_string doc_dirname;
- copyright_list doc_copyrights;
- docinfo_string doc_purpose;
- docinfo_list doc_categories;
- author_list doc_authors;
- docinfo_string doc_license;
- docinfo_string doc_last_revision;
- biblioid_list doc_biblioid_items;
- docinfo_string doc_lang;
         std::string include_doc_id;
- //temporary state
- biblioid_item doc_biblioid;
- docinfo_string doc_id_tmp;
- author name;
- copyright_item copyright;
- docinfo_string doc_category;
-
 
     // main output stream
         collector out;
@@ -101,26 +82,13 @@
         std::stack<string_symbols> macro_stack;
 
     // temporary or global state
- std::string element_id;
- std::string table_title;
- unsigned table_span;
- std::string table_header;
         std::string macro_id;
         std::stack<mark_type> list_marks;
         int list_indent;
         bool condition;
- std::string template_identifier;
- string_list template_info;
         int template_depth;
- bool template_escape;
- bool template_block;
- std::vector<quickbook::template_body>
- template_args;
         template_stack templates;
         int error_count;
- std::string image_fileref;
- std::string attribute_name;
- attribute_map attributes;
         string_list anchors;
         string_list saved_anchors;
         bool no_eols;
@@ -137,19 +105,6 @@
     // actions
     ///////////////////////////////////////////////////////////////////////////
         error_action error;
- phrase_to_docinfo_action extract_doc_title;
- phrase_to_docinfo_action extract_doc_license;
- phrase_to_docinfo_action extract_doc_purpose;
- phrase_to_docinfo_action extract_doc_version;
- phrase_to_docinfo_action extract_doc_id;
- phrase_to_docinfo_action extract_doc_dirname;
- phrase_to_docinfo_action extract_copyright_second;
- phrase_to_docinfo_action extract_name_second;
- phrase_to_docinfo_action extract_name_first;
- phrase_to_docinfo_action extract_doc_last_revision;
- phrase_to_docinfo_action extract_doc_category;
- phrase_to_docinfo_action extract_doc_biblioid;
- phrase_to_docinfo_action extract_doc_lang;
 
         scoped_parser<scoped_block_push>
                                 scoped_block;
@@ -170,7 +125,6 @@
         plain_char_action plain_char;
         raw_char_action raw_char;
         escape_unicode_action escape_unicode;
- attribute_action attribute;
         image_action image;
         cond_phrase_action_pre cond_phrase_pre;
         scoped_parser<cond_phrase_push>
@@ -221,27 +175,18 @@
         simple_phrase_action simple_strikethrough;
 
         variablelist_action variablelist;
- markup_action start_varlistentry;
- markup_action end_varlistentry;
- markup_action start_varlistterm;
- markup_action end_varlistterm;
- tagged_action varlistitem;
 
         break_action break_;
         macro_identifier_action macro_identifier;
         macro_definition_action macro_definition;
         do_macro_action do_macro;
         template_body_action template_body;
- template_arg_action template_arg;
         do_template_action do_template;
         link_action url_pre;
         markup_action url_post;
         link_action link_pre;
         markup_action link_post;
         table_action table;
- start_row_action start_row;
- markup_action end_row;
- col_action cell;
         anchor_action anchor;
 
         begin_section_action begin_section;

Modified: trunk/tools/quickbook/src/block_element_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/block_element_grammar.cpp (original)
+++ trunk/tools/quickbook/src/block_element_grammar.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -11,6 +11,8 @@
 #include "utils.hpp"
 #include "actions_class.hpp"
 #include "grammar_impl.hpp"
+#include "table_tags.hpp"
+#include "template_tags.hpp"
 #include <boost/spirit/include/classic_assign_actor.hpp>
 #include <boost/spirit/include/classic_if.hpp>
 #include <boost/spirit/include/classic_clear_actor.hpp>
@@ -41,33 +43,24 @@
         block_element_grammar_local& local = store_.create();
 
         local.element_id =
- ':'
- >>
- (
- cl::if_p(qbk_since(105u)) [space]
- >> (+(cl::alnum_p | '_')) [cl::assign_a(actions.element_id)]
+ !( ':'
+ >> ( cl::if_p(qbk_since(105u)) [space]
+ >> (+(cl::alnum_p | '_')) [actions.values.entry(general_tags::element_id)]
                 | cl::eps_p [actions.element_id_warning]
- [cl::assign_a(actions.element_id)]
                 )
- | cl::eps_p [cl::assign_a(actions.element_id)]
+ )
             ;
         
         local.element_id_1_5 =
                 cl::if_p(qbk_since(105u)) [
                     local.element_id
                 ]
- .else_p [
- cl::eps_p [cl::assign_a(actions.element_id)]
- ]
                 ;
 
         local.element_id_1_6 =
                 cl::if_p(qbk_since(106u)) [
                     local.element_id
                 ]
- .else_p [
- cl::eps_p [cl::assign_a(actions.element_id)]
- ]
                 ;
 
         elements.add
@@ -104,14 +97,10 @@
         local.h5 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h5];
         local.h6 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h6];
         
- static const bool true_ = true;
- static const bool false_ = false;
-
         elements.add("blurb", element_info(element_info::block, &local.blurb));
 
         local.blurb =
- actions.scoped_block[inside_paragraph]
- [actions.blurb]
+ inside_paragraph [actions.blurb]
             ;
 
         elements.add
@@ -119,8 +108,7 @@
             ;
 
         local.blockquote =
- blank >> actions.scoped_block[inside_paragraph]
- [actions.blockquote]
+ blank >> inside_paragraph [actions.blockquote]
             ;
 
         elements.add
@@ -132,28 +120,23 @@
             ;
 
         local.warning =
- actions.scoped_block[inside_paragraph]
- [actions.warning]
+ inside_paragraph [actions.warning]
             ;
 
         local.caution =
- actions.scoped_block[inside_paragraph]
- [actions.caution]
+ inside_paragraph [actions.caution]
             ;
 
         local.important =
- actions.scoped_block[inside_paragraph]
- [actions.important]
+ inside_paragraph [actions.important]
             ;
 
         local.note =
- actions.scoped_block[inside_paragraph]
- [actions.note]
+ inside_paragraph [actions.note]
             ;
 
         local.tip =
- actions.scoped_block[inside_paragraph]
- [actions.tip]
+ inside_paragraph [actions.tip]
             ;
 
         elements.add
@@ -190,22 +173,21 @@
 
         local.template_ =
                space
- >> local.template_id [cl::assign_a(actions.template_identifier)]
- [cl::clear_a(actions.template_info)]
- >>
+ >> local.template_id [actions.values.reset][actions.values.entry]
+ >> actions.values.scoped[
             !(
                 space >> '['
>> *(
                         space
- >> local.template_id [cl::push_back_a(actions.template_info)]
+ >> local.template_id [actions.values.entry]
                     )
>> space >> ']'
             )
+ ]
>> ( cl::eps_p(*cl::blank_p >> cl::eol_p)
- [cl::assign_a(actions.template_block, true_)]
- | cl::eps_p [cl::assign_a(actions.template_block, false_)]
- )
- >> local.template_body [actions.template_body]
+ >> local.template_body [actions.values.entry(template_tags::block)]
+ | local.template_body [actions.values.entry(template_tags::phrase)]
+ ) [actions.template_body]
             ;
 
         local.template_body =
@@ -220,7 +202,7 @@
 
         local.variablelist =
                 (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
- >> (*(cl::anychar_p - eol)) [cl::assign_a(actions.table_title)]
+ >> (*(cl::anychar_p - eol)) [actions.values.entry(table_tags::title)]
>> (+eol) [actions.output_pre]
>> *local.varlistentry
>> cl::eps_p [actions.variablelist]
@@ -228,48 +210,40 @@
 
         local.varlistentry =
             space
- >> cl::ch_p('[') [actions.start_varlistentry]
- >>
- (
+ >> cl::ch_p('[')
+ >> actions.values.scoped
+ [
                 (
                     local.varlistterm
- >> ( actions.scoped_block [+local.varlistitem]
- [actions.varlistitem]
+ >> ( +local.varlistitem
                         | cl::eps_p [actions.error]
                         )
- >> cl::ch_p(']') [actions.end_varlistentry]
+ >> cl::ch_p(']')
>> space
                 )
                 | cl::eps_p [actions.error]
- )
+ ]
             ;
 
         local.varlistterm =
             space
- >> cl::ch_p('[') [actions.start_varlistterm]
- >>
- (
- (
- phrase
- >> cl::ch_p(']') [actions.end_varlistterm]
- >> space
- )
- | cl::eps_p [actions.error]
- )
+ >> cl::ch_p('[')
+ >> actions.values.save
+ [ phrase
+ >> cl::ch_p(']')
+ >> space
+ | cl::eps_p [actions.error]
+ ] [actions.phrase_value]
             ;
 
         local.varlistitem =
             space
>> cl::ch_p('[')
- >>
- (
- (
- inside_paragraph
- >> cl::ch_p(']')
- >> space
+ >> ( inside_paragraph
+ >> cl::ch_p(']')
+ >> space
+ | cl::eps_p [actions.error]
                 )
- | cl::eps_p [actions.error]
- )
             ;
 
         elements.add
@@ -280,7 +254,7 @@
                 (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
>> local.element_id_1_5
>> (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
- >> (*(cl::anychar_p - eol)) [cl::assign_a(actions.table_title)]
+ >> (*(cl::anychar_p - eol)) [actions.values.entry(table_tags::title)]
>> (+eol) [actions.output_pre]
>> *local.table_row
>> cl::eps_p [actions.table]
@@ -288,12 +262,12 @@
 
         local.table_row =
             space
- >> cl::ch_p('[') [actions.start_row]
+ >> cl::ch_p('[')
>>
             (
                 (
- *local.table_cell
- >> cl::ch_p(']') [actions.end_row]
+ actions.values.scoped(table_tags::row)[*local.table_cell]
+ >> cl::ch_p(']')
>> space
                 )
                 | cl::eps_p [actions.error]
@@ -303,11 +277,10 @@
         local.table_cell =
                 space
>> cl::ch_p('[')
- >> ( actions.scoped_block [
- inside_paragraph
- >> cl::ch_p(']')
- >> space
- ] [actions.cell]
+ >> ( cl::eps_p [actions.values.tag(table_tags::cell)]
+ >> inside_paragraph
+ >> cl::ch_p(']')
+ >> space
                 | cl::eps_p [actions.error]
                 )
             ;

Modified: trunk/tools/quickbook/src/doc_info_actions.cpp
==============================================================================
--- trunk/tools/quickbook/src/doc_info_actions.cpp (original)
+++ trunk/tools/quickbook/src/doc_info_actions.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -15,41 +15,102 @@
 #include "utils.hpp"
 #include "input_path.hpp"
 #include "actions_class.hpp"
+#include "doc_info_tags.hpp"
 
 namespace quickbook
 {
- std::string const& docinfo_string::get(unsigned version) const
+ static void write_document_title(collector& out, value const& title, value const& version);
+
+ static std::string doc_info_output(value const& p, unsigned version)
+ {
+ return (qbk_version_n < version) ? p.get_quickbook() : p.get_boostbook();
+ }
+
+ value consume_last(value_consumer& c, value::tag_type tag,
+ std::vector<std::string>* duplicates)
     {
- return (qbk_version_n < version) ? raw : encoded;
+ value p;
+
+ int count = 0;
+ while(c.is(tag)) {
+ p = c.consume();
+ ++count;
+ }
+
+ if(count > 1) duplicates->push_back(doc_info_attributes::name(tag));
+
+ return p;
     }
 
- static void write_document_title(collector& out, quickbook::actions& actions);
- static void write_document_info(collector& out, quickbook::actions& actions);
+ std::vector<value> consume_multiple(value_consumer& c, value::tag_type tag)
+ {
+ std::vector<value> values;
+
+ while(c.is(tag)) {
+ values.push_back(c.consume());
+ }
+
+ return values;
+ }
 
     void pre(collector& out, quickbook::actions& actions, bool ignore_docinfo)
     {
         // The doc_info in the file has been parsed. Here's what we'll do
         // *before* anything else.
 
- if (!actions.doc_id_tmp.empty())
- actions.doc_id = actions.doc_id_tmp.get(106);
+ value_consumer values = actions.values.get();
+ std::vector<std::string> duplicates;
+
+ value doc_title;
+ if (values.is())
+ {
+ actions.doc_type = values.consume(doc_info_tags::type).get_quickbook();
+ doc_title = values.consume(doc_info_tags::title);
+ actions.doc_title_qbk = doc_title.get_quickbook();
+ }
+
+ value id = consume_last(values, doc_info_attributes::id, &duplicates);
+ value dirname = consume_last(values, doc_info_attributes::dirname, &duplicates);
+ value last_revision = consume_last(values, doc_info_attributes::last_revision, &duplicates);
+ value purpose = consume_last(values, doc_info_attributes::purpose, &duplicates);
+ std::vector<value> categories = consume_multiple(values, doc_info_attributes::category);
+ value lang = consume_last(values, doc_info_attributes::lang, &duplicates);
+ value version = consume_last(values, doc_info_attributes::version, &duplicates);
+ std::vector<value> authors = consume_multiple(values, doc_info_attributes::authors);
+ std::vector<value> copyrights = consume_multiple(values, doc_info_attributes::copyright);
+ value license = consume_last(values, doc_info_attributes::license, &duplicates);
+ std::vector<value> biblioids = consume_multiple(values, doc_info_attributes::biblioid);
+
+ BOOST_ASSERT(!values.is());
+
+ if(!duplicates.empty())
+ {
+ detail::outwarn(actions.filename,1)
+ << (duplicates.size() > 1 ?
+ "Duplicate attributes" : "Duplicate attribute")
+ << ":" << detail::utf8(boost::algorithm::join(duplicates, ", "))
+ << "\n"
+ ;
+ }
+
+ if (!id.is_empty())
+ actions.doc_id = id.get_quickbook();
 
         if (actions.doc_id.empty())
             actions.doc_id = detail::make_identifier(
- actions.doc_title.raw.begin(),actions.doc_title.raw.end());
-
- if (actions.doc_dirname.empty() && actions.doc_type == "library") {
- if (!actions.doc_id_tmp.empty()) {
- actions.doc_dirname = actions.doc_id_tmp;
+ actions.doc_title_qbk.begin(),actions.doc_title_qbk.end());
+
+ if (dirname.is_empty() && actions.doc_type == "library") {
+ if (!id.is_empty()) {
+ dirname = id;
             }
             else {
- actions.doc_dirname.raw = actions.doc_dirname.encoded = actions.doc_id;
+ dirname = qbk_bbk_value(actions.doc_id, doc_info_attributes::dirname);
             }
         }
 
- actions.doc_id_tmp.clear();
 
- if (actions.doc_last_revision.empty())
+ if (last_revision.is_empty())
         {
             // default value for last-revision is now
 
@@ -61,7 +122,7 @@
                     "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"),
                 current_gm_time
             );
- actions.doc_last_revision.raw = actions.doc_last_revision.encoded = strdate;
+ last_revision = qbk_bbk_value(strdate, doc_info_attributes::last_revision);
         }
 
         // if we're ignoring the document info, we're done.
@@ -111,13 +172,13 @@
         {
             std::vector<std::string> invalid_attributes;
 
- if (!actions.doc_purpose.empty())
+ if (!purpose.is_empty())
                 invalid_attributes.push_back("purpose");
 
- if (!actions.doc_categories.empty())
+ if (!categories.empty())
                 invalid_attributes.push_back("category");
 
- if (!actions.doc_dirname.empty())
+ if (!dirname.is_empty())
                 invalid_attributes.push_back("dirname");
 
             if(!invalid_attributes.empty())
@@ -144,176 +205,157 @@
             << actions.doc_id
             << "\"\n";
         
- if(!actions.doc_lang.empty())
+ if(!lang.is_empty())
         {
             out << " lang=\""
- << actions.doc_lang.get(106)
+ << doc_info_output(lang, 106)
                 << "\"\n";
         }
 
         if(actions.doc_type == "library")
         {
- out << " name=\"" << actions.doc_title.get(106) << "\"\n";
+ out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n";
         }
 
- if(!actions.doc_dirname.empty())
+ if(!dirname.is_empty())
         {
             out << " dirname=\""
- << actions.doc_dirname.get(106)
+ << doc_info_output(dirname, 106)
                 << "\"\n";
         }
 
         out << " last-revision=\""
- << actions.doc_last_revision.get(106)
+ << doc_info_output(last_revision, 106)
             << "\" \n"
             << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n";
-
- if(actions.doc_type == "library") {
- write_document_info(out, actions);
- write_document_title(out, actions);
- }
- else {
- write_document_title(out, actions);
- write_document_info(out, actions);
- }
- }
-
- void post(collector& out, quickbook::actions& actions, bool ignore_docinfo)
- {
- // if we're ignoring the document info, do nothing.
- if (ignore_docinfo)
- {
- return;
- }
-
- // We've finished generating our output. Here's what we'll do
- // *after* everything else.
- out << "\n</" << actions.doc_type << ">\n\n";
- }
 
- void write_document_title(collector& out, quickbook::actions& actions)
- {
- if (!actions.doc_title.empty())
- {
- out << " <title>"
- << actions.doc_title.get(106);
- if (!actions.doc_version.empty()) {
- out << ' ' << actions.doc_version.get(106);
- }
- out<< "</title>\n\n\n";
- }
- }
-
- void write_document_info(collector& out, quickbook::actions& actions)
- {
         std::ostringstream tmp;
 
- if(!actions.doc_authors.empty())
+ if(!authors.empty())
         {
             tmp << " <authorgroup>\n";
- for(actions::author_list::const_iterator
- it = actions.doc_authors.begin(),
- end = actions.doc_authors.end();
- it != end; ++it)
+ BOOST_FOREACH(value_consumer author_values, authors)
             {
- tmp << " <author>\n"
- << " <firstname>"
- << it->first.get(106)
- << "</firstname>\n"
- << " <surname>"
- << it->second.get(106)
- << "</surname>\n"
- << " </author>\n";
+ while (author_values.is()) {
+ value surname = author_values.consume(doc_info_tags::author_surname);
+ value first = author_values.consume(doc_info_tags::author_first);
+
+ tmp << " <author>\n"
+ << " <firstname>"
+ << doc_info_output(first, 106)
+ << "</firstname>\n"
+ << " <surname>"
+ << doc_info_output(surname, 106)
+ << "</surname>\n"
+ << " </author>\n";
+ }
             }
             tmp << " </authorgroup>\n";
         }
 
- if (!actions.doc_copyrights.empty())
+ BOOST_FOREACH(value_consumer copyright, copyrights)
         {
- for(actions::copyright_list::const_iterator
- it = actions.doc_copyrights.begin(),
- end = actions.doc_copyrights.end();
- it != end; ++it)
+ tmp << "\n" << " <copyright>\n";
+
+ while(copyright.is(doc_info_tags::copyright_year))
             {
- tmp << "\n" << " <copyright>\n";
-
- for(actions::string_list::const_iterator
- it2 = it->first.begin(),
- end = it->first.end();
- it2 != end; ++it2)
- {
- tmp << " <year>" << *it2 << "</year>\n";
- }
-
- tmp << " <holder>"
- << it->second.get(106)
- << "</holder>\n"
- << " </copyright>\n"
- << "\n"
- ;
+ tmp << " <year>" << copyright.consume().get_quickbook() << "</year>\n";
             }
+
+ tmp << " <holder>"
+ << doc_info_output(copyright.consume(doc_info_tags::copyright_name), 106)
+ << "</holder>\n"
+ << " </copyright>\n"
+ << "\n"
+ ;
         }
 
- if (!actions.doc_license.empty())
+ if (!license.is_empty())
         {
             tmp << " <legalnotice>\n"
                 << " <para>\n"
- << " " << actions.doc_license.get(103) << "\n"
+ << " " << doc_info_output(license, 103) << "\n"
                 << " </para>\n"
                 << " </legalnotice>\n"
                 << "\n"
             ;
         }
 
- if (!actions.doc_purpose.empty())
+ if (!purpose.is_empty())
         {
             tmp << " <" << actions.doc_type << "purpose>\n"
- << " " << actions.doc_purpose.get(103)
+ << " " << doc_info_output(purpose, 103)
                 << " </" << actions.doc_type << "purpose>\n"
                 << "\n"
                 ;
         }
 
- if (!actions.doc_categories.empty())
- {
- for(actions::docinfo_list::const_iterator
- it = actions.doc_categories.begin(),
- end = actions.doc_categories.end();
- it != end; ++it)
- {
- if (!it->empty())
- {
- tmp << " <" << actions.doc_type << "category name=\"category:"
- << it->get(106)
- << "\"></" << actions.doc_type << "category>\n"
- << "\n"
- ;
- }
+ BOOST_FOREACH(value const& category, categories) {
+ if(!category.is_empty()) {
+ tmp << " <" << actions.doc_type << "category name=\"category:"
+ << doc_info_output(category, 106)
+ << "\"></" << actions.doc_type << "category>\n"
+ << "\n"
+ ;
             }
         }
 
- for (actions::biblioid_list::const_iterator
- it = actions.doc_biblioid_items.begin(),
- end = actions.doc_biblioid_items.end();
- it != end; ++it)
+ BOOST_FOREACH(value_consumer biblioid, biblioids)
         {
+ value class_ = biblioid.consume(doc_info_tags::biblioid_class);
+ value value_ = biblioid.consume(doc_info_tags::biblioid_value);
+
             tmp << " <biblioid class=\""
- << it->first
+ << class_.get_quickbook()
                 << "\">"
- << it->second.get(103)
+ << doc_info_output(value_, 106)
                 << "</biblioid>"
                 << "\n"
                 ;
         }
 
- std::string value = tmp.str();
- if(!value.empty())
+ if(actions.doc_type != "library") {
+ write_document_title(out, doc_title, version);
+ }
+
+ std::string docinfo = tmp.str();
+ if(!docinfo.empty())
         {
             out << " <" << actions.doc_type << "info>\n"
- << value
+ << docinfo
                 << " </" << actions.doc_type << "info>\n"
                 << "\n"
             ;
         }
+
+ if(actions.doc_type == "library") {
+ write_document_title(out, doc_title, version);
+ }
+ }
+
+ void post(collector& out, quickbook::actions& actions, bool ignore_docinfo)
+ {
+ // if we're ignoring the document info, do nothing.
+ if (ignore_docinfo)
+ {
+ return;
+ }
+
+ // We've finished generating our output. Here's what we'll do
+ // *after* everything else.
+ out << "\n</" << actions.doc_type << ">\n\n";
+ }
+
+ static void write_document_title(collector& out, value const& title, value const& version)
+ {
+ if (!title.is_empty())
+ {
+ out << " <title>"
+ << doc_info_output(title, 106);
+ if (!version.is_empty()) {
+ out << ' ' << doc_info_output(version, 106);
+ }
+ out<< "</title>\n\n\n";
+ }
     }
 }

Modified: trunk/tools/quickbook/src/doc_info_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/doc_info_grammar.cpp (original)
+++ trunk/tools/quickbook/src/doc_info_grammar.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -10,6 +10,7 @@
 
 #include "grammar_impl.hpp"
 #include "actions_class.hpp"
+#include "doc_info_tags.hpp"
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/spirit/include/classic_actor.hpp>
 #include <boost/spirit/include/classic_loops.hpp>
@@ -20,15 +21,60 @@
 {
     namespace cl = boost::spirit::classic;
 
+ struct attribute_info
+ {
+ attribute_info(value::tag_type t, cl::rule<scanner>* r)
+ : tag(t), rule(r)
+ {}
+
+ value::tag_type tag;
+ cl::rule<scanner>* 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];
+ }
+
+ doc_info_grammar_local& l;
+ };
+
+ struct fallback_attribute_type
+ {
+ fallback_attribute_type(doc_info_grammar_local& l)
+ : l(l)
+ {}
+
+ void operator()(iterator, iterator) const {
+ l.attribute_rule = l.doc_fallback;
+ }
+
+ doc_info_grammar_local& l;
+ };
+
         cl::rule<scanner>
- doc_title, doc_version, doc_id, doc_dirname,
- doc_copyright, doc_purpose, doc_category, doc_authors,
- doc_author, doc_license,
- doc_last_revision, doc_source_mode, doc_biblioid, doc_lang,
+ doc_title, doc_simple, doc_phrase, doc_fallback,
+ doc_copyright, doc_authors, doc_author,
+ doc_source_mode, doc_biblioid,
                         quickbook_version, char_;
         cl::symbols<> doc_types;
+ cl::symbols<value::tag_type> doc_attributes;
+ std::map<value::tag_type, cl::rule<scanner>* > attribute_rules;
+ cl::rule<scanner> attribute_rule;
+ assign_attribute_type assign_attribute;
+ fallback_attribute_type fallback_attribute;
+
+ doc_info_grammar_local()
+ : assign_attribute(*this)
+ , fallback_attribute(*this)
+ {}
     };
 
     void quickbook_grammar::impl::init_doc_info()
@@ -42,40 +88,46 @@
           , "appendix", "preface", "qandadiv", "qandaset"
           , "reference", "set"
         ;
+
+ BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
+ local.doc_attributes.add(doc_info_attributes::name(t), t);
+ }
         
         doc_info_details =
             space
>> '[' >> space
>> (local.doc_types >> cl::eps_p)
- [cl::assign_a(actions.doc_type)]
+ [actions.values.reset]
+ [actions.values.entry(doc_info_tags::type)]
>> hard_space
>> ( *(~cl::eps_p(cl::ch_p('[') | ']' | cl::eol_p) >> local.char_)
- ) [actions.extract_doc_title]
+ ) [actions.values.tag(doc_info_tags::title)]
+ [actions.docinfo_value]
>> !(
                     space >> '[' >>
                         local.quickbook_version
>> space >> ']'
                 )
- >>
- *(
- space >> '[' >>
- (
- local.doc_version
- | local.doc_id
- | local.doc_dirname
- | local.doc_copyright [cl::push_back_a(actions.doc_copyrights, actions.copyright)]
- | local.doc_purpose
- | local.doc_category
- | local.doc_authors
- | local.doc_license
- | local.doc_last_revision
- | local.doc_source_mode
- | local.doc_biblioid
- | local.doc_lang
+ >> *(
+ space
+ >> '['
+ >> space
+ >> ( local.doc_attributes
+ [local.assign_attribute]
+ [actions.values.tag]
+ | (+(cl::alnum_p | '_' | '-'))
+ [local.fallback_attribute]
+ [actions.error("Unrecognized document attribute: '%s'.")]
                     )
- >> space >> ']' >> +cl::eol_p
+ >> hard_space
+ >> local.attribute_rule
+ >> space
+ >> ']'
+ >> +cl::eol_p
                 )
- >> space >> ']' >> +cl::eol_p
+ >> space [actions.values.sort]
+ >> ']'
+ >> +cl::eol_p
             ;
 
         local.quickbook_version =
@@ -86,106 +138,89 @@
                 )
             ;
 
- local.doc_version =
- "version" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_version]
- ;
+ // TODO: Clear phrase afterwards?
 
- // TODO: Restrictions on doc_id?
- local.doc_id =
- "id" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_id]
- ;
+ local.doc_fallback = (*(~cl::eps_p(']') >> local.char_));
 
- // TODO: Restrictions on doc_dirname?
- local.doc_dirname =
- "dirname" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_dirname]
- ;
+ // TODO: Restrictions on doc_id and doc_dirname?
+
+ local.doc_simple = (*(~cl::eps_p(']') >> local.char_)) [actions.docinfo_value];
+ 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.doc_copyright =
- "copyright"
- >> hard_space [cl::clear_a(actions.copyright.first)]
- >> +( cl::repeat_p(4)[cl::digit_p]
- [cl::push_back_a(actions.copyright.first)]
+ actions.values.scoped(doc_info_attributes::copyright)
+ [
+ +( cl::repeat_p(4)[cl::digit_p]
+ [actions.values.entry(doc_info_tags::copyright_year)]
>> space
                 )
>> space
>> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_copyright_second]
+ [actions.values.tag(doc_info_tags::copyright_name)]
+ [actions.docinfo_value]
+ ]
             ;
 
- local.doc_purpose =
- "purpose" >> hard_space
- >> simple_phrase [actions.extract_doc_purpose]
- ;
+ local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright;
 
- local.doc_category =
- "category" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_category]
- [cl::push_back_a(actions.doc_categories, actions.doc_category)]
- ;
+ local.doc_phrase = simple_phrase[actions.docinfo_value];
+ local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase;
+ local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase;
 
         local.doc_author =
- '[' >> space
+ '['
+ >> space
>> (*(~cl::eps_p(',') >> local.char_))
- [actions.extract_name_second]
+ [actions.values.tag(doc_info_tags::author_surname)]
+ [actions.docinfo_value]
>> ',' >> space
>> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_name_first]
+ [actions.values.tag(doc_info_tags::author_first)]
+ [actions.docinfo_value]
>> ']'
             ;
 
         local.doc_authors =
- "authors"
- >> hard_space
- >> local.doc_author [cl::push_back_a(actions.doc_authors, actions.name)]
- >> space
- >> *( !(cl::ch_p(',') >> space)
- >> local.doc_author [cl::push_back_a(actions.doc_authors, actions.name)]
+ actions.values.scoped(doc_info_attributes::authors)
+ [
+ local.doc_author
>> space
- )
- ;
-
- local.doc_license =
- "license" >> hard_space
- >> simple_phrase [actions.extract_doc_license]
+ >> *( !(cl::ch_p(',') >> space)
+ >> local.doc_author
+ >> space
+ )
+ ]
             ;
 
- local.doc_last_revision =
- "last-revision" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_last_revision]
- ;
+ local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors;
 
         local.doc_source_mode =
- "source-mode" >> hard_space
- >> (
+ (
                    cl::str_p("c++")
                 | "python"
                 | "teletype"
                 ) [cl::assign_a(actions.source_mode)]
             ;
 
+ local.attribute_rules[doc_info_attributes::source_mode] = &local.doc_source_mode;
+
         local.doc_biblioid =
- "biblioid"
- >> hard_space
- >> (+cl::alnum_p) [cl::assign_a(actions.doc_biblioid.first)]
- >> hard_space
- >> (+(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_biblioid]
- [cl::push_back_a(actions.doc_biblioid_items, actions.doc_biblioid)]
+ actions.values.scoped(doc_info_attributes::biblioid)
+ [
+ (+cl::alnum_p) [actions.values.entry(doc_info_tags::biblioid_class)]
+ >> hard_space
+ >> (+(~cl::eps_p(']') >> local.char_))
+ [actions.values.tag(doc_info_tags::biblioid_value)]
+ [actions.docinfo_value]
+ ]
             ;
 
- local.doc_lang =
- "lang" >> hard_space
- >> (*(~cl::eps_p(']') >> local.char_))
- [actions.extract_doc_lang]
- ;
+ local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
 
         local.char_ =
                 cl::str_p("\\n") [actions.break_]

Modified: trunk/tools/quickbook/src/main_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/main_grammar.cpp (original)
+++ trunk/tools/quickbook/src/main_grammar.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -11,6 +11,7 @@
 #include "grammar_impl.hpp"
 #include "actions_class.hpp"
 #include "utils.hpp"
+#include "template_tags.hpp"
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/spirit/include/classic_confix.hpp>
 #include <boost/spirit/include/classic_chset.hpp>
@@ -73,7 +74,7 @@
                         template_args,
                         template_args_1_4, template_arg_1_4,
                         template_inner_arg_1_4, brackets_1_4,
- template_args_1_5, template_arg_1_5,
+ template_args_1_5, template_arg_1_5, template_arg_1_5_content,
                         template_inner_arg_1_5, brackets_1_5,
                         command_line_macro_identifier, command_line_phrase,
                         dummy_block
@@ -163,6 +164,7 @@
>> local.element
>> cl::eps_p(local.check_element(element_info::in_block))
                                                 [actions.inside_paragraph]
+ [actions.values.reset]
>> ( local.element_rule
>> ( (space >> ']')
                     | cl::eps_p [actions.error]
@@ -225,31 +227,24 @@
>> actions.macro [actions.do_macro]
             ;
 
- static const bool true_ = true;
- static const bool false_ = false;
-
         local.template_ =
- (
- cl::ch_p('`') [cl::assign_a(actions.template_escape,true_)]
- |
- cl::eps_p [cl::assign_a(actions.template_escape,false_)]
- )
+ cl::eps_p [actions.values.reset]
+ >> !cl::str_p("`") [actions.values.entry(template_tags::escape)]
>>
             ( (
                 (cl::eps_p(cl::punct_p)
>> actions.templates.scope
- ) [cl::assign_a(actions.template_identifier)]
- [cl::clear_a(actions.template_args)]
+ ) [actions.values.entry(template_tags::identifier)]
>> !local.template_args
             ) | (
                 (actions.templates.scope
>> cl::eps_p(hard_space)
- ) [cl::assign_a(actions.template_identifier)]
- [cl::clear_a(actions.template_args)]
+ ) [actions.values.entry(template_tags::identifier)]
>> space
>> !local.template_args
             ) )
>> cl::eps_p(']')
+ >> cl::eps_p [actions.do_template]
             ;
 
         local.template_args =
@@ -263,11 +258,10 @@
         local.template_args_1_4 = local.template_arg_1_4 >> *(".." >> local.template_arg_1_4);
 
         local.template_arg_1_4 =
- ( cl::eps_p(*cl::blank_p >> cl::eol_p)
- [cl::assign_a(actions.template_block, true_)]
- | cl::eps_p [cl::assign_a(actions.template_block, false_)]
- )
- >> local.template_inner_arg_1_4 [actions.template_arg]
+ ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_inner_arg_1_4 [actions.values.entry(template_tags::block)]
+ | local.template_inner_arg_1_4 [actions.values.entry(template_tags::phrase)]
+ )
             ;
 
         local.template_inner_arg_1_4 =
@@ -281,12 +275,14 @@
         local.template_args_1_5 = local.template_arg_1_5 >> *(".." >> local.template_arg_1_5);
 
         local.template_arg_1_5 =
- ( cl::eps_p(*cl::blank_p >> cl::eol_p)
- [cl::assign_a(actions.template_block, true_)]
- | cl::eps_p [cl::assign_a(actions.template_block, false_)]
- )
- >> (+(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p("..") | '[' | ']'))))
- [actions.template_arg]
+ ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_arg_1_5_content [actions.values.entry(template_tags::block)]
+ | local.template_arg_1_5_content [actions.values.entry(template_tags::phrase)]
+ )
+ ;
+
+ local.template_arg_1_5_content =
+ +(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p("..") | '[' | ']')))
             ;
 
         local.template_inner_arg_1_5 =
@@ -361,10 +357,14 @@
             ;
 
         inside_paragraph =
+ actions.scoped_block[
+ actions.values.save[
             (*( common
             | (cl::anychar_p - phrase_end) [actions.plain_char]
             | (+eol) [actions.inside_paragraph]
             )) [actions.inside_paragraph]
+ ]
+ ]
             ;
 
         local.phrase_element
@@ -373,7 +373,7 @@
>> ( local.element
>> cl::eps_p(local.check_element(element_info::in_phrase))
>> local.element_rule
- | local.template_ [actions.do_template]
+ | local.template_
                 | cl::str_p("br") [actions.break_]
                 )
>> ']'

Modified: trunk/tools/quickbook/src/phrase_element_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/phrase_element_grammar.cpp (original)
+++ trunk/tools/quickbook/src/phrase_element_grammar.cpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -55,25 +55,26 @@
             ;
 
         local.image =
- blank [cl::clear_a(actions.attributes)]
+ blank [actions.values.reset]
>> cl::if_p(qbk_since(105u)) [
                         (+(
                             *cl::space_p
>> +(cl::anychar_p - (cl::space_p | phrase_end | '['))
- )) [cl::assign_a(actions.image_fileref)]
+ )) [actions.values.entry]
>> hard_space
- >> *(
+ >> *actions.values.scoped[
                             '['
- >> (*(cl::alnum_p | '_')) [cl::assign_a(actions.attribute_name)]
+ >> (*(cl::alnum_p | '_'))
+ [actions.values.entry]
>> space
>> (*(cl::anychar_p - (phrase_end | '[')))
- [actions.attribute]
+ [actions.values.entry]
>> ']'
>> space
- )
+ ]
                 ].else_p [
                         (*(cl::anychar_p - phrase_end))
- [cl::assign_a(actions.image_fileref)]
+ [actions.values.entry]
                 ]
>> cl::eps_p(']') [actions.image]
             ;

Modified: trunk/tools/quickbook/src/scoped_parser.hpp
==============================================================================
--- trunk/tools/quickbook/src/scoped_parser.hpp (original)
+++ trunk/tools/quickbook/src/scoped_parser.hpp 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -13,6 +13,7 @@
 #define BOOST_QUICKBOOK_SCOPED_PARSER_HPP
 
 #include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_nil.hpp>
 
 namespace quickbook {
     namespace cl = boost::spirit::classic;
@@ -25,12 +26,7 @@
         typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<ScopeT, DataT, ParserT> > > base_t;
 
         template <typename ScannerT>
- struct result :
- ScopeT::template result<
- typename cl::parser_result<ParserT, ScannerT>::type
- >
- {
- };
+ struct result { typedef cl::match<> type; };
 
         scoped_parser_impl(DataT& actions, ParserT const &p)
             : base_t(p)
@@ -48,7 +44,8 @@
                 = this->subject().parse(scan);
 
             if (result) {
- return scan.create_match(result.length(), scope.success(result), save, scan.first);
+ scope.success(result);
+ return scan.create_match(result.length(), cl::nil_t(), save, scan.first);
             }
             else {
                 scope.failure();

Modified: trunk/tools/quickbook/test/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/test/Jamfile.v2 (original)
+++ trunk/tools/quickbook/test/Jamfile.v2 2011-03-19 07:45:49 EDT (Sat, 19 Mar 2011)
@@ -12,6 +12,7 @@
     ;
 
 build-project doc-info ;
+build-project unit ;
 
 import quickbook-testing : quickbook-test quickbook-fail-test ;
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk