$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r59298 - in branches/quickbook-1.5-spirit2: . detail
From: daniel_james_at_[hidden]
Date: 2010-01-27 17:01:35
Author: danieljames
Date: 2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
New Revision: 59298
URL: http://svn.boost.org/trac/boost/changeset/59298
Log:
Call template.
Added:
   branches/quickbook-1.5-spirit2/phrase_template.cpp   (contents, props changed)
Text files modified: 
   branches/quickbook-1.5-spirit2/Jamfile.v2               |     1                                         
   branches/quickbook-1.5-spirit2/detail/actions.cpp       |   283 ----------------------------------------
   branches/quickbook-1.5-spirit2/detail/actions.hpp       |    15 --                                      
   branches/quickbook-1.5-spirit2/detail/actions_class.cpp |     1                                         
   branches/quickbook-1.5-spirit2/detail/actions_class.hpp |     1                                         
   branches/quickbook-1.5-spirit2/phrase.cpp               |    37 +++-                                    
   branches/quickbook-1.5-spirit2/phrase.hpp               |     9 +                                       
   7 files changed, 33 insertions(+), 314 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:01:34 EST (Wed, 27 Jan 2010)
@@ -30,6 +30,7 @@
     phrase.cpp
     phrase_actions.cpp
     phrase_image.cpp
+    phrase_template.cpp
     block.cpp
     doc_info.cpp
     detail/syntax_highlight.cpp
Modified: branches/quickbook-1.5-spirit2/detail/actions.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions.cpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions.cpp	2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
@@ -387,289 +387,6 @@
         actions.template_info.clear();
     }
 
-    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_
-          , boost::spirit::classic::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
-          , boost::spirit::classic::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
-          , boost::spirit::classic::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.out.swap(result);
-            }
-            return r;
-        }
-    }
-
-    void do_template_action::operator()(iterator p, bool template_escape,
-        template_symbol const& symbol, std::vector<std::string> params) const
-    {
-        boost::spirit::classic::file_position const pos = p.get_position();
-        ++actions.template_depth;
-        if (actions.template_depth > actions.max_template_depth)
-        {
-            detail::outerr(pos.file,pos.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>(symbol));
-
-            std::vector<std::string> template_ = boost::get<0>(symbol);
-            boost::spirit::classic::file_position template_pos = boost::get<1>(symbol);
-
-            ///////////////////////////////////
-            // Break the arguments
-            if (!break_arguments(params, template_, pos))
-            {
-                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, pos, 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, template_escape, actions))
-            {
-                detail::outerr(pos.file,pos.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;
-    }
-
     void variablelist_action::operator()(std::string const& title) const
     {
         actions.out << "<variablelist>\n";
Modified: branches/quickbook-1.5-spirit2/detail/actions.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions.hpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions.hpp	2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
@@ -468,21 +468,6 @@
         quickbook::actions& actions;
     };
 
-    struct do_template_action
-    {
-        template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-        struct result { typedef void type; };
-        
-        // Handles template substitutions
-
-        do_template_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator, bool, template_symbol const&, std::vector<std::string>) const;
-
-        quickbook::actions& actions;
-    };
-
     struct variablelist_action
     {
         // Handles variable lists
Modified: branches/quickbook-1.5-spirit2/detail/actions_class.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions_class.cpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions_class.cpp	2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
@@ -117,7 +117,6 @@
         , macro_definition(*this)
         , do_macro(phrase)
         , template_body(*this)
-        , do_template(*this)
         , url_pre(url_pre_)
         , url_post(url_post_)
         , link_pre(link_pre_)
Modified: branches/quickbook-1.5-spirit2/detail/actions_class.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions_class.hpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions_class.hpp	2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
@@ -139,7 +139,6 @@
         macro_definition_action macro_definition;
         do_macro_action         do_macro;
         template_body_action    template_body;
-        do_template_action      do_template;
         char const*             url_pre;
         char const*             url_post;
         char const*             link_pre;
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:01:34 EST (Wed, 27 Jan 2010)
@@ -69,6 +69,14 @@
     (std::string, content)
 )
 
+BOOST_FUSION_ADAPT_STRUCT(
+    quickbook::template_,
+    (quickbook::file_position, position)
+    (bool, escape)
+    (quickbook::template_symbol, symbol)
+    (std::vector<std::string>, params)
+)
+
 namespace quickbook
 {
     namespace qi = boost::spirit::qi;
@@ -94,7 +102,6 @@
                         phrase_end,
                         escape, common,
                         hard_space, eol, inline_code, simple_format,
-                        template_,
                         code_block, replaceable, macro,
                         dummy_block,
                         brackets_1_4, template_inner_arg_1_5, brackets_1_5
@@ -102,6 +109,7 @@
 
         qi::rule<iterator, file_position()> position;
 
+        qi::rule<iterator, quickbook::template_()> template_;
         qi::rule<iterator, std::string()> template_arg_1_4, template_arg_1_5;
         qi::rule<iterator, std::vector<std::string>() > template_args;
 
@@ -192,15 +200,16 @@
         // Template call
 
         template_ =
-            (   qi::raw[qi::eps]                    // For the position of the template
-            >>  -qi::char_('`')                     // Attribute implicitly cast to bool
+                position
+            >>  (   '`' >> qi::attr(true)
+                |   qi::attr(false)
+                )
             >>  (                                   // Lookup the template name
                     (&qi::punct >> actions.templates.scope)
                 |   (actions.templates.scope >> hard_space)
                 )
             >>  template_args
             >>  &qi::lit(']')
-            ) [ph::bind(actions.do_template, ph::begin(qi::_1), qi::_2, qi::_3, qi::_4)]
             ;
 
         template_args =
@@ -306,17 +315,17 @@
 
         phrase_markup =
                 '['
-            >>  (   cond_phrase                     [actions.process]
-                |   image                           [actions.process]
-                |   url                             [actions.process]
-                |   link                            [actions.process]
-                |   anchor                          [actions.process]
-                |   source_mode                     [actions.process]
-                |   formatted                       [actions.process]
-                |   footnote                        [actions.process]
+            >>  (   cond_phrase
+                |   image
+                |   url
+                |   link
+                |   anchor
+                |   source_mode
+                |   formatted
+                |   footnote
                 |   template_
-                |   break_                          [actions.process]
-                )
+                |   break_
+                )                                   [actions.process]
             >>  ']'
             ;
 
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:01:34 EST (Wed, 27 Jan 2010)
@@ -13,6 +13,7 @@
 #include <string>
 #include <map>
 #include <boost/spirit/include/classic_position_iterator.hpp>
+#include "detail/template_stack.hpp"
 
 namespace quickbook
 {
@@ -36,6 +37,13 @@
         char const* pre;
         char const* post;
     };
+    
+    struct template_ {
+        file_position position;
+        bool escape;
+        template_symbol symbol;
+        std::vector<std::string> params;
+    };
 
     struct anchor {
         char const* dummy;
@@ -72,6 +80,7 @@
     };
 
     void process(quickbook::actions&, source_mode const&);
+    void process(quickbook::actions&, template_ const&);
     void process(quickbook::actions&, anchor const&);
     void process(quickbook::actions&, link const&);
     void process(quickbook::actions&, formatted const&);
Added: branches/quickbook-1.5-spirit2/phrase_template.cpp
==============================================================================
--- (empty file)
+++ branches/quickbook-1.5-spirit2/phrase_template.cpp	2010-01-27 17:01:34 EST (Wed, 27 Jan 2010)
@@ -0,0 +1,300 @@
+/*=============================================================================
+    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 "./detail/actions_class.hpp"
+#include "./detail/quickbook.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_
+          , boost::spirit::classic::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
+          , boost::spirit::classic::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
+          , boost::spirit::classic::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.out.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);
+            boost::spirit::classic::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