File: parse_tree_to_dot.hpp

package info (click to toggle)
tao-json 0.0%2Bgit20200604.f357d72-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 8,900 kB
  • sloc: cpp: 48,129; makefile: 55
file content (105 lines) | stat: -rw-r--r-- 3,004 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP
#define TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP

#include <cassert>
#include <ostream>
#include <string>

#include "parse_tree.hpp"

namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree
{
   namespace internal
   {
      inline void escape( std::ostream& os, const std::string_view s )
      {
         static const char* h = "0123456789abcdef";

         const char* p = s.data();
         const char* l = p;
         const char* const e = s.data() + s.size();
         while( p != e ) {
            const unsigned char c = *p;
            if( c == '\\' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\\\\\\";
            }
            else if( c == '"' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\\\\\"";
            }
            else if( c < 32 ) {
               os.write( l, p - l );
               l = ++p;
               switch( c ) {
                  case '\b':
                     os << "\\\\b";
                     break;
                  case '\f':
                     os << "\\\\f";
                     break;
                  case '\n':
                     os << "\\\\n";
                     break;
                  case '\r':
                     os << "\\\\r";
                     break;
                  case '\t':
                     os << "\\\\t";
                     break;
                  default:
                     os << "\\\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ];
               }
            }
            else if( c == 127 ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\\u007f";
            }
            else {
               ++p;
            }
         }
         os.write( l, p - l );
      }

      template< typename Node >
      void print_dot_node( std::ostream& os, const Node& n, const std::string_view s )
      {
         os << "  x" << &n << " [ label=\"";
         escape( os, s );
         if( n.has_content() ) {
            os << "\\n\\\"";
            escape( os, n.string_view() );
            os << "\\\"";
         }
         os << "\" ]\n";
         if( !n.children.empty() ) {
            os << "  x" << &n << " -> { ";
            for( auto& up : n.children ) {
               os << "x" << up.get() << ( ( up == n.children.back() ) ? " }\n" : ", " );
            }
            for( auto& up : n.children ) {
               print_dot_node( os, *up, up->type );
            }
         }
      }

   }  // namespace internal

   template< typename Node >
   void print_dot( std::ostream& os, const Node& n )
   {
      os << "digraph parse_tree\n{\n";
      internal::print_dot_node( os, n, n.is_root() ? "ROOT" : n.type );
      os << "}\n";
   }

}  // namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree

#endif