os/ossrv/ossrv_pub/boost_apis/boost/spirit/debug/debug_node.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*=============================================================================
     2     Copyright (c) 2001-2003 Joel de Guzman
     3     Copyright (c) 2002-2003 Hartmut Kaiser
     4     Copyright (c) 2003 Gustavo Guerra
     5     http://spirit.sourceforge.net/
     6 
     7     Use, modification and distribution is subject to the Boost Software
     8     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
     9     http://www.boost.org/LICENSE_1_0.txt)
    10 =============================================================================*/
    11 #if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
    12 #define BOOST_SPIRIT_DEBUG_NODE_HPP
    13 
    14 #if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
    15 #error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
    16 #endif
    17 
    18 #if defined(BOOST_SPIRIT_DEBUG)
    19 
    20 #include <string>
    21 
    22 #include <boost/type_traits/is_convertible.hpp>
    23 #include <boost/mpl/if.hpp>
    24 #include <boost/mpl/and.hpp>
    25 #include <boost/spirit/core/primitives/primitives.hpp> // for iscntrl_
    26 
    27 namespace boost { namespace spirit {
    28 
    29 ///////////////////////////////////////////////////////////////////////////////
    30 //
    31 //  Debug helper classes for rules, which ensure maximum non-intrusiveness of
    32 //  the Spirit debug support
    33 //
    34 ///////////////////////////////////////////////////////////////////////////////
    35 
    36 namespace impl {
    37 
    38     struct token_printer_aux_for_chars
    39     {
    40         template<typename CharT>
    41         static void print(std::ostream& o, CharT c)
    42         {
    43             if (c == static_cast<CharT>('\a'))
    44                 o << "\\a";
    45 
    46             else if (c == static_cast<CharT>('\b'))
    47                 o << "\\b";
    48 
    49             else if (c == static_cast<CharT>('\f'))
    50                 o << "\\f";
    51 
    52             else if (c == static_cast<CharT>('\n'))
    53                 o << "\\n";
    54 
    55             else if (c == static_cast<CharT>('\r'))
    56                 o << "\\r";
    57 
    58             else if (c == static_cast<CharT>('\t'))
    59                 o << "\\t";
    60 
    61             else if (c == static_cast<CharT>('\v'))
    62                 o << "\\v";
    63 
    64             else if (iscntrl_(c))
    65                 o << "\\" << static_cast<int>(c);
    66 
    67             else
    68                 o << static_cast<char>(c);
    69         }
    70     };
    71 
    72     // for token types where the comparison with char constants wouldn't work
    73     struct token_printer_aux_for_other_types
    74     {
    75         template<typename CharT>
    76         static void print(std::ostream& o, CharT c)
    77         {
    78             o << c;
    79         }
    80     };
    81 
    82     template <typename CharT>
    83     struct token_printer_aux
    84     :   mpl::if_<
    85             mpl::and_<
    86                 is_convertible<CharT, char>,
    87                 is_convertible<char, CharT> >,
    88             token_printer_aux_for_chars,
    89             token_printer_aux_for_other_types
    90         >::type
    91     {
    92     };
    93 
    94     template<typename CharT>
    95     inline void token_printer(std::ostream& o, CharT c)
    96     {
    97     #if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
    98 
    99         token_printer_aux<CharT>::print(o, c);
   100 
   101     #else
   102 
   103         BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
   104 
   105     #endif
   106     }
   107 
   108 ///////////////////////////////////////////////////////////////////////////////
   109 //
   110 //  Dump infos about the parsing state of a rule
   111 //
   112 ///////////////////////////////////////////////////////////////////////////////
   113 
   114 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   115     template <typename IteratorT>
   116     inline void
   117     print_node_info(bool hit, int level, bool close, std::string const& name,
   118         IteratorT first, IteratorT last)
   119     {
   120         if (!name.empty())
   121         {
   122             for (int i = 0; i < level; ++i)
   123                 BOOST_SPIRIT_DEBUG_OUT << "  ";
   124             if (close)
   125             {
   126                 if (hit)
   127                     BOOST_SPIRIT_DEBUG_OUT << "/";
   128                 else
   129                     BOOST_SPIRIT_DEBUG_OUT << "#";
   130             }
   131             BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
   132             IteratorT iter = first;
   133             IteratorT ilast = last;
   134             for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
   135             {
   136                 if (iter == ilast)
   137                     break;
   138 
   139                 token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
   140                 ++iter;
   141             }
   142             BOOST_SPIRIT_DEBUG_OUT << "\"\n";
   143         }
   144     }
   145 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   146 
   147 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
   148     template <typename ResultT>
   149     inline ResultT &
   150     print_closure_info(ResultT &hit, int level, std::string const& name)
   151     {
   152         if (!name.empty())
   153         {
   154             for (int i = 0; i < level-1; ++i)
   155                 BOOST_SPIRIT_DEBUG_OUT << "  ";
   156 
   157         // for now, print out the return value only
   158             BOOST_SPIRIT_DEBUG_OUT << "^" << name << ":\t";
   159             if (hit.has_valid_attribute())
   160                 BOOST_SPIRIT_DEBUG_OUT << hit.value();
   161             else
   162                 BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
   163             BOOST_SPIRIT_DEBUG_OUT << "\n";
   164         }
   165         return hit;
   166     }
   167 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
   168 
   169 }
   170 
   171 ///////////////////////////////////////////////////////////////////////////////
   172 //
   173 //  Implementation note: The parser_context_linker, parser_scanner_linker and
   174 //  closure_context_linker classes are wrapped by a PP constant to allow
   175 //  redefinition of this classes outside of Spirit
   176 //
   177 ///////////////////////////////////////////////////////////////////////////////
   178 #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
   179 #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
   180 
   181     ///////////////////////////////////////////////////////////////////////////
   182     //
   183     //  parser_context_linker is a debug wrapper for the ContextT template
   184     //  parameter of the rule<>, subrule<> and the grammar<> classes
   185     //
   186     ///////////////////////////////////////////////////////////////////////////
   187     template<typename ContextT>
   188     struct parser_context_linker : public ContextT
   189     {
   190         typedef ContextT base_t;
   191 
   192         template <typename ParserT>
   193         parser_context_linker(ParserT const& p)
   194         : ContextT(p) {}
   195 
   196         template <typename ParserT, typename ScannerT>
   197         void pre_parse(ParserT const& p, ScannerT &scan)
   198         {
   199             this->base_t::pre_parse(p, scan);
   200 
   201 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   202             if (trace_parser(p.derived())) {
   203                 impl::print_node_info(
   204                     false,
   205                     scan.get_level(),
   206                     false,
   207                     parser_name(p.derived()),
   208                     scan.first,
   209                     scan.last);
   210             }
   211             scan.get_level()++;
   212 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   213         }
   214 
   215         template <typename ResultT, typename ParserT, typename ScannerT>
   216         ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
   217         {
   218 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   219             --scan.get_level();
   220             if (trace_parser(p.derived())) {
   221                 impl::print_node_info(
   222                     hit,
   223                     scan.get_level(),
   224                     true,
   225                     parser_name(p.derived()),
   226                     scan.first,
   227                     scan.last);
   228             }
   229 #endif  // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
   230 
   231             return this->base_t::post_parse(hit, p, scan);
   232         }
   233     };
   234 
   235 #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
   236 
   237 #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
   238 #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
   239 
   240 ///////////////////////////////////////////////////////////////////////////////
   241 //  This class is to avoid linker problems and to ensure a real singleton
   242 //  'level' variable
   243     struct debug_support
   244     {
   245         int& get_level()
   246         {
   247             static int level = 0;
   248             return level;
   249         }
   250     };
   251 
   252     template<typename ScannerT>
   253     struct parser_scanner_linker : public ScannerT
   254     {
   255         parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
   256         {}
   257 
   258         int &get_level()
   259         { return debug.get_level(); }
   260 
   261         private: debug_support debug;
   262     };
   263 
   264 #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
   265 
   266 #if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
   267 #define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
   268 
   269     ///////////////////////////////////////////////////////////////////////////
   270     //
   271     //  closure_context_linker is a debug wrapper for the closure template
   272     //  parameter of the rule<>, subrule<> and grammar classes
   273     //
   274     ///////////////////////////////////////////////////////////////////////////
   275 
   276     template<typename ContextT>
   277     struct closure_context_linker : public parser_context_linker<ContextT>
   278     {
   279         typedef parser_context_linker<ContextT> base_t;
   280 
   281         template <typename ParserT>
   282         closure_context_linker(ParserT const& p)
   283         : parser_context_linker<ContextT>(p) {}
   284 
   285         template <typename ParserT, typename ScannerT>
   286         void pre_parse(ParserT const& p, ScannerT &scan)
   287         { this->base_t::pre_parse(p, scan); }
   288 
   289         template <typename ResultT, typename ParserT, typename ScannerT>
   290         ResultT&
   291         post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
   292         {
   293 #if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
   294             if (hit && trace_parser(p.derived())) {
   295             // for now, print out the return value only
   296                 return impl::print_closure_info(
   297                     this->base_t::post_parse(hit, p, scan),
   298                     scan.get_level(),
   299                     parser_name(p.derived())
   300                 );
   301             }
   302 #endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
   303 
   304             return this->base_t::post_parse(hit, p, scan);
   305         }
   306     };
   307 
   308 #endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
   309 
   310 }} // namespace boost::spirit
   311 
   312 #endif // defined(BOOST_SPIRIT_DEBUG)
   313 
   314 #endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
   315