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