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) | ||
|  | 
 |