TEST_F(TestDFA, Equivalence) {
    instance << "q0";
    instance << "q1";
    instance.addTransition("q0", "q1", 'a');
    instance.accept("q1");

    DFA copy;
    ASSERT_NO_THROW(copy = ~~instance);
    ASSERT_EQ(instance.size(), copy.size());

    DFA almostEqual;
    almostEqual << "q0";
    almostEqual << "q1";
    almostEqual.addTransition("q0", "q1", 'b');
    almostEqual.accept("q1");

    bool r;
    ASSERT_NO_THROW(r = (copy == instance));
    EXPECT_TRUE(r);
    EXPECT_EQ(2, instance.size());
    EXPECT_EQ(2, copy.size());

    ASSERT_NO_THROW(r = (almostEqual == instance));
    EXPECT_FALSE(r);
    EXPECT_EQ(2, instance.size());
    EXPECT_EQ(2, almostEqual.size());
}
TEST_F(TestDFA, Union) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'a');
    instance.addTransition("q2", "q0", 'a');
    instance.accept("q0");

    DFA second;
    second << "q0";
    second << "q1";
    second.addTransition("q0", "q1", 'a');
    second.addTransition("q1", "q0", 'a');
    second.accept("q0");

    DFA unionDFA = instance | second;
    EXPECT_EQ(3, instance.size());
    EXPECT_EQ(2, second.size());
    EXPECT_EQ(6, unionDFA.size());
    EXPECT_TRUE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_FALSE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_TRUE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_TRUE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_TRUE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_FALSE(unionDFA.accepts());
    unionDFA.read("a");
    EXPECT_TRUE(unionDFA.accepts());
}
TEST_F(TestDFA, DeadStateRemoval) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance << "q3";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'b');
    instance.addTransition("q2", "q2", 'c');
    instance.addTransition("q3", "q3", 'd');
    EXPECT_EQ(4, instance.size());
    DFA other = instance.withoutDeadStates();
    EXPECT_EQ(0, other.size());

    instance.accept("q1");
    other = instance.withoutDeadStates();
    EXPECT_EQ(2, other.size());
    EXPECT_EQ(other.initialState(), instance.initialState());

    instance.accept("q3");
    other = instance.withoutDeadStates();
    EXPECT_EQ(3, other.size());
    EXPECT_EQ(other.initialState(), instance.initialState());

    DFA empty;
    ASSERT_NO_THROW(empty.withoutDeadStates());
    EXPECT_EQ(0, empty.withoutDeadStates().size());
}
TEST_F(TestDFA, Intersection) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'a');
    instance.addTransition("q2", "q0", 'a');
    instance.accept("q0");

    DFA second;
    second << "q0";
    second << "q1";
    second.addTransition("q0", "q1", 'a');
    second.addTransition("q1", "q0", 'a');
    second.accept("q0");

    DFA intersection = instance & second;
    EXPECT_EQ(3, instance.size());
    EXPECT_EQ(2, second.size());
    EXPECT_EQ(6, intersection.size());
    EXPECT_TRUE(intersection.accepts());
    intersection.read("a");
    EXPECT_FALSE(intersection.accepts());
    intersection.read("a");
    EXPECT_FALSE(intersection.accepts());
    intersection.read("a");
    EXPECT_FALSE(intersection.accepts());
    intersection.read("a");
    EXPECT_FALSE(intersection.accepts());
    intersection.read("a");
    EXPECT_FALSE(intersection.accepts());
    intersection.read("a");
    EXPECT_TRUE(intersection.accepts());
}
TEST_F(TestDFA, Containment) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance << "q3";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q0", "q1", 'b');
    instance.addTransition("q1", "q2", 'a');
    instance.addTransition("q1", "q2", 'b');
    instance.addTransition("q2", "q3", 'a');
    instance.addTransition("q2", "q3", 'b');
    instance.addTransition("q3", "q0", 'a');
    instance.addTransition("q3", "q0", 'b');
    instance.accept("q0");
    instance.accept("q2");

    DFA second;
    second << "q0";
    second << "q1";
    second.addTransition("q0", "q1", 'a');
    second.addTransition("q1", "q0", 'a');
    second.accept("q0");

    bool r1, r2;
    ASSERT_NO_THROW(r1 = instance.contains(second));
    ASSERT_NO_THROW(r2 = second.contains(instance));

    EXPECT_TRUE(r1);
    EXPECT_FALSE(r2);

    EXPECT_EQ(4, instance.size());
    EXPECT_EQ(2, second.size());
}
TEST_F(TestDFA, Complement) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'a');
    instance.addTransition("q2", "q0", 'a');
    instance.accept("q0");

    DFA complement;
    ASSERT_NO_THROW(complement = ~instance);

    EXPECT_EQ(3, instance.size());
    EXPECT_EQ(3, complement.size());

    EXPECT_TRUE(instance.accepts());
    EXPECT_FALSE(complement.accepts());

    instance.read("a");
    complement.read("a");
    EXPECT_FALSE(instance.accepts());
    EXPECT_TRUE(complement.accepts());

    instance.read("a");
    complement.read("a");
    EXPECT_FALSE(instance.accepts());
    EXPECT_TRUE(complement.accepts());

    instance.read("a");
    complement.read("a");
    EXPECT_TRUE(instance.accepts());
    EXPECT_FALSE(complement.accepts());
}
TEST_F(TestDFA, MinimizationStress) {
    auto fn = [](unsigned i) -> std::string {
        return std::to_string(i);
    };

    unsigned limit = 999;
    instance.reserve(limit);
    for (unsigned i = 0; i < limit; i++) {
        instance << ("q" + fn(i));
    }

    instance.accept("q" + fn(limit - 2));
    instance.accept("q" + fn(limit - 1));
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q0", "q2", 'b');
    for (unsigned i = 1; i < limit - 2; i += 2) {
        unsigned next = (i + 1) % limit;
        instance.addTransition("q" + fn(i), "q" + fn(next), 'a');
        instance.addTransition("q" + fn(next), "q" + fn(i), 'a');
        instance.addTransition("q" + fn(i), "q" + fn((i + 2) % limit), 'b');
        instance.addTransition("q" + fn(next), "q" + fn((i + 3) % limit), 'b');
    }

    DFA other;
    ASSERT_NO_THROW(other = instance.minimized());
    EXPECT_EQ((limit + 1)/2, other.size());
}
TEST_F(TestDFA, EquivalentStateRemoval) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance << "q3";
    instance << "q4";
    instance << "q5";
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'b');
    instance.addTransition("q2", "q2", 'c');
    instance.addTransition("q3", "q3", 'd');
    instance.addTransition("q3", "q4", 'a');
    instance.addTransition("q4", "q5", 'a');
    instance.addTransition("q5", "q3", 'a');
    instance.accept("q2");
    EXPECT_EQ(6, instance.size());
    instance.read("abc");
    EXPECT_TRUE(instance.accepts());
    instance.read("d");
    EXPECT_FALSE(instance.accepts());

    DFA other = instance.withoutDeadStates();
    EXPECT_EQ(3, other.size());
    EXPECT_EQ(other.initialState(), instance.initialState());

    other.read("abc");
    EXPECT_TRUE(other.accepts());
    other.read("d");
    EXPECT_FALSE(other.accepts());
}
Beispiel #9
0
bool DFAMerger::add(const DFA& dfa) {
	if (_start == -1) {
		_start = new_state();
	}
	assert(_start >= 0);

	size_t size = dfa.size();
	size_t base = _trans.size();
	_trans.resize(base + size);

	for (size_t i = 0; i < size; i++) {
		const DFATran& tran = dfa[i];
		for (DFATran::const_iterator it = tran.begin();
				it != tran.end(); ++it) {
			_trans[base + i][it->first].insert(base + it->second);
		}
		const Tag& tag = dfa.tags(i);
		if (!tag.empty()) {
			Tag& to = _tags[base + i];
			to.insert(tag.begin(), tag.end());
		}
	}


	_trans[_start][EPSILON].insert(base + dfa.start());

	const States& last = dfa.last();
	for (States::const_iterator it = last.begin();
		it != last.end(); ++it) {
		_last.insert(base + *it);
	}

	return true;
}
Beispiel #10
0
unsigned long regex_parser::parse_regex_group(FILE *file, int group[]){
	unsigned long size = _INFINITY;
	do {
		NFA *nfa = group_regex(file, group);
		nfa->remove_epsilon();
		nfa->reduce();
		DFA *dfa = nfa->nfa2dfa();
		delete nfa;
		size = dfa->size();
		delete dfa;
	} while (0);

	return size;
}
TEST_F(TestDFA, UselessStateRemoval) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance << "q3";
    instance.accept("q1");
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q1", "q2", 'b');
    instance.addTransition("q2", "q2", 'c');
    instance.addTransition("q3", "q3", 'd');
    EXPECT_EQ(4, instance.size());
    
    DFA other = instance.withoutUselessStates();
    EXPECT_EQ(2, other.size());
    EXPECT_EQ(other.initialState(), instance.initialState());
}
TEST_F(TestDFA, Minimization) {
    instance << "q0";
    instance << "q1";
    instance << "q2";
    instance << "q3";
    instance << "q4";
    instance << "q5";
    instance.accept("q3");
    instance.addTransition("q0", "q1", 'a');
    instance.addTransition("q0", "q2", 'b');
    instance.addTransition("q1", "q2", 'b');
    instance.addTransition("q2", "q1", 'b');
    instance.addTransition("q1", "q3", 'c');
    instance.addTransition("q2", "q3", 'c');
    instance.addTransition("q3", "q4", 'a');
    instance.addTransition("q4", "q4", 'b');
    instance.addTransition("q5", "q2", 'a');

    DFA minimized;
    ASSERT_NO_THROW(minimized = instance.minimized());
    EXPECT_EQ(3, minimized.size());
    EXPECT_EQ(minimized.initialState().getName(), instance.initialState().getName());
}
Beispiel #13
0
void print_dfa(const DFA& dfa) {
	cout << "start  : " << dfa.start() << endl;
	cout << "last   : ";
	const ::mpl::lexer::detail::States& last = dfa.last();
	print_set(last);
	cout << endl;

	for (size_t i = 0; i < dfa.size(); i++) {
		const ::mpl::lexer::detail::DFATran& tran = dfa[i];
		for (::mpl::lexer::detail::DFATran::const_iterator it = tran.begin();
			it != tran.end(); ++it) {
			cout << i << "(";
			if (it->first == ::mpl::lexer::detail::EPSILON) {
				cout << "\\0";
			} else if (it->first == ::mpl::lexer::detail::OTHER) {
				cout << "-1";
			} else {
				//cout << it->first;
				cout << "0x" << hex << (int)(it->first & 0xFF) << dec;
			}
			cout << ")";
			cout << "\t->\t";
			cout << it->second;
			cout << endl;
		}
	}

	for (::mpl::lexer::detail::States::const_iterator it = last.begin();
		it != last.end(); ++it) {
		const ::mpl::lexer::detail::Tag& tag = dfa.tags(*it);

		cout << *it << ": ";
		print_set(tag);
		cout << endl;
	}
}