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