ajout de nos fichiers
This commit is contained in:
677
Anna et Vincent/nfa.c
Normal file
677
Anna et Vincent/nfa.c
Normal file
@@ -0,0 +1,677 @@
|
||||
/***************************/
|
||||
/* Implémentation des NFAs */
|
||||
/***************************/
|
||||
|
||||
#include "nfa.h"
|
||||
#include "error.h"
|
||||
#include "graphs.h"
|
||||
#include "type_dequeue.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(ptr) \
|
||||
if (ptr == NULL) { \
|
||||
ERROR("malloc failed"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
static char *uint_to_chars(const uint i) {
|
||||
char *str = malloc(12 * sizeof(char));
|
||||
// 12 car un uint peut avoir 10 chiffres + le '\0' (4 294 967 295) + jsp
|
||||
CHECK(str);
|
||||
sprintf(str, "%u", i);
|
||||
return str;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Affichage des noms si ce sont des pointeurs sur des entiers */
|
||||
/***************************************************************/
|
||||
|
||||
void nfa_print_letter(const nfa *thenfa, const uint num_letter, FILE *out) {
|
||||
printf("nfa_print_letter\n");
|
||||
fprintf(out, "%c", thenfa->alpha_names[num_letter]);
|
||||
}
|
||||
|
||||
char *nfa_copy_alpha(const nfa *thenfa) {
|
||||
printf("nfa_copy_alpha\n");
|
||||
char *copy = malloc((thenfa->trans->size_alpha) * sizeof(char));
|
||||
CHECK(copy);
|
||||
for (uint i = 0; i < thenfa->trans->size_alpha; i++) {
|
||||
copy[i] = thenfa->alpha_names[i];
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
void nfa_print_state(const nfa *thenfa, const uint numstate, FILE *out) {
|
||||
printf("nfa_print_state\n");
|
||||
if (thenfa->state_names == NULL) {
|
||||
fprintf(out, "%u", numstate);
|
||||
} else {
|
||||
fprintf(out, "%s", thenfa->state_names[numstate]);
|
||||
}
|
||||
}
|
||||
|
||||
void nfa_reset_state_names(nfa *thenfa) {
|
||||
printf("nfa_reset_state_names\n");
|
||||
if (thenfa->state_names != NULL) {
|
||||
for (uint i = 0; i < thenfa->trans->size_alpha; i++) {
|
||||
if (thenfa->state_names[i] != NULL) {
|
||||
free(thenfa->state_names[i]);
|
||||
}
|
||||
}
|
||||
free(thenfa->state_names);
|
||||
thenfa->state_names = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *nfa_copy_one_name(const nfa *thenfa, const uint thestate) {
|
||||
printf("nfa_copy_one_name\n");
|
||||
if (thenfa->state_names == NULL) {
|
||||
return uint_to_chars(thestate);
|
||||
}
|
||||
const size_t len = strlen(thenfa->state_names[thestate]) + 1;
|
||||
//+1 car strlen ne compte pas le '\0'
|
||||
char *copy = malloc(len * sizeof(char));
|
||||
CHECK(copy);
|
||||
strncpy(copy, thenfa->state_names[thestate], len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
char **nfa_copy_all_names(nfa *thenfa) {
|
||||
printf("nfa_copy_all_names\n");
|
||||
// Vérifier si le NFA utilise des noms pour les états
|
||||
if (thenfa->state_names == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allouer de la mémoire pour le tableau de noms
|
||||
char **copy_names = malloc(thenfa->trans->size_graph * sizeof(char *));
|
||||
CHECK(copy_names);
|
||||
|
||||
// Copier chaque nom d'état
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
copy_names[i] = nfa_copy_one_name(thenfa, i);
|
||||
}
|
||||
|
||||
return copy_names;
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/* Initialisation et suppression */
|
||||
/*********************************/
|
||||
|
||||
nfa *create_emptylang(void) {
|
||||
printf("create_emptylang\n");
|
||||
nfa *empty = malloc(sizeof(nfa));
|
||||
CHECK(empty);
|
||||
empty->trans = create_lgraph_noedges(0, 0);
|
||||
empty->initials = create_dequeue();
|
||||
empty->finals = create_dequeue();
|
||||
empty->alpha_names = malloc(sizeof(char));
|
||||
CHECK(empty->alpha_names);
|
||||
empty->alpha_names[0] = '\0';
|
||||
empty->state_names = NULL;
|
||||
return empty;
|
||||
}
|
||||
|
||||
nfa *create_sing_epsilon(void) {
|
||||
printf("create_sing_epsilon\n");
|
||||
nfa *epsilon = malloc(sizeof(nfa));
|
||||
CHECK(epsilon);
|
||||
epsilon->trans = create_lgraph_noedges(1, 0);
|
||||
epsilon->initials = create_dequeue();
|
||||
epsilon->finals = create_dequeue();
|
||||
lefins_dequeue(0, epsilon->initials);
|
||||
lefins_dequeue(0, epsilon->finals);
|
||||
epsilon->alpha_names = malloc(sizeof(char));
|
||||
CHECK(epsilon->alpha_names);
|
||||
epsilon->alpha_names[0] = '\0';
|
||||
epsilon->state_names = malloc(sizeof(char *));
|
||||
CHECK(epsilon->state_names);
|
||||
epsilon->state_names[0] = "ε";
|
||||
return epsilon;
|
||||
}
|
||||
|
||||
nfa *create_sing_letter(const char theletter) {
|
||||
printf("create_sing_letter\n");
|
||||
// Créer le graphe des transitions avec 2 états et 1 lettre dans l'alphabet
|
||||
lgraph *trans = create_lgraph_noedges(2, 1);
|
||||
|
||||
// Ajouter une transition de l'état 0 à l'état 1 avec la lettre theletter
|
||||
dequeue *transition = create_dequeue();
|
||||
rigins_dequeue(1, transition);
|
||||
trans->edges[0][0] = transition;
|
||||
|
||||
// Créer la liste des états initiaux (état 0)
|
||||
dequeue *initials = create_dequeue();
|
||||
rigins_dequeue(0, initials);
|
||||
|
||||
// Créer la liste des états finaux (état 1)
|
||||
dequeue *finals = create_dequeue();
|
||||
rigins_dequeue(1, finals);
|
||||
|
||||
// Allouer de la mémoire pour le nom de la lettre
|
||||
char *alpha_names = malloc(sizeof(char));
|
||||
CHECK(alpha_names);
|
||||
alpha_names[0] = theletter;
|
||||
|
||||
// Créer le NFA
|
||||
nfa *thenfa = malloc(sizeof(nfa));
|
||||
thenfa->trans = trans;
|
||||
thenfa->initials = initials;
|
||||
thenfa->finals = finals;
|
||||
thenfa->alpha_names = alpha_names;
|
||||
thenfa->state_names = NULL; // Pas de noms d'états
|
||||
return thenfa;
|
||||
}
|
||||
|
||||
void nfa_delete(nfa *thenfa) {
|
||||
printf("nfa_delete\n");
|
||||
// ne free pas le pointeur !
|
||||
nfa_reset_state_names(thenfa);
|
||||
delete_lgraph(thenfa->trans);
|
||||
delete_dequeue(thenfa->initials);
|
||||
delete_dequeue(thenfa->finals);
|
||||
free(thenfa->alpha_names);
|
||||
}
|
||||
|
||||
void nfa_overwrite(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_overwrite\n");
|
||||
nfa_delete(nfa1);
|
||||
*nfa1 = *nfa2;
|
||||
free(nfa2);
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
/* Opérations simples sur les NFAs */
|
||||
/***********************************/
|
||||
|
||||
nfa *nfa_copy(nfa *thenfa) {
|
||||
printf("nfa_copy\n");
|
||||
nfa *copy = malloc(sizeof(nfa));
|
||||
CHECK(copy);
|
||||
copy->initials = create_dequeue();
|
||||
copy->finals = create_dequeue();
|
||||
copy_dequeue_right(copy->initials, thenfa->initials, 0);
|
||||
copy_dequeue_right(copy->finals, thenfa->finals, 0);
|
||||
copy->alpha_names = nfa_copy_alpha(thenfa);
|
||||
copy->state_names = nfa_copy_all_names(thenfa);
|
||||
copy->trans = create_lgraph_noedges(thenfa->trans->size_graph,
|
||||
thenfa->trans->size_alpha);
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
for (uint j = 0; j < thenfa->trans->size_alpha; j++) {
|
||||
dequeue *edges = create_dequeue();
|
||||
copy_dequeue_right(edges, thenfa->trans->edges[i][j], 0);
|
||||
copy->trans->edges[i][j] = edges;
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
nfa *nfa_copy_exalpha(nfa *thenfa, const char *letters, const uchar tabsize) {
|
||||
nfa *copy = nfa_copy(thenfa);
|
||||
CHECK(copy);
|
||||
char *alpha = malloc(sizeof(char) * (copy->trans->size_alpha + tabsize));
|
||||
CHECK(alpha);
|
||||
for (uint l = 0; l < copy->trans->size_alpha; l++) {
|
||||
alpha[l] = copy->alpha_names[l];
|
||||
}
|
||||
for (uint l = 0; l < tabsize; l++) {
|
||||
alpha[l + copy->trans->size_alpha] = letters[l];
|
||||
}
|
||||
free(copy->alpha_names);
|
||||
copy->alpha_names = alpha;
|
||||
return copy;
|
||||
}
|
||||
|
||||
// Union disjointe de deux nfas
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
nfa *nfa_union(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_union\n");
|
||||
// nfa1 U nfa2 = nfa1 + nfa2 - (nfa1 ∩ nfa2)
|
||||
nfa *nfa_uni =
|
||||
nfa_copy_exalpha(nfa1, nfa2->alpha_names, nfa2->trans->size_alpha);
|
||||
|
||||
// On remplace les noms d'états
|
||||
nfa_reset_state_names(nfa_uni);
|
||||
|
||||
// On unie les états initiaux
|
||||
copy_dequeue_right(nfa_uni->initials, nfa2->initials,
|
||||
nfa1->trans->size_graph);
|
||||
|
||||
// On unie les états finaux
|
||||
copy_dequeue_right(nfa_uni->finals, nfa2->finals, nfa1->trans->size_graph);
|
||||
|
||||
// on crée le graphe
|
||||
lgraph *g =
|
||||
create_lgraph_noedges(nfa1->trans->size_graph + nfa2->trans->size_graph,
|
||||
nfa1->trans->size_alpha + nfa2->trans->size_alpha);
|
||||
|
||||
// on récupère le premier graphe
|
||||
for (uint sommet = 0; sommet < nfa1->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa1->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet][lettre],
|
||||
nfa1->trans->edges[sommet][lettre], 0);
|
||||
}
|
||||
}
|
||||
// on récupère le second graphe
|
||||
const uint d1 = nfa1->trans->size_graph;
|
||||
const uint d2 = nfa1->trans->size_alpha;
|
||||
for (uint sommet = 0; sommet < nfa2->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet + d1][lettre + d2],
|
||||
nfa2->trans->edges[sommet][lettre], d1);
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(nfa_uni->trans);
|
||||
nfa_uni->trans = g;
|
||||
return nfa_uni;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
nfa *nfa_concat(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_concat\n");
|
||||
// nfa1 . nfa2 <=> ε -> nfa1 -> nfa2 -> ε
|
||||
nfa *nfa_concaten =
|
||||
nfa_copy_exalpha(nfa1, nfa2->alpha_names, nfa2->trans->size_alpha);
|
||||
|
||||
// On remplace les noms d'états
|
||||
nfa_reset_state_names(nfa_concaten);
|
||||
|
||||
// on corrige les états finaux
|
||||
delete_dequeue(nfa_concaten->finals);
|
||||
nfa_concaten->finals = create_dequeue();
|
||||
copy_dequeue_right(nfa_concaten->finals, nfa2->finals,
|
||||
nfa1->trans->size_alpha);
|
||||
|
||||
// on crée le graphe
|
||||
const uint cumul = size_dequeue(nfa2->initials);
|
||||
lgraph *g = create_lgraph_noedges(
|
||||
nfa1->trans->size_graph + nfa2->trans->size_graph - cumul,
|
||||
nfa1->trans->size_alpha + nfa2->trans->size_alpha);
|
||||
|
||||
// on récupère le premier graphe
|
||||
for (uint sommet = 0; sommet < nfa1->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa1->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet][lettre],
|
||||
nfa1->trans->edges[sommet][lettre], 0);
|
||||
}
|
||||
}
|
||||
// on récupère le second graphe
|
||||
uint d1 = nfa1->trans->size_alpha;
|
||||
uint d2 = nfa1->trans->size_graph;
|
||||
for (uint sommet = 0; sommet < nfa2->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet + d2 - cumul][lettre + d1],
|
||||
nfa2->trans->edges[sommet][lettre], d2 - cumul);
|
||||
}
|
||||
}
|
||||
|
||||
// on recupère les arrêtes de transition entre les deux graphes
|
||||
uint size = size_dequeue(nfa2->initials);
|
||||
uint size2 = size_dequeue(nfa1->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint depart = lefread_dequeue(nfa2->initials, i);
|
||||
for (uint j = 0; i < size2; i++) {
|
||||
const uint arrivee = lefread_dequeue(nfa1->finals, j);
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[arrivee][lettre + nfa1->trans->size_alpha],
|
||||
nfa2->trans->edges[depart][lettre],
|
||||
nfa1->trans->size_alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(nfa_concaten->trans);
|
||||
nfa_concaten->trans = g;
|
||||
return nfa_concaten;
|
||||
}
|
||||
|
||||
// Étoile de Kleene d'un NFA
|
||||
nfa *nfa_star(nfa *thenfa) {
|
||||
printf("nfa_star\n");
|
||||
// final pointe chaque initial et on rajoute un epsilon
|
||||
// ajoute les epsilon
|
||||
nfa *kleene = nfa_copy(thenfa);
|
||||
bool eps = false;
|
||||
|
||||
// reconstitution du graphes avec un Epsilon
|
||||
lgraph *g = create_lgraph_noedges(kleene->trans->size_graph + 1,
|
||||
kleene->trans->size_alpha);
|
||||
for (uint sommet = 0; sommet < kleene->trans->size_graph; sommet++) {
|
||||
if (mem_dequeue(sommet, kleene->finals) &&
|
||||
mem_dequeue(sommet, kleene->initials)) { // ε
|
||||
eps = true;
|
||||
continue;
|
||||
}
|
||||
// on récupère nos arrêtes
|
||||
for (uint lettre = 0; lettre < kleene->trans->size_alpha; lettre++) {
|
||||
dequeue *edges = kleene->trans->edges[sommet][lettre];
|
||||
copy_dequeue_right(g->edges[sommet][lettre], edges, 0);
|
||||
// on ajoute les états initiaux à tout ce qui pointes sur un état
|
||||
// final
|
||||
uint size = size_dequeue(kleene->finals);
|
||||
for (uint s = 0; s < size; s++) {
|
||||
const uint sortie = lefread_dequeue(kleene->finals, s);
|
||||
// si on a une transition vers un état final, on ajoute les états
|
||||
// initiaux aux transitions
|
||||
if (mem_dequeue_sorted(sortie, edges)) {
|
||||
uint size2 = size_dequeue(kleene->initials);
|
||||
for (uint e = 0; e < size2; e++) {
|
||||
const uint entree = lefread_dequeue(kleene->initials, e);
|
||||
lefins_dequeue(entree, g->edges[sommet][lettre]);
|
||||
}
|
||||
sort_dequeue_norepeat(g->edges[sommet][lettre]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!eps) {
|
||||
insert_dequeue(kleene->initials, kleene->trans->size_graph);
|
||||
insert_dequeue(kleene->finals, kleene->trans->size_graph);
|
||||
} else {
|
||||
// on supprime l'état réservé pour l'epsilon
|
||||
g->size_graph--;
|
||||
for (uint lettre = 0; lettre < g->size_alpha; lettre++) {
|
||||
free(g->edges[g->size_graph][lettre]);
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(kleene->trans);
|
||||
kleene->trans = g;
|
||||
return kleene;
|
||||
}
|
||||
|
||||
// note les états accessibles depuis l'état donné
|
||||
// note les états depuis lesquels on peut atteindre un état final à partir
|
||||
// de l'état donné
|
||||
static bool trimer(nfa *thenfa, bool *reachable,
|
||||
bool *may_exit, // NOLINT(*-no-recursion)
|
||||
const uint sommet) {
|
||||
printf("trimer\n");
|
||||
if (reachable[sommet]) {
|
||||
// on a déjà visité cet état
|
||||
return may_exit[sommet];
|
||||
}
|
||||
reachable[sommet] = true;
|
||||
const lgraph *g = thenfa->trans;
|
||||
for (uint i = 0; i < g->size_alpha; i++) {
|
||||
dequeue *edges = g->edges[sommet][i];
|
||||
const uint size = size_dequeue(edges);
|
||||
for (uint j = 0; j < size; j++) {
|
||||
const uint etat = lefread_dequeue(edges, j);
|
||||
if (trimer(thenfa, reachable, may_exit, etat)) {
|
||||
may_exit[sommet] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mem_dequeue_sorted(sommet, thenfa->finals);
|
||||
}
|
||||
|
||||
// Élimination des états non-accessibles et non-co-accessibles
|
||||
// Le NFA produit n'est pas nécessairement complet
|
||||
nfa *nfa_trim(nfa *thenfa) {
|
||||
printf("nfa_trim\n");
|
||||
nfa *trimmed = nfa_copy(thenfa);
|
||||
bool reachable[trimmed->trans->size_graph];
|
||||
bool may_end[trimmed->trans->size_graph];
|
||||
for (uint i = 0; i < trimmed->trans->size_graph; i++) {
|
||||
reachable[i] = false;
|
||||
may_end[i] = false;
|
||||
}
|
||||
// on marque les états accessibles
|
||||
uint size = size_dequeue(trimmed->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(trimmed->initials, i);
|
||||
trimer(trimmed, reachable, may_end, etat);
|
||||
}
|
||||
// on compte les états accessibles
|
||||
int c = 0;
|
||||
for (uint i = 0; i < trimmed->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
// on crée un nouveau graphe
|
||||
lgraph *new_graph = create_lgraph_noedges(c, trimmed->trans->size_alpha);
|
||||
for (uint i = 0; i < new_graph->size_graph; i++) {
|
||||
for (uint j = 0; j < new_graph->size_alpha; j++) {
|
||||
// on récupère les arêtes accessibles
|
||||
dequeue *edges = new_graph->edges[i][j];
|
||||
dequeue *old_edges = trimmed->trans->edges[i][j];
|
||||
size = size_dequeue(old_edges);
|
||||
for (uint k = 0; k < size; k++) {
|
||||
const uint etat = lefread_dequeue(old_edges, k);
|
||||
if (reachable[etat] && may_end[etat]) {
|
||||
lefins_dequeue(etat, edges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// on remplace le graphe
|
||||
delete_lgraph(trimmed->trans);
|
||||
trimmed->trans = new_graph;
|
||||
|
||||
// on supprime les états finaux non accessibles
|
||||
size = size_dequeue(trimmed->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(trimmed->finals);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, trimmed->finals);
|
||||
}
|
||||
}
|
||||
// on supprime les états initiaux non accessibles
|
||||
size = size_dequeue(trimmed->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(trimmed->initials);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, trimmed->initials);
|
||||
}
|
||||
}
|
||||
|
||||
// on supprime les états non accessibles
|
||||
char **new_state_names = malloc(sizeof(char *) * c);
|
||||
CHECK(new_state_names);
|
||||
c = 0;
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
new_state_names[c] = nfa_copy_one_name(thenfa, i);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
free(trimmed->state_names);
|
||||
trimmed->state_names = new_state_names;
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
// Élimination des états non-accessibles (modifie le NFA originel)
|
||||
void nfa_trim_mod(nfa *thenfa) {
|
||||
printf("nfa_trim_mod\n");
|
||||
bool reachable[thenfa->trans->size_graph];
|
||||
bool may_end[thenfa->trans->size_graph];
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
reachable[i] = false;
|
||||
may_end[i] = false;
|
||||
}
|
||||
// on marque les états accessibles
|
||||
uint size = size_dequeue(thenfa->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(thenfa->initials, i);
|
||||
trimer(thenfa, reachable, may_end, etat);
|
||||
}
|
||||
// on compte les états accessibles
|
||||
int c = 0;
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
// on crée un nouveau graphe
|
||||
lgraph *new_graph = create_lgraph_noedges(c, thenfa->trans->size_alpha);
|
||||
for (uint i = 0; i < new_graph->size_graph; i++) {
|
||||
for (uint j = 0; j < new_graph->size_alpha; j++) {
|
||||
// on récupère les arêtes accessibles
|
||||
dequeue *edges = new_graph->edges[i][j];
|
||||
dequeue *old_edges = thenfa->trans->edges[i][j];
|
||||
size = size_dequeue(old_edges);
|
||||
for (uint k = 0; k < size; k++) {
|
||||
const uint etat = lefread_dequeue(old_edges, k);
|
||||
if (reachable[etat] && may_end[etat]) {
|
||||
lefins_dequeue(etat, edges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// on remplace le graphe
|
||||
const uint saved_size = thenfa->trans->size_graph; // utile pour plus tard
|
||||
delete_lgraph(thenfa->trans);
|
||||
thenfa->trans = new_graph;
|
||||
|
||||
// on supprime les états finaux non accessibles
|
||||
size = size_dequeue(thenfa->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(thenfa->finals);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, thenfa->finals);
|
||||
}
|
||||
}
|
||||
// on supprime les états initiaux non accessibles
|
||||
size = size_dequeue(thenfa->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(thenfa->initials);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, thenfa->initials);
|
||||
}
|
||||
}
|
||||
|
||||
// on supprime les états non accessibles
|
||||
char **new_state_names = malloc(sizeof(char *) * c);
|
||||
CHECK(new_state_names);
|
||||
c = 0;
|
||||
for (uint i = 0; i < saved_size; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
new_state_names[c] = nfa_copy_one_name(thenfa, i);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
free(thenfa->state_names);
|
||||
thenfa->state_names = new_state_names;
|
||||
}
|
||||
|
||||
// Miroir
|
||||
nfa *nfa_mirror(nfa *thenfa) {
|
||||
printf("nfa_mirror\n");
|
||||
nfa *mirror = malloc(sizeof(nfa));
|
||||
CHECK(mirror);
|
||||
// on inverse les états initiaux et finaux
|
||||
mirror->initials = create_dequeue();
|
||||
copy_dequeue_right(mirror->initials, thenfa->finals, 0);
|
||||
mirror->finals = create_dequeue();
|
||||
copy_dequeue_right(mirror->finals, thenfa->initials, 0);
|
||||
// on copie les alphabets
|
||||
mirror->alpha_names = nfa_copy_alpha(thenfa);
|
||||
// on copie les noms d'états
|
||||
mirror->state_names = nfa_copy_all_names(thenfa);
|
||||
// on prépare le graphe
|
||||
lgraph *g = create_lgraph_noedges(thenfa->trans->size_graph,
|
||||
thenfa->trans->size_alpha);
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
dequeue *edge = thenfa->trans->edges[sommet][lettre];
|
||||
const uint size = size_dequeue(edge);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(edge, i);
|
||||
lefins_dequeue(sommet, g->edges[etat][lettre]);
|
||||
}
|
||||
}
|
||||
}
|
||||
mirror->trans = g;
|
||||
return mirror;
|
||||
}
|
||||
|
||||
/************************/
|
||||
/* Informations sur NFA */
|
||||
/************************/
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
int nfa_nb_trans(nfa *thenfa) {
|
||||
printf("nf_nb_trans\n");
|
||||
int nb_trans = 0;
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
nb_trans += (int)size_dequeue(thenfa->trans->edges[sommet][lettre]);
|
||||
}
|
||||
}
|
||||
return nb_trans;
|
||||
}
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
bool nfa_is_det(nfa *thenfa) {
|
||||
printf("nfa_is_det\n");
|
||||
printf("'ça va pas marcher mais chhhh...\n");
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
if (size_dequeue(thenfa->trans->edges[sommet][lettre]) > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nfa_is_comp(nfa *thenfa) {
|
||||
printf("nfa_is_comp\n");
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
if (size_dequeue(thenfa->trans->edges[sommet][lettre]) < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
bool nfa_is_empty(nfa *thenfa) {
|
||||
printf("nfa_is_empty\n");
|
||||
return thenfa->trans->size_alpha == 0 && thenfa->trans->size_graph == 0;
|
||||
}
|
||||
|
||||
bool nfa_accepts(nfa *thenfa, const char *theword) {
|
||||
printf("nfa_accepts\n");
|
||||
dequeue *runs = nfa_compute_runs(thenfa, theword);
|
||||
const uint size = size_dequeue(runs);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(runs, i);
|
||||
if (mem_dequeue_sorted(etat, thenfa->finals)) {
|
||||
delete_dequeue(runs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete_dequeue(runs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calcule les états qui sont atteints par un mot dans un NFA.
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
dequeue *nfa_compute_runs(nfa *thenfa, const char *theword) {
|
||||
printf("nfa_compute_runs\n");
|
||||
dequeue *runs = create_dequeue();
|
||||
uint indice = 0;
|
||||
uint size = size_dequeue(thenfa->initials);
|
||||
while (indice < strlen(theword)) {
|
||||
dequeue *new_runs = create_dequeue();
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(thenfa->initials, i);
|
||||
const uint lettre = (uint)theword[indice];
|
||||
merge_sorted_dequeue(new_runs, thenfa->trans->edges[etat][lettre]);
|
||||
}
|
||||
delete_dequeue(runs);
|
||||
runs = new_runs;
|
||||
size = size_dequeue(runs);
|
||||
indice++;
|
||||
}
|
||||
return runs;
|
||||
}
|
||||
Reference in New Issue
Block a user