From e478c5befbed3574046038f701a2a4ae76e47376 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 24 Mar 2011 21:25:18 +0000 Subject: [PATCH] Quickbook: Use values for templates and snippets. [SVN r70528] --- src/actions.cpp | 70 ++++++++++++++------------------ src/code_snippet.cpp | 92 +++++++++++++++++++++++++----------------- src/template_stack.cpp | 19 +++++++++ src/template_stack.hpp | 30 ++++---------- src/values.cpp | 38 +++++++++++++---- src/values.hpp | 11 ++++- 6 files changed, 154 insertions(+), 106 deletions(-) diff --git a/src/actions.cpp b/src/actions.cpp index 109b84e..e83d192 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -27,7 +27,6 @@ #include "actions_class.hpp" #include "grammar.hpp" #include "input_path.hpp" -#include "template_tags.hpp" #include "block_tags.hpp" #include "phrase_tags.hpp" @@ -883,10 +882,8 @@ namespace quickbook template_symbol( identifier, template_values, - body.get_quickbook(), + body, actions.filename, - body.get_position(), - body.get_tag() == template_tags::block, &actions.templates.top_scope()))) { file_position const pos = body.get_position(); @@ -991,18 +988,18 @@ namespace quickbook // arguments, or if there are no more spaces left. template_body& body = args.back(); - iterator begin(body.content.begin(), body.position); - iterator end(body.content.end()); + iterator begin = body.content.get_quickbook_range().begin(); + iterator end = body.content.get_quickbook_range().end(); std::pair pos = find_seperator(begin, end); if (pos.second == end) break; template_body second( - std::string(pos.second, end), - body.filename, - pos.second.get_position(), - false); - body.content = std::string(begin, pos.first); + qbk_value(pos.second, end, template_tags::phrase), + body.filename); + + body.content = qbk_value(begin, pos.first, + body.content.get_tag()).store(); args.push_back(second); } } @@ -1040,7 +1037,7 @@ namespace quickbook { if (!actions.templates.add( template_symbol(*tpl, empty_params, arg->content, - arg->filename, arg->position, arg->is_block, &scope))) + arg->filename, &scope))) { detail::outerr(actions.filename, pos.line) << "Duplicate Symbol Found" << std::endl; @@ -1069,17 +1066,17 @@ namespace quickbook { // escape the body of the template // we just copy out the literal body - (body.is_block ? actions.out : actions.phrase) << body.content; + (body.is_block() ? actions.out : actions.phrase) << body.content.get_quickbook(); return true; } else { - if (!body.is_block) + if (!body.is_block()) { // do a phrase level parse actions.filename = body.filename; - iterator first(body.content.begin(), body.position); - iterator last(body.content.end()); + iterator first = body.content.get_quickbook_range().begin(); + iterator last = body.content.get_quickbook_range().end(); return cl::parse(first, last, actions.grammar().simple_phrase).full; } @@ -1090,8 +1087,8 @@ namespace quickbook // the need to check for end of file in the grammar. actions.filename = body.filename; - std::string content = body.content + "\n\n"; - iterator first(content.begin(), body.position); + std::string content = body.content.get_quickbook() + "\n\n"; + iterator first(content.begin(), body.content.get_position()); iterator last(content.end()); return cl::parse(first, last, actions.grammar().block).full; @@ -1123,17 +1120,7 @@ namespace quickbook 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 - )); + args.push_back(template_body(arg, actions.filename)); } values.finish(); @@ -1177,7 +1164,7 @@ namespace quickbook /////////////////////////////////// // Initialise the arguments - if (!symbol->callout) + if (!symbol->callouts.check()) { // Break the arguments for a template @@ -1214,7 +1201,9 @@ namespace quickbook code += "linkends=\"" + callout_id + "\" />"; code += "'''"; - args.push_back(template_body(code, actions.filename, pos, false)); + args.push_back(template_body( + qbk_value(code, pos, template_tags::phrase), + actions.filename)); } } @@ -1241,11 +1230,11 @@ namespace quickbook file_position const pos = first.get_position(); detail::outerr(actions.filename, pos.line) << "Expanding " - << (symbol->body.is_block ? "block" : "phrase") + << (symbol->body.is_block() ? "block" : "phrase") << " template: " << detail::utf8(symbol->identifier) << std::endl << std::endl << "------------------begin------------------" << std::endl - << detail::utf8(symbol->body.content) + << detail::utf8(symbol->body.content.get_quickbook()) << "------------------end--------------------" << std::endl << std::endl; actions.pop(); // restore the actions' states @@ -1270,27 +1259,28 @@ namespace quickbook actions.phrase.swap(phrase); actions.pop(); // restore the actions' states - if(symbol->callout && symbol->callouts.size() > 0) + if(!symbol->callouts.empty()) { BOOST_ASSERT(phrase.empty()); block += ""; - BOOST_FOREACH(template_body const& c, symbol->callouts) + BOOST_FOREACH(value c, symbol->callouts) { std::string callout_id = actions.doc_id + boost::lexical_cast(detail::callout_id++); std::string callout_value; actions.push(); - bool r = parse_template(c, false, actions); + bool r = parse_template( + template_body(c, symbol->body.filename), false, actions); actions.out.swap(callout_value); actions.pop(); if(!r) { - detail::outerr(c.filename, c.position.line) + detail::outerr(symbol->body.filename, c.get_position().line) << "Expanding callout." << std::endl << "------------------begin------------------" << std::endl - << detail::utf8(c.content) + << detail::utf8(c.get_quickbook()) << std::endl << "------------------end--------------------" << std::endl ; @@ -1306,7 +1296,7 @@ namespace quickbook block += ""; } - if(symbol->body.is_block || !block.empty()) { + if(symbol->body.is_block() || !block.empty()) { actions.paragraph(); // For paragraphs before the template call. actions.out << block; actions.phrase << phrase; @@ -1749,7 +1739,7 @@ namespace quickbook ts.parent = &actions.templates.top_scope(); if (!actions.templates.add(ts)) { - detail::outerr(ts.body.filename, ts.body.position.line) + detail::outerr(ts.body.filename, ts.body.content.get_position().line) << "Template Redefinition: " << detail::utf8(tname) << std::endl; ++actions.error_count; } diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp index 4391299..54c621e 100644 --- a/src/code_snippet.cpp +++ b/src/code_snippet.cpp @@ -7,14 +7,15 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ -#include #include #include #include +#include #include #include #include "template_stack.hpp" #include "actions.hpp" +#include "values.hpp" namespace quickbook { @@ -52,17 +53,34 @@ namespace quickbook , start_code(false) , end_code(false) {} - + std::string id; int callout_base_id; std::string content; bool start_code; bool end_code; - std::vector callouts; + value_builder callouts; + boost::shared_ptr next; }; + void push_snippet_data(std::string const& id, int callout_base_id) + { + boost::shared_ptr new_snippet( + new snippet_data(id, callout_base_id)); + new_snippet->next = snippet_stack; + snippet_stack = new_snippet; + } + + boost::shared_ptr pop_snippet_data() + { + boost::shared_ptr snippet(snippet_stack); + snippet_stack = snippet->next; + snippet->next.reset(); + return snippet; + } + int callout_id; - std::stack snippet_stack; + boost::shared_ptr snippet_stack; std::string code; std::string id; std::vector& storage; @@ -323,8 +341,8 @@ namespace quickbook void code_snippet_actions::append_code() { - if(snippet_stack.empty()) return; - snippet_data& snippet = snippet_stack.top(); + if(!snippet_stack) return; + snippet_data& snippet = *snippet_stack; if (!code.empty()) { @@ -350,8 +368,8 @@ namespace quickbook void code_snippet_actions::close_code() { - if(snippet_stack.empty()) return; - snippet_data& snippet = snippet_stack.top(); + if(!snippet_stack) return; + snippet_data& snippet = *snippet_stack; if(snippet.end_code) { @@ -362,30 +380,29 @@ namespace quickbook void code_snippet_actions::pass_thru(iterator first, iterator last) { - if(snippet_stack.empty()) return; + if(!snippet_stack) return; code.append(first, last); } void code_snippet_actions::pass_thru_char(char c) { - if(snippet_stack.empty()) return; + if(!snippet_stack) return; code += c; } void code_snippet_actions::callout(iterator first, iterator last) { - if(snippet_stack.empty()) return; + if(!snippet_stack) return; code += "``[[callout" + boost::lexical_cast(callout_id) + "]]``"; - snippet_stack.top().callouts.push_back( - template_body(std::string(first, last), filename, first.get_position(), true)); + snippet_stack->callouts.insert(qbk_value(first, last, template_tags::block).store()); ++callout_id; } void code_snippet_actions::escaped_comment(iterator first, iterator last) { - if(snippet_stack.empty()) return; - snippet_data& snippet = snippet_stack.top(); + if(!snippet_stack) return; + snippet_data& snippet = *snippet_stack; append_code(); close_code(); @@ -400,50 +417,53 @@ namespace quickbook void code_snippet_actions::start_snippet(iterator, iterator) { append_code(); - snippet_stack.push(snippet_data(id, callout_id)); + push_snippet_data(id, callout_id); id.clear(); } void code_snippet_actions::end_snippet(iterator first, iterator) { // TODO: Error? - if(snippet_stack.empty()) return; + if(!snippet_stack) return; append_code(); - snippet_data snippet = snippet_stack.top(); - snippet_stack.pop(); + boost::shared_ptr snippet = pop_snippet_data(); + value callouts = snippet->callouts.get(); std::string body; - if(snippet.start_code) { + if(snippet->start_code) { body += "\n\n"; body += source_type; body += "```\n"; } - body += snippet.content; - if(snippet.end_code) { + body += snippet->content; + if(snippet->end_code) { body += "```\n\n"; } - + std::vector params; - for (size_t i = 0; i < snippet.callouts.size(); ++i) + int i = 0; + for(value::iterator it = callouts.begin(); it != callouts.end(); ++it) { - params.push_back("[callout" + boost::lexical_cast(snippet.callout_base_id + i) + "]"); + params.push_back("[callout" + boost::lexical_cast(snippet->callout_base_id + i) + "]"); + ++i; } // TODO: Save position in start_snippet - template_symbol symbol(snippet.id, params, body, filename, first.get_position(), true); - symbol.callout = true; - symbol.callouts = snippet.callouts; + template_symbol symbol(snippet->id, params, + qbk_value(body, first.get_position(), template_tags::block), + filename); + symbol.callouts = callouts; storage.push_back(symbol); // Merge the snippet into its parent - if(!snippet_stack.empty()) + if(snippet_stack) { - snippet_data& next = snippet_stack.top(); - if(!snippet.content.empty()) { - if(!snippet.start_code) { + snippet_data& next = *snippet_stack; + if(!snippet->content.empty()) { + if(!snippet->start_code) { close_code(); } else if(!next.end_code) { @@ -452,11 +472,11 @@ namespace quickbook next.content += "```\n"; } - next.content += snippet.content; - next.end_code = snippet.end_code; + next.content += snippet->content; + next.end_code = snippet->end_code; } - - next.callouts.insert(next.callouts.end(), snippet.callouts.begin(), snippet.callouts.end()); + + next.callouts.extend(callouts); } } } diff --git a/src/template_stack.cpp b/src/template_stack.cpp index f9caa4b..f7d9f8d 100644 --- a/src/template_stack.cpp +++ b/src/template_stack.cpp @@ -6,6 +6,8 @@ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ + +#include #include "template_stack.hpp" #ifdef BOOST_MSVC @@ -14,6 +16,23 @@ namespace quickbook { + template_body::template_body( + value const& content, + fs::path const& filename + ) + : content(content.store()) + , filename(filename) + { + assert(content.get_tag() == template_tags::block || + content.get_tag() == template_tags::phrase); + } + + bool template_body::is_block() const + { + return content.get_tag() == template_tags::block; + } + + template_stack::template_stack() : scope(template_stack::parser(*this)) , scopes() diff --git a/src/template_stack.hpp b/src/template_stack.hpp index a776e16..6119305 100644 --- a/src/template_stack.hpp +++ b/src/template_stack.hpp @@ -19,6 +19,8 @@ #include #include #include "fwd.hpp" +#include "values.hpp" +#include "template_tags.hpp" namespace quickbook { @@ -26,23 +28,11 @@ namespace quickbook struct template_body { - template_body( - std::string const& content, - fs::path const& filename, - file_position const& position, - bool is_block - ) - : content(content) - , filename(filename) - , position(position) - , is_block(is_block) - { - } + template_body(value const&, fs::path const&); + bool is_block() const; - std::string content; + value content; fs::path filename; - file_position position; - bool is_block; }; struct template_scope; @@ -52,16 +42,13 @@ namespace quickbook template_symbol( std::string const& identifier, std::vector const& params, - std::string const& body, + value const& content, fs::path const& filename, - file_position const& position, - bool is_block, template_scope const* parent = 0) : identifier(identifier) , params(params) - , body(body, filename, position, is_block) + , body(content, filename) , parent(parent) - , callout(false) , callouts() {} std::string identifier; @@ -73,8 +60,7 @@ namespace quickbook // or static_parent for clarity. template_scope const* parent; - bool callout; - std::vector callouts; + value callouts; }; typedef boost::spirit::classic::symbols template_symbols; diff --git a/src/values.cpp b/src/values.cpp index 9c2a439..ae73dc2 100644 --- a/src/values.cpp +++ b/src/values.cpp @@ -44,10 +44,12 @@ namespace quickbook file_position value_node::get_position() const { UNDEFINED_ERROR(); } int value_node::get_int() const { UNDEFINED_ERROR(); } std::string value_node::get_quickbook() const { UNDEFINED_ERROR(); } + value_node::qbk_range value_node::get_quickbook_range() const { UNDEFINED_ERROR(); } std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); } value_node* value_node::get_list() const { UNDEFINED_ERROR(); } bool value_node::empty() const { return false; } + bool value_node::check() const { return true; } bool value_node::is_list() const { return false; } bool value_node::is_string() const { return false; } } @@ -76,6 +78,9 @@ namespace quickbook virtual bool empty() const { return true; } + + virtual bool check() const + { return false; } friend value quickbook::empty_value(value::tag_type); }; @@ -151,12 +156,9 @@ namespace quickbook intrusive_ptr_release(value_); } - void value_counted::store() + value value_counted::store() const { - value_node* new_value = value_->store(); - intrusive_ptr_add_ref(new_value); - intrusive_ptr_release(value_); - value_ = new_value; + return value(value_->store()); } } @@ -289,6 +291,7 @@ namespace quickbook virtual value_node* clone() const; virtual file_position get_position() const; virtual std::string get_quickbook() const; + qbk_range get_quickbook_range() const; virtual bool is_string() const; virtual bool empty() const; @@ -308,6 +311,7 @@ namespace quickbook virtual value_node* store(); virtual file_position get_position() const; virtual std::string get_quickbook() const; + qbk_range get_quickbook_range() const; virtual bool is_string() const; virtual bool empty() const; @@ -332,6 +336,7 @@ namespace quickbook virtual value_node* clone() const; virtual file_position get_position() const; virtual std::string get_quickbook() const; + qbk_range get_quickbook_range() const; virtual std::string get_boostbook() const; virtual bool is_string() const; virtual bool empty() const; @@ -408,6 +413,11 @@ namespace quickbook std::string value_qbk_string_impl::get_quickbook() const { return value_; } + value::qbk_range value_qbk_string_impl::get_quickbook_range() const + { return qbk_range( + iterator(value_.begin(), position_), + iterator(value_.end())); } + bool value_qbk_string_impl::is_string() const { return true; } @@ -443,6 +453,9 @@ namespace quickbook std::string value_qbk_ref_impl::get_quickbook() const { return std::string(begin_.base(), end_.base()); } + value::qbk_range value_qbk_ref_impl::get_quickbook_range() const + { return qbk_range(begin_, end_); } + bool value_qbk_ref_impl::is_string() const { return true; } @@ -503,6 +516,11 @@ namespace quickbook std::string value_qbk_bbk_impl::get_quickbook() const { return qbk_value_; } + value::qbk_range value_qbk_bbk_impl::get_quickbook_range() const + { return qbk_range( + iterator(qbk_value_.begin(), position_), + iterator(qbk_value_.end())); } + std::string value_qbk_bbk_impl::get_boostbook() const { return bbk_value_; } @@ -687,7 +705,6 @@ namespace quickbook return new value_list_impl(head_, tag_); } - // TODO: Could reuse nodes is any node has a reference count of 1. value_node* value_list_impl::store() { value_node* pos = head_; @@ -762,7 +779,6 @@ namespace quickbook if(other.back_ == &head_) other.back_ = &other.head_; } - // TODO: Multiple list refs are incompatible with 'store' value_node* value_list_builder::get() const { return head_; } @@ -825,6 +841,14 @@ namespace quickbook current.append(item.value_); } + void value_builder::extend(value const& list) { + for (value::iterator begin = list.begin(), end = list.end(); + begin != end; ++begin) + { + insert(*begin); + } + } + void value_builder::start_list(value::tag_type tag) { value::tag_type saved_tag = tag; save(); diff --git a/src/values.hpp b/src/values.hpp index 0b060ec..09e45da 100644 --- a/src/values.hpp +++ b/src/values.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "fwd.hpp" @@ -38,6 +39,7 @@ namespace quickbook public: typedef int tag_type; + typedef boost::iterator_range qbk_range; protected: explicit value_node(tag_type); @@ -51,8 +53,10 @@ namespace quickbook virtual file_position get_position() const; virtual std::string get_quickbook() const; virtual std::string get_boostbook() const; + virtual qbk_range get_quickbook_range() const; virtual int get_int() const; + virtual bool check() const; virtual bool empty() const; virtual bool is_list() const; virtual bool is_string() const; @@ -83,6 +87,7 @@ namespace quickbook typedef iterator const_iterator; typedef value_node::tag_type tag_type; enum { default_tag = 0 }; + typedef boost::iterator_range qbk_range; protected: explicit value_base(value_node* base) @@ -96,6 +101,7 @@ namespace quickbook public: void swap(value_base& x) { std::swap(value_, x.value_); } + bool check() const { return value_->check(); } bool empty() const { return value_->empty(); } bool is_list() const { return value_->is_list(); } bool is_string() const { return value_->is_string(); } @@ -109,6 +115,8 @@ namespace quickbook { return value_->get_position(); } std::string get_quickbook() const { return value_->get_quickbook(); } + qbk_range get_quickbook_range() const + { return value_->get_quickbook_range(); } std::string get_boostbook() const { return value_->get_boostbook(); } int get_int() const @@ -181,7 +189,7 @@ namespace quickbook value_counted& operator=(value_counted); ~value_counted(); - void store(); + value store() const; }; //////////////////////////////////////////////////////////////////////// @@ -257,6 +265,7 @@ namespace quickbook void reset(); void set_tag(value::tag_type); void insert(value const&); + void extend(value const&); void start_list(value::tag_type = value::default_tag); void finish_list();