1 #ifdef RE2C_DEBUG
2 
3 #include "src/util/c99_stdint.h"
4 #include <map>
5 #include <stdio.h>
6 #include <string>
7 #include <utility>
8 #include <valarray>
9 #include <vector>
10 
11 #include "src/adfa/adfa.h"
12 #include "src/debug/debug.h"
13 #include "src/dfa/tcmd.h"
14 #include "src/regexp/rule.h"
15 #include "src/regexp/tag.h"
16 
17 
18 namespace re2c {
19 
dump_adfa_range(uint32_t lower,uint32_t upper)20 static void dump_adfa_range(uint32_t lower, uint32_t upper)
21 {
22     fprintf(stderr, "%u", lower);
23     if (--upper > lower) {
24         fprintf(stderr, "-%u", upper);
25     }
26 }
27 
dump_adfa(const DFA & dfa)28 void dump_adfa(const DFA &dfa)
29 {
30     std::map<const State*, uint32_t> st2idx;
31     uint32_t idx = 0;
32     for (const State *s = dfa.head; s; s = s->next) {
33         st2idx[s] = idx++;
34     }
35 
36     fprintf(stderr,
37         "digraph DFA {\n"
38         "  rankdir=LR\n"
39         "  node[shape=Mrecord fontname=fixed]\n"
40         "  edge[arrowhead=vee fontname=fixed]\n\n");
41 
42     fprintf(stderr,
43         "  n [shape=point]"
44         "  n -> n%u [style=dotted label=\"", st2idx[dfa.head]);
45     dump_tcmd(dfa.tcpool[dfa.tags0]);
46     fprintf(stderr, "\"]\n");
47 
48     for (const State *s = dfa.head; s; s = s->next) {
49         const char *attr;
50         Action::type_t action = s->action.type;
51 
52         if (action == Action::ACCEPT) {
53             attr = "style=filled fillcolor=gray";
54         } else if (action == Action::RULE) {
55             attr = "style=filled fillcolor=lightgray";
56         } else {
57             attr = "";
58         }
59         fprintf(stderr, "  n%u [height=0.2 width=0.2 label=\"", st2idx[s]);
60         if (s->fill && action != Action::MOVE) {
61             fprintf(stderr, "F(%u) ", (uint32_t)s->fill);
62         }
63         if (action == Action::RULE) {
64             const Rule &r = dfa.rules[s->action.info.rule];
65             for (size_t t = r.ltag; t < r.htag; ++t) {
66                 if (t > r.ltag) fprintf(stderr, " ");
67                 const std::string *name = dfa.tags[t].name;
68                 fprintf(stderr, "%s(%d)",
69                     name ? name->c_str() : "/", dfa.finvers[t]);
70             }
71         }
72         dump_tcmd(dfa.tcpool[s->stadfa_tags]);
73         dump_tcmd(dfa.tcpool[s->go.tags]);
74         fprintf(stderr, "\" %s]\n", attr);
75 
76         if (action == Action::ACCEPT) {
77             const accept_t &accept = *s->action.info.accepts;
78             for (uint32_t i = 0; i < accept.size(); ++i) {
79                 fprintf(stderr, "  n%u -> n%u [label=\"", st2idx[s],
80                     st2idx[accept[i].first]);
81                 dump_tcmd(dfa.tcpool[accept[i].second]);
82                 fprintf(stderr, "\" style=dotted]\n");
83             }
84         }
85 
86         const Span *x = s->go.span, *e = x + s->go.nspans;
87         for (uint32_t lb = 0; x < e; lb = x->ub, ++x) {
88             if (!x->to) continue;
89 
90             bool eat = true;
91             const Action::type_t act = x->to->action.type;
92             if (act == Action::MOVE || act == Action::RULE) {
93                 attr = "style=dotted";
94                 eat = false;
95             } else {
96                 attr = "";
97             }
98             fprintf(stderr, "  n%u -> n%u [label=\"", st2idx[s], st2idx[x->to]);
99             if (eat) dump_adfa_range(lb, x->ub);
100             dump_tcmd(dfa.tcpool[x->tags]);
101             fprintf(stderr, "\" %s]\n", attr);
102         }
103     }
104 
105     fprintf(stderr, "}\n");
106 }
107 
108 } // namespace re2c
109 
110 #endif // RE2C_DEBUG
111