Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:08:59

0001 /*=============================================================================
0002     Copyright (c) 2001-2003 Joel de Guzman
0003     Copyright (c) 2002-2003 Hartmut Kaiser
0004     Copyright (c) 2003 Gustavo Guerra
0005     http://spirit.sourceforge.net/
0006 
0007   Distributed under the Boost Software License, Version 1.0. (See accompanying
0008   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 =============================================================================*/
0010 #if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
0011 #define BOOST_SPIRIT_DEBUG_NODE_HPP
0012 
0013 #if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
0014 #error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
0015 #endif
0016 
0017 #if defined(BOOST_SPIRIT_DEBUG)
0018 
0019 #include <string>
0020 
0021 #include <boost/type_traits/is_convertible.hpp>
0022 #include <boost/mpl/if.hpp>
0023 #include <boost/mpl/and.hpp>
0024 #include <boost/spirit/home/classic/namespace.hpp>
0025 #include <boost/spirit/home/classic/core/primitives/primitives.hpp> // for iscntrl_
0026 
0027 namespace boost { namespace spirit {
0028 
0029 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0030 
0031 ///////////////////////////////////////////////////////////////////////////////
0032 //
0033 //  Debug helper classes for rules, which ensure maximum non-intrusiveness of
0034 //  the Spirit debug support
0035 //
0036 ///////////////////////////////////////////////////////////////////////////////
0037 
0038 namespace impl {
0039 
0040     struct token_printer_aux_for_chars
0041     {
0042         template<typename CharT>
0043         static void print(std::ostream& o, CharT c)
0044         {
0045             if (c == static_cast<CharT>('\a'))
0046                 o << "\\a";
0047 
0048             else if (c == static_cast<CharT>('\b'))
0049                 o << "\\b";
0050 
0051             else if (c == static_cast<CharT>('\f'))
0052                 o << "\\f";
0053 
0054             else if (c == static_cast<CharT>('\n'))
0055                 o << "\\n";
0056 
0057             else if (c == static_cast<CharT>('\r'))
0058                 o << "\\r";
0059 
0060             else if (c == static_cast<CharT>('\t'))
0061                 o << "\\t";
0062 
0063             else if (c == static_cast<CharT>('\v'))
0064                 o << "\\v";
0065 
0066             else if (iscntrl_(c))
0067                 o << "\\" << static_cast<int>(c);
0068 
0069             else
0070                 o << static_cast<char>(c);
0071         }
0072     };
0073 
0074     // for token types where the comparison with char constants wouldn't work
0075     struct token_printer_aux_for_other_types
0076     {
0077         template<typename CharT>
0078         static void print(std::ostream& o, CharT c)
0079         {
0080             o << c;
0081         }
0082     };
0083 
0084     template <typename CharT>
0085     struct token_printer_aux
0086     :   mpl::if_<
0087             mpl::and_<
0088                 is_convertible<CharT, char>,
0089                 is_convertible<char, CharT> >,
0090             token_printer_aux_for_chars,
0091             token_printer_aux_for_other_types
0092         >::type
0093     {
0094     };
0095 
0096     template<typename CharT>
0097     inline void token_printer(std::ostream& o, CharT c)
0098     {
0099     #if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
0100 
0101         token_printer_aux<CharT>::print(o, c);
0102 
0103     #else
0104 
0105         BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
0106 
0107     #endif
0108     }
0109 
0110 ///////////////////////////////////////////////////////////////////////////////
0111 //
0112 //  Dump infos about the parsing state of a rule
0113 //
0114 ///////////////////////////////////////////////////////////////////////////////
0115 
0116 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0117     template <typename IteratorT>
0118     inline void
0119     print_node_info(bool hit, int level, bool close, std::string const& name,
0120         IteratorT first, IteratorT last)
0121     {
0122         if (!name.empty())
0123         {
0124             for (int i = 0; i < level; ++i)
0125                 BOOST_SPIRIT_DEBUG_OUT << "  ";
0126             if (close)
0127             {
0128                 if (hit)
0129                     BOOST_SPIRIT_DEBUG_OUT << "/";
0130                 else
0131                     BOOST_SPIRIT_DEBUG_OUT << "#";
0132             }
0133             BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
0134             IteratorT iter = first;
0135             IteratorT ilast = last;
0136             for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
0137             {
0138                 if (iter == ilast)
0139                     break;
0140 
0141                 token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
0142                 ++iter;
0143             }
0144             BOOST_SPIRIT_DEBUG_OUT << "\"\n";
0145         }
0146     }
0147 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0148 
0149 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
0150     template <typename ResultT>
0151     inline ResultT &
0152     print_closure_info(ResultT &hit, int level, std::string const& name)
0153     {
0154         if (!name.empty())
0155         {
0156             for (int i = 0; i < level-1; ++i)
0157                 BOOST_SPIRIT_DEBUG_OUT << "  ";
0158 
0159         // for now, print out the return value only
0160             BOOST_SPIRIT_DEBUG_OUT << "^" << name << ":\t";
0161             if (hit.has_valid_attribute())
0162                 BOOST_SPIRIT_DEBUG_OUT << hit.value();
0163             else
0164                 BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
0165             BOOST_SPIRIT_DEBUG_OUT << "\n";
0166         }
0167         return hit;
0168     }
0169 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
0170 
0171 }
0172 
0173 ///////////////////////////////////////////////////////////////////////////////
0174 //
0175 //  Implementation note: The parser_context_linker, parser_scanner_linker and
0176 //  closure_context_linker classes are wrapped by a PP constant to allow
0177 //  redefinition of this classes outside of Spirit
0178 //
0179 ///////////////////////////////////////////////////////////////////////////////
0180 #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
0181 #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
0182 
0183     ///////////////////////////////////////////////////////////////////////////
0184     //
0185     //  parser_context_linker is a debug wrapper for the ContextT template
0186     //  parameter of the rule<>, subrule<> and the grammar<> classes
0187     //
0188     ///////////////////////////////////////////////////////////////////////////
0189     template<typename ContextT>
0190     struct parser_context_linker : public ContextT
0191     {
0192         typedef ContextT base_t;
0193 
0194         template <typename ParserT>
0195         parser_context_linker(ParserT const& p)
0196         : ContextT(p) {}
0197 
0198         template <typename ParserT, typename ScannerT>
0199         void pre_parse(ParserT const& p, ScannerT &scan)
0200         {
0201             this->base_t::pre_parse(p, scan);
0202 
0203 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0204             if (trace_parser(p.derived())) {
0205                 impl::print_node_info(
0206                     false,
0207                     scan.get_level(),
0208                     false,
0209                     parser_name(p.derived()),
0210                     scan.first,
0211                     scan.last);
0212             }
0213             scan.get_level()++;
0214 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0215         }
0216 
0217         template <typename ResultT, typename ParserT, typename ScannerT>
0218         ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
0219         {
0220 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0221             --scan.get_level();
0222             if (trace_parser(p.derived())) {
0223                 impl::print_node_info(
0224                     hit,
0225                     scan.get_level(),
0226                     true,
0227                     parser_name(p.derived()),
0228                     scan.first,
0229                     scan.last);
0230             }
0231 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
0232 
0233             return this->base_t::post_parse(hit, p, scan);
0234         }
0235     };
0236 
0237 #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
0238 
0239 #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
0240 #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
0241 
0242 ///////////////////////////////////////////////////////////////////////////////
0243 //  This class is to avoid linker problems and to ensure a real singleton
0244 //  'level' variable
0245     struct debug_support
0246     {
0247         int& get_level()
0248         {
0249             static int level = 0;
0250             return level;
0251         }
0252     };
0253 
0254     template<typename ScannerT>
0255     struct parser_scanner_linker : public ScannerT
0256     {
0257         parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
0258         {}
0259 
0260         int &get_level()
0261         { return debug.get_level(); }
0262 
0263         private: debug_support debug;
0264     };
0265 
0266 #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
0267 
0268 #if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
0269 #define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
0270 
0271     ///////////////////////////////////////////////////////////////////////////
0272     //
0273     //  closure_context_linker is a debug wrapper for the closure template
0274     //  parameter of the rule<>, subrule<> and grammar classes
0275     //
0276     ///////////////////////////////////////////////////////////////////////////
0277 
0278     template<typename ContextT>
0279     struct closure_context_linker : public parser_context_linker<ContextT>
0280     {
0281         typedef parser_context_linker<ContextT> base_t;
0282 
0283         template <typename ParserT>
0284         closure_context_linker(ParserT const& p)
0285         : parser_context_linker<ContextT>(p) {}
0286 
0287         template <typename ParserT, typename ScannerT>
0288         void pre_parse(ParserT const& p, ScannerT &scan)
0289         { this->base_t::pre_parse(p, scan); }
0290 
0291         template <typename ResultT, typename ParserT, typename ScannerT>
0292         ResultT&
0293         post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
0294         {
0295 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
0296             if (hit && trace_parser(p.derived())) {
0297             // for now, print out the return value only
0298                 return impl::print_closure_info(
0299                     this->base_t::post_parse(hit, p, scan),
0300                     scan.get_level(),
0301                     parser_name(p.derived())
0302                 );
0303             }
0304 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
0305 
0306             return this->base_t::post_parse(hit, p, scan);
0307         }
0308     };
0309 
0310 #endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
0311 
0312 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0313 
0314 }} // namespace BOOST_SPIRIT_CLASSIC_NS
0315 
0316 #endif // defined(BOOST_SPIRIT_DEBUG)
0317 
0318 #endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
0319