• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2014 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_X3_SIMPLE_TRACE_DECEMBER_06_2008_1102AM)
9 #define BOOST_SPIRIT_X3_SIMPLE_TRACE_DECEMBER_06_2008_1102AM
10 
11 #include <boost/spirit/home/x3/support/unused.hpp>
12 #include <boost/spirit/home/x3/support/traits/print_token.hpp>
13 #include <boost/spirit/home/x3/support/traits/print_attribute.hpp>
14 #include <boost/spirit/home/x3/nonterminal/debug_handler_state.hpp>
15 #include <boost/type_traits/is_same.hpp>
16 #include <iostream>
17 
18 //  The stream to use for debug output
19 #if !defined(BOOST_SPIRIT_X3_DEBUG_OUT)
20 #define BOOST_SPIRIT_X3_DEBUG_OUT std::cerr
21 #endif
22 
23 //  number of tokens to print while debugging
24 #if !defined(BOOST_SPIRIT_X3_DEBUG_PRINT_SOME)
25 #define BOOST_SPIRIT_X3_DEBUG_PRINT_SOME 20
26 #endif
27 
28 //  number of spaces to indent
29 #if !defined(BOOST_SPIRIT_X3_DEBUG_INDENT)
30 #define BOOST_SPIRIT_X3_DEBUG_INDENT 2
31 #endif
32 
33 namespace boost { namespace spirit { namespace x3
34 {
35     namespace detail
36     {
37         template <typename Char>
token_printer(std::ostream & o,Char c)38         inline void token_printer(std::ostream& o, Char c)
39         {
40             // allow customization of the token printer routine
41             x3::traits::print_token(o, c);
42         }
43     }
44 
45     template <int IndentSpaces = 2, int CharsToPrint = 20>
46     struct simple_trace
47     {
simple_traceboost::spirit::x3::simple_trace48         simple_trace(std::ostream& out)
49           : out(out), indent(0) {}
50 
print_indentboost::spirit::x3::simple_trace51         void print_indent(int n) const
52         {
53             n *= IndentSpaces;
54             for (int i = 0; i != n; ++i)
55                 out << ' ';
56         }
57 
58         template <typename Iterator>
print_someboost::spirit::x3::simple_trace59         void print_some(
60             char const* tag
61           , Iterator first, Iterator const& last) const
62         {
63             print_indent(indent);
64             out << '<' << tag << '>';
65             int const n = CharsToPrint;
66             for (int i = 0; first != last && i != n && *first; ++i, ++first)
67                 detail::token_printer(out, *first);
68             out << "</" << tag << '>' << std::endl;
69 
70             // $$$ FIXME convert invalid xml characters (e.g. '<') to valid
71             // character entities. $$$
72         }
73 
74         template <typename Iterator, typename Attribute, typename State>
operator ()boost::spirit::x3::simple_trace75         void operator()(
76             Iterator const& first
77           , Iterator const& last
78           , Attribute const& attr
79           , State state
80           , std::string const& rule_name) const
81         {
82             switch (state)
83             {
84                 case pre_parse:
85                     print_indent(indent++);
86                     out
87                         << '<' << rule_name << '>'
88                         << std::endl;
89                     print_some("try", first, last);
90                     break;
91 
92                 case successful_parse:
93                     print_some("success", first, last);
94                     if (!is_same<Attribute, unused_type>::value)
95                     {
96                         print_indent(indent);
97                         out
98                             << "<attributes>";
99                         traits::print_attribute(out, attr);
100                         out
101                             << "</attributes>";
102                         out << std::endl;
103                     }
104                     print_indent(--indent);
105                     out
106                         << "</" << rule_name << '>'
107                         << std::endl;
108                     break;
109 
110                 case failed_parse:
111                     print_indent(indent);
112                     out << "<fail/>" << std::endl;
113                     print_indent(--indent);
114                     out
115                         << "</" << rule_name << '>'
116                         << std::endl;
117                     break;
118             }
119         }
120 
121         std::ostream& out;
122         mutable int indent;
123     };
124 
125     namespace detail
126     {
127         typedef simple_trace<
128             BOOST_SPIRIT_X3_DEBUG_INDENT, BOOST_SPIRIT_X3_DEBUG_PRINT_SOME>
129         simple_trace_type;
130 
131         inline simple_trace_type&
get_simple_trace()132         get_simple_trace()
133         {
134             static simple_trace_type tracer(BOOST_SPIRIT_X3_DEBUG_OUT);
135             return tracer;
136         }
137     }
138 }}}
139 
140 #endif
141