Move procedure for running NFA into FSA module
This commit is contained in:
parent
557ab451a8
commit
018aec5339
21
lib/fsa.c
21
lib/fsa.c
@ -65,3 +65,24 @@ void fsa_add_rule(fsa_t *fsa, int from, int to, int input)
|
||||
rule->next = to;
|
||||
++state->count;
|
||||
}
|
||||
|
||||
bool fsa_accepts(const fsa_t *dfa, const char *input, int len)
|
||||
{
|
||||
const char *end = input + len;
|
||||
int current = dfa->initial;
|
||||
while (input < end) {
|
||||
bool found = false;
|
||||
const fsa_rule_t *rules = dfa->states[current].rules;
|
||||
for (int i = 0; i < dfa->states[current].count; ++i) {
|
||||
if (rules[i].input == *input) {
|
||||
current = rules[i].next;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
++input;
|
||||
}
|
||||
return dfa->states[current].final;
|
||||
}
|
||||
|
@ -35,4 +35,6 @@ void fsa_free(const fsa_t *fsa);
|
||||
int fsa_add_state(fsa_t *fsa);
|
||||
void fsa_add_rule(fsa_t *fsa, int from, int to, int input);
|
||||
|
||||
bool fsa_accepts(const fsa_t *dfa, const char *input, int len);
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "convert.h"
|
||||
#include "testing.h"
|
||||
|
||||
#define ACCEPTS(dfa, s) fsa_accepts(dfa, s, strlen(s))
|
||||
|
||||
static bool is_deterministic(const fsa_t *fsa)
|
||||
{
|
||||
for (int i = 0; i < fsa->count; ++i) {
|
||||
@ -23,26 +25,6 @@ static bool is_deterministic(const fsa_t *fsa)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool accepts(const fsa_t *dfa, const char *input)
|
||||
{
|
||||
int current = dfa->initial;
|
||||
while ('\0' != *input) {
|
||||
bool found = false;
|
||||
const fsa_rule_t *rules = dfa->states[current].rules;
|
||||
for (int i = 0; i < dfa->states[current].count; ++i) {
|
||||
if (rules[i].input == *input) {
|
||||
current = rules[i].next;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
++input;
|
||||
}
|
||||
return dfa->states[current].final;
|
||||
}
|
||||
|
||||
static void test_trivial_case(void)
|
||||
{
|
||||
fsa_t nfa;
|
||||
@ -56,9 +38,9 @@ static void test_trivial_case(void)
|
||||
convert_to_dfa(&nfa, &dfa);
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
ASSERT_TRUE(accepts(&dfa, "a"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aa"));
|
||||
ASSERT_FALSE(accepts(&dfa, "b"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aa"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "b"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
@ -80,13 +62,13 @@ static void test_epsilon_move(void)
|
||||
convert_to_dfa(&nfa, &dfa);
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
ASSERT_TRUE(accepts(&dfa, "a"));
|
||||
ASSERT_TRUE(accepts(&dfa, "b"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aa"));
|
||||
ASSERT_FALSE(accepts(&dfa, "bb"));
|
||||
ASSERT_FALSE(accepts(&dfa, "ab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "ba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "c"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "b"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aa"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "bb"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "ab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "ba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "c"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
@ -110,13 +92,13 @@ static void test_branch(void)
|
||||
convert_to_dfa(&nfa, &dfa);
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
ASSERT_TRUE(accepts(&dfa, "aa"));
|
||||
ASSERT_TRUE(accepts(&dfa, "ab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "a"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaa"));
|
||||
ASSERT_FALSE(accepts(&dfa, "abb"));
|
||||
ASSERT_FALSE(accepts(&dfa, "c"));
|
||||
ASSERT_FALSE(accepts(&dfa, "ac"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "ab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaa"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "abb"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "c"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "ac"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
@ -145,19 +127,19 @@ static void test_nfa_a(void)
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
|
||||
ASSERT_TRUE(accepts(&dfa, ""));
|
||||
ASSERT_TRUE(accepts(&dfa, "a"));
|
||||
ASSERT_TRUE(accepts(&dfa, "b"));
|
||||
ASSERT_TRUE(accepts(&dfa, "ab"));
|
||||
ASSERT_TRUE(accepts(&dfa, "ba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaaab"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, ""));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "b"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "ab"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "ba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaaab"));
|
||||
|
||||
ASSERT_FALSE(accepts(&dfa, "aaab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaabb"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaaba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaabb"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaabb"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaaba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabb"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
@ -184,21 +166,21 @@ static void test_nfa_b(void)
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
|
||||
ASSERT_TRUE(accepts(&dfa, ""));
|
||||
ASSERT_TRUE(accepts(&dfa, "a"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaaaaa"));
|
||||
ASSERT_TRUE(accepts(&dfa, "b"));
|
||||
ASSERT_TRUE(accepts(&dfa, "bbbbb"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaaaaa"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaaaabaa"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaaaabaab"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, ""));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaaaaa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "b"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "bbbbb"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaaaaa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaaaabaa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaaaabaab"));
|
||||
|
||||
ASSERT_FALSE(accepts(&dfa, "ba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "abab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaaba"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaabaaa"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aaaaabbaabbaaa"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "ba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "abab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaaba"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabaaa"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabbaabbaaa"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
@ -230,24 +212,24 @@ static void test_nfa_c(void)
|
||||
|
||||
ASSERT_TRUE(is_deterministic(&dfa));
|
||||
|
||||
ASSERT_TRUE(accepts(&dfa, "a"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "aaba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "abaaba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "ba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "babba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "baaa"));
|
||||
ASSERT_TRUE(accepts(&dfa, "baba"));
|
||||
ASSERT_TRUE(accepts(&dfa, "babaa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "a"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "aaba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "abaaba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "ba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "babba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "baaa"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "baba"));
|
||||
ASSERT_TRUE(ACCEPTS(&dfa, "babaa"));
|
||||
|
||||
ASSERT_FALSE(accepts(&dfa, ""));
|
||||
ASSERT_FALSE(accepts(&dfa, "ab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "abbab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "b"));
|
||||
ASSERT_FALSE(accepts(&dfa, "bb"));
|
||||
ASSERT_FALSE(accepts(&dfa, "baaabab"));
|
||||
ASSERT_FALSE(accepts(&dfa, "aabababab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, ""));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "ab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "abbab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "b"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "bb"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "baaabab"));
|
||||
ASSERT_FALSE(ACCEPTS(&dfa, "aabababab"));
|
||||
|
||||
fsa_free(&nfa);
|
||||
fsa_free(&dfa);
|
||||
|
Loading…
x
Reference in New Issue
Block a user