rose: pick up more prefix->lookaround conversions

This commit is contained in:
Justin Viiret 2016-06-16 16:08:48 +10:00 committed by Matthew Barr
parent d3c56b532b
commit cdaf705a87
2 changed files with 56 additions and 12 deletions

View File

@ -1160,7 +1160,11 @@ bool buildLeftfixes(RoseBuildImpl &tbi, build_context &bc,
u32 lag = g[v].left.lag; u32 lag = g[v].left.lag;
bool is_transient = contains(tbi.transient, leftfix); bool is_transient = contains(tbi.transient, leftfix);
if (is_transient && tbi.cc.grey.roseLookaroundMasks) { // Transient leftfixes can sometimes be implemented solely with
// lookarounds, in which case we don't need to build an engine.
// TODO: Handle SOM-tracking cases as well.
if (cc.grey.roseLookaroundMasks && is_transient &&
!g[v].left.tracksSom()) {
vector<LookEntry> lookaround; vector<LookEntry> lookaround;
if (makeLeftfixLookaround(tbi, v, lookaround)) { if (makeLeftfixLookaround(tbi, v, lookaround)) {
DEBUG_PRINTF("implementing as lookaround!\n"); DEBUG_PRINTF("implementing as lookaround!\n");

View File

@ -538,6 +538,36 @@ void findLookaroundMasks(const RoseBuildImpl &tbi, const RoseVertex v,
} }
} }
static
bool hasSingleFloatingStart(const NGHolder &g) {
NFAVertex initial = NGHolder::null_vertex();
for (auto v : adjacent_vertices_range(g.startDs, g)) {
if (v == g.startDs) {
continue;
}
if (initial != NGHolder::null_vertex()) {
DEBUG_PRINTF("more than one start\n");
return false;
}
initial = v;
}
if (initial == NGHolder::null_vertex()) {
DEBUG_PRINTF("no floating starts\n");
return false;
}
// Anchored start must have no successors other than startDs and initial.
for (auto v : adjacent_vertices_range(g.start, g)) {
if (v != initial && v != g.startDs) {
DEBUG_PRINTF("anchored start\n");
return false;
}
}
return true;
}
static static
bool getTransientPrefixReach(const NGHolder &g, u32 lag, bool getTransientPrefixReach(const NGHolder &g, u32 lag,
map<s32, CharReach> &look) { map<s32, CharReach> &look) {
@ -546,15 +576,9 @@ bool getTransientPrefixReach(const NGHolder &g, u32 lag,
return false; return false;
} }
// Currently we don't handle anchored prefixes, as we would need to be able // Must be a floating chain wired to startDs.
// to represent the bounds from the anchor as well. if (!hasSingleFloatingStart(g)) {
if (out_degree(g.start, g) != 1) { DEBUG_PRINTF("not a single floating start\n");
DEBUG_PRINTF("anchored\n");
return false;
}
if (out_degree(g.startDs, g) != 2) {
DEBUG_PRINTF("more than one start\n");
return false; return false;
} }
@ -569,12 +593,28 @@ bool getTransientPrefixReach(const NGHolder &g, u32 lag,
look[0 - i] = g[v].char_reach; look[0 - i] = g[v].char_reach;
if (in_degree(v, g) != 1) { NFAVertex next = NGHolder::null_vertex();
for (auto u : inv_adjacent_vertices_range(v, g)) {
if (u == g.start) {
continue; // Benign, checked by hasSingleFloatingStart
}
if (next == NGHolder::null_vertex()) {
next = u;
continue;
}
DEBUG_PRINTF("branch\n"); DEBUG_PRINTF("branch\n");
return false; return false;
} }
v = *(inv_adjacent_vertices(v, g).first); if (next == NGHolder::null_vertex() || next == v) {
DEBUG_PRINTF("no predecessor or only self-loop\n");
// This graph is malformed -- all vertices in a graph that makes it
// to this analysis should have predecessors.
assert(0);
return false;
}
v = next;
i++; i++;
} }