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));

	}
Esempio n. 2
0
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);
}