1 /*============================================================================= 2 Copyright (c) 2002 2004 2006 Joel de Guzman 3 http://spirit.sourceforge.net/ 4 5 Use, modification and distribution is subject to the Boost Software 6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 10 #include "template_stack.hpp" 11 #include <cassert> 12 #include "files.hpp" 13 14 #ifdef BOOST_MSVC 15 #pragma warning(disable : 4355) 16 #endif 17 18 namespace quickbook 19 { template_symbol(std::string const & identifier_,std::vector<std::string> const & params_,value const & content_,template_scope const * lexical_parent_)20 template_symbol::template_symbol( 21 std::string const& identifier_, 22 std::vector<std::string> const& params_, 23 value const& content_, 24 template_scope const* lexical_parent_) 25 : identifier(identifier_) 26 , params(params_) 27 , content(content_) 28 , lexical_parent(lexical_parent_) 29 { 30 assert( 31 content.get_tag() == template_tags::block || 32 content.get_tag() == template_tags::phrase || 33 content.get_tag() == template_tags::snippet); 34 } 35 template_stack()36 template_stack::template_stack() 37 : scope(template_stack::parser(*this)), scopes(), parent_1_4(0) 38 { 39 scopes.push_front(template_scope()); 40 parent_1_4 = &scopes.front(); 41 } 42 find(std::string const & symbol) const43 template_symbol* template_stack::find(std::string const& symbol) const 44 { 45 for (template_scope const* i = &*scopes.begin(); i; 46 i = i->parent_scope) { 47 if (template_symbol* ts = 48 boost::spirit::classic::find(i->symbols, symbol.c_str())) 49 return ts; 50 } 51 return 0; 52 } 53 find_top_scope(std::string const & symbol) const54 template_symbol* template_stack::find_top_scope( 55 std::string const& symbol) const 56 { 57 return boost::spirit::classic::find( 58 scopes.front().symbols, symbol.c_str()); 59 } 60 top() const61 template_symbols const& template_stack::top() const 62 { 63 BOOST_ASSERT(!scopes.empty()); 64 return scopes.front().symbols; 65 } 66 top_scope() const67 template_scope const& template_stack::top_scope() const 68 { 69 BOOST_ASSERT(!scopes.empty()); 70 return scopes.front(); 71 } 72 add(template_symbol const & ts)73 bool template_stack::add(template_symbol const& ts) 74 { 75 BOOST_ASSERT(!scopes.empty()); 76 BOOST_ASSERT(ts.lexical_parent); 77 78 if (this->find_top_scope(ts.identifier)) { 79 return false; 80 } 81 82 boost::spirit::classic::add( 83 scopes.front().symbols, ts.identifier.c_str(), ts); 84 85 return true; 86 } 87 push()88 void template_stack::push() 89 { 90 template_scope const& old_front = scopes.front(); 91 scopes.push_front(template_scope()); 92 scopes.front().parent_1_4 = parent_1_4; 93 scopes.front().parent_scope = &old_front; 94 parent_1_4 = &scopes.front(); 95 } 96 pop()97 void template_stack::pop() 98 { 99 parent_1_4 = scopes.front().parent_1_4; 100 scopes.pop_front(); 101 } 102 start_template(template_symbol const * symbol)103 void template_stack::start_template(template_symbol const* symbol) 104 { 105 // Quickbook 1.4-: When expanding the template continue to use the 106 // current scope (the dynamic scope). 107 // Quickbook 1.5+: Use the scope the template was defined in 108 // (the static scope). 109 if (symbol->content.get_file()->version() >= 105u) { 110 parent_1_4 = scopes.front().parent_1_4; 111 scopes.front().parent_scope = symbol->lexical_parent; 112 } 113 else { 114 scopes.front().parent_scope = scopes.front().parent_1_4; 115 } 116 } 117 } 118