diff --git a/src/nfagraph/ng_rose.cpp b/src/nfagraph/ng_rose.cpp index 1f79b55f..d24c3392 100644 --- a/src/nfagraph/ng_rose.cpp +++ b/src/nfagraph/ng_rose.cpp @@ -807,86 +807,7 @@ bool can_match(const NGHolder &g, const ue2_literal &lit, bool overhang_ok) { return !curr.empty(); } -u32 removeTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, - u32 max_delay, bool overhang_ok) { - assert(isCorrectlyTopped(g)); - if (max_delay == MO_INVALID_IDX) { - max_delay--; - } - - DEBUG_PRINTF("killing off '%s'\n", dumpString(lit).c_str()); - set curr, next; - curr.insert(g.accept); - - auto it = lit.rbegin(); - for (u32 delay = max_delay; delay > 0 && it != lit.rend(); delay--, ++it) { - next.clear(); - for (auto v : curr) { - for (auto u : inv_adjacent_vertices_range(v, g)) { - if (u == g.start) { - if (overhang_ok) { - DEBUG_PRINTF("bail\n"); - goto bail; /* things got complicated */ - } else { - continue; /* it is not possible for a lhs literal to - * overhang the start */ - } - } - - const CharReach &cr = g[u].char_reach; - if (!overlaps(*it, cr)) { - DEBUG_PRINTF("skip\n"); - continue; - } - if (isSubsetOf(*it, cr)) { - next.insert(u); - } else { - DEBUG_PRINTF("bail\n"); - goto bail; /* things got complicated */ - } - } - } - - curr.swap(next); - } - bail: - if (curr.empty()) { - /* This can happen when we have an edge representing a cross from two - * sides of an alternation. This whole edge needs to be marked as - * dead */ - assert(0); /* should have been picked up by can match */ - return MO_INVALID_IDX; - } - - u32 delay = distance(lit.rbegin(), it); - assert(delay <= max_delay); - assert(delay <= lit.length()); - DEBUG_PRINTF("managed delay %u (of max %u)\n", delay, max_delay); - - set pred; - for (auto v : curr) { - insert(&pred, inv_adjacent_vertices_range(v, g)); - } - - clear_in_edges(g.accept, g); - clearReports(g); - - for (auto v : pred) { - NFAEdge e = add_edge(v, g.accept, g); - g[v].reports.insert(0); - if (is_triggered(g) && v == g.start) { - g[e].tops.insert(DEFAULT_TOP); - } - } - - pruneUseless(g); - assert(allMatchStatesHaveReports(g)); - assert(isCorrectlyTopped(g)); - - DEBUG_PRINTF("graph has %zu vertices left\n", num_vertices(g)); - return delay; -} - +static void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, u32 delay, const vector &preds) { assert(delay <= lit.length()); @@ -922,6 +843,7 @@ void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, assert(isCorrectlyTopped(g)); } +static void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, u32 delay) { vector preds; diff --git a/src/nfagraph/ng_rose.h b/src/nfagraph/ng_rose.h index 1634adf0..9f69fe0c 100644 --- a/src/nfagraph/ng_rose.h +++ b/src/nfagraph/ng_rose.h @@ -63,18 +63,6 @@ bool finalChanceRose(RoseBuild &rose, const NGHolder &h, bool prefilter, bool checkRose(const ReportManager &rm, const NGHolder &h, bool prefilter, const CompileContext &cc); -/** \brief Returns the delay or MO_INVALID_IDX if the graph cannot match with - * the trailing literal. */ -u32 removeTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, - u32 max_delay, bool overhang_ok = true); - -void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, - u32 delay); - -void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, - u32 delay, - const std::vector &preds); - } // namespace ue2 #endif // NG_ROSE_H diff --git a/src/nfagraph/ng_util.cpp b/src/nfagraph/ng_util.cpp index 5252eb18..0776fa04 100644 --- a/src/nfagraph/ng_util.cpp +++ b/src/nfagraph/ng_util.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, Intel Corporation + * Copyright (c) 2015-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -34,6 +34,7 @@ #include "grey.h" #include "ng_depth.h" // for NFAVertexDepth #include "ng_dump.h" +#include "ng_prune.h" #include "ue2common.h" #include "nfa/limex_limits.h" // for NFA_MAX_TOP_MASKS. #include "parser/position.h" @@ -43,6 +44,7 @@ #include "util/ue2string.h" #include "util/report_manager.h" +#include #include #include #include @@ -672,6 +674,86 @@ void reverseHolder(const NGHolder &g_in, NGHolder &g) { assert(num_edges(g) == num_edges(g_in)); } +u32 removeTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, + u32 max_delay, bool overhang_ok) { + assert(isCorrectlyTopped(g)); + if (max_delay == numeric_limits::max()) { + max_delay--; + } + + DEBUG_PRINTF("killing off '%s'\n", dumpString(lit).c_str()); + set curr, next; + curr.insert(g.accept); + + auto it = lit.rbegin(); + for (u32 delay = max_delay; delay > 0 && it != lit.rend(); delay--, ++it) { + next.clear(); + for (auto v : curr) { + for (auto u : inv_adjacent_vertices_range(v, g)) { + if (u == g.start) { + if (overhang_ok) { + DEBUG_PRINTF("bail\n"); + goto bail; /* things got complicated */ + } else { + continue; /* it is not possible for a lhs literal to + * overhang the start */ + } + } + + const CharReach &cr = g[u].char_reach; + if (!overlaps(*it, cr)) { + DEBUG_PRINTF("skip\n"); + continue; + } + if (isSubsetOf(*it, cr)) { + next.insert(u); + } else { + DEBUG_PRINTF("bail\n"); + goto bail; /* things got complicated */ + } + } + } + + curr.swap(next); + } + bail: + if (curr.empty()) { + /* This can happen when we have an edge representing a cross from two + * sides of an alternation. This whole edge needs to be marked as + * dead */ + assert(0); /* should have been picked up by can match */ + return numeric_limits::max(); + } + + u32 delay = distance(lit.rbegin(), it); + assert(delay <= max_delay); + assert(delay <= lit.length()); + DEBUG_PRINTF("managed delay %u (of max %u)\n", delay, max_delay); + + set pred; + for (auto v : curr) { + insert(&pred, inv_adjacent_vertices_range(v, g)); + } + + clear_in_edges(g.accept, g); + clearReports(g); + + for (auto v : pred) { + NFAEdge e = add_edge(v, g.accept, g); + g[v].reports.insert(0); + if (is_triggered(g) && v == g.start) { + g[e].tops.insert(DEFAULT_TOP); + } + } + + pruneUseless(g); + assert(allMatchStatesHaveReports(g)); + assert(isCorrectlyTopped(g)); + + DEBUG_PRINTF("graph has %zu vertices left\n", num_vertices(g)); + return delay; +} + #ifndef NDEBUG bool allMatchStatesHaveReports(const NGHolder &g) { diff --git a/src/nfagraph/ng_util.h b/src/nfagraph/ng_util.h index a0752533..f3fa1354 100644 --- a/src/nfagraph/ng_util.h +++ b/src/nfagraph/ng_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, Intel Corporation + * Copyright (c) 2015-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -275,6 +275,11 @@ void duplicateReport(NGHolder &g, ReportID r_old, ReportID r_new); * accepts. */ void reverseHolder(const NGHolder &g, NGHolder &out); +/** \brief Returns the delay or ~0U if the graph cannot match with + * the trailing literal. */ +u32 removeTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, + u32 max_delay, bool overhang_ok = true); + #ifndef NDEBUG // Assertions: only available in internal builds. diff --git a/src/nfagraph/ng_violet.cpp b/src/nfagraph/ng_violet.cpp index 715c5b5c..182e2471 100644 --- a/src/nfagraph/ng_violet.cpp +++ b/src/nfagraph/ng_violet.cpp @@ -1821,6 +1821,40 @@ bool makeTransientFromLongLiteral(NGHolder &h, RoseInGraph &vg, return true; } +static +void restoreTrailingLiteralStates(NGHolder &g, const ue2_literal &lit, + u32 delay, const vector &preds) { + assert(delay <= lit.length()); + assert(isCorrectlyTopped(g)); + DEBUG_PRINTF("adding on '%s' %u\n", dumpString(lit).c_str(), delay); + + NFAVertex prev = g.accept; + auto it = lit.rbegin(); + while (delay--) { + NFAVertex curr = add_vertex(g); + assert(it != lit.rend()); + g[curr].char_reach = *it; + add_edge(curr, prev, g); + ++it; + prev = curr; + } + + for (auto v : preds) { + NFAEdge e = add_edge(v, prev, g); + if (v == g.start && is_triggered(g)) { + g[e].tops.insert(DEFAULT_TOP); + } + } + + // Every predecessor of accept must have a report. + set_report(g, 0); + + renumber_vertices(g); + renumber_edges(g); + assert(allMatchStatesHaveReports(g)); + assert(isCorrectlyTopped(g)); +} + static void restoreTrailingLiteralStates(NGHolder &g, const vector> &lits) {