source: NonGTP/Boost/boost/spirit/debug/debug_node.hpp @ 857

Revision 857, 10.1 KB checked in by igarcia, 19 years ago (diff)
Line 
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/
6
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
13
14#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
15#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
16#endif
17
18#if defined(BOOST_SPIRIT_DEBUG)
19
20#include <string>
21
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_
26
27namespace boost { namespace spirit {
28
29///////////////////////////////////////////////////////////////////////////////
30//
31//  Debug helper classes for rules, which ensure maximum non-intrusiveness of
32//  the Spirit debug support
33//
34///////////////////////////////////////////////////////////////////////////////
35
36namespace impl {
37
38    struct token_printer_aux_for_chars
39    {
40        template<typename CharT>
41        static void print(std::ostream& o, CharT c)
42        {
43            if (c == static_cast<CharT>('\a'))
44                o << "\\a";
45
46            else if (c == static_cast<CharT>('\b'))
47                o << "\\b";
48
49            else if (c == static_cast<CharT>('\f'))
50                o << "\\f";
51
52            else if (c == static_cast<CharT>('\n'))
53                o << "\\n";
54
55            else if (c == static_cast<CharT>('\r'))
56                o << "\\r";
57
58            else if (c == static_cast<CharT>('\t'))
59                o << "\\t";
60
61            else if (c == static_cast<CharT>('\v'))
62                o << "\\v";
63
64            else if (iscntrl_(c))
65                o << "\\" << static_cast<int>(c);
66
67            else
68                o << static_cast<char>(c);
69        }
70    };
71
72    // for token types where the comparison with char constants wouldn't work
73    struct token_printer_aux_for_other_types
74    {
75        template<typename CharT>
76        static void print(std::ostream& o, CharT c)
77        {
78            o << c;
79        }
80    };
81
82    template <typename CharT>
83    struct token_printer_aux
84    :   mpl::if_<
85            mpl::and_<
86                is_convertible<CharT, char>,
87                is_convertible<char, CharT> >,
88            token_printer_aux_for_chars,
89            token_printer_aux_for_other_types
90        >::type
91    {
92    };
93
94    template<typename CharT>
95    inline void token_printer(std::ostream& o, CharT c)
96    {
97    #if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
98
99        token_printer_aux<CharT>::print(o, c);
100
101    #else
102
103        BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
104
105    #endif
106    }
107
108///////////////////////////////////////////////////////////////////////////////
109//
110//  Dump infos about the parsing state of a rule
111//
112///////////////////////////////////////////////////////////////////////////////
113
114#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
115    template <typename IteratorT>
116    inline void
117    print_node_info(bool hit, int level, bool close, std::string const& name,
118        IteratorT first, IteratorT last)
119    {
120        if (!name.empty())
121        {
122            for (int i = 0; i < level; ++i)
123                BOOST_SPIRIT_DEBUG_OUT << "  ";
124            if (close)
125            {
126                if (hit)
127                    BOOST_SPIRIT_DEBUG_OUT << "/";
128                else
129                    BOOST_SPIRIT_DEBUG_OUT << "#";
130            }
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)
135            {
136                if (iter == ilast)
137                    break;
138
139                token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
140                ++iter;
141            }
142            BOOST_SPIRIT_DEBUG_OUT << "\"\n";
143        }
144    }
145#endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
146
147#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
148    template <typename ResultT>
149    inline ResultT &
150    print_closure_info(ResultT &hit, int level, std::string const& name)
151    {
152        if (!name.empty())
153        {
154            for (int i = 0; i < level-1; ++i)
155                BOOST_SPIRIT_DEBUG_OUT << "  ";
156
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();
161            else
162                BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
163            BOOST_SPIRIT_DEBUG_OUT << "\n";
164        }
165        return hit;
166    }
167#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
168
169}
170
171///////////////////////////////////////////////////////////////////////////////
172//
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
176//
177///////////////////////////////////////////////////////////////////////////////
178#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
179#define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
180
181    ///////////////////////////////////////////////////////////////////////////
182    //
183    //  parser_context_linker is a debug wrapper for the ContextT template
184    //  parameter of the rule<>, subrule<> and the grammar<> classes
185    //
186    ///////////////////////////////////////////////////////////////////////////
187    template<typename ContextT>
188    struct parser_context_linker : public ContextT
189    {
190        typedef ContextT base_t;
191
192        template <typename ParserT>
193        parser_context_linker(ParserT const& p)
194        : ContextT(p) {}
195
196        template <typename ParserT, typename ScannerT>
197        void pre_parse(ParserT const& p, ScannerT &scan)
198        {
199            this->base_t::pre_parse(p, scan);
200
201#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
202            if (trace_parser(p.derived())) {
203                impl::print_node_info(
204                    false,
205                    scan.get_level(),
206                    false,
207                    parser_name(p.derived()),
208                    scan.first,
209                    scan.last);
210            }
211            scan.get_level()++;
212#endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
213        }
214
215        template <typename ResultT, typename ParserT, typename ScannerT>
216        ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
217        {
218#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
219            --scan.get_level();
220            if (trace_parser(p.derived())) {
221                impl::print_node_info(
222                    hit,
223                    scan.get_level(),
224                    true,
225                    parser_name(p.derived()),
226                    scan.first,
227                    scan.last);
228            }
229#endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
230
231            return this->base_t::post_parse(hit, p, scan);
232        }
233    };
234
235#endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
236
237#if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
238#define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
239
240///////////////////////////////////////////////////////////////////////////////
241//  This class is to avoid linker problems and to ensure a real singleton
242//  'level' variable
243    struct debug_support
244    {
245        int& get_level()
246        {
247            static int level = 0;
248            return level;
249        }
250    };
251
252    template<typename ScannerT>
253    struct parser_scanner_linker : public ScannerT
254    {
255        parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
256        {}
257
258        int &get_level()
259        { return debug.get_level(); }
260
261        private: debug_support debug;
262    };
263
264#endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
265
266#if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
267#define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
268
269    ///////////////////////////////////////////////////////////////////////////
270    //
271    //  closure_context_linker is a debug wrapper for the closure template
272    //  parameter of the rule<>, subrule<> and grammar classes
273    //
274    ///////////////////////////////////////////////////////////////////////////
275
276    template<typename ContextT>
277    struct closure_context_linker : public parser_context_linker<ContextT>
278    {
279        typedef parser_context_linker<ContextT> base_t;
280
281        template <typename ParserT>
282        closure_context_linker(ParserT const& p)
283        : parser_context_linker<ContextT>(p) {}
284
285        template <typename ParserT, typename ScannerT>
286        void pre_parse(ParserT const& p, ScannerT &scan)
287        { this->base_t::pre_parse(p, scan); }
288
289        template <typename ResultT, typename ParserT, typename ScannerT>
290        ResultT&
291        post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
292        {
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),
298                    scan.get_level(),
299                    parser_name(p.derived())
300                );
301            }
302#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
303
304            return this->base_t::post_parse(hit, p, scan);
305        }
306    };
307
308#endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
309
310}} // namespace boost::spirit
311
312#endif // defined(BOOST_SPIRIT_DEBUG)
313
314#endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
315
Note: See TracBrowser for help on using the repository browser.