320 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			320 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /*=============================================================================
 | |
|     Copyright (c) 2001-2003 Joel de Guzman
 | |
|     Copyright (c) 2002-2003 Hartmut Kaiser
 | |
|     Copyright (c) 2003 Gustavo Guerra
 | |
|     http://spirit.sourceforge.net/
 | |
| 
 | |
|   Distributed under the Boost Software License, Version 1.0. (See accompanying
 | |
|   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
| =============================================================================*/
 | |
| #if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
 | |
| #define BOOST_SPIRIT_DEBUG_NODE_HPP
 | |
| 
 | |
| #if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
 | |
| #error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
 | |
| #endif
 | |
| 
 | |
| #if defined(BOOST_SPIRIT_DEBUG)
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #include <boost/type_traits/is_convertible.hpp>
 | |
| #include <boost/mpl/if.hpp>
 | |
| #include <boost/mpl/and.hpp>
 | |
| #include <boost/spirit/home/classic/namespace.hpp>
 | |
| #include <boost/spirit/home/classic/core/primitives/primitives.hpp> // for iscntrl_
 | |
| 
 | |
| namespace boost { namespace spirit {
 | |
| 
 | |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| //  Debug helper classes for rules, which ensure maximum non-intrusiveness of
 | |
| //  the Spirit debug support
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| namespace impl {
 | |
| 
 | |
|     struct token_printer_aux_for_chars
 | |
|     {
 | |
|         template<typename CharT>
 | |
|         static void print(std::ostream& o, CharT c)
 | |
|         {
 | |
|             if (c == static_cast<CharT>('\a'))
 | |
|                 o << "\\a";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\b'))
 | |
|                 o << "\\b";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\f'))
 | |
|                 o << "\\f";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\n'))
 | |
|                 o << "\\n";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\r'))
 | |
|                 o << "\\r";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\t'))
 | |
|                 o << "\\t";
 | |
| 
 | |
|             else if (c == static_cast<CharT>('\v'))
 | |
|                 o << "\\v";
 | |
| 
 | |
|             else if (iscntrl_(c))
 | |
|                 o << "\\" << static_cast<int>(c);
 | |
| 
 | |
|             else
 | |
|                 o << static_cast<char>(c);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     // for token types where the comparison with char constants wouldn't work
 | |
|     struct token_printer_aux_for_other_types
 | |
|     {
 | |
|         template<typename CharT>
 | |
|         static void print(std::ostream& o, CharT c)
 | |
|         {
 | |
|             o << c;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     template <typename CharT>
 | |
|     struct token_printer_aux
 | |
|     :   mpl::if_<
 | |
|             mpl::and_<
 | |
|                 is_convertible<CharT, char>,
 | |
|                 is_convertible<char, CharT> >,
 | |
|             token_printer_aux_for_chars,
 | |
|             token_printer_aux_for_other_types
 | |
|         >::type
 | |
|     {
 | |
|     };
 | |
| 
 | |
|     template<typename CharT>
 | |
|     inline void token_printer(std::ostream& o, CharT c)
 | |
|     {
 | |
|     #if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
 | |
| 
 | |
|         token_printer_aux<CharT>::print(o, c);
 | |
| 
 | |
|     #else
 | |
| 
 | |
|         BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
 | |
| 
 | |
|     #endif
 | |
|     }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| //  Dump infos about the parsing state of a rule
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
|     template <typename IteratorT>
 | |
|     inline void
 | |
|     print_node_info(bool hit, int level, bool close, std::string const& name,
 | |
|         IteratorT first, IteratorT last)
 | |
|     {
 | |
|         if (!name.empty())
 | |
|         {
 | |
|             for (int i = 0; i < level; ++i)
 | |
|                 BOOST_SPIRIT_DEBUG_OUT << "  ";
 | |
|             if (close)
 | |
|             {
 | |
|                 if (hit)
 | |
|                     BOOST_SPIRIT_DEBUG_OUT << "/";
 | |
|                 else
 | |
|                     BOOST_SPIRIT_DEBUG_OUT << "#";
 | |
|             }
 | |
|             BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
 | |
|             IteratorT iter = first;
 | |
|             IteratorT ilast = last;
 | |
|             for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
 | |
|             {
 | |
|                 if (iter == ilast)
 | |
|                     break;
 | |
| 
 | |
|                 token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
 | |
|                 ++iter;
 | |
|             }
 | |
|             BOOST_SPIRIT_DEBUG_OUT << "\"\n";
 | |
|         }
 | |
|     }
 | |
| #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
| 
 | |
| #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
 | |
|     template <typename ResultT>
 | |
|     inline ResultT &
 | |
|     print_closure_info(ResultT &hit, int level, std::string const& name)
 | |
|     {
 | |
|         if (!name.empty())
 | |
|         {
 | |
|             for (int i = 0; i < level-1; ++i)
 | |
|                 BOOST_SPIRIT_DEBUG_OUT << "  ";
 | |
| 
 | |
|         // for now, print out the return value only
 | |
|             BOOST_SPIRIT_DEBUG_OUT << "^" << name << ":\t";
 | |
|             if (hit.has_valid_attribute())
 | |
|                 BOOST_SPIRIT_DEBUG_OUT << hit.value();
 | |
|             else
 | |
|                 BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
 | |
|             BOOST_SPIRIT_DEBUG_OUT << "\n";
 | |
|         }
 | |
|         return hit;
 | |
|     }
 | |
| #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
 | |
| 
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| //  Implementation note: The parser_context_linker, parser_scanner_linker and
 | |
| //  closure_context_linker classes are wrapped by a PP constant to allow
 | |
| //  redefinition of this classes outside of Spirit
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
 | |
| #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
 | |
| 
 | |
|     ///////////////////////////////////////////////////////////////////////////
 | |
|     //
 | |
|     //  parser_context_linker is a debug wrapper for the ContextT template
 | |
|     //  parameter of the rule<>, subrule<> and the grammar<> classes
 | |
|     //
 | |
|     ///////////////////////////////////////////////////////////////////////////
 | |
|     template<typename ContextT>
 | |
|     struct parser_context_linker : public ContextT
 | |
|     {
 | |
|         typedef ContextT base_t;
 | |
| 
 | |
|         template <typename ParserT>
 | |
|         parser_context_linker(ParserT const& p)
 | |
|         : ContextT(p) {}
 | |
| 
 | |
|         template <typename ParserT, typename ScannerT>
 | |
|         void pre_parse(ParserT const& p, ScannerT &scan)
 | |
|         {
 | |
|             this->base_t::pre_parse(p, scan);
 | |
| 
 | |
| #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
|             if (trace_parser(p.derived())) {
 | |
|                 impl::print_node_info(
 | |
|                     false,
 | |
|                     scan.get_level(),
 | |
|                     false,
 | |
|                     parser_name(p.derived()),
 | |
|                     scan.first,
 | |
|                     scan.last);
 | |
|             }
 | |
|             scan.get_level()++;
 | |
| #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
|         }
 | |
| 
 | |
|         template <typename ResultT, typename ParserT, typename ScannerT>
 | |
|         ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
 | |
|         {
 | |
| #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
|             --scan.get_level();
 | |
|             if (trace_parser(p.derived())) {
 | |
|                 impl::print_node_info(
 | |
|                     hit,
 | |
|                     scan.get_level(),
 | |
|                     true,
 | |
|                     parser_name(p.derived()),
 | |
|                     scan.first,
 | |
|                     scan.last);
 | |
|             }
 | |
| #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
 | |
| 
 | |
|             return this->base_t::post_parse(hit, p, scan);
 | |
|         }
 | |
|     };
 | |
| 
 | |
| #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
 | |
| 
 | |
| #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
 | |
| #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //  This class is to avoid linker problems and to ensure a real singleton
 | |
| //  'level' variable
 | |
|     struct debug_support
 | |
|     {
 | |
|         int& get_level()
 | |
|         {
 | |
|             static int level = 0;
 | |
|             return level;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     template<typename ScannerT>
 | |
|     struct parser_scanner_linker : public ScannerT
 | |
|     {
 | |
|         parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
 | |
|         {}
 | |
| 
 | |
|         int &get_level()
 | |
|         { return debug.get_level(); }
 | |
| 
 | |
|         private: debug_support debug;
 | |
|     };
 | |
| 
 | |
| #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
 | |
| 
 | |
| #if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
 | |
| #define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
 | |
| 
 | |
|     ///////////////////////////////////////////////////////////////////////////
 | |
|     //
 | |
|     //  closure_context_linker is a debug wrapper for the closure template
 | |
|     //  parameter of the rule<>, subrule<> and grammar classes
 | |
|     //
 | |
|     ///////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|     template<typename ContextT>
 | |
|     struct closure_context_linker : public parser_context_linker<ContextT>
 | |
|     {
 | |
|         typedef parser_context_linker<ContextT> base_t;
 | |
| 
 | |
|         template <typename ParserT>
 | |
|         closure_context_linker(ParserT const& p)
 | |
|         : parser_context_linker<ContextT>(p) {}
 | |
| 
 | |
|         template <typename ParserT, typename ScannerT>
 | |
|         void pre_parse(ParserT const& p, ScannerT &scan)
 | |
|         { this->base_t::pre_parse(p, scan); }
 | |
| 
 | |
|         template <typename ResultT, typename ParserT, typename ScannerT>
 | |
|         ResultT&
 | |
|         post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
 | |
|         {
 | |
| #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
 | |
|             if (hit && trace_parser(p.derived())) {
 | |
|             // for now, print out the return value only
 | |
|                 return impl::print_closure_info(
 | |
|                     this->base_t::post_parse(hit, p, scan),
 | |
|                     scan.get_level(),
 | |
|                     parser_name(p.derived())
 | |
|                 );
 | |
|             }
 | |
| #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
 | |
| 
 | |
|             return this->base_t::post_parse(hit, p, scan);
 | |
|         }
 | |
|     };
 | |
| 
 | |
| #endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
 | |
| 
 | |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END
 | |
| 
 | |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS
 | |
| 
 | |
| #endif // defined(BOOST_SPIRIT_DEBUG)
 | |
| 
 | |
| #endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
 | |
| 
 | 
