TEST(RuleBody, Basic) { RuleBody body; // start with an A auto a = RuleBody::atom(new AstAtom("A")); EXPECT_EQ("A()", toString(a)); a.conjunct(RuleBody::atom(new AstAtom("B"))); EXPECT_EQ("A(),B()", toString(a)); a.disjunct(RuleBody::atom(new AstAtom("C"))); EXPECT_EQ("A(),B();C()", toString(a)); }
static void replaceAssertVertex(NGWrapper &g, NFAVertex t, edge_cache_t &edge_cache, u32 &assert_edge_count) { DEBUG_PRINTF("replacing assert vertex %u\n", g[t].index); const u32 flags = g[t].assert_flags; DEBUG_PRINTF("consider assert vertex %u with flags %u\n", g[t].index, flags); // Wire up all the predecessors to all the successors. for (const auto &inEdge : in_edges_range(t, g)) { NFAVertex u = source(inEdge, g); if (u == t) { continue; // ignore self-loops } const u32 flags_inc_in = conjunct(g[inEdge].assert_flags, flags); if (flags_inc_in == DEAD_EDGE) { DEBUG_PRINTF("fail, in-edge has bad flags %d\n", g[inEdge].assert_flags); continue; } for (const auto &outEdge : out_edges_range(t, g)) { NFAVertex v = target(outEdge, g); DEBUG_PRINTF("consider path [%u,%u,%u]\n", g[u].index, g[t].index, g[v].index); if (v == t) { continue; // ignore self-loops } const u32 flags_final = conjunct(g[outEdge].assert_flags, flags_inc_in); if (flags_final == DEAD_EDGE) { DEBUG_PRINTF("fail, out-edge has bad flags %d\n", g[outEdge].assert_flags); continue; } if ((g[u].assert_flags & POS_FLAG_MULTILINE_START) && v == g.acceptEod) { DEBUG_PRINTF("fail, (?m)^ does not match \\n at eod\n"); continue; } /* Replace path (u,t,v) with direct edge (u,v), unless the edge * already exists, in which case we just need to edit its * properties. * * Use edge_cache to prevent us going O(N). */ auto cache_key = make_pair(u, v); auto ecit = edge_cache.find(cache_key); if (ecit == edge_cache.end()) { DEBUG_PRINTF("adding edge %u %u\n", g[u].index, g[v].index); NFAEdge e = add_edge(u, v, g).first; edge_cache.emplace(cache_key, e); g[e].assert_flags = flags; if (++assert_edge_count > MAX_ASSERT_EDGES) { throw CompileError(g.expressionIndex, "Pattern is too large."); } } else { NFAEdge e = ecit->second; DEBUG_PRINTF("updating edge %u %u [a %u]\n", g[u].index, g[v].index, g[t].index); // Edge already exists. u32 &e_flags = g[e].assert_flags; e_flags = disjunct(e_flags, flags_final); assert(e_flags != DEAD_EDGE); } } } // Clear vertex t to remove all the old edges. /* no need to clear the cache, as we will never look up its edge as it is * unreachable */ clear_vertex(t, g); }