'--dump-dfa-raw': show shadowed NFA sub-states.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 31 Jan 2017 09:50:58 +0000 (09:50 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 31 Jan 2017 09:52:40 +0000 (09:52 +0000)
re2c/src/ir/dfa/closure.cc
re2c/src/ir/dfa/closure.h
re2c/src/ir/dfa/determinization.cc
re2c/src/ir/dfa/dump.cc
re2c/src/ir/dfa/dump.h

index 91eb24541847ee1bc73b95e270b8d5431ec78b34..f0d536bfac80c0eecc3ff3a3c7ceae75af23e24f 100644 (file)
@@ -6,7 +6,7 @@
 namespace re2c
 {
 
-static void closure_one(closure_t &clos, Tagpool &tagpool, clos_t &c0, nfa_state_t *n, tagver_t *tags);
+static void closure_one(closure_t &clos, Tagpool &tagpool, clos_t &c0, nfa_state_t *n, tagver_t *tags, closure_t *shadow);
 bool is_better(const clos_t &c1, const clos_t &c2, Tagpool &tagpool);
 static bool compare_by_rule(const clos_t &c1, const clos_t &c2);
 static void prune_final_items(closure_t &clos, std::valarray<Rule> &rules);
@@ -14,14 +14,15 @@ static void update_versions(closure_t &clos, Tagpool &tagpool, tagver_t &maxver,
 
 void closure(closure_t &clos1, closure_t &clos2, Tagpool &tagpool,
        std::valarray<Rule> &rules, tagver_t &maxver, tagver_t *newvers,
-       bool lookahead)
+       bool lookahead, closure_t *shadow)
 {
        // build tagged epsilon-closure of the given set of NFA states
        clos2.clear();
+       if (shadow) shadow->clear();
        tagver_t *tags = tagpool.buffer1;
        std::fill(tags, tags + tagpool.ntags, TAGVER_ZERO);
        for (clositer_t c = clos1.begin(); c != clos1.end(); ++c) {
-               closure_one(clos2, tagpool, *c, c->state, tags);
+               closure_one(clos2, tagpool, *c, c->state, tags, shadow);
        }
 
        // The only difference between TDFA and LATDFA is here:
@@ -60,7 +61,7 @@ void closure(closure_t &clos1, closure_t &clos2, Tagpool &tagpool,
  * ambiguous. All tags are merged together; ambiguity is reported.
  */
 void closure_one(closure_t &clos, Tagpool &tagpool, clos_t &c0,
-       nfa_state_t *n, tagver_t *tags)
+       nfa_state_t *n, tagver_t *tags, closure_t *shadow)
 {
        // trace the first iteration of each loop:
        // epsilon-loops may add ney tags and reveal conflicts
@@ -71,17 +72,17 @@ void closure_one(closure_t &clos, Tagpool &tagpool, clos_t &c0,
        ++n->loop;
        switch (n->type) {
                case nfa_state_t::NIL:
-                       closure_one(clos, tagpool, c0, n->nil.out, tags);
+                       closure_one(clos, tagpool, c0, n->nil.out, tags, shadow);
                        break;
                case nfa_state_t::ALT:
-                       closure_one(clos, tagpool, c0, n->alt.out1, tags);
-                       closure_one(clos, tagpool, c0, n->alt.out2, tags);
+                       closure_one(clos, tagpool, c0, n->alt.out1, tags, shadow);
+                       closure_one(clos, tagpool, c0, n->alt.out2, tags, shadow);
                        break;
                case nfa_state_t::TAG: {
                        const size_t t = n->tag.info;
                        const tagver_t old = tags[t];
                        tags[t] = n->tag.bottom ? TAGVER_BOTTOM : TAGVER_CURSOR;
-                       closure_one(clos, tagpool, c0, n->tag.out, tags);
+                       closure_one(clos, tagpool, c0, n->tag.out, tags, shadow);
                        tags[t] = old;
                        break;
                }
@@ -95,8 +96,9 @@ void closure_one(closure_t &clos, Tagpool &tagpool, clos_t &c0,
                        for (; c != e && c->state != n; ++c);
                        if (c == e) {
                                clos.push_back(c0);
-                       } else if (is_better(*c, c0, tagpool)) {
-                               *c = c0;
+                       } else {
+                               if (shadow) shadow->push_back(*c);
+                               if (is_better(*c, c0, tagpool)) *c = c0;
                        }
                        break;
                }
index cb80da0802402896ea6ba831371cf95d01dc1d45..6cc30dbfdf87d4971f927bae4823330e8ad6db5e 100644 (file)
@@ -27,7 +27,7 @@ typedef closure_t::const_iterator cclositer_t;
 
 void closure(closure_t &clos1, closure_t &clos2, Tagpool &tagpool,
        std::valarray<Rule> &rules, tagver_t &maxver, tagver_t *newvers,
-       bool lookahead);
+       bool lookahead, closure_t *shadow);
 
 } // namespace re2c
 
index 8c0dbea208d73d59b736b6eb0d89c013ca3d335f..4ba8479e99f38d68d0b099974dc8a2934683fa95 100644 (file)
@@ -87,14 +87,14 @@ dfa_t::dfa_t(const nfa_t &nfa, const charset_t &charset, const opt_t *opts,
        clos_t c0 = {NULL, nfa.root, INITIAL_TAGS, ZERO_TAGS, ZERO_TAGS};
        clos1.push_back(c0);
        std::fill(newvers, newvers + ntag * 2, TAGVER_ZERO);
-       closure(clos1, clos2, tagpool, rules, maxtagver, newvers, lookahead);
+       closure(clos1, clos2, tagpool, rules, maxtagver, newvers, lookahead, dump.shadow);
        find_state(*this, dfa_t::NIL, 0/* any */, tagpool, kernels, clos2, dump);
 
        for (size_t i = 0; i < kernels.size(); ++i) {
                std::fill(newvers, newvers + ntag * 2, TAGVER_ZERO);
                for (size_t c = 0; c < nchars; ++c) {
                        reach(kernels[i], clos1, charset[c]);
-                       closure(clos1, clos2, tagpool, rules, maxtagver, newvers, lookahead);
+                       closure(clos1, clos2, tagpool, rules, maxtagver, newvers, lookahead, dump.shadow);
                        find_state(*this, i, c, tagpool, kernels, clos2, dump);
                }
        }
index bd327d4bdfdedec38f45bef07303068cb71a25e6..fb57ca1fc8c75d4463ce5c205519077b6c7f802b 100644 (file)
@@ -16,12 +16,14 @@ dump_dfa_t::dump_dfa_t(const dfa_t &d, const Tagpool &pool, const nfa_t &n, bool
        , tagpool(pool)
        , uniqidx(0)
        , base(n.states)
+       , shadow(NULL)
 {
        if (!debug) return;
 
+       shadow = new closure_t;
        fprintf(stderr, "digraph DFA {\n"
                "  rankdir=LR\n"
-               "  node[shape=Mrecord fontname=fixed]\n"
+               "  node[shape=plaintext fontname=fixed]\n"
                "  edge[arrowhead=vee fontname=fixed]\n\n");
 }
 
@@ -29,6 +31,7 @@ dump_dfa_t::~dump_dfa_t()
 {
        if (!debug) return;
 
+       delete shadow;
        fprintf(stderr, "}\n");
 }
 
@@ -37,43 +40,66 @@ uint32_t dump_dfa_t::index(const nfa_state_t *s)
        return static_cast<uint32_t>(s - base);
 }
 
-void dump_dfa_t::closure(const closure_t &clos, uint32_t state, bool isnew)
+void dump_dfa_t::closure_tags(cclositer_t c)
 {
        if (!debug) return;
 
-       fprintf(stderr, "  %s%u [label=\"", isnew ? "" : "i", state);
-
        const size_t ntag = tagpool.ntags;
-       cclositer_t b = clos.begin(), e = clos.end(), c;
-       for (c = b; c != e; ++c) {
-
-               if (c != b) fprintf(stderr, "|");
-               fprintf(stderr, "<%u> %u", index(c->state), index(c->state));
-
-               if (c->tvers != ZERO_TAGS) {
-                       fprintf(stderr, "/");
-                       const tagver_t *vers = tagpool[c->tvers];
-                       for (size_t t = 0; t < ntag; ++t) {
-                               if (t > 0) fprintf(stderr, " ");
-                               fprintf(stderr, "%s%d", tagname(dfa.vartags[t]), abs(vers[t]));
-                       }
+
+       if (c->tvers != ZERO_TAGS) {
+               fprintf(stderr, "/");
+               const tagver_t *vers = tagpool[c->tvers];
+               for (size_t t = 0; t < ntag; ++t) {
+                       if (t > 0) fprintf(stderr, " ");
+                       fprintf(stderr, "%s%d", tagname(dfa.vartags[t]), abs(vers[t]));
                }
+       }
 
-               if (c->tlook != ZERO_TAGS) {
-                       fprintf(stderr, "/");
-                       const tagver_t *look = tagpool[c->tlook];
-                       for (size_t t = 0; t < ntag; ++t) {
-                               const char *name = tagname(dfa.vartags[t]);
-                               switch (look[t]) {
-                                       case TAGVER_ZERO: break;
-                                       case TAGVER_CURSOR: fprintf(stderr, "%s ", name); break;
-                                       case TAGVER_BOTTOM: fprintf(stderr, "%s? ", name); break;
-                               }
+       if (c->tlook != ZERO_TAGS) {
+               fprintf(stderr, "/");
+               const tagver_t *look = tagpool[c->tlook];
+               for (size_t t = 0; t < ntag; ++t) {
+                       const char *name = tagname(dfa.vartags[t]);
+                       switch (look[t]) {
+                               case TAGVER_ZERO: break;
+                               case TAGVER_CURSOR: fprintf(stderr, "%s ", name); break;
+                               case TAGVER_BOTTOM: fprintf(stderr, "%s? ", name); break;
                        }
                }
        }
+}
 
-       fprintf(stderr, "\"]\n");
+void dump_dfa_t::closure(const closure_t &clos, uint32_t state, bool isnew)
+{
+       if (!debug) return;
+
+       const char
+               *style = isnew ? "" : " STYLE=\"dotted\"",
+               *color = " COLOR=\"lightgray\"";
+
+       fprintf(stderr, "  %s%u [label=<<TABLE"
+               " BORDER=\"0\""
+               " CELLBORDER=\"1\""
+               " CELLSPACING=\"0\""
+               " CELLPADDING=\"4\""
+               ">", isnew ? "" : "i", state);
+
+       for (cclositer_t b = shadow->begin(), c = b; c != shadow->end(); ++c) {
+               fprintf(stderr, "<TR><TD PORT=\"_%u_%ld\"%s%s><FONT%s>%u",
+                       index(c->state), c - b, color, style, color, index(c->state));
+               closure_tags(c);
+               fprintf(stderr, "</FONT></TD></TR>");
+       }
+       if (!shadow->empty()) {
+               fprintf(stderr, "<TR><TD BORDER=\"0\"></TD></TR>");
+       }
+       for (cclositer_t c = clos.begin(); c != clos.end(); ++c) {
+               fprintf(stderr, "<TR><TD PORT=\"%u\"%s>%u",
+                       index(c->state), style, index(c->state));
+               closure_tags(c);
+               fprintf(stderr, "</TD></TR>");
+       }
+       fprintf(stderr, "</TABLE>>]\n");
 }
 
 void dump_dfa_t::state0(const closure_t &clos)
@@ -82,6 +108,11 @@ void dump_dfa_t::state0(const closure_t &clos)
 
        closure(clos, 0, true);
        fprintf(stderr, "  void [shape=point]\n");
+       for (cclositer_t c = shadow->begin(); c != shadow->end(); ++c) {
+               fprintf(stderr, "  void -> 0:_%u_%ld:w [style=dotted color=lightgray label=\"", index(c->state), c - shadow->begin());
+               dump_tags(tagpool, c->ttran, c->tvers);
+               fprintf(stderr, "\"]\n");
+       }
        for (cclositer_t c = clos.begin(); c != clos.end(); ++c) {
                fprintf(stderr, "  void -> 0:%u:w [style=dotted label=\"", index(c->state));
                dump_tags(tagpool, c->ttran, c->tvers);
@@ -109,12 +140,18 @@ void dump_dfa_t::state(const closure_t &clos, size_t state, size_t symbol, bool
        closure(clos, z, isnew);
        if (!isnew) {
                fprintf(stderr, "  i%u [style=dotted]\n"
-                       "  i%u -> %u [style=dotted label=\"", z, z, y);
+                       "  i%u:s -> %u:s [style=dotted label=\"", z, z, y);
                for (const tagcopy_t *p = copy; p; p = p->next) {
                        fprintf(stderr, "%d=%d ", p->lhs, p->rhs);
                }
                fprintf(stderr, "\"]\n");
        }
+       for (cclositer_t b = shadow->begin(), c = b; c != shadow->end(); ++c) {
+               fprintf(stderr, "  %u:%u -> %s%u:_%u_%ld [color=lightgray fontcolor=lightgray label=\"%u",
+                       x, index(c->origin), prefix, z, index(c->state), c - b, a);
+               dump_tags(tagpool, c->ttran, c->tvers);
+               fprintf(stderr, "\"]\n");
+       }
        for (cclositer_t c = clos.begin(); c != clos.end(); ++c) {
                fprintf(stderr, "  %u:%u -> %s%u:%u [label=\"%u",
                        x, index(c->origin), prefix, z, index(c->state), a);
index 8fb397fd554a10694a4a91e0c442791f4bd4f86b..ac8b4a48ac3ca3844c170eed00381a9cd40dbda8 100644 (file)
@@ -14,9 +14,11 @@ struct dump_dfa_t
        const Tagpool &tagpool;
        uint32_t uniqidx;
        const nfa_state_t *base;
+       closure_t *shadow;
 
        dump_dfa_t(const dfa_t &d, const Tagpool &pool, const nfa_t &n, bool dbg);
        ~dump_dfa_t();
+       void closure_tags(cclositer_t c);
        void closure(const closure_t &clos, uint32_t state, bool isnew);
        void state0(const closure_t &clos);
        void state(const closure_t &clos, size_t state, size_t symbol, bool isnew);