Move procedure for running NFA into FSA module

This commit is contained in:
Camden Dixie O'Brien 2024-11-02 15:40:58 +00:00
parent 557ab451a8
commit 018aec5339
3 changed files with 85 additions and 80 deletions

View File

@ -65,3 +65,24 @@ void fsa_add_rule(fsa_t *fsa, int from, int to, int input)
rule->next = to; rule->next = to;
++state->count; ++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;
}

View File

@ -35,4 +35,6 @@ void fsa_free(const fsa_t *fsa);
int fsa_add_state(fsa_t *fsa); int fsa_add_state(fsa_t *fsa);
void fsa_add_rule(fsa_t *fsa, int from, int to, int input); 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 #endif

View File

@ -6,6 +6,8 @@
#include "convert.h" #include "convert.h"
#include "testing.h" #include "testing.h"
#define ACCEPTS(dfa, s) fsa_accepts(dfa, s, strlen(s))
static bool is_deterministic(const fsa_t *fsa) static bool is_deterministic(const fsa_t *fsa)
{ {
for (int i = 0; i < fsa->count; ++i) { for (int i = 0; i < fsa->count; ++i) {
@ -23,26 +25,6 @@ static bool is_deterministic(const fsa_t *fsa)
return true; 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) static void test_trivial_case(void)
{ {
fsa_t nfa; fsa_t nfa;
@ -56,9 +38,9 @@ static void test_trivial_case(void)
convert_to_dfa(&nfa, &dfa); convert_to_dfa(&nfa, &dfa);
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "a")); ASSERT_TRUE(ACCEPTS(&dfa, "a"));
ASSERT_FALSE(accepts(&dfa, "aa")); ASSERT_FALSE(ACCEPTS(&dfa, "aa"));
ASSERT_FALSE(accepts(&dfa, "b")); ASSERT_FALSE(ACCEPTS(&dfa, "b"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);
@ -80,13 +62,13 @@ static void test_epsilon_move(void)
convert_to_dfa(&nfa, &dfa); convert_to_dfa(&nfa, &dfa);
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "a")); ASSERT_TRUE(ACCEPTS(&dfa, "a"));
ASSERT_TRUE(accepts(&dfa, "b")); ASSERT_TRUE(ACCEPTS(&dfa, "b"));
ASSERT_FALSE(accepts(&dfa, "aa")); ASSERT_FALSE(ACCEPTS(&dfa, "aa"));
ASSERT_FALSE(accepts(&dfa, "bb")); ASSERT_FALSE(ACCEPTS(&dfa, "bb"));
ASSERT_FALSE(accepts(&dfa, "ab")); ASSERT_FALSE(ACCEPTS(&dfa, "ab"));
ASSERT_FALSE(accepts(&dfa, "ba")); ASSERT_FALSE(ACCEPTS(&dfa, "ba"));
ASSERT_FALSE(accepts(&dfa, "c")); ASSERT_FALSE(ACCEPTS(&dfa, "c"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);
@ -110,13 +92,13 @@ static void test_branch(void)
convert_to_dfa(&nfa, &dfa); convert_to_dfa(&nfa, &dfa);
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "aa")); ASSERT_TRUE(ACCEPTS(&dfa, "aa"));
ASSERT_TRUE(accepts(&dfa, "ab")); ASSERT_TRUE(ACCEPTS(&dfa, "ab"));
ASSERT_FALSE(accepts(&dfa, "a")); ASSERT_FALSE(ACCEPTS(&dfa, "a"));
ASSERT_FALSE(accepts(&dfa, "aaa")); ASSERT_FALSE(ACCEPTS(&dfa, "aaa"));
ASSERT_FALSE(accepts(&dfa, "abb")); ASSERT_FALSE(ACCEPTS(&dfa, "abb"));
ASSERT_FALSE(accepts(&dfa, "c")); ASSERT_FALSE(ACCEPTS(&dfa, "c"));
ASSERT_FALSE(accepts(&dfa, "ac")); ASSERT_FALSE(ACCEPTS(&dfa, "ac"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);
@ -145,19 +127,19 @@ static void test_nfa_a(void)
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "")); ASSERT_TRUE(ACCEPTS(&dfa, ""));
ASSERT_TRUE(accepts(&dfa, "a")); ASSERT_TRUE(ACCEPTS(&dfa, "a"));
ASSERT_TRUE(accepts(&dfa, "b")); ASSERT_TRUE(ACCEPTS(&dfa, "b"));
ASSERT_TRUE(accepts(&dfa, "ab")); ASSERT_TRUE(ACCEPTS(&dfa, "ab"));
ASSERT_TRUE(accepts(&dfa, "ba")); ASSERT_TRUE(ACCEPTS(&dfa, "ba"));
ASSERT_TRUE(accepts(&dfa, "aaaab")); ASSERT_TRUE(ACCEPTS(&dfa, "aaaab"));
ASSERT_FALSE(accepts(&dfa, "aaab")); ASSERT_FALSE(ACCEPTS(&dfa, "aaab"));
ASSERT_FALSE(accepts(&dfa, "aaaba")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaba"));
ASSERT_FALSE(accepts(&dfa, "aaabb")); ASSERT_FALSE(ACCEPTS(&dfa, "aaabb"));
ASSERT_FALSE(accepts(&dfa, "aaaaab")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaab"));
ASSERT_FALSE(accepts(&dfa, "aaaaaba")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaaba"));
ASSERT_FALSE(accepts(&dfa, "aaaaabb")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabb"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);
@ -184,21 +166,21 @@ static void test_nfa_b(void)
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "")); ASSERT_TRUE(ACCEPTS(&dfa, ""));
ASSERT_TRUE(accepts(&dfa, "a")); ASSERT_TRUE(ACCEPTS(&dfa, "a"));
ASSERT_TRUE(accepts(&dfa, "aaaaaa")); ASSERT_TRUE(ACCEPTS(&dfa, "aaaaaa"));
ASSERT_TRUE(accepts(&dfa, "b")); ASSERT_TRUE(ACCEPTS(&dfa, "b"));
ASSERT_TRUE(accepts(&dfa, "bbbbb")); ASSERT_TRUE(ACCEPTS(&dfa, "bbbbb"));
ASSERT_TRUE(accepts(&dfa, "aaaaaa")); ASSERT_TRUE(ACCEPTS(&dfa, "aaaaaa"));
ASSERT_TRUE(accepts(&dfa, "aaaaabaa")); ASSERT_TRUE(ACCEPTS(&dfa, "aaaaabaa"));
ASSERT_TRUE(accepts(&dfa, "aaaaabaab")); ASSERT_TRUE(ACCEPTS(&dfa, "aaaaabaab"));
ASSERT_FALSE(accepts(&dfa, "ba")); ASSERT_FALSE(ACCEPTS(&dfa, "ba"));
ASSERT_FALSE(accepts(&dfa, "aba")); ASSERT_FALSE(ACCEPTS(&dfa, "aba"));
ASSERT_FALSE(accepts(&dfa, "abab")); ASSERT_FALSE(ACCEPTS(&dfa, "abab"));
ASSERT_FALSE(accepts(&dfa, "aaaaaba")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaaba"));
ASSERT_FALSE(accepts(&dfa, "aaaaabaaa")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabaaa"));
ASSERT_FALSE(accepts(&dfa, "aaaaabbaabbaaa")); ASSERT_FALSE(ACCEPTS(&dfa, "aaaaabbaabbaaa"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);
@ -230,24 +212,24 @@ static void test_nfa_c(void)
ASSERT_TRUE(is_deterministic(&dfa)); ASSERT_TRUE(is_deterministic(&dfa));
ASSERT_TRUE(accepts(&dfa, "a")); ASSERT_TRUE(ACCEPTS(&dfa, "a"));
ASSERT_TRUE(accepts(&dfa, "aba")); ASSERT_TRUE(ACCEPTS(&dfa, "aba"));
ASSERT_TRUE(accepts(&dfa, "aaba")); ASSERT_TRUE(ACCEPTS(&dfa, "aaba"));
ASSERT_TRUE(accepts(&dfa, "abaaba")); ASSERT_TRUE(ACCEPTS(&dfa, "abaaba"));
ASSERT_TRUE(accepts(&dfa, "ba")); ASSERT_TRUE(ACCEPTS(&dfa, "ba"));
ASSERT_TRUE(accepts(&dfa, "babba")); ASSERT_TRUE(ACCEPTS(&dfa, "babba"));
ASSERT_TRUE(accepts(&dfa, "baaa")); ASSERT_TRUE(ACCEPTS(&dfa, "baaa"));
ASSERT_TRUE(accepts(&dfa, "baba")); ASSERT_TRUE(ACCEPTS(&dfa, "baba"));
ASSERT_TRUE(accepts(&dfa, "babaa")); ASSERT_TRUE(ACCEPTS(&dfa, "babaa"));
ASSERT_FALSE(accepts(&dfa, "")); ASSERT_FALSE(ACCEPTS(&dfa, ""));
ASSERT_FALSE(accepts(&dfa, "ab")); ASSERT_FALSE(ACCEPTS(&dfa, "ab"));
ASSERT_FALSE(accepts(&dfa, "aab")); ASSERT_FALSE(ACCEPTS(&dfa, "aab"));
ASSERT_FALSE(accepts(&dfa, "abbab")); ASSERT_FALSE(ACCEPTS(&dfa, "abbab"));
ASSERT_FALSE(accepts(&dfa, "b")); ASSERT_FALSE(ACCEPTS(&dfa, "b"));
ASSERT_FALSE(accepts(&dfa, "bb")); ASSERT_FALSE(ACCEPTS(&dfa, "bb"));
ASSERT_FALSE(accepts(&dfa, "baaabab")); ASSERT_FALSE(ACCEPTS(&dfa, "baaabab"));
ASSERT_FALSE(accepts(&dfa, "aabababab")); ASSERT_FALSE(ACCEPTS(&dfa, "aabababab"));
fsa_free(&nfa); fsa_free(&nfa);
fsa_free(&dfa); fsa_free(&dfa);