Compare commits

..

6 Commits

Author SHA1 Message Date
48c3648813 Téléverser les fichiers vers "Anna et Ethan" 2024-12-16 08:31:15 +00:00
Aloyse ARNAUD
1bd783c958 changement dossier 2024-12-16 02:49:02 +01:00
Aloyse ARNAUD
b06c2fcc82 changement dossier 2024-12-16 02:48:28 +01:00
Aloyse ARNAUD
6606b1f872 ajout de nos fichiers 2024-12-16 02:40:29 +01:00
a913fd240b regexp 2024-12-16 01:09:03 +00:00
ecdf33a2a5 shell_test.c type_dequeue.c
Mise à jour des tests et de dequeue
2024-12-15 20:29:35 +01:00
32 changed files with 13464 additions and 38 deletions

64
Aloyse et Vincent/a.c Normal file
View File

@@ -0,0 +1,64 @@
// Généré automatiquement à partir d'un automate reconnaissant le langage a.
// Ensemble des états : {0, 1, 2}
// État initiaux : {0}
// États finaux : {1}
// Transitions :
// 0 -a-> 1
// 1 -a-> 2
// 2 -a-> 2
#include <stdio.h>
#include <stdbool.h>
int main(void){
int c, numline = 0;
char *line = NULL;
size_t linecap = 0;
ssize_t linelen;
while ((linelen = getline(&line, &linecap, stdin)) > 0){
int state;
numline++;
state = 0;
for (int k = 0; k < linelen; k++){
c = line[k];
switch (state){
case 0:
switch (c){
case ('a'):
state = 1;
break;
default:
state = 0;
break;
}
break;
case 1:
switch (c){
case ('a'):
state = 2;
break;
default:
state = 0;
break;
}
break;
case 2:
switch (c){
case ('a'):
state = 2;
break;
default:
state = 0;
break;
}
break;
}
if (false || state == 1 || state == 2){
fprintf(stdout, "%4d: ", numline);
fwrite(line, linelen, 1, stdout);
fflush(stdout);
break;
}
}
}
}

29
Aloyse et Vincent/alloc.c Normal file
View File

@@ -0,0 +1,29 @@
/**
* @file alloc.c
* @brief Fonctions d'allocation mémoire.
*/
#include "alloc.h"
void multiple_free(void *p, ...) {
va_list ap;
va_start(ap, p);
while (p != NULL) {
free(p);
p = va_arg(ap, void *);
}
va_end(ap);
}
void check_null(const char *function, char *file, int line, int n, ...) {
va_list ap;
char *s;
va_start(ap, n);
for (int i = 0; i < n; i++) {
void *p = va_arg(ap, void *);
s = va_arg(ap, char *);
if (p == NULL)
PRINT_ERROR(KO, "CRITICAL", function, file, line, "%s is NULL.", s);
}
}

View File

@@ -0,0 +1,7 @@
div.image img[src="en_cours.png"]{
width:350px;
}
div.image img[src="moves.png"]{
width:850px;
}

550
Aloyse et Vincent/files.c Normal file
View File

@@ -0,0 +1,550 @@
/***********************/
/* Gestion de fichiers */
/***********************/
#include "files.h"
static void reg_to_string_aux(regexp *r, char *buffer) {
TRACE("reg_to_string_aux");
if (r == NULL) {
return;
}
switch (r->op) {
case CHAR: {
char mess[2];
mess[0] = r->letter;
mess[1] = '\0';
strcat(buffer, mess);
} break;
case EMPTY:
strcat(buffer, "0");
break;
case EPSILON:
strcat(buffer, "1");
break;
case UNION:
strcat(buffer, "(");
reg_to_string_aux(r->left, buffer);
strcat(buffer, " + ");
reg_to_string_aux(r->right, buffer);
strcat(buffer, ")");
break;
case INTER:
strcat(buffer, "(");
reg_to_string_aux(r->left, buffer);
strcat(buffer, " & ");
reg_to_string_aux(r->right, buffer);
strcat(buffer, ")");
break;
case CONCAT:
strcat(buffer, "(");
reg_to_string_aux(r->left, buffer);
strcat(buffer, " ");
reg_to_string_aux(r->right, buffer);
strcat(buffer, ")");
break;
case STAR:
strcat(buffer, "(");
reg_to_string_aux(r->left, buffer);
strcat(buffer, ")*");
break;
case COMPLEMENT:
strcat(buffer, "!(");
reg_to_string_aux(r->left, buffer);
strcat(buffer, ")");
break;
default:
CRITICAL("Unknown regexp operator (%d)", r->op);
break;
}
}
void reg_to_string(regexp *r, char *buffer) {
TRACE("reg_to_string");
if (!r) {
return;
}
reg_to_string_aux(r, buffer);
}
unsigned short autocount = 0;
/***********************************************/
/* Manipulation de structures JSON - Automates */
/***********************************************/
json_object *files_auto_to_json(automata *theauto) {
// Création de l'objet json
json_object *root = json_object_new_object();
if (!root) {
fprintf(stderr, "Failed to create the JSON object.\n");
return NULL;
}
json_object_object_add(root, "TYPE", json_object_new_string("AUTO"));
nfa *A = theauto->nfa;
// Taille de l'alphabet
json_object_object_add(root, "N_ALPH",
json_object_new_int(A->trans->size_alpha));
// Taille de l'automate (nombre d'états)
json_object_object_add(root, "N_SIZE",
json_object_new_int(A->trans->size_graph));
// Alphabet
char *alphabet;
MALLOC(alphabet, A->trans->size_alpha + 1);
for (uint i = 0; i < A->trans->size_alpha; i++) {
alphabet[i] = A->alpha_names[i];
}
alphabet[A->trans->size_alpha] = '\0';
json_object_object_add(root, "L_ALPH", json_object_new_string(alphabet));
free(alphabet);
// Liste des transitions (on commence par compter le nombre de transitions)
uint num_trans = 0;
for (uint q = 0; q < A->trans->size_graph; q++) {
for (uint a = 0; a < A->trans->size_alpha; a++) {
num_trans = num_trans + size_dequeue(A->trans->edges[q][a]);
}
}
json_object *trans = json_object_new_array_ext(num_trans);
for (uint q = 0; q < A->trans->size_graph; q++) {
for (uint a = 0; a < A->trans->size_alpha; a++) {
for (uint i = 0; i < size_dequeue(A->trans->edges[q][a]); i++) {
json_object *onetrans = json_object_new_array_ext(3);
json_object_array_add(onetrans, json_object_new_int(q));
json_object_array_add(onetrans, json_object_new_int(a));
json_object_array_add(onetrans, json_object_new_int(lefread_dequeue(
A->trans->edges[q][a], i)));
json_object_array_add(trans, onetrans);
}
}
}
json_object_object_add(root, "L_TRAN", trans);
// Liste des états initiaux
json_object *initials = json_object_new_array_ext(size_dequeue(A->initials));
for (uint i = 0; i < size_dequeue(A->initials); i++) {
json_object_array_add(initials,
json_object_new_int(lefread_dequeue(A->initials, i)));
}
json_object_object_add(root, "L_INIT", initials);
// Liste des états finaux
json_object *finals = json_object_new_array_ext(size_dequeue(A->finals));
for (uint i = 0; i < size_dequeue(A->finals); i++) {
json_object_array_add(finals,
json_object_new_int(lefread_dequeue(A->finals, i)));
}
json_object_object_add(root, "L_FINA", finals);
return root;
}
json_object *files_lang_to_json(language *thelang) {
json_object *root = json_object_new_object();
if (!root) {
fprintf(stderr, "Failed to create the JSON object.\n");
return NULL;
}
json_object_object_add(root, "TYPE", json_object_new_string("LANG"));
if (thelang->type == SPE_REG) {
json_object_object_add(root, "SPEC", json_object_new_string("REXP"));
char *newexp;
MALLOC(newexp, EXPSIZE);
newexp[0] = 0;
reg_to_string(thelang->reg, newexp);
json_object_object_add(root, "REXP", json_object_new_string(newexp));
free(newexp);
}
if (thelang->type == SPE_NFA) {
json_object_object_add(root, "SPEC", json_object_new_string("AUTO"));
json_object_object_add(root, "AUTO",
files_auto_to_json(objects[thelang->nfa]->aut));
}
return root;
}
nfa *files_json_to_nfa(json_object *root) {
// Récupération de la taille de l'automate
json_object *jsize_graph;
if (!json_object_object_get_ex(root, "N_SIZE", &jsize_graph) ||
json_object_get_type(jsize_graph) != json_type_int) {
fprintf(stderr, "Error: cannot read the size of the automaton.\n");
return NULL;
}
uint size_graph = json_object_get_int(jsize_graph);
// Récupération de la taille de l'alphabet
json_object *jsize_alpha;
if (!json_object_object_get_ex(root, "N_ALPH", &jsize_alpha) ||
json_object_get_type(jsize_alpha) != json_type_int) {
fprintf(stderr, "Error: cannot read the size of the alphabet.\n");
return NULL;
}
uint size_alpha = json_object_get_int(jsize_alpha);
// Création du NFA
nfa *A;
MALLOC(A, 1);
MALLOC(A->alpha_names, size_alpha);
A->trans = create_lgraph_noedges(size_graph, size_alpha);
if (A->trans == NULL) {
fprintf(stderr, "Error: cannot create the transitions\nPlease implement "
"the function create_lgraph_noedges\n");
free(A->alpha_names);
free(A);
return NULL;
}
A->initials = create_dequeue();
if (A->initials == NULL) {
fprintf(stderr, "Error: cannot create the initials\nPlease implement the "
"function create_dequeue\n");
free(A->alpha_names);
free(A);
return NULL;
}
A->finals = create_dequeue();
A->state_names = NULL;
// Récupération de l'alphabet
json_object *jalph;
if (!json_object_object_get_ex(root, "L_ALPH", &jalph) ||
json_object_get_type(jalph) != json_type_string) {
fprintf(stderr, "Error: cannot read the alphabet.\n");
nfa_delete(A);
return NULL;
}
const char *alphabet = json_object_get_string(jalph);
for (uint i = 0; i < size_alpha; i++) {
A->alpha_names[i] = alphabet[i];
}
// Récupération du graphe des transitions
json_object *jtrans;
if (!json_object_object_get_ex(root, "L_TRAN", &jtrans) ||
json_object_get_type(jtrans) != json_type_array) {
fprintf(stderr, "Error: cannot read the list of transitions.\n");
nfa_delete(A);
return NULL;
}
uint len = json_object_array_length(jtrans);
for (uint i = 0; i < len; i++) {
json_object *onetrans = json_object_array_get_idx(jtrans, i);
if (json_object_get_type(onetrans) != json_type_array ||
json_object_array_length(onetrans) != 3) {
fprintf(stderr, "Error: cannot read the list of transitions.\n");
nfa_delete(A);
return NULL;
}
json_object *jq = json_object_array_get_idx(onetrans, 0);
json_object *ja = json_object_array_get_idx(onetrans, 1);
json_object *jr = json_object_array_get_idx(onetrans, 2);
if (json_object_get_type(jq) != json_type_int ||
json_object_get_type(jr) != json_type_int) {
fprintf(stderr, "Error: cannot read the list of transitions.\n");
nfa_delete(A);
return NULL;
}
uint q = json_object_get_int(jq);
uint r = json_object_get_int(jr);
uint a;
if (json_object_get_type(ja) == json_type_int) {
a = json_object_get_int(ja);
} else if (json_object_get_type(ja) == json_type_string &&
json_object_get_string_len(ja) == 1) {
const char *sa = json_object_get_string(ja);
a = sa[0];
int id = -1;
for (uint j = 0; j < size_alpha; j++) {
if (a == (uint)A->alpha_names[j]) {
id = j;
}
}
if (id >= 0) {
a = (uint)id;
} else {
fprintf(stderr, "Error: incorrect letter used in the transitions.\n");
nfa_delete(A);
return NULL;
}
} else {
fprintf(stderr, "Error: cannot read the list of transitions.\n");
nfa_delete(A);
return NULL;
}
if (q < size_graph && r < size_graph && a < size_alpha) {
rigins_dequeue(r, A->trans->edges[q][a]);
} else {
fprintf(stderr,
"Error: incorrect letter or state used in the transitions.\n");
nfa_delete(A);
return NULL;
}
}
for (uint q = 0; q < size_graph; q++) {
for (uint a = 0; a < size_alpha; a++) {
sort_dequeue_norepeat(A->trans->edges[q][a]);
}
}
// Récupération de la liste des états initiaux
A->initials = create_dequeue();
json_object *jini;
if (!json_object_object_get_ex(root, "L_INIT", &jini) ||
json_object_get_type(jini) != json_type_array) {
fprintf(stderr, "Error: cannot read the list of initial states.\n");
nfa_delete(A);
return NULL;
}
len = json_object_array_length(jini);
for (uint i = 0; i < len; i++) {
json_object *jq = json_object_array_get_idx(jini, i);
if (json_object_get_type(jq) != json_type_int) {
fprintf(stderr, "Error: cannot read the list of final states.\n");
nfa_delete(A);
return NULL;
}
uint q = json_object_get_int(jq);
if (q < size_graph) {
rigins_dequeue(q, A->initials);
} else {
fprintf(stderr,
"Error: incorrect state in the list of initial states.\n");
nfa_delete(A);
return NULL;
}
}
sort_dequeue_norepeat(A->initials);
// Récupération de la liste des états finaux
A->finals = create_dequeue();
json_object *jfin;
if (!json_object_object_get_ex(root, "L_FINA", &jfin) ||
json_object_get_type(jfin) != json_type_array) {
fprintf(stderr, "Error: cannot read the list of final states.\n");
nfa_delete(A);
return NULL;
}
len = json_object_array_length(jfin);
for (uint i = 0; i < len; i++) {
json_object *jq = json_object_array_get_idx(jfin, i);
if (json_object_get_type(jq) != json_type_int) {
fprintf(stderr, "Error: cannot read the list of final states.\n");
nfa_delete(A);
return NULL;
}
uint q = json_object_get_int(jq);
if (q < size_graph) {
rigins_dequeue(q, A->finals);
} else {
fprintf(stderr, "Error: incorrect state in the list of final states.\n");
nfa_delete(A);
return NULL;
}
}
sort_dequeue_norepeat(A->finals);
return A;
}
/************************************/
/* Lecture/écriture dans un fichier */
/************************************/
void files_save_object(object *theobj, char *filename) {
json_object *root = NULL;
switch (theobj->type) {
case LANGUAGE:
root = files_lang_to_json(theobj->lan);
break;
case AUTOMATON:
root = files_auto_to_json(theobj->aut);
break;
default:
return;
break;
}
// Sauvegarde
if (json_object_to_file(filename, root)) {
fprintf(stderr, "Error: failed to save %s.\n", filename);
} else {
printf("%s saved.\n", filename);
}
// Libération du JSON
json_object_put(root);
}
static void files_read_object_aux(json_object *root, char *varname) {
json_object *obj_type;
if (!json_object_object_get_ex(root, "TYPE", &obj_type) ||
json_object_get_type(obj_type) != json_type_string) {
fprintf(stderr, "Error: cannot read the type of the object.\n");
return;
}
const char *thetype = json_object_get_string(obj_type);
if (strcmp(thetype, "AUTO") == 0) {
fprintf(stdout, "Reading an automaton.\n");
nfa *A = files_json_to_nfa(root);
object_add_automata(varname, A);
return;
}
if (strcmp(thetype, "LANG") == 0) {
fprintf(stdout, "Reading a language.\n");
json_object *lang_spe;
if (!json_object_object_get_ex(root, "SPEC", &lang_spe) ||
json_object_get_type(lang_spe) != json_type_string) {
fprintf(stderr,
"Error: cannot read the specification type of the language.\n");
return;
}
const char *thespec = json_object_get_string(lang_spe);
if (strcmp(thespec, "REXP") == 0) {
json_object *theregexp;
if (!json_object_object_get_ex(root, "REXP", &theregexp) ||
json_object_get_type(theregexp) != json_type_string) {
fprintf(stderr, "Error: cannot read the regular expression specifying "
"the language.\n");
return;
}
const char *exp = json_object_get_string(theregexp);
regexp *myexp = parse_string_regexp(exp);
if (myexp == NULL) {
return;
}
reg_print(myexp);
object_add_language_reg(varname, myexp);
}
if (strcmp(thespec, "AUTO") == 0) {
json_object *theauto;
if (!json_object_object_get_ex(root, "AUTO", &theauto) ||
json_object_get_type(theauto) != json_type_object) {
fprintf(stderr,
"Error: cannot read the automaton specifying the language.\n");
return;
}
nfa *A = files_json_to_nfa(theauto);
char *newname;
MALLOC(newname, 20);
sprintf(newname, "SYSAUTO%04d", autocount++);
int j = object_add_automata(newname, A);
object_add_language_nfa(varname, j);
return;
}
return;
}
}
void files_read_object(char *filename, char *varname) {
json_object *root = json_object_from_file(filename);
if (!root) {
fprintf(stderr, "Failed to read the file.\n");
return;
}
files_read_object_aux(root, varname);
json_object_put(root);
return;
}
void files_save_session(char *filename) {
// Création de l'objet json
json_object *root = json_object_new_object();
if (!root) {
fprintf(stderr, "Failed to create the JSON object.\n");
return;
}
json_object_object_add(root, "TYPE", json_object_new_string("SESSION"));
uint size = 0;
for (int i = 0; i < nb_objects; i++) {
{
if (objects[i]->parent == -1) {
size++;
}
}
}
json_object *thetable = json_object_new_array_ext(size);
for (int i = 0; i < nb_objects; i++) {
if (objects[i]->parent == -1) {
json_object *oneobj = json_object_new_array_ext(2);
json_object_array_add(oneobj, json_object_new_string(objects[i]->name));
if (objects[i]->type == LANGUAGE) {
json_object_array_add(oneobj, files_lang_to_json(objects[i]->lan));
}
if (objects[i]->type == AUTOMATON) {
json_object_array_add(oneobj, files_auto_to_json(objects[i]->aut));
}
json_object_array_add(thetable, oneobj);
}
}
json_object_object_add(root, "OBJS", thetable);
// Sauvegarde
if (json_object_to_file(filename, root)) {
fprintf(stderr, "Error: failed to save %s.\n", filename);
} else {
printf("%s saved.\n", filename);
}
// Libération du JSON
json_object_put(root);
}
void files_load_session(char *filename) {
json_object *root = json_object_from_file(filename);
if (!root) {
fprintf(stderr, "Failed to read the file.\n");
return;
}
// Récupération du type
json_object *obj_type;
if (!json_object_object_get_ex(root, "TYPE", &obj_type) ||
json_object_get_type(obj_type) != json_type_string) {
fprintf(stderr, "Error: cannot read the type of the object.\n");
return;
}
const char *thetype = json_object_get_string(obj_type);
if (strcmp(thetype, "SESSION") != 0) {
fprintf(stderr, "Error: not a session file.\n");
return;
}
// Récupération des objets
json_object *jobjs;
if (!json_object_object_get_ex(root, "OBJS", &jobjs) ||
json_object_get_type(jobjs) != json_type_array) {
fprintf(stderr, "Error: cannot read the list of objects.\n");
return;
}
uint len = json_object_array_length(jobjs);
for (uint i = 0; i < len; i++) {
json_object *oneobj = json_object_array_get_idx(jobjs, i);
if (json_object_get_type(oneobj) != json_type_array ||
json_object_array_length(oneobj) != 2) {
fprintf(stderr, "Error: cannot read the list of objects.\n");
return;
}
json_object *varname = json_object_array_get_idx(oneobj, 0);
json_object *theobje = json_object_array_get_idx(oneobj, 1);
const char *thename = json_object_get_string(varname);
files_read_object_aux(theobje, strdup(thename));
}
json_object_put(root);
}

127
Aloyse et Vincent/graphs.c Normal file
View File

@@ -0,0 +1,127 @@
/********************************************/
/* Structures pour stocker les machines */
/* Ensuite spécialisées pour NFA,DFA,Cayley */
/********************************************/
#include "graphs.h"
/*****************************/
/*+ Création et suppression +*/
/*****************************/
lgraph *create_lgraph_noedges(const uint nb_vertices, const uint size_alpha) {
lgraph *graph = malloc(sizeof(lgraph));
if(graph == NULL){
fprintf(stderr, "Erreur d'allocation de mémoire\n");
exit(EXIT_FAILURE);
}
graph->size_graph = nb_vertices;
graph->size_alpha = size_alpha;
if(nb_vertices == 0 || size_alpha == 0) {
graph->edges = NULL;
return graph;
}
graph->edges = malloc(nb_vertices * sizeof(dequeue **));
if(graph->edges == NULL){
fprintf(stderr, "Erreur d'allocation de mémoire\n");
exit(EXIT_FAILURE);
}
for(uint i = 0; i < nb_vertices; i++){
graph->edges[i] = malloc(size_alpha * sizeof(dequeue *));
if(graph->edges[i] == NULL){
fprintf(stderr, "Erreur d'allocation de mémoire\n");
exit(EXIT_FAILURE);
}
for(uint j = 0; j < size_alpha; j++){
graph->edges[i][j] = create_dequeue();
}
}
return graph;
}
void delete_lgraph(lgraph *thegraph) {
free(thegraph->edges);
free(thegraph);
}
/**************************************/
/*+ Fusion disjointe de deux graphes +*/
/**************************************/
// ReSharper disable twice CppParameterMayBeConstPtrOrRef
lgraph *merge_lgraphs(lgraph *graph1, lgraph *graph2) {
if(graph1->size_alpha != graph2->size_alpha){
return NULL;
}
lgraph *merge = create_lgraph_noedges(graph1->size_graph + graph2->size_graph, graph1->size_alpha);
for(uint i = 0; i < graph1->size_graph; i++){
// ReSharper disable once CppDFANullDereference
merge->edges[i] = graph1->edges[i];
}
const uint l = graph1->size_graph;
for(uint i = 0; i < graph2->size_graph; i++){
// ReSharper disable once CppDFANullDereference
merge->edges[i + l] = graph2->edges[i];
}
return merge;
}
/*****************************************************************/
/*+ Récupération des sommets adjacents à un ensemble de sommets +*/
/*****************************************************************/
dequeue *lgraph_reachable(lgraph *g, dequeue *deq, const uint letter) {
dequeue *reach = create_dequeue();
//on stocke la taille de la liste pour éviter de la recalculer
const uint s = size_dequeue(deq);
for(uint i = 0; i < s; i++) {
dequeue *temp = g->edges[lefread_dequeue(deq, i)][letter];
//on insère (trié) les sommets atteignables dans la liste
merge_sorted_dequeue(reach, temp);
delete_dequeue(temp);
}
return reach;
}
/********************************************************/
/*+ Récupération d'une liste d'arêtes pour l'affichage +*/
/********************************************************/
stack *lgraph_to_multi_edges(lgraph *thegraph){
multi_edge *tab[thegraph->size_graph * thegraph->size_graph];
//on va créer une multi_edge pour chaque couple de sommet
for(uint i = 0; i < thegraph->size_graph; i++) {
for(uint j = 0; j < thegraph->size_graph; j++) {
multi_edge *edges = malloc(sizeof(multi_edge));
edges->in = i;
edges->out = j;
edges->lab = create_dequeue();
tab[i * thegraph->size_graph + j] = edges;
}
}
//on remplit les labels des milti_edges
for(uint i = 0; i < thegraph->size_graph; i++) { //on parcourt les sommets
for(uint j = 0; j < thegraph->size_alpha; j++) { //on parcourt les lettres
dequeue *temp = thegraph->edges[i][j];
const uint s = size_dequeue(temp);
for(uint k = 0; k < s; k++) { //on parcourt les sommets atteignables
insert_dequeue(tab[i * thegraph->size_graph + lefread_dequeue(temp, k)]->lab, j);
}
}
}
//on réccupère les multi_edges non vides et on libère les autres
stack *result = create_stack();
for(uint i = 0; i < thegraph->size_graph; i++) {
for(uint j = 0; j < thegraph->size_graph; j++) {
dequeue *temp = tab[i * thegraph->size_graph + j]->lab; //on récupère le multi_edge de chaque couple
if(!isempty_dequeue(temp)){
push(tab[i * thegraph->size_graph + j], result);
}
else {
delete_dequeue(temp);
}
}
}
return result;
}

94
Aloyse et Vincent/main.c Normal file
View File

@@ -0,0 +1,94 @@
#include "main.h"
#include "regexp.h"
#include "nfa.h"
#include "printing.h"
#include "alloc.h"
#include "shell_tools.h"
#include "string.h"
#include "time.h"
#include "shell_keywords.h"
#include "files.h"
#include <readline/readline.h>
#include <readline/history.h>
extern const char *all_strings[];
char **keyword_name_completion(const char *, int, int);
char *keyword_name_generator(const char *, int);
char **keyword_name_completion(const char *text, int start, int end) {
int z = start;
start = z;
z = end;
end = z;
rl_attempted_completion_over = 1;
return rl_completion_matches(text, keyword_name_generator);
}
char *keyword_name_generator(const char *text, int state) {
static int index, len;
const char *name;
if (!state) {
index = 0;
len = strlen(text);
}
while ((name = all_strings[index++])) {
if (strncmp(name, text, len) == 0) {
return strdup(name);
}
}
return NULL;
}
int main(int argc, char *argv[]) {
assert(argc > 0); // pour éviter un warning.
// Création du répertoire outputs
system("mkdir -p " OUTPUT_DIR);
// Readline
rl_attempted_completion_function = keyword_name_completion;
// rl_basic_word_break_characters = " \t\n\"\\'`@$><;|&{(,.=";
rl_basic_word_break_characters = " \t.=";
char *histfile;
char *str;
str = strrchr(argv[0], '/');
if (str != NULL) {
str++;
}
else {
str = argv[0];
}
CALLOC(histfile, 10 + strlen(str));
histfile[0] = '.';
strcpy(histfile + 1, str);
strcpy(histfile + 1 + strlen(str), "_history");
srand(time(NULL));
using_history();
int err = read_history(histfile);
if (err) {
WARNING("Pas de fichier d'historique trouvé, %d.\n", err);
}
keywords_add_all_keys();
print_title_box(5, true, stdout, 1,
"Bienvenue dans LEA (Langages, Expressions et Automates)");
shell_parse();
write_history(histfile);
free(histfile);
return EXIT_SUCCESS;
}

677
Aloyse et Vincent/nfa.c Normal file
View 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;
}

View File

@@ -0,0 +1,246 @@
/********************************************/
/* Determinisation et Minimisation des NFAs */
/********************************************/
#include "nfa_determi.h"
#include "nfa.h"
/************************/
/* Procédure principale */
/************************/
// Fonction auxiliaire pour convertir une file d'états en une représentation
// entière unique
static uint dequeue_to_uint(dequeue *states) {
uint result = 0;
for (uint i = 0; i < size_dequeue(states); ++i) {
result |= (1 << lefread_dequeue(states, i));
}
return result;
}
// Fonction auxiliaire pour vérifier si un ensemble d'états est final
static bool is_final_state(dequeue *states, dequeue *finals) {
for (uint i = 0; i < size_dequeue(states); ++i) {
if (mem_dequeue(lefread_dequeue(states, i), finals)) {
return true;
}
}
return false;
}
// Procédure de déterminisation. Le Booléen names indique si les noms des
// nouveaux états (des ensembles d'états de l'ancien NFA) doivent être
// sauvegardés dans le DFA.
nfa *nfa_determinize(nfa *thenfa, bool recording) {
printf("Déterminisation de l'automate1\n");
fflush(stdout);
// Créer un nouvel automate pour représenter le DFA
nfa *dfa = (nfa *)malloc(sizeof(nfa));
// Créer un graphe avec la taille de l'alphabet de l'automate initial
dfa->trans = create_lgraph_noedges(0, thenfa->trans->size_alpha);
dfa->initials = create_dequeue();
dfa->finals = create_dequeue();
// Copier les noms des lettres de l'alphabet;
dfa->alpha_names = nfa_copy_alpha(thenfa);
// Initialiser les noms des états si nécessaire
if (recording) {
dfa->state_names = (char **)malloc(sizeof(char *));
} else {
dfa->state_names = NULL;
}
// Initialiser l'état initial du DFA
// recopier les états initiaux de l'automate initial
dequeue *initial_set = create_dequeue();
copy_dequeue_right(initial_set, thenfa->initials, 0);
// on les transforme en binaires
uint initial_state = dequeue_to_uint(initial_set);
// On ajoute l'état initial du DFA en decimal à la file des états initiaux du
// DFA
lefins_dequeue(initial_state, dfa->initials);
// Utiliser une file pour gérer les ensembles d'états à explorer
dequeue *queue = create_dequeue();
// Ajouter l'état initial à la file
lefins_dequeue(initial_state, queue);
// tableau de booléens pour marquer les états visités de taille 2^size_graph
barray *visited = create_barray(1 << thenfa->trans->size_graph);
// Marquer l'état initial comme visité
settrue_barray(visited, initial_state);
// Carte pour stocker les ensembles d'états réels
dequeue **state_sets =
(dequeue **)malloc((1 << thenfa->trans->size_graph) * sizeof(dequeue *));
// on int
state_sets[initial_state] = initial_set;
// Traiter chaque ensemble d'états
while (!isempty_dequeue(queue)) {
uint current_state = lefpull_dequeue(queue);
// stocke cet ensemble d'états initiaux dans le tableau `state_sets` à
// l'indice `initial_state`
dequeue *current_set = state_sets[current_state];
// Vérifier si l'état actuel est un état final
if (is_final_state(current_set, thenfa->finals)) {
lefins_dequeue(current_state, dfa->finals);
}
// Traiter chaque lettre de l'alphabet
for (uint letter = 0; letter < thenfa->trans->size_alpha; ++letter) {
dequeue *next_set = create_dequeue();
// Calculer l'ensemble des états atteignables par la lettre actuelle
for (uint i = 0; i < size_dequeue(current_set); ++i) {
uint state = lefread_dequeue(current_set, i);
dequeue *transitions = thenfa->trans->edges[state][letter];
for (uint j = 0; j < size_dequeue(transitions); ++j) {
uint next_state = lefread_dequeue(transitions, j);
if (!mem_dequeue(next_state, next_set)) {
lefins_dequeue(next_state, next_set);
}
}
}
// Convertir le prochain ensemble en une représentation entière unique
uint next_state = dequeue_to_uint(next_set);
// Si le prochain état n'a pas été visité, l'ajouter à la file et le
// marquer comme visité
if (!getval_barray(visited, next_state)) {
settrue_barray(visited, next_state);
lefins_dequeue(next_state, queue);
state_sets[next_state] = next_set;
} else {
delete_dequeue(next_set);
}
// Ajouter la transition au DFA
if (dfa->trans->size_graph <= current_state) {
dfa->trans->size_graph = current_state + 1;
dfa->trans->edges = (dequeue ***)realloc(
dfa->trans->edges, dfa->trans->size_graph * sizeof(dequeue **));
for (uint k = 0; k < dfa->trans->size_graph; ++k) {
dfa->trans->edges[k] =
(dequeue **)malloc(dfa->trans->size_alpha * sizeof(dequeue *));
for (uint l = 0; l < dfa->trans->size_alpha; ++l) {
dfa->trans->edges[k][l] = create_dequeue();
}
}
}
lefins_dequeue(next_state, dfa->trans->edges[current_state][letter]);
}
// Enregistrer le nom de l'état si nécessaire
if (recording) {
char *state_name = (char *)malloc(256 * sizeof(char));
sprintf(state_name, "{");
for (uint i = 0; i < size_dequeue(current_set); ++i) {
if (i > 0) {
strcat(state_name, ",");
}
char buffer[10];
sprintf(buffer, "%u", lefread_dequeue(current_set, i));
strcat(state_name, buffer);
}
strcat(state_name, "}");
dfa->state_names[current_state] = state_name;
}
delete_dequeue(current_set);
}
// Nettoyage
delete_dequeue(queue);
delete_barray(visited);
free(state_sets);
printf("Fin de la déterminisation1\n");
fflush(stdout);
return dfa;
}
// Complementation
nfa *nfa_complement(nfa *thenfa) {
printf("Complémentation de l'automate\n");
fflush(stdout);
// Déterminiser l'automate
nfa *det_nfa = nfa_determinize(thenfa, false);
// Compléter l'automate déterminisé
uint num_states = det_nfa->trans->size_graph;
uint num_letters = det_nfa->trans->size_alpha;
printf("Complémentation de l'automate1\n");
fflush(stdout);
// Créer un nouvel état de puits
uint sink_state = num_states;
lgraph *new_trans = create_lgraph_noedges(num_states + 1, num_letters);
printf("Complémentation de l'automate2\n");
fflush(stdout);
// Copier les transitions existantes
for (uint state = 0; state < num_states; state++) {
for (uint letter = 0; letter < num_letters; letter++) {
printf("Complémentation de l'automate3\n");
fflush(stdout);
dequeue *transitions = det_nfa->trans->edges[state][letter];
if (transitions != NULL) {
printf("Complémentation de l'automate4\n");
fflush(stdout);
new_trans->edges[state][letter] = transitions;
} else {
printf("Complémentation de l'automate5\n");
fflush(stdout);
new_trans->edges[state][letter] = create_dequeue();
printf("Complémentation de l'automate6\n");
fflush(stdout);
rigins_dequeue(sink_state, new_trans->edges[state][letter]);
printf("Complémentation de l'automate7\n");
fflush(stdout);
}
}
}
// Ajouter des transitions vers l'état de puits pour les transitions
// manquantes
for (uint letter = 0; letter < num_letters; letter++) {
new_trans->edges[sink_state][letter] = create_dequeue();
rigins_dequeue(sink_state, new_trans->edges[sink_state][letter]);
}
printf("Complémentation de l'automate8\n");
fflush(stdout);
// Créer le nouvel automate avec les transitions complétées
nfa *comp_nfa = (nfa *)malloc(sizeof(nfa));
comp_nfa->trans = new_trans;
comp_nfa->initials = det_nfa->initials;
comp_nfa->alpha_names = nfa_copy_alpha(det_nfa);
comp_nfa->state_names = nfa_copy_all_names(det_nfa);
// Inverser les états finaux et non finaux
barray *finals_barray = create_barray(num_states + 1);
for (uint state = 0; state < num_states; state++) {
if (!mem_dequeue(state, det_nfa->finals)) {
settrue_barray(finals_barray, state);
}
}
settrue_barray(finals_barray, sink_state);
// Créer la liste des états finaux
comp_nfa->finals = create_dequeue();
for (uint state = 0; state <= num_states; state++) {
if (getval_barray(finals_barray, state)) {
rigins_dequeue(state, comp_nfa->finals);
}
}
printf("Complémentation de l'automate9\n");
fflush(stdout);
// Libérer la mémoire
delete_barray(finals_barray);
nfa_delete(det_nfa);
return comp_nfa;
}

View File

@@ -0,0 +1,145 @@
/************************/
/* Intersection of NFAs */
/************************/
#include "nfa_intersec.h"
/************************************************************************************************/
/* Construction classique: calcul de l'automate produit en ne gardant que les
* états accessibles */
/************************************************************************************************/
// Intersection
nfa *nfa_intersect(nfa *nfa1, nfa *nfa2, bool nom) {
printf("Intersection de l'automate\n");
fflush(stdout);
// Vérifier que les alphabets des deux automates sont identiques
if (nfa1->trans->size_alpha != nfa2->trans->size_alpha) {
fprintf(stderr,
"Les alphabets des deux automates doivent être identiques.\n");
return NULL;
}
// Créer un nouveau NFA pour l'automate produit
nfa *result = (nfa *)malloc(sizeof(nfa));
if (!result) {
perror("Erreur d'allocation de mémoire pour l'automate produit");
return NULL;
}
// Initialiser les champs de l'automate produit
result->trans =
create_lgraph_noedges(nfa1->trans->size_graph * nfa2->trans->size_graph,
nfa1->trans->size_alpha);
result->initials = create_dequeue();
result->finals = create_dequeue();
result->alpha_names = nfa_copy_alpha(nfa1);
result->state_names =
nom ? (char **)malloc(result->trans->size_graph * sizeof(char *)) : NULL;
// Ajouter les états initiaux
for (uint i = 0; i < size_dequeue(nfa1->initials); i++) {
for (uint j = 0; j < size_dequeue(nfa2->initials); j++) {
// Récupérer les états initiaux des deux automates
uint state1 = lefread_dequeue(nfa1->initials, i);
uint state2 = lefread_dequeue(nfa2->initials, j);
// Calcule de l'indice du nouvel état initial dans l'automate produit
uint new_state = state1 * nfa2->trans->size_graph + state2;
// Ajouter le nouvel état initial à la liste des états initiaux de
// l'automate produit
insert_dequeue(result->initials, new_state);
}
}
printf("Intersection de l'automate1\n");
fflush(stdout);
// Ajouter les états finaux
for (uint i = 0; i < size_dequeue(nfa1->finals); i++) {
for (uint j = 0; j < size_dequeue(nfa2->finals); j++) {
// Récupérer les états finaux des deux automates
uint state1 = lefread_dequeue(nfa1->finals, i);
uint state2 = lefread_dequeue(nfa2->finals, j);
// Calcule de l'indice du nouvel état final dans l'automate produit
uint new_state = state1 * nfa2->trans->size_graph + state2;
// Ajouter le nouvel état final à la liste des états finaux de l'automate
// produit
insert_dequeue(result->finals, new_state);
}
}
printf("Intersection de l'automate2\n");
fflush(stdout);
// Ajouter les transitions
for (uint state1 = 0; state1 < nfa1->trans->size_graph; state1++) {
for (uint state2 = 0; state2 < nfa2->trans->size_graph; state2++) {
// Calcule de l'indice du nouvel dans l'automate produit
uint new_state = state1 * nfa2->trans->size_graph + state2;
for (uint letter = 0; letter < nfa1->trans->size_alpha; letter++) {
// Récupérer les états atteignables depuis state1 et state2 avec la
// lettre courante
// tuyau de tout les états atteignables depuis state1 avec la lettre
dequeue *reachable1 = nfa1->trans->edges[state1][letter];
// tuyau de tout les états atteignables depuis state2 avec la lettre
dequeue *reachable2 = nfa2->trans->edges[state2][letter];
// pour toute les combinaisons d'états atteignables depuis state1 et
// state2 avec la lettre
for (uint i = 0; i < size_dequeue(reachable1); i++) {
for (uint j = 0; j < size_dequeue(reachable2); j++) {
// Récupérer les états atteignables
uint next_state1 = lefread_dequeue(reachable1, i);
uint next_state2 = lefread_dequeue(reachable2, j);
// Calculer le nouvel état atteignable dans l'automate produit
uint new_next_state =
next_state1 * nfa2->trans->size_graph + next_state2;
// Ajouter la transition dans l'automate produit
rigins_dequeue(new_next_state,
result->trans->edges[new_state][letter]);
}
}
}
}
}
printf("Intersection de l'automate3\n");
fflush(stdout);
// Enregistrer les noms des états si nécessaire
if (nom) {
for (uint state1 = 0; state1 < nfa1->trans->size_graph; state1++) {
for (uint state2 = 0; state2 < nfa2->trans->size_graph; state2++) {
// Calculer le nouvel état dans l'automate produit
uint new_state = state1 * nfa2->trans->size_graph + state2;
// Récupérer les noms des états des deux automates
printf("c'est pas ici\n");
fflush(stdout);
char *name1 = nfa_copy_one_name(nfa1, state1);
char *name2 = nfa_copy_one_name(nfa2, state2);
// Calculer la longueur des noms
printf("vincent c'est un genie\n");
fflush(stdout);
size_t len1 = name1 ? strlen(name1) : 0;
size_t len2 = name2 ? strlen(name2) : 0;
// Allouer de la mémoire pour le nom du nouvel état
result->state_names[new_state] =
(char *)malloc((len1 + len2 + 4) * sizeof(char));
printf("blem de malloc\n");
fflush(stdout);
// Copier le nom du premier état
if (name1) {
strcpy(result->state_names[new_state], name1);
free(name1);
}
printf("truc bizzar de copilot\n");
fflush(stdout);
// Ajouter une virgule pour séparer les noms
strcat(result->state_names[new_state], ",");
// Copier le nom du second état
if (name2) {
strcat(result->state_names[new_state], name2);
free(name2);
}
}
}
}
printf("fin Intersection de l'automate\n");
fflush(stdout);
// Retourner l'automate produit
return result;
}

View File

@@ -0,0 +1,127 @@
#include "nfa_mccluskey.h"
#include "regexp.h"
#include <stdio.h>
mccluskey_auto *nfa_to_mccluskey(nfa *thenfa) {
// Nombre d'états dans le NFA
uint n = thenfa->trans->size_graph;
// Créer l'automate généralisé avec n+2 états
mccluskey_auto *mccluskey = (mccluskey_auto *)malloc(sizeof(mccluskey_auto));
mccluskey->size = n + 2;
mccluskey->matrix = (regexp ***)malloc((n + 2) * sizeof(regexp **));
// Initialiser toutes les cellules de la matrice à NULL
for (uint i = 0; i < n + 2; i++) {
mccluskey->matrix[i] = (regexp **)malloc((n + 2) * sizeof(regexp *));
for (uint j = 0; j < n + 2; j++) {
mccluskey->matrix[i][j] = NULL;
}
}
// Ajouter les transitions du NFA à l'automate généralisé
for (uint q = 0; q < n; q++) {
// 0 à taille de l'alphabet
for (uint a = 0; a < thenfa->trans->size_alpha; a++) {
// récupérer la liste des états accessibles depuis l'état `q` par une
// transition étiquetée par la lettre `a` dans le NFA
dequeue *transitions = thenfa->trans->edges[q][a];
for (uint k = 0; k < size_dequeue(transitions); k++) {
uint r = lefread_dequeue(transitions, k);
// regarde si la transition existe déjà
if (mccluskey->matrix[q + 2][r + 2] == NULL) {
// si elle n'existe pas on la crée
// on crée une expression régulière qui représentant la lettre a
mccluskey->matrix[q + 2][r + 2] = reg_letter(thenfa->alpha_names[a]);
} else {
// si elle existe on fait l'union avec la lettre a
mccluskey->matrix[q + 2][r + 2] =
reg_union(mccluskey->matrix[q + 2][r + 2],
reg_letter(thenfa->alpha_names[a]));
}
}
}
}
// Ajouter les transitions de l'état initial de l'automate généralisé vers les
// états initiaux du NFA
for (uint i = 0; i < size_dequeue(thenfa->initials); i++) {
// on lie l'état initial
uint initial_state = lefread_dequeue(thenfa->initials, i);
// on crée une transition epsilon pour decaler les états initiaux du NFA
// pour n'avoir qu'un seul état initial
mccluskey->matrix[0][initial_state + 2] = reg_epsilon();
}
// Ajouter les transitions des états finaux du NFA vers l'état final de
// l'automate généralisé
for (uint i = 0; i < size_dequeue(thenfa->finals); i++) {
// on lie l'état final
uint final_state = lefread_dequeue(thenfa->finals, i);
// on crée une transition epsilon pour decaler les états finaux du NFA pour
// n'avoir qu'un seul état final
mccluskey->matrix[final_state + 2][1] = reg_epsilon();
}
return mccluskey;
}
regexp *nfa_mccluskey(nfa *thenfa) {
// Convertir le NFA en un automate généralisé
// on recupère le mccluskey_auto de thenfa
// premiere transphormation du NFA en automate généralisé
mccluskey_auto *gen_auto = nfa_to_mccluskey(thenfa);
// Nombre d'états dans l'automate
uint n = gen_auto->size;
// on recupère la matrice de l'automate
regexp ***matrix = gen_auto->matrix;
// Appliquer l'algorithme de Brzozowski-McCluskey
// k est l'état intermédiaire que l'on veut supprimer
for (uint k = 2; k < n; ++k) {
for (uint i = 0; i < n; ++i) {
for (uint j = 0; j < n; ++j) {
// si il y a une transition de i à k et de k à j
if (matrix[i][k] != NULL && matrix[k][j] != NULL) {
regexp *new_expr;
// on crée une nouvelle transition de i à j en passant par k
// on verifie si il y a une boucle sur k
if (matrix[k][k] != NULL) {
new_expr = reg_concat(matrix[i][k], reg_star(matrix[k][k]));
new_expr = reg_concat(new_expr, matrix[k][j]);
} else {
// Créer une nouvelle expression pour la transition de i à j via k
// sans boucle
new_expr = reg_concat(matrix[i][k], matrix[k][j]);
}
// Si une transition directe de i à j existe déjà, faire l'union des
// deux expressions
if (matrix[i][j] != NULL) {
new_expr = reg_union(matrix[i][j], new_expr);
}
// Mettre à jour la matrice avec la nouvelle expression
matrix[i][j] = new_expr;
}
}
}
}
// L'expression régulière finale est dans matrix[0][1]
regexp *final_regexp = matrix[0][1];
// Libérer la mémoire de l'automate généralisé
for (uint i = 0; i < n; ++i) {
for (uint j = 0; j < n; ++j) {
if (matrix[i][j] && !(i == 0 && j == 1)) {
// reg_free(matrix[i][j]);
}
}
free(matrix[i]);
}
free(matrix);
free(gen_auto);
return final_regexp;
}

View File

@@ -0,0 +1,29 @@
#include "nfa_minimization.h"
/******************************/
/*+ Algorithme de Brzozowski +*/
/******************************/
nfa *nfa_brzozowski(nfa *) {
return NULL;
}
/****************************/
/*+ Algorithme de Hopcroft +*/
/****************************/
hopcroft_partition *nfa_hopcroft_initial(uint, dequeue *) {
return NULL;
}
nfa *nfa_hopcroft_genauto(nfa *, hopcroft_partition *) {
return NULL;
}
void nfa_hopcroft_free(hopcroft_partition *) {
return;
}
nfa *nfa_hopcroft(nfa *) {
return NULL;
}

View File

@@ -0,0 +1,9 @@
#include "nfa_tocode.h"
#include "nfa_determi.h"
#include "printing.h"
#include "error.h"
#include <stdio.h>
void nfa2code(nfa *, char *) {
return;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,302 @@
#include "printing.h"
#include <sys/utsname.h>
#define LINUX_VIEW_COMMAND "| convert - -resize 70% sixel:- | cat"
#define OSX_VIEW_COMMAND "| ./imgcat -W auto"
static char *view_command(void) {
struct utsname name;
uname(&name);
if (strcmp(name.sysname, "Darwin") == 0) {
return OSX_VIEW_COMMAND;
}
else {
return LINUX_VIEW_COMMAND;
}
}
bool external_viewer = false;
/**********************/
/* Printing functions */
/**********************/
// Print d'un sommet, version noms contenus dans un deq
void list_print_state(void *p, FILE *out) {
if (isempty_dequeue(p)) {
fprintf(out, "E");
}
else {
for (uint j = 0; j < size_dequeue(p) - 1; j++) {
fprintf(out, "%d,", lefread_dequeue(p, j));
}
fprintf(out, "%d", lefread_dequeue(p, size_dequeue(p) - 1));
}
}
/********************************/
/* Print des arêtes d'un graphe */
/********************************/
void named_lgedges_print(stack *theedges, nfa *A, FILE *out) {
for (uint i = 0; i < size_stack(theedges); i++) { // Boucle sur les états de départ
fprintf(out, "%d -> %d [label = \"",
((multi_edge *)read_stack(theedges, i))->in,
((multi_edge *)read_stack(theedges, i))->out);
if (!isempty_dequeue(((multi_edge *)read_stack(theedges, i))->lab)) {
for (uint j = 0;
j < size_dequeue(((multi_edge *)read_stack(theedges, i))->lab) - 1;
j++) {
uint letnum =
lefread_dequeue(((multi_edge *)read_stack(theedges, i))->lab, j);
if (A->alpha_names[letnum] == ' ') {
fprintf(out, "%s,", "");
}
else if (A->alpha_names[letnum] == '\"') {
fprintf(out, "\\\",");
}
else {
fprintf(out, "%c,", A->alpha_names[letnum]);
}
}
uint letnum = lefread_dequeue(
((multi_edge *)read_stack(theedges, i))->lab,
size_dequeue(((multi_edge *)read_stack(theedges, i))->lab) - 1);
if (A->alpha_names[letnum] == ' ') {
fprintf(out, "%s\"]\n", "");
}
else if (A->alpha_names[letnum] == '\"') {
fprintf(out, "\\\"\"]\n");
}
else {
fprintf(out, "%c\"]\n", A->alpha_names[letnum]);
}
}
}
}
/******************/
/* Print d'un NFA */
/******************/
bool nfa_print(nfa *A, FILE *out) {
fprintf(out, "digraph {\n");
fprintf(out, "gradientangle=90\n");
fprintf(out, "fontname=\"Helvetica,Arial,sans-serif\"\n");
fprintf(out, "resolution= \"200.0,0.0\"\n");
fprintf(out, "node [fontname=\"Helvetica,Arial,sans-serif\"]\n");
fprintf(out, "edge [fontname=\"Helvetica,Arial,sans-serif\"]\n");
fprintf(out, "rankdir=LR;\n\n");
uint i = 0;
uint f = 0;
for (uint k = 0; k < A->trans->size_graph; k++) {
fprintf(out, "%d [style=solid", k);
if (A->state_names) {
fprintf(out, ",label=\"%s\"", A->state_names[k]);
}
if ((i < size_dequeue(A->initials) &&
lefread_dequeue(A->initials, i) == k) &&
(f < size_dequeue(A->finals) && lefread_dequeue(A->finals, f) == k)) {
fprintf(
out,
",fillcolor=\"blue:green\",style=filled,shape = doublecircle];\n");
i++;
f++;
continue;
}
if (i < size_dequeue(A->initials) && lefread_dequeue(A->initials, i) == k) {
fprintf(out, ",fillcolor=\"blue:green\",style=filled,shape = circle];\n");
i++;
continue;
}
if (f < size_dequeue(A->finals) && lefread_dequeue(A->finals, f) == k) {
fprintf(out, ",shape = doublecircle];\n");
f++;
continue;
}
fprintf(out, ",shape = circle];\n");
}
stack *theedges;
// Calcul de l'ensemble de transitions
theedges = lgraph_to_multi_edges(A->trans);
if (!theedges) {
fprintf(stderr, "Error when printing: unable to convert graph to "
"multi_edges.\nPlease implement lgraph_to_multi_edges().");
return false;
}
named_lgedges_print(theedges, A, out);
while (!isempty_stack(theedges)) {
multi_edge *new = pop(theedges);
delete_dequeue(new->lab);
free(new);
}
delete_stack(theedges);
fprintf(out, "}\n");
return true;
}
/**************************/
/* Affichage sur le shell */
/**************************/
// Affichage d'un NFA
void nfa_view(nfa *thenfa) {
if (!thenfa) {
CRITICAL("NFA is NULL, impossible to display it.");
return;
}
char tmp_filename[] = "/tmp/nfa-XXXXXX.dot";
int d = mkostemps(tmp_filename, 4, O_APPEND);
char png_filename[1 + strlen(tmp_filename)];
strcpy(png_filename, tmp_filename);
strcpy(png_filename + strlen(tmp_filename) - 3, "png");
FILE *f_tmp = fdopen(d, "w");
if (!f_tmp) {
CRITICAL("Unable to open temporary file");
}
nfa_print(thenfa, f_tmp);
fclose(f_tmp);
char *command;
if (!external_viewer) {
command = multiple_strcat("dot -Tpng ", tmp_filename, view_command(), NULL);
}
else {
command = multiple_strcat("dot -Tpng ", tmp_filename, " -o ", png_filename,
"&& open ", png_filename, NULL);
}
TRACE("%s", command);
system(command);
free(command);
}
// Affichage de regexp, pour le débogage.
// Ces fonctions vous sont fournies pour vous aider à déboguer votre code.
static void reg_print_helper(regexp *r, regelem parent) {
TRACE("reg_print_helper");
if (r == NULL) {
return;
}
switch (r->op) {
case CHAR:
if (r->letter == ' ') {
fprintf(stdout, "%s", "");
}
else {
fprintf(stdout, "%c", r->letter);
}
break;
case EMPTY:
print_color("", BLUE, stdout);
break;
case EPSILON:
print_color("ε", YELLOW, stdout);
break;
case UNION:
DEBUG("Union");
if (parent != UNION && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, UNION);
print_color(" + ", RED, stdout);
reg_print_helper(r->right, UNION);
if (parent != UNION && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case INTER:
if (parent != INTER && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, INTER);
printf("");
reg_print_helper(r->right, INTER);
if (parent != INTER && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case CONCAT:
DEBUG("Concat");
if (parent != CONCAT && parent != UNION && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, CONCAT);
reg_print_helper(r->right, CONCAT);
if (parent != CONCAT && parent != UNION && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case STAR:
DEBUG("Star");
if (r->left->op == CHAR || r->left->op == EPSILON || r->left->op == EMPTY) {
reg_print_helper(r->left, STAR);
print_color("*", CYAN, stdout);
}
else {
// printf("(");
reg_print_helper(r->left, STAR);
// printf(")");
print_color("*", CYAN, stdout);
}
break;
case COMPLEMENT:
if (parent != NONE) {
print_color("(", CYAN, stdout);
}
print_color("¬", RED, stdout);
reg_print_helper(r->left, COMPLEMENT);
if (parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
default:
CRITICAL("Unknown regexp operator (%d)", r->op);
break;
}
}
void reg_print(regexp *r) {
TRACE("reg_print");
reg_print_helper(r, NONE);
printf("\n");
}

116
Aloyse et Vincent/regexp.c Normal file
View File

@@ -0,0 +1,116 @@
#include "regexp.h"
bool reg_issimple(regexp *expr) {
// cas de base epression vide
if (expr == NULL) {
return true;
}
// test si l'expression contient une intersection ou un complement
if (expr->op == INTER || expr->op == COMPLEMENT) {
return false;
}
// on teste les sous expressions
return reg_issimple(expr->left) && reg_issimple(expr->right);
}
void reg_free(regexp *expr) {
if (expr == NULL) {
return;
}
// Libérer récursivement les sous-expressions gauche et droite
reg_free(expr->left);
reg_free(expr->right);
free(expr);
}
regexp *reg_copy(regexp *expr) {
// cas de base
if (expr == NULL) {
return NULL;
}
regexp *new_expr = malloc(sizeof(regexp));
// on complète les champs
new_expr->op = expr->op;
new_expr->letter = expr->letter;
new_expr->left = reg_copy(expr->left);
new_expr->right = reg_copy(expr->right);
return new_expr;
}
regexp *reg_empty(void) {
regexp *void_expr = malloc(sizeof(regexp));
void_expr->op = EMPTY;
void_expr->left = NULL;
void_expr->right = NULL;
void_expr->letter = '\0';
return void_expr;
}
regexp *reg_epsilon(void) {
regexp *epsilon = malloc(sizeof(regexp));
epsilon->op = EPSILON;
epsilon->left = NULL;
epsilon->right = NULL;
epsilon->letter = '\0';
return epsilon;
}
regexp *reg_letter(char c) {
regexp *lettre = malloc(sizeof(regexp));
lettre->op = CHAR;
lettre->left = NULL;
lettre->right = NULL;
// la lettre de l'expression
lettre->letter = c;
return lettre;
}
regexp *reg_union(regexp *expr_left, regexp *expr_right) {
regexp *uni = malloc(sizeof(regexp));
uni->op = UNION;
uni->left = expr_left;
uni->right = expr_right;
uni->letter = '\0';
return uni;
}
regexp *reg_inter(regexp *expr_left, regexp *expr_right) {
regexp *inter = malloc(sizeof(regexp));
inter->op = INTER;
inter->left = expr_left;
inter->right = expr_right;
inter->letter = '\0';
return inter;
}
regexp *reg_concat(regexp *expr_left, regexp *expr_right) {
regexp *concat = malloc(sizeof(regexp));
concat->op = CONCAT;
concat->left = expr_left;
concat->right = expr_right;
concat->letter = '\0';
return concat;
}
regexp *reg_star(regexp *expr) {
regexp *star = malloc(sizeof(regexp));
star->op = STAR;
star->left = expr;
star->right = NULL;
star->letter = '\0';
return star;
}
regexp *reg_complement(regexp *expr) {
regexp *compl = malloc(sizeof(regexp));
compl->op = COMPLEMENT;
compl->left = expr;
compl->right = NULL;
compl->letter = '\0';
return compl;
}

View File

@@ -0,0 +1,364 @@
#include "regexp_tonfa.h"
#include "error.h"
#include "nfa.h"
#include "regexp.h"
#include "type_boolarray.h"
#include "type_dequeue.h"
#include <stdbool.h>
#include <stdlib.h>
/****************************/
/*+ Algorithme de Glushkov +*/
/****************************/
uint reg_countletters(regexp *expr) {
// cas de base epression vide
if (expr == NULL) {
return 0;
}
// compte le nombre de lettre dans les sous expressions
if (expr->op == CHAR) {
return 1;
}
// on teste les sous expressions
return reg_countletters(expr->left) + reg_countletters(expr->right);
}
glushkov_info *reg_create_gk_emp(uint size) {
glushkov_info *gk = malloc(sizeof(glushkov_info));
gk->size = size;
// ensemble vide donc epsilon qui est un mot = false
gk->epsilon = false;
gk->first = create_barray(size);
gk->last = create_barray(size);
gk->follow = create_barray(size * size);
return gk;
}
glushkov_info *reg_create_gk_eps(uint size) {
glushkov_info *gk = malloc(sizeof(glushkov_info));
gk->size = size;
gk->epsilon = true;
gk->first = create_barray(size);
gk->last = create_barray(size);
gk->follow = create_barray(size * size);
return gk;
}
glushkov_info *reg_create_gk_let(uint num, uint size) {
// allocation de la structure
glushkov_info *gk = malloc(sizeof(glushkov_info));
// initialisation de la structure
gk->size = size;
// singleton d'une lettre donc pas de mot vide
gk->epsilon = false;
gk->first = create_barray(size);
settrue_barray(gk->first, num);
gk->last = create_barray(size);
settrue_barray(gk->last, num);
gk->follow = create_barray(size * size);
return gk;
}
glushkov_info *reg_gk_star(glushkov_info *info) {
// allocation de la structure
glushkov_info *gk = malloc(sizeof(glushkov_info));
// initialisation de la structure
gk->size = info->size;
// L'étoile de Kleene d'une expression contient toujours le mot vide
gk->epsilon = true;
// tableau first et last de l'etoile de Kleene sont identiques à ce de départ
gk->first = copy_barray(info->first);
gk->last = copy_barray(info->last);
// Créer le tableau follow pour l'étoile de Kleene à partir de celui de
// l'expression de départ
gk->follow = copy_barray(info->follow);
// Ajouter les transitions pour l'étoile de Kleene
for (uint i = 0; i < info->size; i++) {
// Si la lettre i peut etre à la fin du mots je regarde si elle peut etre a
// coté d'une autre lettreen debut de mot
if (getval_barray(info->last, i)) {
for (uint j = 0; j < info->size; j++) {
if (getval_barray(info->first, j)) {
settrue_barray(gk->follow, i * info->size + j);
}
}
}
}
return gk;
}
glushkov_info *reg_gk_union(glushkov_info *info_left,
glushkov_info *info_right) {
// allocation de la structure
glushkov_info *gk = malloc(sizeof(glushkov_info));
// initialisation de la structure
gk->size = info_left->size;
gk->epsilon = false;
if (info_left->epsilon || info_right->epsilon) {
gk->epsilon = true;
}
gk->first = or_barray(info_left->first, info_right->first);
gk->last = or_barray(info_left->last, info_right->last);
gk->follow = or_barray(info_left->follow, info_right->follow);
return gk;
}
glushkov_info *reg_gk_concat(glushkov_info *ptr_info_left,
glushkov_info *ptr_info_right) {
glushkov_info *new_ptr = malloc(sizeof(glushkov_info));
if (new_ptr == NULL) {
ERROR("reg_gk_union : malloc failed");
}
new_ptr->size = ptr_info_left->size;
new_ptr->epsilon = (ptr_info_left->epsilon && ptr_info_right->epsilon);
if (ptr_info_left->epsilon) {
new_ptr->first = or_barray(ptr_info_left->first, ptr_info_right->first);
} else {
new_ptr->first = copy_barray(ptr_info_left->first);
}
if (ptr_info_right->epsilon) {
new_ptr->last = or_barray(ptr_info_left->last, ptr_info_right->last);
} else {
new_ptr->last = copy_barray(ptr_info_right->last);
}
new_ptr->follow = or_barray(ptr_info_left->follow, ptr_info_right->follow);
for (uint l = 0; l < new_ptr->size; l++) {
for (uint f = 0; f < new_ptr->size; f++) {
if (getval_barray(ptr_info_left->last, l) &&
getval_barray(ptr_info_right->first, f)) {
settrue_barray(new_ptr->follow, (l * new_ptr->size) + f);
}
}
}
return new_ptr;
}
void reg_gk_delete(glushkov_info *info) {
if (info == NULL) {
return;
}
delete_barray(info->first);
delete_barray(info->last);
delete_barray(info->follow);
free(info);
}
glushkov_info *gk_indexleaves(regexp *ptr_regexp, uint nbr_letter,
uint *ptr_index, char *ptr_map) {
switch (ptr_regexp->op) {
case EMPTY:
return reg_create_gk_emp(nbr_letter);
case EPSILON:
return reg_create_gk_eps(nbr_letter);
case CHAR:
ptr_map[*ptr_index] = ptr_regexp->letter;
// On renomme la lettre par un entier
ptr_regexp->letter = *ptr_index;
(*ptr_index)++;
return reg_create_gk_let((*ptr_index - 1), nbr_letter);
case UNION:
glushkov_info *left_union =
gk_indexleaves(ptr_regexp->left, nbr_letter, ptr_index, ptr_map);
glushkov_info *right_union =
gk_indexleaves(ptr_regexp->right, nbr_letter, ptr_index, ptr_map);
return reg_gk_union(left_union, right_union);
/*
return reg_gk_union(gk_indexleaves(ptr_regexp->left, nbr_letter,
ptr_index, ptr_map),
gk_indexleaves(ptr_regexp->right, nbr_letter,
ptr_index, ptr_map));*/
case CONCAT:
glushkov_info *left_concat =
gk_indexleaves(ptr_regexp->left, nbr_letter, ptr_index, ptr_map);
glushkov_info *right_concat =
gk_indexleaves(ptr_regexp->right, nbr_letter, ptr_index, ptr_map);
return reg_gk_concat(left_concat, right_concat);
/*
return reg_gk_concat(gk_indexleaves(ptr_regexp->left, nbr_letter,
ptr_index, ptr_map),
gk_indexleaves(ptr_regexp->right, nbr_letter,
ptr_index, ptr_map));*/
case STAR:
return reg_gk_star(
gk_indexleaves(ptr_regexp->left, nbr_letter, ptr_index, ptr_map));
default:
return NULL;
}
}
nfa *reg_glushkov(regexp *ptr_regexp) {
// Si l'expression régulière n'est pas simple
if (!reg_issimple(ptr_regexp)) {
return NULL;
}
// On compte le nombre de lettres dans l'expression régulière
uint nb_letters = reg_countletters(ptr_regexp);
// On initialise l'index des lettres
uint index = 0;
// On initialise le tableau de correspondance des lettres
char *map = malloc(sizeof(char) * nb_letters);
// On l'initialise à NULL
for (uint i = 0; i < nb_letters; i++) {
map[i] = '\0';
}
// On calcul l'objet de type glushkov_info
glushkov_info *ptr_glu_info =
gk_indexleaves(ptr_regexp, nb_letters, &index, map);
// On crée un NFA
nfa *ptr_nfa = malloc(sizeof(nfa));
if (ptr_nfa == NULL) {
ERROR("reg_glushkov : malloc failed");
return NULL;
}
// On calcul le nombre de sommets
uint nb_sommet = ptr_glu_info->size + 1;
ptr_nfa->trans = create_lgraph_noedges(nb_sommet, ptr_glu_info->size);
// On initialise le tableau edges
// On parcourt le tableau de follow
for (uint ind_follow = 0;
ind_follow < ptr_glu_info->size * ptr_glu_info->size; ind_follow++) {
// Si la case est vraie alors les deux sommets indéxés par la case
// sont reliés par une arrête indéxée par la deuxième lettre
if (getval_barray(ptr_glu_info->follow, ind_follow)) {
// On récupère les deux lettres / sommets
uint sommet_b = ind_follow % ptr_glu_info->size;
uint sommet_a = (ind_follow - sommet_b) / ptr_glu_info->size;
// On ajoute une arrête à la liste triée entre les deux sommets
insert_dequeue(ptr_nfa->trans->edges[sommet_a][sommet_b], sommet_b);
}
}
// En plus tous les états initiaux sont reliés a epsilon
// On parcourt les états initiaux et on modifie edges [O][i] pour i une
// lettre dans la liste des états initiaux
for (uint ind_init = 0; ind_init < ptr_glu_info->size; ind_init++) {
if (getval_barray(ptr_glu_info->first, ind_init)) {
insert_dequeue(ptr_nfa->trans->edges[nb_sommet - 1][ind_init], ind_init);
}
}
// On initialise les états initiaux et finaux
ptr_nfa->initials = create_dequeue();
// On ajoute le sommet représenté par epsilon aux états initiaux
// représenté par le numéro nb_sommet-1
insert_dequeue(ptr_nfa->initials, nb_sommet - 1);
ptr_nfa->finals = create_dequeue();
// On ajoute les sommets qui sont dans last aux états finaux + espilon
// si est dans l'expression régulière totale On parcourt le tableau last
for (uint ind_last = 0; ind_last < ptr_glu_info->size; ind_last++) {
// Si la lettre est dans last
if (getval_barray(ptr_glu_info->last, ind_last)) {
// On ajoute le sommet i aux états finaux
insert_dequeue(ptr_nfa->finals, ind_last);
}
}
// Si epsilon est dans l'expression régulière totale
if (ptr_glu_info->epsilon) {
// On ajoute le sommet représenté par epsilon aux états finaux
insert_dequeue(ptr_nfa->finals, nb_sommet - 1);
}
// On initialise le tableau du noms des lettres
ptr_nfa->alpha_names = malloc(ptr_nfa->trans->size_alpha * sizeof(char));
// On récupère l'équivalence entre les lettres et leur numéro avec le
// tableau map
for (uint ind_map = 0; ind_map < nb_letters; ind_map++) {
ptr_nfa->alpha_names[ind_map] = map[ind_map];
}
ptr_nfa->state_names = NULL;
if (ptr_glu_info != NULL) {
reg_gk_delete(ptr_glu_info);
}
return ptr_nfa;
}
/****************************/
/*+ Algorithme de Thompson +*/
/****************************/
nfa *reg_thompson(regexp *expr) {
if (expr == NULL) {
return NULL;
}
switch (expr->op) {
case EMPTY:
return create_emptylang();
case EPSILON:
return create_sing_epsilon();
case CHAR:
return create_sing_letter(expr->letter);
case UNION: {
nfa *left_nfa = reg_thompson(expr->left);
nfa *right_nfa = reg_thompson(expr->right);
nfa *result_nfa = nfa_union(left_nfa, right_nfa);
nfa_delete(left_nfa);
nfa_delete(right_nfa);
return result_nfa;
}
case CONCAT: {
nfa *left_nfa = reg_thompson(expr->left);
nfa *right_nfa = reg_thompson(expr->right);
nfa *result_nfa = nfa_concat(left_nfa, right_nfa);
nfa_delete(left_nfa);
nfa_delete(right_nfa);
return result_nfa;
}
case STAR: {
nfa *sub_nfa = reg_thompson(expr->left);
nfa *result_nfa = nfa_star(sub_nfa);
nfa_delete(sub_nfa);
return result_nfa;
}
case INTER: {
nfa *left_nfa = reg_thompson(expr->left);
nfa *right_nfa = reg_thompson(expr->right);
nfa *result_nfa = nfa_intersect(left_nfa, right_nfa, false);
nfa_delete(left_nfa);
nfa_delete(right_nfa);
return result_nfa;
}
case COMPLEMENT: {
nfa *sub_nfa = reg_thompson(expr->left);
nfa *det_nfa = nfa_determinize(sub_nfa, false);
nfa *comp_nfa = nfa_mirror(det_nfa);
nfa_delete(sub_nfa);
nfa_delete(det_nfa);
return comp_nfa;
}
default:
return NULL;
}
}

2123
Aloyse et Vincent/scan.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
#include "shell_help.h"
#define PAD1 30
#define PAD2 33
#define PADC 8
void help(void) {
FILE *p = stdout;
print_dtitle_box(100, true, p, 1, "Bienvenue dans l'aide du programme LEA !");
print_title_box(100, true, p, 1, "Commandes de base");
fprintf(p, "%4s%-*sAffiche cette aide.\n", "", PAD1, "help");
fprintf(p, "%4s%-*sQuitte le programme.\n", "", PAD1, "quit ou exit ou Ctrl-D");
fprintf(p, "%4s%-*sAffiche les langages définis.\n", "", PAD1, "languages");
fprintf(p, "%4s%-*sAffiche les automates définis.\n", "", PAD1, "automata");
fprintf(p, "%4s%-*sTrie tous les objets par leur nom.\n", "", PAD1, "sort");
fprintf(p, "%4s%-*sSupprime un objet (langage ou automate).\n", "", PAD1,
"delete(<variable>)");
fprintf(p, "%4s%-*sSauve tous les objets définis dans un fichier.\n", "", PAD1,
"savesession(\"<filename>\")");
fprintf(p, "%4s%-*sCharge tous les objets définis dans un fichier.\n", "", PAD1,
"loadsession(\"<filename>\")");
fprintf(p, "%4s%-*sExécute la fonction test() de shell_test.c.\n", "", PAD1, "test");
fprintf(p, "\n");
print_title_box(100, true, p, 1, "Utilisation de variables de langages");
fprintf(p, "\n#### Définition, mémorisation d'un langage dans une variable :\n\n");
fprintf(p, "%4s## Spécification par une expression régulière :\n\n", "");
fprintf(p, "%8s<variable> = \"<regexp>\"\n\n", "");
fprintf(p,
"%4sLes guillemets sont obligatoires.\n"
"%4sNoms de variables : commencent par une majuscule, éventuellement suivie par lettres, chiffres et '_'\n\n",
"", ""
);
fprintf(p,
"%4sSyntaxe des expressions régulières (généralisées avec complément et intersection) :\n",
"");
fprintf(p, "%12se := e + e | e e | e* | !e | e & e | (e) | \\1 | \\0 | {<variable>}\n", "");
fprintf(p, "%8soù,\n", "");
fprintf(p,
"%10s- \\0 représente ∅, \\1 représente ε, ! représente le complément, & représente l'intersection.\n",
"");
fprintf(p, "%10s- Les espaces ne sont pas significatifs.\n", "");
fprintf(p, "%10s- {L} désigne l'expression mémorisée dans la variable L.\n", "");
fprintf(p,
"%10s- Pour utiliser une lettre parmi ' ', '\"', '+', '{', '}', '(', ')', '+', '*', '!' ou '&',\n",
"");
fprintf(p,
"%10s la faire précéder d'un caractère '\\' (exemple : \\+ représente la lettre '+').\n\n",
"");
fprintf(p, "%4s## Spécification par un automate :\n\n", "");
fprintf(p, "%8s<variable> = link(<nom_de_variable_d_un_automate>)\n\n", "");
fprintf(p,
"%8sB = link(A) définit une variable de langage définie par la variable d'automate A.\n"
"%8sA devient protégée, c'est-à-dire non effaçable tant que B n'est pas changée ou détruite.\n",
"", "");
fprintf(p, "\n#### Manipulation de langages :\n\n");
fprintf(p, "%4s%-*sAffiche l' expression régulière ou l'automate qui définit L.\n", "", PAD1,
"L");
fprintf(p, "%4s%-*sL'automate minimal de L : fonctionne comme une variable d'automate.\n", "",
PAD1, "L.minimal");
fprintf(p, "\n");
print_title_box(100, true, p, 1, "Utilisation de variables d'automates");
fprintf(p, "\n#### Définition, mémorisation d'un automate dans une variable A :\n\n");
fprintf(p, "%4s%-*sFait une copie de l'automate B.\n", "", PAD1, "A = B");
fprintf(p, "%4s%-*sAlgorithme de Brzozowski-McCluskey (A doit être un automate).\n", "", PAD1,
"mccluskey(A)");
fprintf(p,
"%4s%-*sAlgorithme de Thompson (L doit être spécifié par une expression régulière).\n",
"", PAD1, "thompson(L)");
fprintf(p,
"%4s%-*sAlgorithme de Glushkov (L doit être spécifié par une expression régulière simple).\n",
"", PAD1, "glushkov(L)");
fprintf(p,
"%4s%-*sÉlimination de tous les états qui sont non accessibles ou non co-accessibles de l'automate B.\n",
"", PAD1, "trim(B)");
fprintf(p, "%4s%-*sUnion non déterministe des automates B1 et B2.\n", "", PAD1,
"union(B1, B2)");
fprintf(p, "%4s%-*sIntersection des automates B1 et B2.\n", "", PAD1, "intersection(B1, B2)");
fprintf(p, "%4s%-*sConcaténation des automates B1 et B2.\n", "", PAD1, "concatenation(B1, B2)");
fprintf(p, "%4s%-*sÉtoile de Kleene de l'automate B.\n", "", PAD1, "kleene(B)");
fprintf(p, "%4s%-*sDéterminisation de l'automate B.\n", "", PAD1, "determinization(B)");
fprintf(p, "%4s%-*sMinimisation de l'automate par l'algorithme de Brzozowski.\n", "", PAD1,
"brzozowski(B)");
fprintf(p, "%4s%-*sMinimisation de l'automate par l'algorithme de Hopcroft.\n", "", PAD1,
"hopcroft(B)");
fprintf(p, "%4s%-*sSuppression des noms des états dans l'automate B (si il y en a).\n", "",
PAD1,
"resetnames(B)");
fprintf(p, "\n#### Manipulation :\n\n");
fprintf(p, "%4s%-*sAffiche l'automate.\n", "", PAD1, "A");
fprintf(p, "%4s%-*sCalcule l'ensemble des états de A atteints sur le mot d'entrée word.\n", "",
PAD1,
"A.run(word)");
fprintf(p, "%4s%-*sÉcrit le code de l'automate A dans un fichier C.\n", "", PAD1,
"code(A, \"filename.c\")");
fprintf(p, "%4s%-*sSauvegarde l'automate A dans un fichier.\n", "", PAD1,
"save(A, \"filename\")");
fprintf(p, "%4s%-*sCharge dans A le NFA mémorisé dans un fichier.\n", "", PAD1,
"A = open(\"filename\")");
fprintf(p, "\n");
}

View File

@@ -0,0 +1,347 @@
#include "shell_keywords.h"
#include <ctype.h>
/************************/
/* Tableau des keywords */
/************************/
// Tableaux pour mémoriser l'association entre les keywords et les chaînes à
// utiliser dans le parser
#define KEYWORDS_MAX 512
uint keywords_count, strings_count;
com_keyword keywords_keyarray[KEYWORDS_MAX];
const char *keywords_strarray[KEYWORDS_MAX];
const char *all_strings[KEYWORDS_MAX];
// Ajout d'un keyword
void keywords_add_key(com_keyword thekey, const char *thename) {
keywords_keyarray[keywords_count] = thekey;
keywords_strarray[keywords_count] = thename;
keywords_count++;
all_strings[strings_count++] = thename;
}
// Ajout de tous les keywords
void keywords_add_all_keys(void) {
// Interface
keywords_add_key(CM_INTERFACE, "exit");
keywords_add_key(CM_INTERFACE, "help");
keywords_add_key(CM_INTERFACE, "automata");
keywords_add_key(CM_INTERFACE, "languages");
keywords_add_key(CM_INTERFACE, "help");
// Mots-clés
keywords_add_key(CM_COMPLEM, "complement");
keywords_add_key(CM_DETERMIN, "determinization");
keywords_add_key(CM_IMAGE, "image");
keywords_add_key(CM_INFO, "info");
keywords_add_key(CM_INTERSEC, "intersection");
keywords_add_key(CM_CONCAT, "concatenation");
keywords_add_key(CM_KLEENE, "kleene");
keywords_add_key(CM_LOADSESSION, "loadsession");
keywords_add_key(CM_MINI, "minimal");
keywords_add_key(CM_MULT, "multiplication");
keywords_add_key(CM_OPEN, "open");
keywords_add_key(CM_RUN, "run");
keywords_add_key(CM_SAVE, "save");
keywords_add_key(CM_CODE, "code");
keywords_add_key(CM_SAVESESSION, "savesession");
keywords_add_key(CM_THOMPSON, "thompson");
keywords_add_key(CM_GLUSHKOV, "glushkov");
keywords_add_key(CM_HOPCROFT, "hopcroft");
keywords_add_key(CM_BRZOZO, "brzozowski");
keywords_add_key(CM_BMCK, "mccluskey");
keywords_add_key(CM_TRIMNFA, "trim");
keywords_add_key(CM_RESET, "resetnames");
keywords_add_key(CM_DELETE, "delete");
keywords_add_key(CM_UNION, "union");
keywords_add_key(CM_MIRROR, "mirror");
keywords_add_key(CM_LINK, "link");
keywords_add_key(CM_SORT, "sort");
all_strings[keywords_count] = NULL;
}
/********************************/
/* Messages d'érreur génériques */
/********************************/
// Commande invalide
void shell_command_error(void) {
fprintf(stderr, "Error: this is not a valid command.\n");
}
// Arguments invalides
void shell_arguments_error(void) {
fprintf(stderr, "Error: these are not valid arguments.\n");
}
// Variable inconnue
void shell_variable_error(void) {
fprintf(stderr, "Error: unknown variable.\n");
}
/**************************************/
/* Conversion d'une chaîne en élement */
/**************************************/
static bool keywords_comp_chain(const char *s, const char *slow) {
uint len = strlen(s);
if (strlen(s) != strlen(slow)) {
return false;
}
for (uint i = 0; i < len; i++) {
if (tolower(s[i]) != tolower(slow[i])) {
return false;
}
}
return true;
}
com_keyword string_to_keyword(char *s) {
for (uint i = 0; i < keywords_count; i++) {
if (keywords_comp_chain(s, keywords_strarray[i])) {
return keywords_keyarray[i];
}
}
return KY_NULL;
}
// Fonction qui teste si un nom de variable est autorisé
// Est-ce qu'on évite les keywords ?
// Est-ce que la première lettre est bien une majuscule ?
// Est-ce que ce n'est pas une variable protégée?
bool check_varname(char *name) {
if (name == NULL || name[0] < 'A' || name[0] > 'Z') {
fprintf(stderr, "Error: a variable name must start with an upper case letter.\n");
return false;
}
for (uint i = 0; i < keywords_count; i++) {
if (keywords_comp_chain(name, keywords_strarray[i])) {
fprintf(stderr, "Error: this variable name is disallowed.\n");
return false;
}
}
int i = object_get_from_name(name);
if (i != -1 && objects[i]->parent != -1) {
fprintf(stderr, "Error: cannot overwrite a protected variable.\n");
return false;
}
return true;
}
/*********************************/
/* Informations sur une commande */
/*********************************/
// Teste si une commande est constituée d'un maillon correspondant à une chaîne
// brute
bool com_israw(com_command *thecom) {
if (thecom == NULL || thecom->main == NULL || thecom->main->next != NULL ||
thecom->params != NULL || thecom->thetype != CMT_RAW) {
return false;
}
return true;
}
// Teste si une commande est constituée d'un maillon unique SANS paramètres
bool com_single(com_command *thecom) {
if (thecom == NULL || thecom->main == NULL || thecom->main->next != NULL ||
thecom->params != NULL) {
return false;
}
return true;
}
// Teste si une commande est constituée d'un maillon unique avec ou sans
// paramètres
bool com_single_par(com_command *thecom) {
if (thecom == NULL || thecom->main == NULL || thecom->main->next != NULL) {
return false;
}
return true;
}
// Récupération du nombre de paramètres d'une commande
int com_nbparams(com_parameters *thepar) {
int res = 0;
while (thepar != NULL) {
thepar = thepar->next;
res++;
}
return res;
}
// Retourne le tableau des paramètres d'une commande
com_command **com_getparamarray(com_parameters *thepar) {
com_command **array = NULL;
int n = com_nbparams(thepar);
if (n != 0) {
MALLOC(array, n);
for (int i = 0; i < n; i++) {
array[i] = thepar->param;
thepar = thepar->next;
}
}
return array;
}
// Récupération du nième paramètre d'une commande (qui est lui-même une
// commande)
com_command *com_getparam(com_parameters *thepar, int n) {
if (thepar == NULL) {
return NULL;
}
if (thepar->count <= n) {
return NULL;
}
while (n > 0) {
thepar = thepar->next;
n--;
}
return thepar->param;
}
// Retourne l'index de l'objet désigné par une chaîne (-1 si il n'y en a pas)
int index_from_string_chain(string_chain *thechain) {
if (thechain == NULL) {
return -1;
}
int i = object_get_from_name(thechain->string);
if (i == -1) {
return -1;
}
string_chain *temp = thechain->next;
while (temp) {
com_keyword key = string_to_keyword(temp->string);
switch (key) {
case CM_MINI:
if (objects[i]->type != LANGUAGE) {
return -1;
}
shell_compute_minimal(i);
i = objects[i]->lan->minauto;
temp = temp->next;
break;
default:
return -1;
break;
}
}
return i;
}
// Retourne le mot-clé associé au premier maillon d'une chaîne (KY_NULL si il
// n'y en a pas)
com_keyword key_from_string_chain(string_chain *thechain) {
if (thechain == NULL) {
return KY_NULL;
}
else {
return string_to_keyword(thechain->string);
}
}
// Retourne le mot-clé associé à une chaîne d'un seul maillon (KY_NULL si il n'y
// en a pas ou si il y a plus d'un maillon)
com_keyword key_from_string_chain_single(string_chain *thechain) {
if (thechain == NULL || thechain->next != NULL) {
return KY_NULL;
}
else {
return string_to_keyword(thechain->string);
}
}
/*******************************/
/* Récupération d'une commande */
/*******************************/
string_chain *com_make_string_chain(char *s, string_chain *thechain) {
string_chain *new;
MALLOC(new, 1);
new->string = s;
new->next = thechain;
return new;
}
com_parameters *com_make_parameters(com_command *theparam, com_parameters *params) {
com_parameters *new;
MALLOC(new, 1);
if (params) {
new->count = params->count + 1;
}
else {
new->count = 1;
}
new->next = params;
new->param = theparam;
return new;
}
com_command *com_make_command(char *s, com_command *thecom) {
string_chain *new;
MALLOC(new, 1);
new->string = s;
new->next = thecom->main;
thecom->main = new;
return thecom;
}
com_command *com_init_command(char *s, com_parameters *params) {
string_chain *new;
MALLOC(new, 1);
new->string = s;
new->next = NULL;
com_command *thecom;
MALLOC(thecom, 1);
thecom->thetype = CMT_KEY;
thecom->params = params;
thecom->main = new;
return thecom;
}
com_command *com_init_rawcommand(char *s) {
string_chain *new;
MALLOC(new, 1);
new->string = s;
new->next = NULL;
com_command *thecom;
MALLOC(thecom, 1);
thecom->thetype = CMT_RAW;
thecom->params = NULL;
thecom->main = new;
return thecom;
}
//
void com_free_string_chain(string_chain *thechain) {
if (thechain) {
com_free_string_chain(thechain->next);
free(thechain->string);
free(thechain);
}
}
void com_free_parameters(com_parameters *params) {
if (params) {
com_free_parameters(params->next);
com_free_command(params->param);
free(params);
}
}
void com_free_command(com_command *thecom) {
if (thecom) {
com_free_string_chain(thecom->main);
com_free_parameters(thecom->params);
free(thecom);
}
}
//

View File

@@ -0,0 +1,353 @@
#include "shell_languages.h"
#include "error.h"
#include "shell_languages.h"
#include "nfa.h"
#include "regexp.h"
// #define MAX_LANGUAGES 2048
// language* languages[MAX_LANGUAGES];
// int nb_languages = 0;
#define MAX_OBJECTS 2048
object* objects[MAX_OBJECTS];
int nb_objects = 0;
unsigned short minicount = 0;
unsigned short syntcount = 0;
/************************/
/* Création/Suppression */
/************************/
object* object_language_new_reg(char* name, regexp* theregexp) {
object* theobject;
MALLOC(theobject, 1);
theobject->name = strdup(name);
theobject->type = LANGUAGE;
theobject->parent = -1;
language* lang;
MALLOC(lang, 1);
lang->type = SPE_REG;
lang->reg = theregexp;
lang->minauto = -1;
theobject->lan = lang;
return theobject;
}
object* object_language_new_nfa(char* name, int i) {
if (objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: this is not an automata variable.\n");
return NULL;
}
object* theobject;
MALLOC(theobject, 1);
theobject->name = strdup(name);
theobject->type = LANGUAGE;
theobject->parent = -1;
language* lang;
MALLOC(lang, 1);
lang->type = SPE_NFA;
lang->nfa = i;
lang->minauto = -1;
theobject->lan = lang;
return theobject;
}
object* object_automata_new(char* name, nfa* A) {
object* theobject;
MALLOC(theobject, 1);
theobject->name = strdup(name);
theobject->type = AUTOMATON;
theobject->parent = -1;
automata* aut;
MALLOC(aut, 1);
aut->nfa = A;
theobject->aut = aut;
return theobject;
}
void object_free(object* theobject) {
if (theobject == NULL) {
return;
}
// Libération du nom
free(theobject->name);
switch (theobject->type) {
case AUTOMATON:
if (theobject->aut == NULL) {
free(theobject);
return;
}
nfa_delete(theobject->aut->nfa);
free(theobject->aut);
break;
case LANGUAGE:
if (theobject->lan == NULL) {
free(theobject);
return;
}
// Si le langage est spécifié par une expression,
// on la libère.
if (theobject->lan->type == SPE_REG) {
if (theobject->lan->reg) {
reg_free(theobject->lan->reg);
}
}
// Si le langage est spécifié par un NFA, on enlève
// le flag qui protège ce NFA.
else if (theobject->lan->type == SPE_NFA) {
objects[theobject->lan->nfa]->parent = -1;
}
// Si le langage est associèe à un minimal, on enlève
// le flag qui protège ce minimal.
if (theobject->lan->minauto != -1) {
objects[theobject->lan->minauto]->parent = -1;
}
free(theobject->lan);
break;
default:
break;
}
free(theobject);
}
/*************************************/
/* Récupération/insertion d'un objet */
/*************************************/
int object_get_from_name(char* name) {
for (int i = 0; i < nb_objects; i++) {
if (objects[i] && strcmp(objects[i]->name, name) == 0) {
return i;
}
}
return -1;
}
int object_delete_from_name(char* name) {
int i = object_get_from_name(name);
if (i == -1) {
fprintf(stderr, "Error: unknown variable.\n");
return -1;
}
else if (objects[i] && objects[i]->parent != -1) {
fprintf(stderr, "Error: this is a protected variable.\n");
return -1;
}
else {
object_free(objects[i]);
nb_objects--;
if (nb_objects > 0) {
objects[i] = objects[nb_objects];
}
return i;
}
}
int object_add_language_reg(char* name, regexp* theregexp) {
if (theregexp == NULL) {
return -1;
}
if (nb_objects == MAX_OBJECTS) {
ERROR("Error: too many objects are already stored in memory.\n");
return -1;
}
int i = object_get_from_name(name);
if (i != -1 && objects[i]->parent == -1) {
// Si il y a déjà un objet à ce nom et qu'il n'est pas protégé
DEBUG("Warning: an object with name %s already exists\n", name);
object_free(objects[i]);
objects[i] = object_language_new_reg(name, theregexp);
return i;
}
else if (i != -1 && objects[i]->parent != -1) {
fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n");
reg_free(theregexp);
return -1;
}
else {
objects[nb_objects++] = object_language_new_reg(name, theregexp);
return nb_objects - 1;
}
}
int object_add_language_nfa(char* name, int j) {
if (j == -1 || objects[j]->type != AUTOMATON) {
return -1;
}
if (nb_objects == MAX_OBJECTS) {
ERROR("Error: too many objects are already stored in memory.\n");
return -1;
}
int i = object_get_from_name(name);
if (i != -1 && objects[i]->parent == -1) {
// Si il y a déjà un objet à ce nom et qu'il n'est pas protégé
DEBUG("Warning: an object with name %s already exists\n", name);
object_free(objects[i]);
objects[i] = object_language_new_nfa(name, j);
objects[j]->parent = i;
return i;
}
else if (i != -1 && objects[i]->parent != -1) {
fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n");
return -1;
}
else {
objects[nb_objects++] = object_language_new_nfa(name, j);
objects[j]->parent = nb_objects - 1;
return nb_objects - 1;
}
}
int object_add_automata(char* name, nfa* A) {
if (A == NULL) {
return -1;
}
if (nb_objects == MAX_OBJECTS) {
ERROR("Error: too many objects are already stored in memory.\n");
return -1;
}
int i = object_get_from_name(name);
// Si il y a déjà un objet à ce nom
if (i != -1 && objects[i]->parent == -1) {
DEBUG("Warning: an object with name %s already exists\n", name);
object_free(objects[i]);
objects[i] = object_automata_new(name, A);
return i;
}
else if (i != -1 && objects[i]->parent != -1) {
fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n");
nfa_delete(A);
return -1;
}
else {
objects[nb_objects++] = object_automata_new(name, A);
return nb_objects - 1;
}
}
static int object_compare(const void* pob1, const void* pob2) {
object* ob1 = *(object* const*)pob1;
object* ob2 = *(object* const*)pob2;
if (ob1 == NULL) {
if (ob2 == NULL) {
return 0;
}
return -1;
}
if (ob2 == NULL) {
return 1;
}
return strcmp(ob1->name, ob2->name);
}
void object_sort_array(void) {
qsort(objects, nb_objects, sizeof(object*), &object_compare);
}
/****************************/
/* Affichage d'informations */
/****************************/
void object_print_langs(void) {
// Calcul du nombre de langages
ushort count = 0;
for (int i = 0; i < nb_objects; i++) {
if (objects[i]->type == LANGUAGE) {
count++;
}
}
printf("#### There are %d language(s) in memory:\n\n", count);
if (count > 0) {
count = 1;
}
for (int i = 0; i < nb_objects; i++) {
if (objects[i]->type == LANGUAGE) {
printf("#### %d: %s\n", count, objects[i]->name);
if (objects[i]->lan->type == SPE_REG) {
printf(" Specified by a regular expression\n");
printf(" Regexp: ");
reg_print(objects[i]->lan->reg);
}
else if (objects[i]->lan->type == SPE_NFA) {
printf(" Specified by an automaton.\n");
}
printf("\n");
count++;
}
}
}
void object_print_autos(void) {
// Calcul du nombre d'automates'
ushort count = 0;
for (int i = 0; i < nb_objects; i++) {
if (objects[i]->type == AUTOMATON) {
count++;
}
}
printf("#### There are %d automata in memory:\n\n", count);
if (count > 0) {
count = 1;
}
for (int i = 0; i < nb_objects; i++) {
if (objects[i]->type == AUTOMATON) {
printf("#### %d: %s\n", count, objects[i]->name);
if (objects[i]->parent != -1 && objects[objects[i]->parent]->type == LANGUAGE) {
printf(" Protected: tied to the language %s.\n",
objects[objects[i]->parent]->name);
}
printf("\n");
count++;
}
}
}
/************************************************/
/* Calculs d'informations sur un objet existant */
/************************************************/
// Calcul du DFA minimal d'un langage
int shell_compute_minimal(int i) {
if (objects[i]->type != LANGUAGE) {
fprintf(stderr, "Should be a language.\n");
return -1;
}
language* lang = objects[i]->lan;
if (lang->minauto == -1) {
DEBUG("Computing the minimal automaton of a language");
nfa* A;
if (lang->type == SPE_REG) {
A = reg_thompson(lang->reg);
}
else {
A = objects[lang->nfa]->aut->nfa;
}
char* newname;
MALLOC(newname, 20);
sprintf(newname, "SYSMINI%04d", minicount++);
lang->minauto = object_add_automata(newname, nfa_brzozowski(A));
free(newname);
// On protège le NFA minimal qu'on a créé
objects[lang->minauto]->parent = i;
nfa_delete(A);
}
return lang->minauto;
}

View File

@@ -0,0 +1,401 @@
#include "shell_test.h"
#include <stdbool.h>
#include <stdio.h>
#include "error.h"
#include "files.h"
#include "graphs.h"
#include "nfa.h"
#include "nfa_determi.h"
#include "nfa_tocode.h"
#include "parse_regexp.h"
#include "parser.h"
#include "shell_languages.h"
#include "shell_tools.h"
#include "type_boolarray.h"
#include "type_dequeue.h"
// Cette fonction est appelée par le shell sur la commande "test".
// Vous pouvez y mettre le code que vous voulez tester.
#define TEST_DEQUEUE true
#define TEST_BOOLARRAY false
#define NB_TESTS_OCCUR 100000
#define NB_MAX_SIZE_DEQUEUE 100
static void printf_dequeue(dequeue *dq, char *function, char *var,
int i_function, int i_result) {
if (function != NULL)
printf("%s(", function);
else
printf("%s\n", var);
if (function != NULL && i_function >= 0)
printf("%d, ", i_function);
if (function != NULL)
printf("%s)", var);
if (function != NULL && i_result >= 0)
printf(" = %d\n", i_result);
else if (function != NULL)
printf("\n");
print_dequeue(dq);
printf("isempty_dequeue(%s) = %d\n", var, isempty_dequeue(dq));
printf("size_dequeue(%s) = %d\n", var, size_dequeue(dq));
printf("\n");
}
static void printf_boolarray(barray *ba, char *function, char *var,
int i_function, int i_result) {
if (function != NULL)
printf("%s(", function);
else
printf("%s\n", var);
if (function != NULL && i_function >= 0)
printf("%d, ", i_function);
if (function != NULL)
printf("%s)", var);
if (function != NULL && i_result >= 0)
printf(" = %d\n", i_result);
else if (function != NULL)
printf("\n");
printf("Boolarray : ");
for (uint i = 0; i < getsize_barray(ba); i++) {
printf("%d ", getval_barray(ba, i));
}
printf("\n");
printf("getsize_barray(%s) = %d\n", var, getsize_barray(ba));
printf("\n");
}
void test(void) {
// regexp *myexp;
// Cette première affectation ne fonctionnera que si vous avez implémenté
// les fonctions du module regexp.h.
// myexp = parse_string_regexp("(a+bb)*");
// L'affichage de l'expression régulière est fait par la fonction reg_print,
// définie dans printing.c et déjà fournie. Vous pouvez la décommenter pour
// afficher l'expression régulière, après avoir implémenté les fonctions
// nécessaires dans regexp.c.
// reg_print(myexp);
// Autre exemple, avec une construction directe de NFA.
// nfa* A = create_sing_epsilon();
// nfa_view(A);
if (NB_MAX_SIZE_DEQUEUE == 0) {
ERROR("NB_MAX_SIZE_DEQUEUE doit être supérieur à 0");
exit(EXIT_FAILURE);
}
// Tests de dequeue
if (TEST_DEQUEUE) {
dequeue *dq = create_dequeue();
printf_dequeue(dq, NULL, "dq", 0, -1);
for (uint i = 11; i <= 20; i++) {
rigins_dequeue(i, dq);
// printf_dequeue(dq, "rigins_dequeue", "dq", i, -1);
}
for (uint i = 10; i > 0; i--) {
lefins_dequeue(i, dq);
// printf_dequeue(dq, "leftins_dequeue", "dq", i, -1);
}
printf("--------------------\n");
printf("Test rigins_dequeue et leftins_dequeue\n"); // Test rigins_dequeue
// et leftins_dequeue
printf("--------------------\n");
for (uint i = 0; i < size_dequeue(dq); i++) {
assert(lefread_dequeue(dq, i) == i + 1);
printf("assert(lefread_dequeue(dq, %d) == %d) check\n", i, i + 1);
}
for (uint i = 0; i < (uint)rand() % 100; i++) {
if (i % 2 == 0) {
uint tmp[i / 2];
for (uint j = 0; j < i / 2; j++) {
// printf_dequeue(dq, "lefread_dequeue", "dq", -1,
// lefread_dequeue(dq, 0));
tmp[j] = lefpull_dequeue(dq);
// printf_dequeue(dq, "lefpull_dequeue",
// "dq", -1, -1);
}
for (uint j = 0; j < i / 2; j++) {
lefins_dequeue(tmp[i / 2 - j - 1], dq);
// printf_dequeue(dq, "lefins_dequeue", "dq", tmp[j], -1);
}
} else {
uint tmp[i / 2];
for (uint j = 0; j < i / 2; j++) {
// printf_dequeue(dq, "rigread_dequeue", "dq", -1,
// rigread_dequeue(dq, 0));
tmp[j] = rigpull_dequeue(dq);
// printf_dequeue(dq, "rigpull_dequeue", "dq", -1, -1);
}
for (uint j = 0; j < i / 2; j++) {
rigins_dequeue(tmp[i / 2 - j - 1], dq);
// printf_dequeue(dq, "rigins_dequeue", "dq", tmp[j], -1);
}
}
}
printf("--------------------\n");
printf("Test lefpull_dequeue et rigpull_dequeue\n"); // Test
// lefpull_dequeue et
// rigpull_dequeue
printf("--------------------\n");
for (uint i = 0; i < size_dequeue(dq); i++) {
assert(lefread_dequeue(dq, i) == i + 1);
printf("assert(lefread_dequeue(dq, %d) == %d) check\n", i, i + 1);
}
printf("--------------------\n");
printf(
"Test makeempty_dequeue et copy_dequeue_right in array [1, 20]\n"); // Test makeempty_dequeue et copy_dequeue_right
printf("--------------------\n");
dequeue *dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
makeempty_dequeue(dq2);
// printf_dequeue(dq2, "makeempty_dequeue", "dq2", -1, -1);
copy_dequeue_right(dq2, dq, i);
// printf_dequeue(dq2, "copy_dequeue_right", "dq2", i, -1);
printf("----------");
printf(" Test +%d ", i);
printf("----------\n");
for (uint j = 0; j < size_dequeue(dq2); j++) {
assert(lefread_dequeue(dq2, j) == lefread_dequeue(dq, j) + i);
printf("assert(lefread_dequeue(dq2, %d) == %d) check\n", j,
lefread_dequeue(dq, j) + i);
}
}
printf("--------------------\n");
printf("Test mem_dequeue in array [1, 20]\n"); // Test mem_dequeue
printf("--------------------\n");
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
uint value = rand() % 100;
// printf_dequeue(dq, "mem_dequeue", "dq2", value,
// mem_dequeue(value, dq));
assert(mem_dequeue(value, dq) == (value > 0 && value <= 20));
printf("assert(mem_dequeue(%d, dq) == %d) check\n", value,
(value > 0 && value <= 20));
}
if (dq == NULL)
delete_dequeue(dq2);
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE + 1; i++) {
lefins_dequeue(rand() % 100, dq2);
}
// printf_dequeue(dq2, "random", "dq2", -1, -1);
sort_dequeue_norepeat(dq2);
// printf_dequeue(dq2, "sort_dequeue_norepeat", "dq2", -1, -1);
printf("--------------------\n");
printf("Test sort_dequeue_norepeat\n"); // Test sort_dequeue_norepeat
printf("--------------------\n");
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2) - 1;
i++) {
assert(lefread_dequeue(dq2, i) < lefread_dequeue(dq2, i + 1));
printf("%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
// for (uint i = 0; i < 20; i++) {
// printf_dequeue(dq2, "mem_dequeue_sorted", "dq2", i,
// mem_dequeue_sorted(i, dq2));
// }
printf("--------------------\n");
printf("Test mem_dequeue_sorted\n"); // Test mem_dequeue_sorted
printf("--------------------\n");
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2); i++) {
assert(mem_dequeue_sorted(i, dq2) == mem_dequeue(i, dq2));
printf("assert(mem_dequeue_sorted(%d, dq2) == %d) check\n", i,
mem_dequeue(i, dq2));
}
if (dq2 == NULL)
delete_dequeue(dq2);
}
printf("--------------------\n");
printf("Test merge_sorted_dequeue\n"); // Test merge_sorted_dequeue
printf("--------------------\n");
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
dq2 = create_dequeue();
dequeue *dq3 = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
sort_dequeue_norepeat(dq2);
copy_dequeue_right(dq3, dq, 0);
merge_sorted_dequeue(dq3, dq2);
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3) - 1;
i++) {
printf("size = %d\n", size_dequeue(dq3));
assert(lefread_dequeue(dq3, i) < lefread_dequeue(dq3, i + 1));
printf("%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3); i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq3, i), dq) ||
mem_dequeue_sorted(lefread_dequeue(dq3, i), dq2));
printf("%u%% - assert(mem_dequeue_sorted(%d, dq) || "
"mem_dequeue_sorted(%d, dq2)) check\n",
k / (NB_TESTS_OCCUR / 100), lefread_dequeue(dq3, i),
lefread_dequeue(dq3, i));
}
for (uint i = 0; size_dequeue(dq) > 0 && i < size_dequeue(dq); i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq, i), dq3));
printf("%u%% - assert(mem_dequeue_sorted(leftread_dequeue(dq, "
"%d), "
"dq3)) check\n",
k / (NB_TESTS_OCCUR / 100), i);
}
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2); i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq2, i), dq3));
printf("%u%% - assert(mem_dequeue_sorted(leftread_dequeue(dq2, "
"%d), "
"dq3)) check\n",
k / (NB_TESTS_OCCUR / 100), i);
}
if (dq == NULL)
delete_dequeue(dq);
if (dq2 == NULL)
delete_dequeue(dq2);
if (dq3 == NULL)
delete_dequeue(dq3);
}
printf("--------------------\n");
printf("Test make_inter_sorted_dequeue\n"); // Test
// make_inter_sorted_dequeue
printf("--------------------\n");
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
sort_dequeue_norepeat(dq2);
dequeue *dq3 = make_inter_sorted_dequeue(dq, dq2);
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3); i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq3, i), dq) &&
mem_dequeue_sorted(lefread_dequeue(dq3, i), dq2));
printf("%u%% - assert(mem_dequeue_sorted(%d, dq) && "
"mem_dequeue_sorted(%d, dq2)) check\n",
k / (NB_TESTS_OCCUR / 100), lefread_dequeue(dq3, i),
lefread_dequeue(dq3, i));
}
if (dq == NULL)
delete_dequeue(dq);
if (dq2 == NULL)
delete_dequeue(dq2);
if (dq3 == NULL)
delete_dequeue(dq3);
}
printf("--------------------\n");
printf("Test intersec_dequeue\n"); // Test
// intersec_dequeue
printf("--------------------\n");
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
sort_dequeue_norepeat(dq2);
bool result = intersec_dequeue(dq, dq2);
dequeue *dq3 = make_inter_sorted_dequeue(dq, dq2);
assert(result == (size_dequeue(dq3) > 0));
printf("%u%% - size_dequeue(make_inter_sorted_dequeue(dq, dq2)) "
"check\n",
k / (NB_TESTS_OCCUR / 100));
if (dq == NULL)
delete_dequeue(dq);
if (dq2 == NULL)
delete_dequeue(dq2);
}
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
sort_dequeue_norepeat(dq);
uint val = rand() % 100;
insert_dequeue(dq, val);
for (uint i = 0; size_dequeue(dq) > 0 && i < size_dequeue(dq) - 1; i++) {
assert(lefread_dequeue(dq, i) < lefread_dequeue(dq, i + 1));
printf("%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
assert(mem_dequeue_sorted(val, dq));
printf("%u%% - assert(mem_dequeue_sorted(%d, dq)) check\n",
k / (NB_TESTS_OCCUR / 100), val);
if (dq == NULL)
delete_dequeue(dq);
}
printf("--------------------\n");
printf("Plus de %d tests effectués avec succès\n", NB_TESTS_OCCUR * 5);
}
// Tests de boolarray
if (TEST_BOOLARRAY) {
barray *ba = create_barray(10);
printf_boolarray(ba, NULL, "ba", 0, -1);
for (uint i = 0; i < 10; i++) {
if (i % 2 == 0) {
settrue_barray(ba, i);
printf_boolarray(ba, "settrue_barray", "ba", i, -1);
} else {
setfalse_barray(ba, i);
printf_boolarray(ba, "setfalse_barray", "ba", i, -1);
}
}
delete_barray(ba);
ba = create_barray(10);
for (uint i = 0; i < 10; i++) {
bool x = rand() % 2;
if (x) {
settrue_barray(ba, i);
printf_boolarray(ba, "settrue_barray", "ba", i, -1);
} else {
setfalse_barray(ba, i);
printf_boolarray(ba, "setfalse_barray", "ba", i, -1);
}
}
barray *ba2 = create_barray(10);
for (uint i = 0; i < 10; i++) {
bool x = rand() % 2;
if (x) {
settrue_barray(ba2, i);
} else {
setfalse_barray(ba2, i);
}
}
printf_boolarray(ba2, NULL, "ba2", -1, -1);
barray *ba3 = or_barray(ba, ba2);
printf_boolarray(ba3, "or_barray", "ba3", -1, -1);
delete_barray(ba3);
ba3 = and_barray(ba, ba2);
printf_boolarray(ba3, "and_barray", "ba3", -1, -1);
delete_barray(ba3);
delete_barray(ba2);
printf_boolarray(ba, NULL, "ba", -1, -1);
ba2 = copy_barray(ba);
printf_boolarray(ba2, "copy_barray", "ba", -1, -1);
delete_barray(ba);
}
}

View File

@@ -0,0 +1,445 @@
#include "shell_tools.h"
static uint num_length_aux(uint n) {
if (n == 0) {
return 0;
}
else {
return num_length_aux(n / 10) + 1;
}
}
uint num_length(uint n) {
if (n == 0) {
return 1;
}
else {
return num_length_aux(n);
}
}
char* multiple_strcat(char* s, ...) {
va_list ap;
char* t = s;
size_t len = 0;
va_start(ap, s);
do
{
len += strlen(t);
} while ((t = va_arg(ap, char*)));
va_end(ap);
char* ret;
CALLOC(ret, len + 1);
t = s;
va_start(ap, s);
do
{
strcat(ret, t);
} while ((t = va_arg(ap, char*)));
va_end(ap);
return ret;
}
void print_top_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_mid_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_bot_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_sep_line(uint length, FILE* out) {
print_top_line(length, out);
print_bot_line(length, out);
}
void print_dtop_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_dmid_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_dbot_line(uint length, FILE* out) {
fprintf(out, "");
for (uint i = 0; i < length; i++) {
fprintf(out, "");
}
fprintf(out, "\n");
}
void print_spaces(uint number, FILE* out) {
for (uint i = 0; i < number; i++) {
fprintf(out, " ");
}
}
void print_char(uint number, char* c, FILE* out) {
for (uint i = 0; i < number; i++) {
fprintf(out, "%s", c);
}
}
uint count_utf8_code_points(const char* s) {
uint count = 0;
while (*s) {
count += (*s++ & 0xC0) != 0x80;
}
return count;
}
// Affichage d'un titre dans une boite.
// La taille minimale autorisée est 100 (le max de length et 100 est utilisé)
void print_title_box(uint length, bool closed, FILE* out, uint nlines, ...) {
// La taille minimale est 100
length = max(length, 100);
// Récupération des lignes à écrire
va_list list;
va_start(list, nlines);
char* input[nlines];
for (uint i = 0; i < nlines; i++) {
input[i] = va_arg(list, char*);
if (count_utf8_code_points(input[i]) > length) {
printf("Printing error, the title is too long for the chosen length\n");
return;
}
if (strchr(input[i], '\n') != NULL) {
printf("Printing error, the title should not contain \"newline\"\n");
return;
}
}
// Si tout s'est bien passé, on passe à la phase d'écriture
print_top_line(length, out);
for (uint i = 0; i < nlines; i++) {
uint titlelen = count_utf8_code_points(input[i]);
fprintf(out, "");
uint pad = length - titlelen;
print_spaces(pad / 2, out);
fprintf(out, "%s", input[i]);
print_spaces((pad / 2) + (pad % 2), out);
fprintf(out, "\n");
}
if (closed) {
print_bot_line(length, out);
}
else {
print_mid_line(length, out);
}
}
void print_title_box_shift(uint length, uint shiftl, uint shiftr, bool closed, FILE* out,
uint nlines, ...) {
// La taille minimale est 100
length = max(length, 100);
// Récupération des lignes à écrire
va_list list;
va_start(list, nlines);
char* input[nlines];
for (uint i = 0; i < nlines; i++) {
input[i] = va_arg(list, char*);
if (count_utf8_code_points(input[i]) > length) {
printf("Printing error, the title is too long for the chosen length\n");
return;
}
if (strchr(input[i], '\n') != NULL) {
printf("Printing error, the title should not contain \"newline\"\n");
return;
}
}
// Si tout s'est bien passé, on passe à la phase d'écriture
print_top_line(length, out);
for (uint i = 0; i < nlines; i++) {
uint titlelen = count_utf8_code_points(input[i]);
fprintf(out, "");
uint pad = length - titlelen;
print_spaces(pad / 2 - shiftl, out);
fprintf(out, "%s", input[i]);
print_spaces((pad / 2) + (pad % 2) - shiftr, out);
fprintf(out, "\n");
}
if (closed) {
print_bot_line(length, out);
}
else {
print_mid_line(length, out);
}
}
void print_dtitle_box(uint length, bool closed, FILE* out, uint nlines, ...) {
// La taille minimale est 100
length = max(length, 100);
// Récupération des lignes à écrire
va_list list;
va_start(list, nlines);
char* input[nlines];
for (uint i = 0; i < nlines; i++) {
input[i] = va_arg(list, char*);
if (count_utf8_code_points(input[i]) > length) {
printf("Printing error, the title is too long for the chosen length\n");
return;
}
if (strchr(input[i], '\n') != NULL) {
printf("Printing error, the title should not contain \"newline\"\n");
return;
}
}
// Si tout s'est bien passé, on passe à la phase d'écriture
print_dtop_line(length, out);
for (uint i = 0; i < nlines; i++) {
uint titlelen = count_utf8_code_points(input[i]);
fprintf(out, "");
uint pad = length - titlelen;
print_spaces(pad / 2, out);
fprintf(out, "%s", input[i]);
print_spaces((pad / 2) + (pad % 2), out);
fprintf(out, "\n");
}
if (closed) {
print_dbot_line(length, out);
}
else {
print_dmid_line(length, out);
}
}
void print_line_box(uint length, FILE* out, char* s) {
// La taille minimale est 100
length = max(length, 100);
uint linelen = count_utf8_code_points(s);
// Récupération des lignes à écrire
if (linelen > length) {
printf("Printing error, the line is too long for the chosen length\n");
return;
}
if (strchr(s, '\n') != NULL) {
printf("Printing error, the line should not contain \"newline\"\n");
return;
}
// Si tout s'est bien passé, on passe à la phase d'écriture
fprintf(out, "");
uint pad = length - linelen;
fprintf(out, "%s", s);
print_spaces(pad, out);
fprintf(out, "\n");
}
void print_dline_box(uint length, FILE* out, char* s) {
// La taille minimale est 100
length = max(length, 100);
uint linelen = count_utf8_code_points(s);
// Récupération des lignes à écrire
if (linelen > length) {
printf("Printing error, the line is too long for the chosen length\n");
return;
}
if (strchr(s, '\n') != NULL) {
printf("Printing error, the line should not contain \"newline\"\n");
return;
}
// Si tout s'est bien passé, on passe à la phase d'écriture
fprintf(out, "");
uint pad = length - linelen;
fprintf(out, "%s", s);
print_spaces(pad, out);
fprintf(out, "\n");
}
void print_booltab_alph(bool* alph_array, uint alph_size, FILE* out) {
uint a = 0;
while (a < alph_size && !alph_array[a]) {
a++;
}
if (a == alph_size) {
fprintf(out, "∅.\n");
}
else {
fprintf(out, "{%c", a + 'a');
a++;
while (a < alph_size) {
if (alph_array[a]) {
fprintf(out, ",%c", a + 'a');
}
a++;
}
fprintf(out, "}.\n");
}
}
void append_power(uint n, char* name) {
if (n != 0) {
uint d = n % 10;
append_power(n / 10, name);
switch (d) {
case 0:
strcat(name, "");
break;
case 1:
strcat(name, "¹");
break;
case 2:
strcat(name, "²");
break;
case 3:
strcat(name, "³");
break;
case 4:
strcat(name, "");
break;
case 5:
strcat(name, "");
break;
case 6:
strcat(name, "");
break;
case 7:
strcat(name, "");
break;
case 8:
strcat(name, "");
break;
case 9:
strcat(name, "");
break;
default:
break;
}
}
}
void print_power(uint n, FILE* out) {
if (n != 0) {
uint d = n % 10;
print_power(n / 10, out);
switch (d) {
case 0:
fprintf(out, "");
break;
case 1:
fprintf(out, "¹");
break;
case 2:
fprintf(out, "²");
break;
case 3:
fprintf(out, "³");
break;
case 4:
fprintf(out, "");
break;
case 5:
fprintf(out, "");
break;
case 6:
fprintf(out, "");
break;
case 7:
fprintf(out, "");
break;
case 8:
fprintf(out, "");
break;
case 9:
fprintf(out, "");
break;
default:
break;
}
}
}
void print_facto_word(char* word, FILE* out) {
uint len = strlen(word);
if (len == 0) {
printf("ε");
}
else {
uint n = 1;
fprintf(out, "%c", word[0]);
for (uint i = 1; i < len; i++) {
if (word[i] != word[i - 1]) {
if (n > 1) {
print_power(n, out);
}
fprintf(out, "%c", word[i]);
n = 1;
}
else {
n++;
}
}
if (n > 1) {
print_power(n, out);
}
}
}
void print_color(char* s, color col, FILE* out) {
switch (col) {
case RED:
fprintf(out, "\033[0;31m%s\033[0m", s);
break;
case GREEN:
fprintf(out, "\033[0;32m%s\033[0m", s);
break;
case YELLOW:
fprintf(out, "\033[0;33m%s\033[0m", s);
break;
case BLUE:
fprintf(out, "\033[0;34m%s\033[0m", s);
break;
case PURPLE:
fprintf(out, "\033[0;35m%s\033[0m", s);
break;
case CYAN:
fprintf(out, "\033[0;36m%s\033[0m", s);
break;
case WHITE:
fprintf(out, "\033[0;37m%s\033[0m", s);
break;
}
}

View File

@@ -0,0 +1,77 @@
#include "type_boolarray.h"
barray *create_barray(const uint size) {
barray *b = malloc(sizeof(barray));
if (b == NULL) {
fprintf(stderr, "Erreur d'allocation de mémoire\n");
exit(EXIT_FAILURE);
}
b->size = size;
if (size % 8 == 0) {
b->size_array = size / 8;
} else {
b->size_array = size / 8 + 1;
}
b->array = calloc(b->size_array, sizeof(uchar));
if (b->array == NULL) {
fprintf(stderr, "Erreur d'allocation de mémoire\n");
exit(EXIT_FAILURE);
}
return b;
}
uint getsize_barray(barray *thearray) { return thearray->size; }
void delete_barray(barray *thearray) {
free(thearray->array);
free(thearray);
}
void settrue_barray(barray *thearray, const uint thecell) {
thearray->array[thecell / 8] |= (1 << thecell % 8);
}
void setfalse_barray(barray *thearray, const uint thecell) {
thearray->array[thecell / 8] &= ~(1 << thecell % 8);
}
bool getval_barray(barray *thearray, const uint thecell) {
return thearray->array[thecell / 8] & (1 << thecell % 8);
}
void print_array(barray *ptr) {
for (uint i = 0; i < getsize_barray(ptr); i++) {
printf("%d ", getval_barray(ptr, i));
}
printf("\n");
}
barray *or_barray(barray *array1, barray *array2) {
if (array1->size != array2->size) {
return NULL;
}
barray *b = create_barray(array1->size);
for (uint i = 0; i < b->size_array; i++) {
b->array[i] = array1->array[i] | array2->array[i];
}
return b;
}
barray *and_barray(barray *array1, barray *array2) {
if (array1->size != array2->size) {
return NULL;
}
barray *b = create_barray(array1->size);
for (uint i = 0; i < b->size_array; i++) {
b->array[i] = array1->array[i] & array2->array[i];
}
return b;
}
barray *copy_barray(barray *thearray) {
barray *b = create_barray(thearray->size);
for (uint i = 0; i < b->size_array; i++) {
b->array[i] = thearray->array[i];
}
return b;
}

View File

@@ -0,0 +1,386 @@
/*****************************************/
/* Implémentations des listes de sommets */
/* Utilisation d'un tuyau par liste */
/*****************************************/
#include "type_dequeue.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "type_boolarray.h"
/************************/
/* Fonctions primitives */
/************************/
/* Création */
dequeue *create_dequeue(void) {
dequeue *ptr = malloc(sizeof(dequeue));
ptr->array = malloc(sizeof(uint) * 1);
ptr->size_array = 1;
ptr->left = 0;
ptr->right = 0;
ptr->empty = true;
return ptr;
}
/* Suppression */
void delete_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("delete_dequeue : ptr NULL");
if (ptr->array != NULL)
free(ptr->array);
if (ptr != NULL)
free(ptr);
ptr = NULL;
}
/* Test du vide */
bool isempty_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("isempty_dequeue : ptr NULL");
return ptr->empty;
}
/* Vidage d'un tuyau*/
void makeempty_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("makeempty_dequeue : ptr NULL");
if (ptr->array != NULL)
free(ptr->array);
ptr->array = malloc(sizeof(uint) * 1);
ptr->size_array = 1;
ptr->left = 0;
ptr->right = 0;
ptr->empty = true;
}
/* Taille */
uint size_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("size_dequeue : ptr NULL");
if (isempty_dequeue(ptr))
return 0;
else if (ptr->right > ptr->left)
return ptr->right - ptr->left;
else if (ptr->right == ptr->left)
return ptr->size_array;
else
return ptr->size_array - ptr->left + ptr->right;
}
/* Lecture */
uint lefread_dequeue(dequeue *ptr, uint i) {
if (ptr == NULL)
ERROR("lefread_dequeue : ptr NULL");
if (isempty_dequeue(ptr))
ERROR("lefread_dequeue : ptr empty");
if (i >= size_dequeue(ptr))
ERROR("lefread_dequeue : i out of bounds");
return ptr->array[(ptr->left + i) % ptr->size_array];
}
uint rigread_dequeue(dequeue *ptr, uint i) {
if (ptr == NULL)
ERROR("rigread_dequeue : ptr NULL");
if (isempty_dequeue(ptr))
ERROR("rigread_dequeue : ptr empty");
if (i >= size_dequeue(ptr))
ERROR("rigread_dequeue : i out of bounds");
return ptr->array[(ptr->right - i - 1) % ptr->size_array];
}
static void grow_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("grow_dequeue : ptr NULL");
while (ptr->left != 0) {
int temp = ptr->array[ptr->left];
for (uint i = 0; i < ptr->size_array; i++) {
ptr->array[(ptr->left + i) % ptr->size_array] =
ptr->array[(ptr->left + i + 1) % ptr->size_array];
}
ptr->array[(ptr->left - 1) % ptr->size_array] = temp;
ptr->left--;
ptr->right = (ptr->right - 1) % ptr->size_array;
}
ptr->right = ptr->size_array;
ptr->left = 0;
ptr->size_array *= 2;
ptr->array = realloc(ptr->array, ptr->size_array * sizeof(int));
return;
}
/* Insérer */
void lefins_dequeue(uint val, dequeue *ptr) {
if (ptr == NULL)
ERROR("lefins_dequeue : ptr NULL");
if (ptr->left == ptr->right && !isempty_dequeue(ptr)) {
grow_dequeue(ptr);
}
ptr->left = (ptr->left - 1 + ptr->size_array) % ptr->size_array;
ptr->array[ptr->left] = val;
ptr->empty = false;
return;
}
void rigins_dequeue(uint val, dequeue *ptr) {
if (ptr == NULL)
ERROR("rigins_dequeue : ptr NULL");
if (ptr->left == ptr->right && !isempty_dequeue(ptr)) {
grow_dequeue(ptr);
}
ptr->array[ptr->right] = val;
ptr->right = (ptr->right + 1) % ptr->size_array;
ptr->empty = false;
return;
}
static void shrink_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("shrink_dequeue : ptr NULL");
uint *aux = malloc((ptr->size_array / 2) * sizeof(uint));
for (uint i = 0; i < size_dequeue(ptr); i++) {
aux[i] = ptr->array[(ptr->left + i) % ptr->size_array];
}
free(ptr->array);
ptr->array = aux;
ptr->left = 0;
ptr->size_array = ptr->size_array / 2;
ptr->right = size_dequeue(ptr);
return;
}
/* Retirer */
uint lefpull_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("lefpull_dequeue : ptr NULL");
if (isempty_dequeue(ptr))
ERROR("lefpull_dequeue : ptr empty");
int val = ptr->array[ptr->left];
ptr->left = (ptr->left + 1) % ptr->size_array;
if (size_dequeue(ptr) <= ptr->size_array / 4 && ptr->size_array > 1) {
shrink_dequeue(ptr);
}
if (ptr->left == ptr->right)
ptr->empty = true;
return val;
}
uint rigpull_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("rigpull_dequeue : ptr NULL");
if (isempty_dequeue(ptr))
ERROR("rigpull_dequeue : ptr empty");
ptr->right = (ptr->right - 1) % ptr->size_array;
int val = ptr->array[ptr->right];
if (size_dequeue(ptr) <= ptr->size_array / 4 && ptr->size_array > 1) {
shrink_dequeue(ptr);
}
if (ptr->left == ptr->right)
ptr->empty = true;
return val;
}
/* Création d'une copie avec décalage */
/*void copy_dequeue_right(dequeue *ptr1, dequeue *ptr2, uint val) {
if (ptr1 == NULL || ptr2 == NULL)
ERROR("copy_dequeue_right : ptr NULL");
if (isempty_dequeue(ptr2))
return;
for (uint i = 0; i < size_dequeue(ptr2); i++) {
lefread_dequeue(ptr2, i);
rigins_dequeue(lefread_dequeue(ptr2, i) + val, ptr1);
}
return;
}
*/
/* Création d'une copie avec décalage */
void copy_dequeue_right(dequeue *ptr1, dequeue *ptr2, uint val) {
if (ptr1 == NULL || ptr2 == NULL)
ERROR("copy_dequeue_right : ptr NULL");
if (isempty_dequeue(ptr2)) {
return;
}
for (uint i = 0; i < size_dequeue(ptr2); i++) {
lefread_dequeue(ptr2, i);
rigins_dequeue(lefread_dequeue(ptr2, i) + val, ptr1);
}
}
/* Teste si un élément appartient à une dequeue*/
bool mem_dequeue(uint val, dequeue *ptr) {
if (ptr == NULL)
ERROR("mem_dequeue : ptr NULL");
for (uint i = 0; i < size_dequeue(ptr); i++) {
if (val == lefread_dequeue(ptr, i))
return true;
}
return false;
}
/* Affichage */
void print_dequeue(dequeue *ptr) {
if (ptr == NULL)
ERROR("print_dequeue : ptr NULL");
printf("Deque : ");
for (uint i = 0; i < size_dequeue(ptr); i++) {
printf("%d ", lefread_dequeue(ptr, i));
}
printf("\n");
return;
}
/* Tri par ordre croissant et suppression des doublons */
void sort_dequeue_norepeat(dequeue *ptr) {
if (ptr == NULL)
ERROR("sort_dequeue_norepeat : ptr NULL");
if (isempty_dequeue(ptr))
return;
if (size_dequeue(ptr) == 1)
return;
for (uint i = 0; i < size_dequeue(ptr); i++) {
for (uint j = i + 1; j < size_dequeue(ptr); j++) {
if (lefread_dequeue(ptr, i) > lefread_dequeue(ptr, j)) {
int temp = lefread_dequeue(ptr, i);
ptr->array[(ptr->left + i) % ptr->size_array] = lefread_dequeue(ptr, j);
ptr->array[(ptr->left + j) % ptr->size_array] = temp;
}
}
}
uint i;
for (i = 0; i < size_dequeue(ptr) &&
lefread_dequeue(ptr, i) != rigread_dequeue(ptr, 0);
i++) {
uint count = 0;
while (i + count < size_dequeue(ptr) &&
lefread_dequeue(ptr, i) == lefread_dequeue(ptr, i + count)) {
count++;
}
for (uint j = 1; j < count; j++) {
for (uint k = i; k < size_dequeue(ptr) - 1; k++) {
ptr->array[(ptr->left + k) % ptr->size_array] =
lefread_dequeue(ptr, k + 1);
}
}
}
ptr->right = (ptr->right - (size_dequeue(ptr) - i - 1)) % ptr->size_array;
return;
}
/*****************************************************************/
/* Fonctions spécifiques aux ensembles triés par ordre croissant */
/*****************************************************************/
bool mem_dequeue_sorted(uint val, dequeue *ptr) {
if (ptr == NULL)
ERROR("mem_dequeue_sorted : ptr NULL");
if (isempty_dequeue(ptr))
return false;
int left = 0;
int right = size_dequeue(ptr) - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (lefread_dequeue(ptr, mid) == val)
return true;
if (lefread_dequeue(ptr, mid) < val) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
void merge_sorted_dequeue(dequeue *ptr1, dequeue *ptr2) {
if (ptr1 == NULL || ptr2 == NULL)
ERROR("merge_sorted_dequeue : ptr NULL");
if (isempty_dequeue(ptr2))
return;
if (isempty_dequeue(ptr1)) {
copy_dequeue_right(ptr1, ptr2, 0);
return;
}
uint i = 0;
uint j = 0;
dequeue *temp = create_dequeue();
while (i < size_dequeue(ptr1) && j < size_dequeue(ptr2)) {
if (lefread_dequeue(ptr1, i) <= lefread_dequeue(ptr2, j)) {
rigins_dequeue(lefread_dequeue(ptr1, i), temp);
i++;
} else {
rigins_dequeue(lefread_dequeue(ptr2, j), temp);
j++;
}
}
while (i < size_dequeue(ptr1)) {
rigins_dequeue(lefread_dequeue(ptr1, i), temp);
i++;
}
while (j < size_dequeue(ptr2)) {
rigins_dequeue(lefread_dequeue(ptr2, j), temp);
j++;
}
makeempty_dequeue(ptr1);
copy_dequeue_right(ptr1, temp, 0);
if (temp == NULL)
delete_dequeue(temp);
for (i = 0; i < size_dequeue(ptr1) &&
lefread_dequeue(ptr1, i) != rigread_dequeue(ptr1, 0);
i++) {
uint count = 0;
while (i + count < size_dequeue(ptr1) &&
lefread_dequeue(ptr1, i) == lefread_dequeue(ptr1, i + count)) {
count++;
}
for (j = 1; j < count; j++) {
for (uint k = i; k < size_dequeue(ptr1) - 1; k++) {
ptr1->array[(ptr1->left + k) % ptr1->size_array] =
lefread_dequeue(ptr1, k + 1);
}
}
}
ptr1->right = (ptr1->right - (size_dequeue(ptr1) - i - 1)) % ptr1->size_array;
return;
}
dequeue *make_inter_sorted_dequeue(dequeue *ptr1, dequeue *ptr2) {
if (ptr1 == NULL || ptr2 == NULL)
ERROR("make_inter_sorted_dequeue : ptr NULL");
dequeue *ptr = create_dequeue();
for (uint i = 0; i < size_dequeue(ptr1); i++) {
if (mem_dequeue_sorted(lefread_dequeue(ptr1, i), ptr2)) {
rigins_dequeue(lefread_dequeue(ptr1, i), ptr);
}
}
return ptr;
}
/* Insére un nouveau sommet dans une liste */
void insert_dequeue(dequeue *ptr, uint val) {
if (ptr == NULL)
ERROR("insert_dequeue : ptr NULL");
if (mem_dequeue_sorted(val, ptr))
return;
dequeue *temp = create_dequeue();
rigins_dequeue(val, temp);
merge_sorted_dequeue(ptr, temp);
}
/* Teste si deux dequeues triées s'intersectent */
bool intersec_dequeue(dequeue *ptr1, dequeue *ptr2) {
if (ptr1 == NULL || ptr2 == NULL)
ERROR("intersec_dequeue : ptr NULL");
if (isempty_dequeue(ptr1) || isempty_dequeue(ptr2))
return false;
for (uint i = 0; i < size_dequeue(ptr1); i++) {
if (mem_dequeue_sorted(lefread_dequeue(ptr1, i), ptr2)) {
return true;
}
}
return false;
}

View File

@@ -0,0 +1,73 @@
#include "type_stack.h"
/************************/
/* Fonctions primitives */
/************************/
static void grow_stack(stack *thestack) {
thestack->array =
realloc(thestack->array, 2 * thestack->size_array * sizeof(void *));
if (thestack->array == NULL) {
ERROR("Erreur d'allocation mémoire");
}
thestack->size_array = 2 * thestack->size_array;
}
static void shrink_stack(stack *thestack) {
thestack->array =
realloc(thestack->array, thestack->size_array * sizeof(void *) / 2);
if (thestack->array == NULL) {
ERROR("Erreur d'allocation mémoire");
}
thestack->size_array = thestack->size_array / 2;
}
/* Création */
stack *create_stack(void) {
stack *thestack = malloc(sizeof(stack));
thestack->size_array = 1;
thestack->size_stack = 0;
thestack->array = malloc(sizeof(void *));
return thestack;
}
/* Suppression */
void delete_stack(stack *thestack) {
free(thestack->array);
free(thestack);
}
/* Test du vide */
bool isempty_stack(stack *thestack) {
return thestack->size_stack == 0;
}
/* Taille*/
uint size_stack(stack *thestack) { return thestack->size_stack; }
/* Lecture */
void *read_stack(stack *thestack, const uint index) { return thestack->array[index]; }
/* Dépiler */
void *pop(stack *thestack) {
if (isempty_stack(thestack)) {
ERROR("La pile est vide.");
}
void *v = thestack->array[(thestack->size_stack) - 1];
thestack->size_stack -= 1;
if (thestack->size_stack <= thestack->size_array / 4 &&
thestack->size_array > 1) {
shrink_stack(thestack);
}
return v;
}
/* Empiler */
void push(void *val, stack *thestack) {
if (thestack->size_array <= thestack->size_stack) {
grow_stack(thestack);
}
thestack->size_stack += 1;
thestack->array[thestack->size_stack - 1] = val;
}

View File

@@ -0,0 +1,84 @@
#include "nfa_mccluskey.h"
#include <stdio.h>
#include "regexp.h"
mccluskey_auto *nfa_to_mccluskey(nfa *thenfa) {
uint n = thenfa->trans->size_graph;
mccluskey_auto *mccluskey =
(mccluskey_auto *)malloc(sizeof(mccluskey_auto));
mccluskey->size = n + 2;
mccluskey->matrix = (regexp ***)malloc(mccluskey->size * sizeof(regexp **));
for (uint i = 0; i < mccluskey->size; i++) {
mccluskey->matrix[i] =
(regexp **)malloc(mccluskey->size * sizeof(regexp *));
for (uint j = 0; j < mccluskey->size; j++)
mccluskey->matrix[i][j] = NULL;
}
for (uint q = 0; q < n; q++) {
for (uint a = 0; a < thenfa->trans->size_alpha; a++) {
dequeue *transitions = thenfa->trans->edges[q][a];
for (uint k = 0; k < size_dequeue(transitions); k++) {
uint r = lefread_dequeue(transitions, k);
mccluskey->matrix[q + 2][r + 2] =
reg_letter(thenfa->alpha_names[a]);
}
}
}
for (uint i = 0; i < size_dequeue(thenfa->initials); i++) {
uint initial_state = lefread_dequeue(thenfa->initials, i);
mccluskey->matrix[0][initial_state + 2] = reg_epsilon();
}
for (uint i = 0; i < size_dequeue(thenfa->finals); i++) {
uint final_state = lefread_dequeue(thenfa->finals, i);
mccluskey->matrix[final_state + 2][1] = reg_epsilon();
}
return mccluskey;
}
regexp *nfa_mccluskey(nfa *thenfa) {
mccluskey_auto *gen_auto = nfa_to_mccluskey(thenfa);
uint n = gen_auto->size;
regexp ***matrix = gen_auto->matrix;
for (uint k = 2; k < n; ++k) {
for (uint i = 0; i < n; ++i) {
for (uint j = 0; j < n; ++j) {
if (matrix[i][k] != NULL && matrix[k][j] != NULL) {
regexp *new_expr;
// Gestion des étoiles
if (matrix[k][k] != NULL && i == j && i == k && j == k) {
new_expr = reg_star(matrix[k][k]);
}
// Gestions des concaténations
else if (matrix[k][k] == NULL ||
(matrix[k][k] != NULL && i != j && i == k)) {
new_expr = reg_concat(matrix[i][k], matrix[k][j]);
}
// Gestion des unions
if (matrix[i][j] != NULL && matrix[k][k] == NULL) {
new_expr = reg_union(matrix[i][j], new_expr);
}
matrix[i][j] = new_expr;
}
}
}
}
regexp *final_regexp = matrix[0][1];
for (uint i = 0; i < n; ++i)
if (matrix[i] != NULL) free(matrix[i]);
if (matrix != NULL) free(matrix);
if (gen_auto != NULL) free(gen_auto);
return final_regexp;
}

133
Anna et Ethan/regexp.c Normal file
View File

@@ -0,0 +1,133 @@
#include "regexp.h"
bool reg_issimple(regexp *expression) {
if (expression == NULL) return true;
if (expression->op == INTER || expression->op == COMPLEMENT) return false;
return reg_issimple(expression->left) && reg_issimple(expression->right);
}
void reg_free(regexp *expression) {
if (expression == NULL) return;
reg_free(expression->left);
reg_free(expression->right);
free(expression);
return;
}
regexp *reg_copy(regexp *expression) {
if (expression == NULL) return NULL;
// on alloue de la mémoire pour la copie
regexp *copy = malloc(sizeof(regexp));
// on copie les champs de l'expression
copy->op = expression->op;
copy->letter = expression->letter;
// on copie les sous-expressions de manière récursive
copy->left = reg_copy(expression->left);
copy->right = reg_copy(expression->right);
// on retourne la copie effectuée
return copy;
}
regexp *reg_empty(void) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_empty : malloc failed");
} else {
ptr->op = EMPTY;
ptr->letter = '\0';
ptr->left = NULL;
ptr->right = NULL;
}
return ptr;
}
regexp *reg_epsilon(void) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_epsilon : malloc failed");
} else {
ptr->op = EPSILON;
ptr->letter = '\0';
ptr->left = NULL;
ptr->right = NULL;
}
return ptr;
}
regexp *reg_letter(char c) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_lettre : malloc failed");
} else {
ptr->op = CHAR;
ptr->letter = c;
ptr->left = NULL;
ptr->right = NULL;
}
return ptr;
}
regexp *reg_union(regexp *ptr_left, regexp *ptr_right) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_union : malloc failed");
} else {
ptr->op = UNION;
ptr->letter = '\0';
ptr->left = ptr_left;
ptr->right = ptr_right;
}
return ptr;
}
regexp *reg_inter(regexp *ptr_left, regexp *ptr_right) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_inter : malloc failed");
} else {
ptr->op = INTER;
ptr->letter = '\0';
ptr->left = ptr_left;
ptr->right = ptr_right;
}
return ptr;
}
regexp *reg_concat(regexp *ptr_left, regexp *ptr_right) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_concat : malloc failed");
} else {
ptr->op = CONCAT;
ptr->letter = '\0';
ptr->left = ptr_left;
ptr->right = ptr_right;
}
return ptr;
}
regexp *reg_star(regexp *expression) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_star : malloc failed");
} else {
ptr->op = STAR;
ptr->letter = '\0';
ptr->left = expression;
ptr->right = NULL;
}
return ptr;
}
regexp *reg_complement(regexp *expression) {
regexp *ptr = malloc(sizeof(regexp));
if (ptr == NULL) {
ERROR("reg_complement : malloc failed");
} else {
ptr->op = COMPLEMENT;
ptr->letter = '\0';
ptr->left = expression;
ptr->right = NULL;
}
return ptr;
}

View File

@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdio.h>
#include "error.h"
#include "files.h"
#include "graphs.h"
#include "nfa.h"
@@ -20,7 +21,8 @@
#define TEST_DEQUEUE true
#define TEST_BOOLARRAY false
#define NB_TESTS_OCCUR 1000
#define NB_TESTS_OCCUR 100000
#define NB_MAX_SIZE_DEQUEUE 100
static void printf_dequeue(dequeue *dq, char *function, char *var,
int i_function, int i_result) {
@@ -78,6 +80,11 @@ void test(void) {
// nfa* A = create_sing_epsilon();
// nfa_view(A);
if (NB_MAX_SIZE_DEQUEUE == 0) {
ERROR("NB_MAX_SIZE_DEQUEUE doit être supérieur à 0");
exit(EXIT_FAILURE);
}
// Tests de dequeue
if (TEST_DEQUEUE) {
dequeue *dq = create_dequeue();
@@ -142,7 +149,7 @@ void test(void) {
"Test makeempty_dequeue et copy_dequeue_right in array [1, 20]\n"); // Test makeempty_dequeue et copy_dequeue_right
printf("--------------------\n");
dequeue *dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
makeempty_dequeue(dq2);
// printf_dequeue(dq2, "makeempty_dequeue", "dq2", -1, -1);
copy_dequeue_right(dq2, dq, i);
@@ -159,7 +166,7 @@ void test(void) {
printf("--------------------\n");
printf("Test mem_dequeue in array [1, 20]\n"); // Test mem_dequeue
printf("--------------------\n");
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
uint value = rand() % 100;
// printf_dequeue(dq, "mem_dequeue", "dq2", value,
// mem_dequeue(value, dq));
@@ -170,7 +177,7 @@ void test(void) {
if (dq == NULL) delete_dequeue(dq2);
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100 + 1; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE + 1; i++) {
lefins_dequeue(rand() % 100, dq2);
}
// printf_dequeue(dq2, "random", "dq2", -1, -1);
@@ -180,14 +187,15 @@ void test(void) {
printf(
"Test sort_dequeue_norepeat\n"); // Test sort_dequeue_norepeat
printf("--------------------\n");
for (uint i = 0; i < size_dequeue(dq2) - 1; i++) {
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2) - 1;
i++) {
assert(lefread_dequeue(dq2, i) < lefread_dequeue(dq2, i + 1));
printf(
"%u - assert(lefread_dequeue(dq2, %d) < "
"%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k, i, i + 1);
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
// for (uint i = 0; i < 20; i++) {
// printf_dequeue(dq2, "mem_dequeue_sorted", "dq2", i,
@@ -196,7 +204,8 @@ void test(void) {
printf("--------------------\n");
printf("Test mem_dequeue_sorted\n"); // Test mem_dequeue_sorted
printf("--------------------\n");
for (uint i = 0; i < size_dequeue(dq2); i++) {
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2);
i++) {
assert(mem_dequeue_sorted(i, dq2) == mem_dequeue(i, dq2));
printf("assert(mem_dequeue_sorted(%d, dq2) == %d) check\n", i,
mem_dequeue(i, dq2));
@@ -210,46 +219,54 @@ void test(void) {
dq = create_dequeue();
dq2 = create_dequeue();
dequeue *dq3 = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
sort_dequeue_norepeat(dq2);
copy_dequeue_right(dq3, dq, 0);
merge_sorted_dequeue(dq3, dq2);
for (uint i = 0; i < size_dequeue(dq3) - 1; i++) {
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3) - 1;
i++) {
printf("size = %d\n", size_dequeue(dq3));
assert(lefread_dequeue(dq3, i) < lefread_dequeue(dq3, i + 1));
printf(
"%u - assert(lefread_dequeue(dq2, %d) < "
"%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k, i, i + 1);
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
for (uint i = 0; i < size_dequeue(dq3); i++) {
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3);
i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq3, i), dq) ||
mem_dequeue_sorted(lefread_dequeue(dq3, i), dq2));
printf(
"%u - assert(mem_dequeue_sorted(%d, dq) || "
"%u%% - assert(mem_dequeue_sorted(%d, dq) || "
"mem_dequeue_sorted(%d, dq2)) check\n",
k, lefread_dequeue(dq3, i), lefread_dequeue(dq3, i));
k / (NB_TESTS_OCCUR / 100), lefread_dequeue(dq3, i),
lefread_dequeue(dq3, i));
}
for (uint i = 0; i < size_dequeue(dq); i++) {
for (uint i = 0; size_dequeue(dq) > 0 && i < size_dequeue(dq);
i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq, i), dq3));
printf(
"%u - assert(mem_dequeue_sorted(leftread_dequeue(dq, %d), "
"%u%% - assert(mem_dequeue_sorted(leftread_dequeue(dq, "
"%d), "
"dq3)) check\n",
k, i);
k / (NB_TESTS_OCCUR / 100), i);
}
for (uint i = 0; i < size_dequeue(dq2); i++) {
for (uint i = 0; size_dequeue(dq2) > 0 && i < size_dequeue(dq2);
i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq2, i), dq3));
printf(
"%u - assert(mem_dequeue_sorted(leftread_dequeue(dq2, %d), "
"%u%% - assert(mem_dequeue_sorted(leftread_dequeue(dq2, "
"%d), "
"dq3)) check\n",
k, i);
k / (NB_TESTS_OCCUR / 100), i);
}
if (dq == NULL) delete_dequeue(dq);
if (dq2 == NULL) delete_dequeue(dq2);
@@ -263,22 +280,24 @@ void test(void) {
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
sort_dequeue_norepeat(dq2);
dequeue *dq3 = make_inter_sorted_dequeue(dq, dq2);
for (uint i = 0; i < size_dequeue(dq3); i++) {
for (uint i = 0; size_dequeue(dq3) > 0 && i < size_dequeue(dq3);
i++) {
assert(mem_dequeue_sorted(lefread_dequeue(dq3, i), dq) &&
mem_dequeue_sorted(lefread_dequeue(dq3, i), dq2));
printf(
"%u - assert(mem_dequeue_sorted(%d, dq) && "
"%u%% - assert(mem_dequeue_sorted(%d, dq) && "
"mem_dequeue_sorted(%d, dq2)) check\n",
k, lefread_dequeue(dq3, i), lefread_dequeue(dq3, i));
k / (NB_TESTS_OCCUR / 100), lefread_dequeue(dq3, i),
lefread_dequeue(dq3, i));
}
if (dq == NULL) delete_dequeue(dq);
if (dq2 == NULL) delete_dequeue(dq2);
@@ -291,10 +310,10 @@ void test(void) {
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
dq2 = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq2);
}
sort_dequeue_norepeat(dq);
@@ -303,30 +322,33 @@ void test(void) {
dequeue *dq3 = make_inter_sorted_dequeue(dq, dq2);
assert(result == (size_dequeue(dq3) > 0));
printf(
"%u - size_dequeue(make_inter_sorted_dequeue(dq, dq2)) check\n",
k);
"%u%% - size_dequeue(make_inter_sorted_dequeue(dq, dq2)) "
"check\n",
k / (NB_TESTS_OCCUR / 100));
if (dq == NULL) delete_dequeue(dq);
if (dq2 == NULL) delete_dequeue(dq2);
}
for (uint k = 0; k < NB_TESTS_OCCUR; k++) {
dq = create_dequeue();
for (uint i = 0; i < (uint)rand() % 100; i++) {
for (uint i = 0; i < (uint)rand() % NB_MAX_SIZE_DEQUEUE; i++) {
lefins_dequeue(rand() % 100, dq);
}
sort_dequeue_norepeat(dq);
uint val = rand() % 100;
insert_dequeue(dq, val);
for (uint i = 0; i < size_dequeue(dq) - 1; i++) {
for (uint i = 0; size_dequeue(dq) > 0 && i < size_dequeue(dq) - 1;
i++) {
assert(lefread_dequeue(dq, i) < lefread_dequeue(dq, i + 1));
printf(
"%u - assert(lefread_dequeue(dq2, %d) < "
"%u%% - assert(lefread_dequeue(dq2, %d) < "
"lefread_dequeue(dq2, "
"%d)) "
"check\n",
k, i, i + 1);
k / (NB_TESTS_OCCUR / 100), i, i + 1);
}
assert(mem_dequeue_sorted(val, dq));
printf("%u - assert(mem_dequeue_sorted(%d, dq)) check\n", k, val);
printf("%u%% - assert(mem_dequeue_sorted(%d, dq)) check\n",
k / (NB_TESTS_OCCUR / 100), val);
if (dq == NULL) delete_dequeue(dq);
}
printf("--------------------\n");
@@ -380,4 +402,3 @@ void test(void) {
delete_barray(ba);
}
}

View File

@@ -164,7 +164,7 @@ uint rigpull_dequeue(dequeue *ptr) {
/* Création d'une copie avec décalage */
void copy_dequeue_right(dequeue *ptr1, dequeue *ptr2, uint val) {
if (ptr1 == NULL || ptr2 == NULL) ERROR("copy_dequeue_right : ptr NULL");
if (isempty_dequeue(ptr2)) ERROR("copy_dequeue_right : ptr2 empty");
if (isempty_dequeue(ptr2)) return;
for (uint i = 0; i < size_dequeue(ptr2); i++) {
lefread_dequeue(ptr2, i);
rigins_dequeue(lefread_dequeue(ptr2, i) + val, ptr1);