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 #if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP) 10 #define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP 11 12 #include <cassert> 13 #include <deque> 14 #include <string> 15 #include <vector> 16 #include <boost/assert.hpp> 17 #include <boost/filesystem/path.hpp> 18 #include <boost/next_prior.hpp> 19 #include <boost/spirit/include/classic_functor_parser.hpp> 20 #include <boost/spirit/include/classic_symbols.hpp> 21 #include <boost/tuple/tuple.hpp> 22 #include "fwd.hpp" 23 #include "template_tags.hpp" 24 #include "values.hpp" 25 26 namespace quickbook 27 { 28 namespace fs = boost::filesystem; 29 30 struct template_scope; 31 32 struct template_symbol 33 { 34 template_symbol( 35 std::string const& identifier, 36 std::vector<std::string> const& params, 37 value const& content, 38 template_scope const* parent = 0); 39 40 std::string identifier; 41 std::vector<std::string> params; 42 value content; 43 44 template_scope const* lexical_parent; 45 }; 46 47 typedef boost::spirit::classic::symbols<template_symbol> template_symbols; 48 49 // template scope 50 // 51 // 1.4-: parent_scope is the previous scope on the dynamic 52 // lookup chain. This moves up the stack skipping 53 // 1.5 templates (but not 1.5 included files). 54 // 1.5+: parent_scope is the template's lexical parent. 55 // 56 // This means that a search along the parent_scope chain will follow the 57 // correct lookup chain for that version of quickboook. 58 // 59 // symbols contains the templates defined in this scope. 60 61 struct template_scope 62 { template_scopequickbook::template_scope63 template_scope() : parent_scope(), parent_1_4() {} 64 template_scope const* parent_scope; 65 template_scope const* parent_1_4; 66 template_symbols symbols; 67 }; 68 69 struct template_stack 70 { 71 typedef std::deque<template_scope> deque; 72 73 struct parser 74 { 75 typedef boost::spirit::classic::nil_t result_t; 76 parserquickbook::template_stack::parser77 parser(template_stack& ts_) : ts(ts_) {} 78 79 template <typename Scanner> operator ()quickbook::template_stack::parser80 std::ptrdiff_t operator()(Scanner const& scan, result_t) const 81 { 82 // search all scopes for the longest matching symbol. 83 typename Scanner::iterator_t f = scan.first; 84 std::ptrdiff_t len = -1; 85 for (template_scope const* i = &*ts.scopes.begin(); i; 86 i = i->parent_scope) { 87 boost::spirit::classic::match<> m = i->symbols.parse(scan); 88 if (m.length() > len) len = m.length(); 89 scan.first = f; 90 } 91 if (len >= 0) scan.first = boost::next(f, len); 92 return len; 93 } 94 95 template_stack& ts; 96 97 private: 98 parser& operator=(parser const&); 99 }; 100 101 template_stack(); 102 template_symbol* find(std::string const& symbol) const; 103 template_symbol* find_top_scope(std::string const& symbol) const; 104 template_symbols const& top() const; 105 template_scope const& top_scope() const; 106 // Add the given template symbol to the current scope. 107 // If it doesn't have a scope, sets the symbol's scope to the current 108 // scope. 109 bool add(template_symbol const&); 110 void push(); 111 void pop(); 112 113 void start_template(template_symbol const*); 114 115 boost::spirit::classic::functor_parser<parser> scope; 116 117 private: 118 friend struct parser; 119 deque scopes; 120 template_scope const* parent_1_4; 121 122 template_stack& operator=(template_stack const&); 123 }; 124 } 125 126 #endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP 127