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 <string> 13 #include <deque> 14 #include <vector> 15 #include <cassert> 16 #include <boost/tuple/tuple.hpp> 17 #include <boost/assert.hpp> 18 #include <boost/spirit/include/classic_functor_parser.hpp> 19 #include <boost/spirit/include/classic_symbols.hpp> 20 #include <boost/next_prior.hpp> 21 #include <boost/filesystem/path.hpp> 22 #include "fwd.hpp" 23 #include "values.hpp" 24 #include "template_tags.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) 78 : ts(ts) {} 79 80 template <typename Scanner> 81 std::ptrdiff_t operator ()quickbook::template_stack::parser82 operator()(Scanner const& scan, result_t) const 83 { 84 // search all scopes for the longest matching symbol. 85 typename Scanner::iterator_t f = scan.first; 86 std::ptrdiff_t len = -1; 87 for (template_scope const* i = &*ts.scopes.begin(); i; i = i->parent_scope) 88 { 89 boost::spirit::classic::match<> m = i->symbols.parse(scan); 90 if (m.length() > len) 91 len = m.length(); 92 scan.first = f; 93 } 94 if (len >= 0) 95 scan.first = boost::next(f, len); 96 return len; 97 } 98 99 template_stack& ts; 100 }; 101 102 template_stack(); 103 template_symbol* find(std::string const& symbol) const; 104 template_symbol* find_top_scope(std::string const& symbol) const; 105 template_symbols const& top() const; 106 template_scope const& top_scope() const; 107 // Add the given template symbol to the current scope. 108 // If it doesn't have a scope, sets the symbol's scope to the current 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 119 friend struct parser; 120 deque scopes; 121 template_scope const* parent_1_4; 122 }; 123 } 124 125 #endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP 126 127