From: Ulya Trofimovich Date: Mon, 10 Aug 2015 11:03:07 +0000 (+0100) Subject: Stop loosing arcs in DFA loops when building path cover with --skeleton. X-Git-Tag: 0.15~140 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=87c08466220673a429be0b5f2ff1bc0c37a85e39;p=re2c Stop loosing arcs in DFA loops when building path cover with --skeleton. The problem with the algorithm was that when one and the same skeleton node is visited for the 3rd time, the algorithm would abandon this branch and drop all the path prefixes that lead to it. It's ok when bruteforcing all paths (the arcs in the dropped prefixes will occur in other paths that lead to final states), but it's not ok for path cover: some arcs may have occured only in these dropped prefixes). The fix is easy: just check if the branch was cancelled and in case it was try the same prefixes with another branch. This small example demonstrates the problem: /*!re2c [^\x00]* [\x00] {} */ DFA skeleton looks like this: state 0: arcs to state 0: [0x01, 0xFF] arcs to state 1: [0x00] state 1: final Before the fix, re2c would generate the following paths (provided path cover construction is forced instead of generating all paths): - 0x01,0x00 - 0x00 Clearly the [0xFF] arc looping from state 0 to state 0 is missing (uncovered). After the fix: - 0x01,0x00 - 0xFF,0x01,0x00 - 0x01,0xFF,0x00 - 0x00 Not a minimal path cover, but we don't need it. We just need a small enough one. --- diff --git a/re2c/src/codegen/skeleton/skeleton.cc b/re2c/src/codegen/skeleton/skeleton.cc index bd3f19ee..a974c978 100644 --- a/re2c/src/codegen/skeleton/skeleton.cc +++ b/re2c/src/codegen/skeleton/skeleton.cc @@ -129,12 +129,15 @@ arccount_t Node::estimate_size_cover (arccount_t wid, arccount_t len) { return arccount_t::limit (); } - if (!path_len_init && i->first->path_len_init) + if (i->first->path_len_init) { - path_len_init = true; - path_len = i->first->path_len + arccount_t (1u); + w = w + new_wid; + if (!path_len_init) + { + path_len_init = true; + path_len = i->first->path_len + arccount_t (1u); + } } - w = w + new_wid; } return size; } @@ -194,16 +197,20 @@ void Node::generate_paths_cover (const std::vector & prefixes, std::vector { std::vector zs; const size_t new_wid = i->second.size (); - for (size_t j = 0; j < new_wid; ++j, ++w) + for (size_t j = 0; j < new_wid; ++j) { - zs.push_back (prefixes[w % wid]); + zs.push_back (prefixes[(w + j) % wid]); zs[j].extend (rule, i->second[j]); } i->first->generate_paths_cover (zs, results); - if (path == NULL && i->first->path != NULL) + if (i->first->path != NULL) { - path = new Path (Path::chars_t (1, i->second[0]), 0, rule); - path->append (i->first->path); + w += new_wid; + if (path == NULL) + { + path = new Path (Path::chars_t (1, i->second[0]), 0, rule); + path->append (i->first->path); + } } } }