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);
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:
* 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
++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;
}
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;
}
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);
}
}
, 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");
}
{
if (!debug) return;
+ delete shadow;
fprintf(stderr, "}\n");
}
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)
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);
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);