Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r59324 - branches/quickbook-1.5-spirit2
From: daniel_james_at_[hidden]
Date: 2010-01-27 17:07:24


Author: danieljames
Date: 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
New Revision: 59324
URL: http://svn.boost.org/trac/boost/changeset/59324

Log:
Move most of the template implementation into template.[ch]pp
Added:
   branches/quickbook-1.5-spirit2/template.cpp (contents, props changed)
      - copied, changed from r59323, /branches/quickbook-1.5-spirit2/phrase_template.cpp
   branches/quickbook-1.5-spirit2/template.hpp (contents, props changed)
Removed:
   branches/quickbook-1.5-spirit2/phrase_template.cpp
   branches/quickbook-1.5-spirit2/template_stack.cpp
   branches/quickbook-1.5-spirit2/template_stack.hpp
Text files modified:
   branches/quickbook-1.5-spirit2/Jamfile.v2 | 3
   branches/quickbook-1.5-spirit2/actions_class.cpp | 1
   branches/quickbook-1.5-spirit2/actions_class.hpp | 3
   branches/quickbook-1.5-spirit2/block.hpp | 11 -
   branches/quickbook-1.5-spirit2/block_actions.cpp | 33 +----
   branches/quickbook-1.5-spirit2/code_snippet.cpp | 7
   branches/quickbook-1.5-spirit2/code_snippet_types.hpp | 6
   branches/quickbook-1.5-spirit2/fwd.hpp | 8 +
   branches/quickbook-1.5-spirit2/parse_types.hpp | 1
   branches/quickbook-1.5-spirit2/phrase.cpp | 16 +-
   branches/quickbook-1.5-spirit2/phrase.hpp | 10
   branches/quickbook-1.5-spirit2/template.cpp | 217 +++++++++++++++++++++++++++++++--------
   12 files changed, 206 insertions(+), 110 deletions(-)

Modified: branches/quickbook-1.5-spirit2/Jamfile.v2
==============================================================================
--- branches/quickbook-1.5-spirit2/Jamfile.v2 (original)
+++ branches/quickbook-1.5-spirit2/Jamfile.v2 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -26,12 +26,11 @@
     input_path.cpp
     post_process.cpp
     collector.cpp
- template_stack.cpp
+ template.cpp
     markups.cpp
     phrase.cpp
     phrase_actions.cpp
     phrase_image.cpp
- phrase_template.cpp
     block.cpp
     block_actions.cpp
     block_list.cpp

Modified: branches/quickbook-1.5-spirit2/actions_class.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/actions_class.cpp (original)
+++ branches/quickbook-1.5-spirit2/actions_class.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -37,7 +37,6 @@
         , source_mode("c++")
 
     // temporary or global state
- , template_info()
         , template_depth(0)
         , templates()
         , error_count(0)

Modified: branches/quickbook-1.5-spirit2/actions_class.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/actions_class.hpp (original)
+++ branches/quickbook-1.5-spirit2/actions_class.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -15,7 +15,7 @@
 #include "fwd.hpp"
 #include "actions.hpp"
 #include "collector.hpp"
-#include "template_stack.hpp"
+#include "template.hpp"
 
 namespace quickbook
 {
@@ -61,7 +61,6 @@
         std::stack<state_tuple> state_stack;
 
     // temporary or global state
- string_list template_info;
         int template_depth;
         template_stack templates;
         int error_count;

Modified: branches/quickbook-1.5-spirit2/block.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/block.hpp (original)
+++ branches/quickbook-1.5-spirit2/block.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -62,14 +62,6 @@
         title content;
     };
 
- struct define_template
- {
- std::string id;
- std::vector<std::string> params;
- quickbook::file_position position;
- std::string body;
- };
-
     struct def_macro
     {
         std::string macro_identifier;
@@ -119,7 +111,6 @@
     void process(quickbook::actions&, end_section const&);
     void process(quickbook::actions&, heading const&);
     void process(quickbook::actions&, def_macro const&);
- void process(quickbook::actions&, define_template const&);
     void process(quickbook::actions&, variablelist const&);
     void process(quickbook::actions&, table const&);
     void process(quickbook::actions&, xinclude const&);
@@ -127,4 +118,4 @@
     void process(quickbook::actions&, include const&);
 }
 
-#endif
\ No newline at end of file
+#endif

Modified: branches/quickbook-1.5-spirit2/block_actions.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/block_actions.cpp (original)
+++ branches/quickbook-1.5-spirit2/block_actions.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -182,20 +182,11 @@
 
     void process(quickbook::actions& actions, define_template const& x)
     {
- if (actions.templates.find_top_scope(x.id))
- {
+ if(!actions.templates.add(x)) {
             detail::outerr(x.position.file, x.position.line)
- << "Template Redefinition: " << actions.template_info[0] << std::endl;
+ << "Template Redefinition: " << x.id << std::endl;
             ++actions.error_count;
         }
-
- std::vector<std::string> info;
- info.reserve(x.params.size() + 2);
- info.push_back(x.id);
- info.insert(info.end(), x.params.begin(), x.params.end());
- info.push_back(x.body);
-
- actions.templates.add(x.id, template_symbol(info, x.position));
     }
 
     void process(quickbook::actions& actions, variablelist const& x)
@@ -300,8 +291,8 @@
     {
         int load_snippets(
             std::string const& file
- , std::vector<template_symbol>& storage // snippets are stored in a
- // vector of template_symbols
+ , std::vector<define_template>& storage // for storing snippets are stored in a
+ // vector of define_templates
           , std::string const& extension
           , std::string const& doc_id)
         {
@@ -442,24 +433,18 @@
     {
         fs::path path = include_search(actions.filename.branch_path(), x.path);
         std::string ext = fs::extension(path);
- std::vector<template_symbol> storage;
+ std::vector<define_template> storage;
         actions.error_count +=
             load_snippets(path.string(), storage, ext, actions.doc_id);
 
- BOOST_FOREACH(template_symbol const& ts, storage)
+ BOOST_FOREACH(define_template const& definition, storage)
         {
- std::string tname = boost::get<0>(ts)[0];
- if (actions.templates.find_top_scope(tname))
+ if (!actions.templates.add(definition))
             {
- file_position const pos = boost::get<1>(ts);
- detail::outerr(pos.file, pos.line)
- << "Template Redefinition: " << tname << std::endl;
+ detail::outerr(definition.position.file, definition.position.line)
+ << "Template Redefinition: " << definition.id << std::endl;
                 ++actions.error_count;
             }
- else
- {
- actions.templates.add(tname, ts);
- }
         }
     }
 }
\ No newline at end of file

Modified: branches/quickbook-1.5-spirit2/code_snippet.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/code_snippet.cpp (original)
+++ branches/quickbook-1.5-spirit2/code_snippet.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -102,10 +102,9 @@
             }
         }
 
- std::vector<std::string> tinfo;
- tinfo.push_back(x.identifier);
- tinfo.push_back(actions.snippet);
- actions.storage.push_back(template_symbol(tinfo, x.position));
+ std::vector<std::string> empty_params;
+ actions.storage.push_back(define_template(
+ x.identifier, empty_params, actions.snippet, x.position));
 
         callout_id += actions.callouts.size();
         actions.callouts.clear();

Modified: branches/quickbook-1.5-spirit2/code_snippet_types.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/code_snippet_types.hpp (original)
+++ branches/quickbook-1.5-spirit2/code_snippet_types.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -17,8 +17,6 @@
 #include <boost/fusion/include/adapt_struct.hpp>
 #include <boost/spirit/include/support_unused.hpp>
 #include "fwd.hpp"
-// TODO: Convert template_symbol into a struct so it can be forward declared.
-#include "template_stack.hpp"
 
 namespace quickbook
 {
@@ -67,7 +65,7 @@
 
     struct code_snippet_actions
     {
- code_snippet_actions(std::vector<template_symbol>& storage,
+ code_snippet_actions(std::vector<define_template>& storage,
                                  std::string const& doc_id,
                                  char const* source_type)
             : process(*this)
@@ -104,7 +102,7 @@
         std::string code;
         std::string snippet;
         std::vector<std::string> callouts;
- std::vector<template_symbol>& storage;
+ std::vector<define_template>& storage;
         std::string const doc_id;
         char const* const source_type;
     };

Modified: branches/quickbook-1.5-spirit2/fwd.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/fwd.hpp (original)
+++ branches/quickbook-1.5-spirit2/fwd.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -22,10 +22,16 @@
 
     struct collector;
     struct string_stream;
-
+
     typedef boost::spirit::classic::position_iterator<
         std::string::const_iterator> iterator;
     typedef boost::spirit::classic::file_position file_position;
+
+ // templates
+
+ struct call_template;
+ struct define_template;
+ struct template_symbol;
 }
 
 #endif
\ No newline at end of file

Modified: branches/quickbook-1.5-spirit2/parse_types.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/parse_types.hpp (original)
+++ branches/quickbook-1.5-spirit2/parse_types.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -16,7 +16,6 @@
 
 namespace quickbook
 {
-
     struct markup {
         markup()
             : pre(""), post("") {}

Modified: branches/quickbook-1.5-spirit2/phrase.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/phrase.cpp (original)
+++ branches/quickbook-1.5-spirit2/phrase.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -25,9 +25,6 @@
 #include "markups.hpp"
 #include "quickbook.hpp"
 #include "parse_utils.hpp"
-/*
-#include "utils.hpp"
-*/
 
 BOOST_FUSION_ADAPT_STRUCT(
     quickbook::anchor,
@@ -54,7 +51,6 @@
     (char const*, dummy)
 )
 
-
 BOOST_FUSION_ADAPT_STRUCT(
     quickbook::image,
     (quickbook::file_position, position)
@@ -69,11 +65,11 @@
 )
 
 BOOST_FUSION_ADAPT_STRUCT(
- quickbook::template_,
+ quickbook::call_template,
     (quickbook::file_position, position)
     (bool, escape)
- (quickbook::template_symbol, symbol)
- (std::vector<std::string>, params)
+ (quickbook::template_symbol const*, symbol)
+ (std::vector<std::string>, args)
 )
 
 namespace quickbook
@@ -100,7 +96,7 @@
 
         qi::rule<iterator, file_position()> position;
 
- qi::rule<iterator, quickbook::template_()> template_;
+ qi::rule<iterator, quickbook::call_template()> call_template;
         qi::rule<iterator, std::string()> template_arg_1_4, template_arg_1_5;
         qi::rule<iterator, std::vector<std::string>() > template_args;
 
@@ -193,7 +189,7 @@
 
         // Template call
 
- template_ =
+ call_template =
                 position
>> ( '`' >> qi::attr(true)
                 | qi::attr(false)
@@ -306,7 +302,7 @@
                 | source_mode
                 | formatted
                 | footnote
- | template_
+ | call_template
                 | break_
                 )
>> ']'

Modified: branches/quickbook-1.5-spirit2/phrase.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/phrase.hpp (original)
+++ branches/quickbook-1.5-spirit2/phrase.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -10,11 +10,11 @@
 #if !defined(BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP)
 #define BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP
 
+#include <vector>
 #include <string>
 #include <map>
 #include "fwd.hpp"
 #include "parse_types.hpp"
-#include "template_stack.hpp"
 
 namespace quickbook
 {
@@ -25,11 +25,11 @@
         std::string mode;
     };
     
- struct template_ {
+ struct call_template {
         file_position position;
         bool escape;
- template_symbol symbol;
- std::vector<std::string> params;
+ template_symbol const* symbol;
+ std::vector<std::string> args;
     };
 
     struct anchor {
@@ -68,7 +68,7 @@
 
     void process(quickbook::actions&, source_mode const&);
     void process(quickbook::actions&, macro const&);
- void process(quickbook::actions&, template_ const&);
+ void process(quickbook::actions&, call_template const&);
     void process(quickbook::actions&, anchor const&);
     void process(quickbook::actions&, link const&);
     void process(quickbook::actions&, simple_markup const&);

Deleted: branches/quickbook-1.5-spirit2/phrase_template.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/phrase_template.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
+++ (empty file)
@@ -1,301 +0,0 @@
-/*=============================================================================
- Copyright (c) 2002 2004 2006 Joel de Guzman
- Copyright (c) 2004 Eric Niebler
- http://spirit.sourceforge.net/
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-
-#include "phrase.hpp"
-#include "grammars.hpp"
-#include "actions_class.hpp"
-#include "quickbook.hpp"
-#include "utils.hpp"
-
-namespace quickbook
-{
- namespace
- {
- std::string::size_type find_bracket_end(std::string const& str, std::string::size_type pos)
- {
- unsigned int depth = 1;
-
- while(depth > 0) {
- pos = str.find_first_of("[]\\", pos);
- if(pos == std::string::npos) return pos;
-
- if(str[pos] == '\\')
- {
- pos += 2;
- }
- else
- {
- depth += (str[pos] == '[') ? 1 : -1;
- ++pos;
- }
- }
-
- return pos;
- }
-
- std::string::size_type find_first_seperator(std::string const& str)
- {
- if(qbk_version_n < 105) {
- return str.find_first_of(" \t\r\n");
- }
- else {
- std::string::size_type pos = 0;
-
- while(true)
- {
- pos = str.find_first_of(" \t\r\n\\[", pos);
- if(pos == std::string::npos) return pos;
-
- switch(str[pos])
- {
- case '[':
- pos = find_bracket_end(str, pos + 1);
- break;
- case '\\':
- pos += 2;
- break;
- default:
- return pos;
- }
- }
- }
- }
-
- bool break_arguments(
- std::vector<std::string>& params
- , std::vector<std::string> const& template_
- , file_position const& pos
- )
- {
- // Quickbook 1.4-: If there aren't enough parameters seperated by
- // '..' then seperate the last parameter using
- // whitespace.
- // Quickbook 1.5+: If '..' isn't used to seperate the parameters
- // then use whitespace to separate them
- // (2 = template name + argument).
-
- if (qbk_version_n < 105 || params.size() == 1)
- {
- // template_.size() - 2 because template_ also includes the name and body.
- while (params.size() < template_.size() - 2 )
- {
- // Try to break the last argument at the first space found
- // and push it into the back of params. Do this
- // recursively until we have all the expected number of
- // arguments, or if there are no more spaces left.
-
- std::string& str = params.back();
- std::string::size_type l_pos = find_first_seperator(str);
- if (l_pos == std::string::npos)
- break;
- std::string first(str.begin(), str.begin()+l_pos);
- std::string::size_type r_pos = str.find_first_not_of(" \t\r\n", l_pos);
- if (r_pos == std::string::npos)
- break;
- std::string second(str.begin()+r_pos, str.end());
- str = first;
- params.push_back(second);
- }
- }
-
- if (params.size() != template_.size() - 2)
- {
- detail::outerr(pos.file, pos.line)
- << "Invalid number of arguments passed. Expecting: "
- << template_.size()-2
- << " argument(s), got: "
- << params.size()
- << " argument(s) instead."
- << std::endl;
- return false;
- }
- return true;
- }
-
- std::pair<bool, std::vector<std::string>::const_iterator>
- get_arguments(
- std::vector<std::string>& params
- , std::vector<std::string> const& template_
- , template_scope const& scope
- , file_position const& pos
- , quickbook::actions& actions
- )
- {
- std::vector<std::string>::const_iterator arg = params.begin();
- std::vector<std::string>::const_iterator tpl = template_.begin()+1;
-
- // Store each of the argument passed in as local templates:
- while (arg != params.end())
- {
- std::vector<std::string> tinfo;
- tinfo.push_back(*tpl);
- tinfo.push_back(*arg);
- template_symbol template_(tinfo, pos, &scope);
-
- if (actions.templates.find_top_scope(*tpl))
- {
- detail::outerr(pos.file,pos.line)
- << "Duplicate Symbol Found" << std::endl;
- ++actions.error_count;
- return std::make_pair(false, tpl);
- }
- else
- {
- actions.templates.add(*tpl, template_);
- }
- ++arg; ++tpl;
- }
- return std::make_pair(true, tpl);
- }
-
- bool parse_template(
- std::string& body
- , std::string& result
- , file_position const& template_pos
- , bool template_escape
- , quickbook::actions& actions
- )
- {
- // How do we know if we are to parse the template as a block or
- // a phrase? We apply a simple heuristic: if the body starts with
- // a newline, then we regard it as a block, otherwise, we parse
- // it as a phrase.
-
- std::string::const_iterator iter = body.begin();
- while (iter != body.end() && ((*iter == ' ') || (*iter == '\t')))
- ++iter; // skip spaces and tabs
- bool is_block = (iter != body.end()) && ((*iter == '\r') || (*iter == '\n'));
- bool r = false;
-
- if (template_escape)
- {
- // escape the body of the template
- // we just copy out the literal body
- result = body;
- r = true;
- }
- else if (!is_block)
- {
- simple_phrase_grammar phrase_p(actions);
-
- // do a phrase level parse
- iterator first(body.begin(), body.end(), actions.filename.native_file_string().c_str());
- first.set_position(template_pos);
- iterator last(body.end(), body.end());
- r = boost::spirit::qi::parse(first, last, phrase_p) && first == last;
- actions.phrase.swap(result);
- }
- else
- {
- block_grammar block_p(actions);
-
- // do a block level parse
- // ensure that we have enough trailing newlines to eliminate
- // the need to check for end of file in the grammar.
- body.push_back('\n');
- body.push_back('\n');
- while (iter != body.end() && ((*iter == '\r') || (*iter == '\n')))
- ++iter; // skip initial newlines
- iterator first(iter, body.end(), actions.filename.native_file_string().c_str());
- first.set_position(template_pos);
- iterator last(body.end(), body.end());
- r = boost::spirit::qi::parse(first, last, block_p) && first == last;
- actions.phrase.swap(result);
- }
- return r;
- }
- }
-
- void process(quickbook::actions& actions, template_ const& x)
- {
- ++actions.template_depth;
- if (actions.template_depth > actions.max_template_depth)
- {
- detail::outerr(x.position.file,x.position.line)
- << "Infinite loop detected" << std::endl;
- --actions.template_depth;
- ++actions.error_count;
- return;
- }
-
- // The template arguments should have the scope that the template was
- // called from, not the template's own scope.
- //
- // Note that for quickbook 1.4- this value is just ignored when the
- // arguments are expanded.
- template_scope const& call_scope = actions.templates.top_scope();
-
- std::string result;
- actions.push(); // scope the actions' states
- {
- // Quickbook 1.4-: When expanding the tempalte continue to use the
- // current scope (the dynamic scope).
- // Quickbook 1.5+: Use the scope the template was defined in
- // (the static scope).
- if (qbk_version_n >= 105)
- actions.templates.set_parent_scope(*boost::get<2>(x.symbol));
-
- std::vector<std::string> template_ = boost::get<0>(x.symbol);
- file_position template_pos = boost::get<1>(x.symbol);
-
- std::vector<std::string> params = x.params;
-
- ///////////////////////////////////
- // Break the arguments
- if (!break_arguments(params, template_, x.position))
- {
- actions.pop(); // restore the actions' states
- --actions.template_depth;
- ++actions.error_count;
- return;
- }
-
- ///////////////////////////////////
- // Prepare the arguments as local templates
- bool get_arg_result;
- std::vector<std::string>::const_iterator tpl;
- boost::tie(get_arg_result, tpl) =
- get_arguments(params, template_,
- call_scope, x.position, actions);
-
- if (!get_arg_result)
- {
- actions.pop(); // restore the actions' states
- --actions.template_depth;
- return;
- }
-
- ///////////////////////////////////
- // parse the template body:
- std::string body;
- body.assign(tpl->begin(), tpl->end());
- body.reserve(body.size()+2); // reserve 2 more
-
- if (!parse_template(body, result, template_pos, x.escape, actions))
- {
- detail::outerr(x.position.file,x.position.line)
- //<< "Expanding template:" << template_info[0] << std::endl
- << std::endl
- << "------------------begin------------------" << std::endl
- << body
- << "------------------end--------------------" << std::endl
- << std::endl;
- actions.pop(); // restore the actions' states
- --actions.template_depth;
- ++actions.error_count;
- return;
- }
- }
-
- actions.pop(); // restore the actions' states
- actions.phrase << result; // print it!!!
- --actions.template_depth;
- }
-}
\ No newline at end of file

Copied: branches/quickbook-1.5-spirit2/template.cpp (from r59323, /branches/quickbook-1.5-spirit2/phrase_template.cpp)
==============================================================================
--- /branches/quickbook-1.5-spirit2/phrase_template.cpp (original)
+++ branches/quickbook-1.5-spirit2/template.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -1,6 +1,5 @@
 /*=============================================================================
     Copyright (c) 2002 2004 2006 Joel de Guzman
- Copyright (c) 2004 Eric Niebler
     http://spirit.sourceforge.net/
 
     Use, modification and distribution is subject to the Boost Software
@@ -8,14 +7,149 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 
+#include <boost/spirit/include/qi_symbols.hpp>
+#include "template.hpp"
 #include "phrase.hpp"
 #include "grammars.hpp"
 #include "actions_class.hpp"
 #include "quickbook.hpp"
 #include "utils.hpp"
 
+#ifdef BOOST_MSVC
+#pragma warning(disable : 4355)
+#endif
+
 namespace quickbook
-{
+{
+ struct template_symbol
+ {
+ template_symbol(
+ std::string const& identifier,
+ std::vector<std::string> const& params,
+ std::string const& body,
+ file_position const& position,
+ template_scope const* parent)
+ : identifier(identifier)
+ , params(params)
+ , body(body)
+ , position(position)
+ , parent(parent) {}
+
+ std::string identifier;
+ std::vector<std::string> params;
+ std::string body;
+ file_position position;
+ template_scope const* parent;
+ };
+
+ typedef boost::spirit::qi::symbols<char, template_symbol> template_symbols;
+
+ // template scope
+ //
+ // 1.4-: parent_scope is the previous scope on the stack
+ // (the template's dynamic parent).
+ // 1.5+: parent_scope is the template's lexical parent.
+ //
+ // This means that a search along the parent_scope chain will follow the
+ // correct lookup chain for that version of quickboook.
+ //
+ // symbols contains the templates defined in this scope.
+
+ struct template_scope
+ {
+ template_scope() : parent_scope() {}
+ template_scope const* parent_scope;
+ template_symbols symbols;
+ };
+
+ template_stack::template_stack()
+ : scope(template_stack::parser(*this))
+ , scopes()
+ {
+ scopes.push_front(template_scope());
+ }
+
+ template_stack::~template_stack() {}
+
+ template_symbol const* template_stack::prefix_find(iterator& first, iterator const& last) const
+ {
+ // search all scopes for the longest matching symbol.
+ iterator found = first;
+ template_symbol const* result = 0;
+ for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
+ {
+ iterator iter = first;
+ template_symbol const* symbol = i->symbols.prefix_find(iter, last);
+ if(symbol && iter.base() > found.base())
+ {
+ found = iter;
+ result = symbol;
+ }
+ }
+ first = found;
+ return result;
+ }
+
+ template_symbol const* template_stack::find(std::string const& symbol) const
+ {
+ for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
+ {
+ if (template_symbol const* ts = i->symbols.find(symbol.c_str()))
+ return ts;
+ }
+ return 0;
+ }
+
+ template_symbol const* template_stack::find_top_scope(std::string const& symbol) const
+ {
+ return scopes.front().symbols.find(symbol.c_str());
+ }
+
+ template_scope const& template_stack::top_scope() const
+ {
+ BOOST_ASSERT(!scopes.empty());
+ return scopes.front();
+ }
+
+ bool template_stack::add(
+ define_template const& definition,
+ template_scope const* parent)
+ {
+ BOOST_ASSERT(!scopes.empty());
+
+ if (this->find_top_scope(definition.id)) {
+ return false;
+ }
+
+ template_symbol ts(
+ definition.id,
+ definition.params,
+ definition.body,
+ definition.position,
+ parent ? parent : &top_scope());
+
+ scopes.front().symbols.add(ts.identifier.c_str(), ts);
+
+ return true;
+ }
+
+ void template_stack::push()
+ {
+ template_scope const& old_front = scopes.front();
+ scopes.push_front(template_scope());
+ set_parent_scope(old_front);
+ }
+
+ void template_stack::pop()
+ {
+ scopes.pop_front();
+ }
+
+ void template_stack::set_parent_scope(template_scope const& parent)
+ {
+ scopes.front().parent_scope = &parent;
+ }
+
     namespace
     {
         std::string::size_type find_bracket_end(std::string const& str, std::string::size_type pos)
@@ -69,8 +203,8 @@
         }
     
         bool break_arguments(
- std::vector<std::string>& params
- , std::vector<std::string> const& template_
+ std::vector<std::string>& args
+ , std::vector<std::string> const& params
           , file_position const& pos
         )
         {
@@ -81,17 +215,16 @@
             // then use whitespace to separate them
             // (2 = template name + argument).
 
- if (qbk_version_n < 105 || params.size() == 1)
+ if (qbk_version_n < 105 || args.size() == 1)
             {
- // template_.size() - 2 because template_ also includes the name and body.
- while (params.size() < template_.size() - 2 )
+ while (args.size() < params.size() )
                 {
                     // Try to break the last argument at the first space found
- // and push it into the back of params. Do this
+ // and push it into the back of args. Do this
                     // recursively until we have all the expected number of
                     // arguments, or if there are no more spaces left.
 
- std::string& str = params.back();
+ std::string& str = args.back();
                     std::string::size_type l_pos = find_first_seperator(str);
                     if (l_pos == std::string::npos)
                         break;
@@ -101,17 +234,17 @@
                         break;
                     std::string second(str.begin()+r_pos, str.end());
                     str = first;
- params.push_back(second);
+ args.push_back(second);
                 }
             }
 
- if (params.size() != template_.size() - 2)
+ if (args.size() != params.size())
             {
                 detail::outerr(pos.file, pos.line)
                     << "Invalid number of arguments passed. Expecting: "
- << template_.size()-2
- << " argument(s), got: "
                     << params.size()
+ << " argument(s), got: "
+ << args.size()
                     << " argument(s) instead."
                     << std::endl;
                 return false;
@@ -121,42 +254,37 @@
 
         std::pair<bool, std::vector<std::string>::const_iterator>
         get_arguments(
- std::vector<std::string>& params
- , std::vector<std::string> const& template_
+ std::vector<std::string>& args
+ , std::vector<std::string> const& params
           , template_scope const& scope
           , file_position const& pos
           , quickbook::actions& actions
         )
         {
- std::vector<std::string>::const_iterator arg = params.begin();
- std::vector<std::string>::const_iterator tpl = template_.begin()+1;
+ std::vector<std::string>::const_iterator arg = args.begin();
+ std::vector<std::string>::const_iterator tpl = params.begin();
 
             // Store each of the argument passed in as local templates:
- while (arg != params.end())
+ while (arg != args.end())
             {
- std::vector<std::string> tinfo;
- tinfo.push_back(*tpl);
- tinfo.push_back(*arg);
- template_symbol template_(tinfo, pos, &scope);
+ std::vector<std::string> empty_params;
 
- if (actions.templates.find_top_scope(*tpl))
+ if (!actions.templates.add(
+ define_template(*tpl, empty_params, *arg, pos),
+ &scope))
                 {
                     detail::outerr(pos.file,pos.line)
                         << "Duplicate Symbol Found" << std::endl;
                     ++actions.error_count;
                     return std::make_pair(false, tpl);
                 }
- else
- {
- actions.templates.add(*tpl, template_);
- }
                 ++arg; ++tpl;
             }
             return std::make_pair(true, tpl);
         }
 
         bool parse_template(
- std::string& body
+ std::string body
           , std::string& result
           , file_position const& template_pos
           , bool template_escape
@@ -167,6 +295,8 @@
             // a phrase? We apply a simple heuristic: if the body starts with
             // a newline, then we regard it as a block, otherwise, we parse
             // it as a phrase.
+
+ body.reserve(body.size() + 2);
 
             std::string::const_iterator iter = body.begin();
             while (iter != body.end() && ((*iter == ' ') || (*iter == '\t')))
@@ -199,8 +329,7 @@
                 // do a block level parse
                 // ensure that we have enough trailing newlines to eliminate
                 // the need to check for end of file in the grammar.
- body.push_back('\n');
- body.push_back('\n');
+ body += "\n\n";
                 while (iter != body.end() && ((*iter == '\r') || (*iter == '\n')))
                     ++iter; // skip initial newlines
                 iterator first(iter, body.end(), actions.filename.native_file_string().c_str());
@@ -213,12 +342,12 @@
         }
     }
 
- void process(quickbook::actions& actions, template_ const& x)
+ void process(quickbook::actions& actions, call_template const& x)
     {
         ++actions.template_depth;
         if (actions.template_depth > actions.max_template_depth)
         {
- detail::outerr(x.position.file,x.position.line)
+ detail::outerr(x.position.file, x.position.line)
                 << "Infinite loop detected" << std::endl;
             --actions.template_depth;
             ++actions.error_count;
@@ -240,16 +369,13 @@
             // Quickbook 1.5+: Use the scope the template was defined in
             // (the static scope).
             if (qbk_version_n >= 105)
- actions.templates.set_parent_scope(*boost::get<2>(x.symbol));
+ actions.templates.set_parent_scope(*x.symbol->parent);
 
- std::vector<std::string> template_ = boost::get<0>(x.symbol);
- file_position template_pos = boost::get<1>(x.symbol);
-
- std::vector<std::string> params = x.params;
+ std::vector<std::string> args = x.args;
     
             ///////////////////////////////////
             // Break the arguments
- if (!break_arguments(params, template_, x.position))
+ if (!break_arguments(args, x.symbol->params, x.position))
             {
                 actions.pop(); // restore the actions' states
                 --actions.template_depth;
@@ -262,7 +388,7 @@
             bool get_arg_result;
             std::vector<std::string>::const_iterator tpl;
             boost::tie(get_arg_result, tpl) =
- get_arguments(params, template_,
+ get_arguments(args, x.symbol->params,
                     call_scope, x.position, actions);
 
             if (!get_arg_result)
@@ -274,17 +400,14 @@
 
             ///////////////////////////////////
             // parse the template body:
- std::string body;
- body.assign(tpl->begin(), tpl->end());
- body.reserve(body.size()+2); // reserve 2 more
 
- if (!parse_template(body, result, template_pos, x.escape, actions))
+ if (!parse_template(x.symbol->body, result, x.symbol->position, x.escape, actions))
             {
                 detail::outerr(x.position.file,x.position.line)
- //<< "Expanding template:" << template_info[0] << std::endl
+ //<< "Expanding template:" << x.symbol->identifier << std::endl
                     << std::endl
                     << "------------------begin------------------" << std::endl
- << body
+ << x.symbol->body
                     << "------------------end--------------------" << std::endl
                     << std::endl;
                 actions.pop(); // restore the actions' states
@@ -298,4 +421,6 @@
         actions.phrase << result; // print it!!!
         --actions.template_depth;
     }
-}
\ No newline at end of file
+}
+
+

Added: branches/quickbook-1.5-spirit2/template.hpp
==============================================================================
--- (empty file)
+++ branches/quickbook-1.5-spirit2/template.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
@@ -0,0 +1,102 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
+
+#include <string>
+#include <deque>
+#include <vector>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/home/qi/detail/assign_to.hpp>
+#include "fwd.hpp"
+
+namespace quickbook
+{
+ namespace qi = boost::spirit::qi;
+
+ struct define_template
+ {
+ define_template() {}
+
+ define_template(
+ std::string id,
+ std::vector<std::string> params,
+ std::string body,
+ quickbook::file_position position)
+ :
+ id(id), params(params), body(body), position(position)
+ {}
+
+ std::string id;
+ std::vector<std::string> params;
+ std::string body;
+ quickbook::file_position position;
+ };
+
+ void process(quickbook::actions&, define_template const&);
+
+ struct template_scope;
+ struct template_symbol;
+
+ struct template_stack
+ {
+ typedef std::deque<template_scope> deque;
+
+ struct parser : boost::spirit::qi::primitive_parser<parser>
+ {
+ template <typename Ctx, typename Itr>
+ struct attribute {
+ typedef template_symbol const* type;
+ };
+
+ parser(template_stack& ts)
+ : ts(ts) {}
+
+ template <typename Context, typename Skipper, typename Attribute>
+ bool parse(iterator& first, iterator const& last
+ , Context& context, Skipper const& skipper, Attribute& attr) const
+ {
+ boost::spirit::qi::skip_over(first, last, skipper);
+ template_symbol const* symbol = ts.prefix_find(first, last);
+ if(symbol) boost::spirit::traits::assign_to(symbol, attr);
+ return symbol;
+ }
+
+ template_stack& ts;
+ };
+
+ template_stack();
+ ~template_stack();
+ template_symbol const* prefix_find(iterator& first, iterator const& last) const;
+ template_symbol const* find(std::string const& symbol) const;
+ template_symbol const* find_top_scope(std::string const& symbol) const;
+ template_scope const& top_scope() const;
+ // Add the given template symbol to the current scope.
+ // If a parent scope isn't supplied, uses the current scope.
+ bool add(define_template const&, template_scope const* parent = 0);
+ void push();
+ void pop();
+
+ // Set the current scope's parent.
+ void set_parent_scope(template_scope const&);
+
+ parser scope;
+
+ private:
+
+ friend struct parser;
+ deque scopes;
+
+ template_stack(template_stack const&);
+ template_stack& operator=(template_stack const&);
+ };
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
+

Deleted: branches/quickbook-1.5-spirit2/template_stack.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/template_stack.cpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
+++ (empty file)
@@ -1,78 +0,0 @@
-/*=============================================================================
- Copyright (c) 2002 2004 2006 Joel de Guzman
- http://spirit.sourceforge.net/
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-#include "template_stack.hpp"
-
-#ifdef BOOST_MSVC
-#pragma warning(disable : 4355)
-#endif
-
-namespace quickbook
-{
- template_stack::template_stack()
- : scope(template_stack::parser(*this))
- , scopes()
- {
- scopes.push_front(template_scope());
- }
-
- template_symbol const* template_stack::find(std::string const& symbol) const
- {
- for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
- {
- if (template_symbol const* ts = i->symbols.find(symbol.c_str()))
- return ts;
- }
- return 0;
- }
-
- template_symbol const* template_stack::find_top_scope(std::string const& symbol) const
- {
- return scopes.front().symbols.find(symbol.c_str());
- }
-
- template_symbols const& template_stack::top() const
- {
- BOOST_ASSERT(!scopes.empty());
- return scopes.front().symbols;
- }
-
- template_scope const& template_stack::top_scope() const
- {
- BOOST_ASSERT(!scopes.empty());
- return scopes.front();
- }
-
- // TODO: Should symbols defined by '[import]' use the current scope?
- void template_stack::add(std::string const& symbol, template_symbol const& ts)
- {
- BOOST_ASSERT(!scopes.empty());
- scopes.front().symbols.add(symbol.c_str(),
- boost::get<2>(ts) ? ts :
- template_symbol(boost::get<0>(ts), boost::get<1>(ts), &top_scope()));
- }
-
- void template_stack::push()
- {
- template_scope const& old_front = scopes.front();
- scopes.push_front(template_scope());
- set_parent_scope(old_front);
- }
-
- void template_stack::pop()
- {
- scopes.pop_front();
- }
-
- void template_stack::set_parent_scope(template_scope const& parent)
- {
- scopes.front().parent_scope = &parent;
- }
-}
-
-

Deleted: branches/quickbook-1.5-spirit2/template_stack.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/template_stack.hpp 2010-01-27 17:07:22 EST (Wed, 27 Jan 2010)
+++ (empty file)
@@ -1,131 +0,0 @@
-/*=============================================================================
- Copyright (c) 2002 2004 2006 Joel de Guzman
- http://spirit.sourceforge.net/
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-#if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP)
-#define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
-
-#include <string>
-#include <deque>
-#include <vector>
-#include <boost/tuple/tuple.hpp>
-#include <boost/spirit/include/qi_symbols.hpp>
-#include <boost/spirit/include/qi_parse.hpp>
-#include <boost/next_prior.hpp>
-#include "fwd.hpp"
-
-namespace quickbook
-{
- struct template_scope;
-
- // template symbols with N arguments are stored as follows:
- //
- // vector<std::string>
- // 0: template name
- // 1: template param name[0]
- // 2: template param name[1]
- // ...
- // N: template param name[N-1]
- // N+1: template body
- // file position
- // template scope (only used for 1.5+, 1.4- uses the dynamic scope)
-
- typedef boost::tuple<
- std::vector<std::string>
- , file_position
- , template_scope const*>
- template_symbol;
-
- typedef boost::spirit::qi::symbols<char, template_symbol> template_symbols;
-
- // template scope
- //
- // 1.4-: parent_scope is the previous scope on the stack
- // (the template's dynamic parent).
- // 1.5+: parent_scope is the template's lexical parent.
- //
- // This means that a search along the parent_scope chain will follow the
- // correct lookup chain for that version of quickboook.
- //
- // symbols contains the templates defined in this scope.
-
- struct template_scope
- {
- template_scope() : parent_scope() {}
- template_scope const* parent_scope;
- template_symbols symbols;
- };
-
- struct template_stack
- {
- typedef std::deque<template_scope> deque;
-
- struct parser : boost::spirit::qi::primitive_parser<parser>
- {
- template <typename Ctx, typename Itr>
- struct attribute {
- typedef template_symbol type;
- };
-
- parser(template_stack& ts)
- : ts(ts) {}
-
- template <typename Iterator, typename Context, typename Skipper, typename Attribute>
- bool parse(Iterator& first, Iterator const& last
- , Context& context, Skipper const& skipper, Attribute& attr) const
- {
- boost::spirit::qi::skip_over(first, last, skipper);
-
- // TODO: Is this right?
- template_symbol result_attr;
-
- // search all scopes for the longest matching symbol.
- Iterator f = first;
- std::ptrdiff_t len = -1;
- for (template_scope const* i = &*ts.scopes.begin(); i; i = i->parent_scope)
- {
- // TODO: Implement this without calling 'base'.
- if(i->symbols.parse(first, last, context, skipper, result_attr) && first.base() - f.base() > len)
- {
- boost::spirit::traits::assign_to(result_attr, attr);
- len = first.base() - f.base();
- }
- first = f;
- }
- if (len >= 0)
- first = boost::next(f, len);
- return len > 0;
- }
-
- template_stack& ts;
- };
-
- template_stack();
- template_symbol const* find(std::string const& symbol) const;
- template_symbol const* find_top_scope(std::string const& symbol) const;
- template_symbols const& top() const;
- template_scope const& top_scope() const;
- // Add the given template symbol to the current scope.
- // If it doesn't have a scope, sets the symbol's scope to the current scope.
- void add(std::string const& symbol, template_symbol const& ts);
- void push();
- void pop();
-
- // Set the current scope's parent.
- void set_parent_scope(template_scope const&);
-
- parser scope;
-
- private:
-
- friend struct parser;
- deque scopes;
- };
-}
-
-#endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
-


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