Update contrib.
1 /*=============================================================================
2 Copyright (c) 2001-2003 Joel de Guzman
3 Copyright (c) 2002-2003 Hartmut Kaiser
4 Copyright (c) 2003 Gustavo Guerra
5 http://spirit.sourceforge.net/
7 Use, modification and distribution is subject to the Boost Software
8 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
11 #if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
12 #define BOOST_SPIRIT_DEBUG_NODE_HPP
14 #if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
15 #error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
18 #if defined(BOOST_SPIRIT_DEBUG)
22 #include <boost/type_traits/is_convertible.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/mpl/and.hpp>
25 #include <boost/spirit/core/primitives/primitives.hpp> // for iscntrl_
27 namespace boost { namespace spirit {
29 ///////////////////////////////////////////////////////////////////////////////
31 // Debug helper classes for rules, which ensure maximum non-intrusiveness of
32 // the Spirit debug support
34 ///////////////////////////////////////////////////////////////////////////////
38 struct token_printer_aux_for_chars
40 template<typename CharT>
41 static void print(std::ostream& o, CharT c)
43 if (c == static_cast<CharT>('\a'))
46 else if (c == static_cast<CharT>('\b'))
49 else if (c == static_cast<CharT>('\f'))
52 else if (c == static_cast<CharT>('\n'))
55 else if (c == static_cast<CharT>('\r'))
58 else if (c == static_cast<CharT>('\t'))
61 else if (c == static_cast<CharT>('\v'))
65 o << "\\" << static_cast<int>(c);
68 o << static_cast<char>(c);
72 // for token types where the comparison with char constants wouldn't work
73 struct token_printer_aux_for_other_types
75 template<typename CharT>
76 static void print(std::ostream& o, CharT c)
82 template <typename CharT>
83 struct token_printer_aux
86 is_convertible<CharT, char>,
87 is_convertible<char, CharT> >,
88 token_printer_aux_for_chars,
89 token_printer_aux_for_other_types
94 template<typename CharT>
95 inline void token_printer(std::ostream& o, CharT c)
97 #if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
99 token_printer_aux<CharT>::print(o, c);
103 BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
108 ///////////////////////////////////////////////////////////////////////////////
110 // Dump infos about the parsing state of a rule
112 ///////////////////////////////////////////////////////////////////////////////
114 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
115 template <typename IteratorT>
117 print_node_info(bool hit, int level, bool close, std::string const& name,
118 IteratorT first, IteratorT last)
122 for (int i = 0; i < level; ++i)
123 BOOST_SPIRIT_DEBUG_OUT << " ";
127 BOOST_SPIRIT_DEBUG_OUT << "/";
129 BOOST_SPIRIT_DEBUG_OUT << "#";
131 BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
132 IteratorT iter = first;
133 IteratorT ilast = last;
134 for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
139 token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
142 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
145 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
147 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
148 template <typename ResultT>
150 print_closure_info(ResultT &hit, int level, std::string const& name)
154 for (int i = 0; i < level-1; ++i)
155 BOOST_SPIRIT_DEBUG_OUT << " ";
157 // for now, print out the return value only
158 BOOST_SPIRIT_DEBUG_OUT << "^" << name << ":\t";
159 if (hit.has_valid_attribute())
160 BOOST_SPIRIT_DEBUG_OUT << hit.value();
162 BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
163 BOOST_SPIRIT_DEBUG_OUT << "\n";
167 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
171 ///////////////////////////////////////////////////////////////////////////////
173 // Implementation note: The parser_context_linker, parser_scanner_linker and
174 // closure_context_linker classes are wrapped by a PP constant to allow
175 // redefinition of this classes outside of Spirit
177 ///////////////////////////////////////////////////////////////////////////////
178 #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
179 #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
181 ///////////////////////////////////////////////////////////////////////////
183 // parser_context_linker is a debug wrapper for the ContextT template
184 // parameter of the rule<>, subrule<> and the grammar<> classes
186 ///////////////////////////////////////////////////////////////////////////
187 template<typename ContextT>
188 struct parser_context_linker : public ContextT
190 typedef ContextT base_t;
192 template <typename ParserT>
193 parser_context_linker(ParserT const& p)
196 template <typename ParserT, typename ScannerT>
197 void pre_parse(ParserT const& p, ScannerT &scan)
199 this->base_t::pre_parse(p, scan);
201 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
202 if (trace_parser(p.derived())) {
203 impl::print_node_info(
207 parser_name(p.derived()),
212 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
215 template <typename ResultT, typename ParserT, typename ScannerT>
216 ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
218 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
220 if (trace_parser(p.derived())) {
221 impl::print_node_info(
225 parser_name(p.derived()),
229 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
231 return this->base_t::post_parse(hit, p, scan);
235 #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
237 #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
238 #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
240 ///////////////////////////////////////////////////////////////////////////////
241 // This class is to avoid linker problems and to ensure a real singleton
247 static int level = 0;
252 template<typename ScannerT>
253 struct parser_scanner_linker : public ScannerT
255 parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
259 { return debug.get_level(); }
261 private: debug_support debug;
264 #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
266 #if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
267 #define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
269 ///////////////////////////////////////////////////////////////////////////
271 // closure_context_linker is a debug wrapper for the closure template
272 // parameter of the rule<>, subrule<> and grammar classes
274 ///////////////////////////////////////////////////////////////////////////
276 template<typename ContextT>
277 struct closure_context_linker : public parser_context_linker<ContextT>
279 typedef parser_context_linker<ContextT> base_t;
281 template <typename ParserT>
282 closure_context_linker(ParserT const& p)
283 : parser_context_linker<ContextT>(p) {}
285 template <typename ParserT, typename ScannerT>
286 void pre_parse(ParserT const& p, ScannerT &scan)
287 { this->base_t::pre_parse(p, scan); }
289 template <typename ResultT, typename ParserT, typename ScannerT>
291 post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
293 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
294 if (hit && trace_parser(p.derived())) {
295 // for now, print out the return value only
296 return impl::print_closure_info(
297 this->base_t::post_parse(hit, p, scan),
299 parser_name(p.derived())
302 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
304 return this->base_t::post_parse(hit, p, scan);
308 #endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
310 }} // namespace boost::spirit
312 #endif // defined(BOOST_SPIRIT_DEBUG)
314 #endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)