• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_SIMPLE_TRACE_DECEMBER_06_2008_1102AM)
9 #define BOOST_SPIRIT_SIMPLE_TRACE_DECEMBER_06_2008_1102AM
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
15 #include <boost/spirit/home/support/unused.hpp>
16 #include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
17 #include <boost/fusion/include/out.hpp>
18 #include <iostream>
19 #include <boost/mpl/if.hpp>
20 #include <boost/mpl/and.hpp>
21 #include <boost/type_traits/is_convertible.hpp>
22 #include <boost/spirit/home/support/attributes.hpp>
23 
24 //  The stream to use for debug output
25 #if !defined(BOOST_SPIRIT_DEBUG_OUT)
26 #define BOOST_SPIRIT_DEBUG_OUT std::cerr
27 #endif
28 
29 //  number of tokens to print while debugging
30 #if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
31 #define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
32 #endif
33 
34 //  number of spaces to indent
35 #if !defined(BOOST_SPIRIT_DEBUG_INDENT)
36 #define BOOST_SPIRIT_DEBUG_INDENT 2
37 #endif
38 
39 namespace boost { namespace spirit { namespace qi
40 {
41     namespace detail
42     {
43         template<typename Char>
token_printer(std::ostream & o,Char c)44         inline void token_printer(std::ostream& o, Char c)
45         {
46             // allow to customize the token printer routine
47             spirit::traits::print_token(o, c);
48         }
49     }
50 
51     struct simple_trace
52     {
get_indentboost::spirit::qi::simple_trace53         int& get_indent() const
54         {
55             static int indent = 0;
56             return indent;
57         }
58 
print_indentboost::spirit::qi::simple_trace59         void print_indent(int n) const
60         {
61             n *= BOOST_SPIRIT_DEBUG_INDENT;
62             for (int i = 0; i != n; ++i)
63                 BOOST_SPIRIT_DEBUG_OUT << ' ';
64         }
65 
66         template <typename Iterator>
print_someboost::spirit::qi::simple_trace67         void print_some(
68             char const* tag
69           , int /*indent*/
70           , Iterator first, Iterator const& last) const
71         {
72             print_indent(get_indent());
73             BOOST_SPIRIT_DEBUG_OUT << '<' << tag << '>';
74             int const n = BOOST_SPIRIT_DEBUG_PRINT_SOME;
75             for (int i = 0; first != last && i != n && *first; ++i, ++first)
76                 detail::token_printer(BOOST_SPIRIT_DEBUG_OUT, *first);
77             BOOST_SPIRIT_DEBUG_OUT << "</" << tag << '>' << std::endl;
78 
79             // $$$ FIXME convert invalid xml characters (e.g. '<') to valid
80             // character entities. $$$
81         }
82 
83         template <typename Iterator, typename Context, typename State>
operator ()boost::spirit::qi::simple_trace84         void operator()(
85             Iterator const& first
86           , Iterator const& last
87           , Context const& context
88           , State state
89           , std::string const& rule_name) const
90         {
91             switch (state)
92             {
93                 case pre_parse:
94                     print_indent(get_indent()++);
95                     BOOST_SPIRIT_DEBUG_OUT
96                         << '<' << rule_name << '>'
97                         << std::endl;
98                     print_some("try", get_indent(), first, last);
99                     break;
100                 case successful_parse:
101                     print_some("success", get_indent(), first, last);
102                     print_indent(get_indent());
103                     BOOST_SPIRIT_DEBUG_OUT
104                         << "<attributes>";
105                     traits::print_attribute(
106                         BOOST_SPIRIT_DEBUG_OUT,
107                         context.attributes
108                     );
109                     BOOST_SPIRIT_DEBUG_OUT
110                         << "</attributes>";
111                     if (!fusion::empty(context.locals))
112                         BOOST_SPIRIT_DEBUG_OUT
113                             << "<locals>"
114                             << context.locals
115                             << "</locals>";
116                     BOOST_SPIRIT_DEBUG_OUT << std::endl;
117                     print_indent(--get_indent());
118                     BOOST_SPIRIT_DEBUG_OUT
119                         << "</" << rule_name << '>'
120                         << std::endl;
121                     break;
122                 case failed_parse:
123                     print_indent(get_indent());
124                     BOOST_SPIRIT_DEBUG_OUT << "<fail/>" << std::endl;
125                     print_indent(--get_indent());
126                     BOOST_SPIRIT_DEBUG_OUT
127                         << "</" << rule_name << '>'
128                         << std::endl;
129                     break;
130             }
131         }
132     };
133 }}}
134 
135 #endif
136