1
/*=============================================================================
3
Copyright (c) 2001-2003 Joel de Guzman
4
Copyright (c) 2002-2003 Hartmut Kaiser
5
Copyright (c) 2003 Gustavo Guerra
6
http://spirit.sourceforge.net/
8
Permission to copy, use, modify, sell and distribute this software is
9
granted provided this copyright notice appears in all copies. This
10
software is provided "as is" without express or implied warranty, and
11
with no claim as to its suitability for any purpose.
12
=============================================================================*/
13
#if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
14
#define BOOST_SPIRIT_DEBUG_NODE_HPP
16
#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
17
#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
20
#if defined(BOOST_SPIRIT_DEBUG)
24
#include <boost/type_traits/is_convertible.hpp>
25
#include <boost/mpl/if.hpp>
26
#include <boost/mpl/and.hpp>
27
#include <boost/spirit/core/primitives/primitives.hpp> // for iscntrl_
29
namespace boost { namespace spirit {
31
///////////////////////////////////////////////////////////////////////////////
33
// Debug helper classes for rules, which ensure maximum non-intrusiveness of
34
// the Spirit debug support
36
///////////////////////////////////////////////////////////////////////////////
40
struct token_printer_aux_for_chars
42
template<typename CharT>
43
static void print(CharT c)
45
if (c == static_cast<CharT>('\a'))
46
BOOST_SPIRIT_DEBUG_OUT << "\\a";
48
else if (c == static_cast<CharT>('\b'))
49
BOOST_SPIRIT_DEBUG_OUT << "\\b";
51
else if (c == static_cast<CharT>('\f'))
52
BOOST_SPIRIT_DEBUG_OUT << "\\f";
54
else if (c == static_cast<CharT>('\n'))
55
BOOST_SPIRIT_DEBUG_OUT << "\\n";
57
else if (c == static_cast<CharT>('\r'))
58
BOOST_SPIRIT_DEBUG_OUT << "\\r";
60
else if (c == static_cast<CharT>('\t'))
61
BOOST_SPIRIT_DEBUG_OUT << "\\t";
63
else if (c == static_cast<CharT>('\v'))
64
BOOST_SPIRIT_DEBUG_OUT << "\\v";
67
BOOST_SPIRIT_DEBUG_OUT << "\\" << static_cast<int>(c);
70
BOOST_SPIRIT_DEBUG_OUT << static_cast<char>(c);
74
// for token types where the comparison with char constants wouldn't work
75
struct token_printer_aux_for_other_types
77
template<typename CharT>
78
static void print(CharT c)
80
BOOST_SPIRIT_DEBUG_OUT << c;
84
template <typename CharT>
85
struct token_printer_aux
88
is_convertible<CharT, char>,
89
is_convertible<char, CharT> >,
90
token_printer_aux_for_chars,
91
token_printer_aux_for_other_types
96
template<typename CharT>
97
inline void token_printer(CharT c)
99
#if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
101
token_printer_aux<CharT>::print(c);
105
BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(BOOST_SPIRIT_DEBUG_OUT, c);
110
///////////////////////////////////////////////////////////////////////////////
112
// Dump infos about the parsing state of a rule
114
///////////////////////////////////////////////////////////////////////////////
116
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
117
template <typename IteratorT>
119
print_node_info(bool hit, int level, bool close, std::string const& name,
120
IteratorT first, IteratorT last)
124
for (int i = 0; i < level; ++i)
125
BOOST_SPIRIT_DEBUG_OUT << " ";
129
BOOST_SPIRIT_DEBUG_OUT << "/";
131
BOOST_SPIRIT_DEBUG_OUT << "#";
133
BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
134
IteratorT iter = first;
135
IteratorT ilast = last;
136
for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
141
token_printer(*iter);
144
BOOST_SPIRIT_DEBUG_OUT << "\"\n";
147
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
149
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
150
template <typename ResultT>
152
print_closure_info(ResultT &hit, int level, std::string const& name)
155
for (int i = 0; i < level-1; ++i)
156
BOOST_SPIRIT_DEBUG_OUT << " ";
158
// for now, print out the return value only
159
BOOST_SPIRIT_DEBUG_OUT
160
<< "^" << name << ":\t" << hit.value() << "\n";
164
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
168
///////////////////////////////////////////////////////////////////////////////
170
// Implementation note: The parser_context_linker, parser_scanner_linker and
171
// closure_context_linker classes are wrapped by a PP constant to allow
172
// redefinition of this classes outside of Spirit
174
///////////////////////////////////////////////////////////////////////////////
175
#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
176
#define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
178
///////////////////////////////////////////////////////////////////////////
180
// parser_context_linker is a debug wrapper for the ContextT template
181
// parameter of the rule<>, subrule<> and the grammar<> classes
183
///////////////////////////////////////////////////////////////////////////
184
template<typename ContextT>
185
struct parser_context_linker : public ContextT
187
typedef ContextT base_t;
189
template <typename ParserT>
190
parser_context_linker(ParserT const& p)
193
template <typename ParserT, typename ScannerT>
194
void pre_parse(ParserT const& p, ScannerT &scan)
196
this->base_t::pre_parse(p, scan);
198
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
199
if (trace_parser(p)) {
200
impl::print_node_info(
209
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
212
template <typename ResultT, typename ParserT, typename ScannerT>
213
ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
215
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
217
if (trace_parser(p)) {
218
impl::print_node_info(
226
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
228
return this->base_t::post_parse(hit, p, scan);
232
#endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
234
#if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
235
#define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
237
///////////////////////////////////////////////////////////////////////////////
238
// This class is to avoid linker problems and to ensure a real singleton
244
static int level = 0;
249
template<typename ScannerT>
250
struct parser_scanner_linker : public ScannerT
252
parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
256
{ return debug.get_level(); }
258
private: debug_support debug;
261
#endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
263
#if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
264
#define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
266
///////////////////////////////////////////////////////////////////////////
268
// closure_context_linker is a debug wrapper for the closure template
269
// parameter of the rule<>, subrule<> and grammar classes
271
///////////////////////////////////////////////////////////////////////////
273
template<typename ContextT>
274
struct closure_context_linker : public parser_context_linker<ContextT>
276
typedef parser_context_linker<ContextT> base_t;
278
template <typename ParserT>
279
closure_context_linker(ParserT const& p)
280
: parser_context_linker<ContextT>(p) {}
282
template <typename ParserT, typename ScannerT>
283
void pre_parse(ParserT const& p, ScannerT &scan)
284
{ this->base_t::pre_parse(p, scan); }
286
template <typename ResultT, typename ParserT, typename ScannerT>
288
post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
290
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
291
if (hit && trace_parser(p)) {
292
// for now, print out the return value only
293
return impl::print_closure_info(
294
this->base_t::post_parse(hit, p, scan),
299
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
301
return this->base_t::post_parse(hit, p, scan);
305
#endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
307
}} // namespace boost::spirit
309
#endif // defined(BOOST_SPIRIT_DEBUG)
311
#endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)