Compare commits
8 Commits
6a43928c0e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 48c3648813 | |||
|
|
1bd783c958 | ||
|
|
b06c2fcc82 | ||
|
|
6606b1f872 | ||
| a913fd240b | |||
| ecdf33a2a5 | |||
| f8cfa7ac38 | |||
| 7487e90c75 |
64
Aloyse et Vincent/a.c
Normal file
64
Aloyse et Vincent/a.c
Normal 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
29
Aloyse et Vincent/alloc.c
Normal 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);
|
||||
}
|
||||
}
|
||||
7
Aloyse et Vincent/extra.css
Normal file
7
Aloyse et Vincent/extra.css
Normal 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
550
Aloyse et Vincent/files.c
Normal 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
127
Aloyse et Vincent/graphs.c
Normal 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
94
Aloyse et Vincent/main.c
Normal 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
677
Aloyse et Vincent/nfa.c
Normal file
@@ -0,0 +1,677 @@
|
||||
/***************************/
|
||||
/* Implémentation des NFAs */
|
||||
/***************************/
|
||||
|
||||
#include "nfa.h"
|
||||
#include "error.h"
|
||||
#include "graphs.h"
|
||||
#include "type_dequeue.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(ptr) \
|
||||
if (ptr == NULL) { \
|
||||
ERROR("malloc failed"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
static char *uint_to_chars(const uint i) {
|
||||
char *str = malloc(12 * sizeof(char));
|
||||
// 12 car un uint peut avoir 10 chiffres + le '\0' (4 294 967 295) + jsp
|
||||
CHECK(str);
|
||||
sprintf(str, "%u", i);
|
||||
return str;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Affichage des noms si ce sont des pointeurs sur des entiers */
|
||||
/***************************************************************/
|
||||
|
||||
void nfa_print_letter(const nfa *thenfa, const uint num_letter, FILE *out) {
|
||||
printf("nfa_print_letter\n");
|
||||
fprintf(out, "%c", thenfa->alpha_names[num_letter]);
|
||||
}
|
||||
|
||||
char *nfa_copy_alpha(const nfa *thenfa) {
|
||||
printf("nfa_copy_alpha\n");
|
||||
char *copy = malloc((thenfa->trans->size_alpha) * sizeof(char));
|
||||
CHECK(copy);
|
||||
for (uint i = 0; i < thenfa->trans->size_alpha; i++) {
|
||||
copy[i] = thenfa->alpha_names[i];
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
void nfa_print_state(const nfa *thenfa, const uint numstate, FILE *out) {
|
||||
printf("nfa_print_state\n");
|
||||
if (thenfa->state_names == NULL) {
|
||||
fprintf(out, "%u", numstate);
|
||||
} else {
|
||||
fprintf(out, "%s", thenfa->state_names[numstate]);
|
||||
}
|
||||
}
|
||||
|
||||
void nfa_reset_state_names(nfa *thenfa) {
|
||||
printf("nfa_reset_state_names\n");
|
||||
if (thenfa->state_names != NULL) {
|
||||
for (uint i = 0; i < thenfa->trans->size_alpha; i++) {
|
||||
if (thenfa->state_names[i] != NULL) {
|
||||
free(thenfa->state_names[i]);
|
||||
}
|
||||
}
|
||||
free(thenfa->state_names);
|
||||
thenfa->state_names = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *nfa_copy_one_name(const nfa *thenfa, const uint thestate) {
|
||||
printf("nfa_copy_one_name\n");
|
||||
if (thenfa->state_names == NULL) {
|
||||
return uint_to_chars(thestate);
|
||||
}
|
||||
const size_t len = strlen(thenfa->state_names[thestate]) + 1;
|
||||
//+1 car strlen ne compte pas le '\0'
|
||||
char *copy = malloc(len * sizeof(char));
|
||||
CHECK(copy);
|
||||
strncpy(copy, thenfa->state_names[thestate], len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
char **nfa_copy_all_names(nfa *thenfa) {
|
||||
printf("nfa_copy_all_names\n");
|
||||
// Vérifier si le NFA utilise des noms pour les états
|
||||
if (thenfa->state_names == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allouer de la mémoire pour le tableau de noms
|
||||
char **copy_names = malloc(thenfa->trans->size_graph * sizeof(char *));
|
||||
CHECK(copy_names);
|
||||
|
||||
// Copier chaque nom d'état
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
copy_names[i] = nfa_copy_one_name(thenfa, i);
|
||||
}
|
||||
|
||||
return copy_names;
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/* Initialisation et suppression */
|
||||
/*********************************/
|
||||
|
||||
nfa *create_emptylang(void) {
|
||||
printf("create_emptylang\n");
|
||||
nfa *empty = malloc(sizeof(nfa));
|
||||
CHECK(empty);
|
||||
empty->trans = create_lgraph_noedges(0, 0);
|
||||
empty->initials = create_dequeue();
|
||||
empty->finals = create_dequeue();
|
||||
empty->alpha_names = malloc(sizeof(char));
|
||||
CHECK(empty->alpha_names);
|
||||
empty->alpha_names[0] = '\0';
|
||||
empty->state_names = NULL;
|
||||
return empty;
|
||||
}
|
||||
|
||||
nfa *create_sing_epsilon(void) {
|
||||
printf("create_sing_epsilon\n");
|
||||
nfa *epsilon = malloc(sizeof(nfa));
|
||||
CHECK(epsilon);
|
||||
epsilon->trans = create_lgraph_noedges(1, 0);
|
||||
epsilon->initials = create_dequeue();
|
||||
epsilon->finals = create_dequeue();
|
||||
lefins_dequeue(0, epsilon->initials);
|
||||
lefins_dequeue(0, epsilon->finals);
|
||||
epsilon->alpha_names = malloc(sizeof(char));
|
||||
CHECK(epsilon->alpha_names);
|
||||
epsilon->alpha_names[0] = '\0';
|
||||
epsilon->state_names = malloc(sizeof(char *));
|
||||
CHECK(epsilon->state_names);
|
||||
epsilon->state_names[0] = "ε";
|
||||
return epsilon;
|
||||
}
|
||||
|
||||
nfa *create_sing_letter(const char theletter) {
|
||||
printf("create_sing_letter\n");
|
||||
// Créer le graphe des transitions avec 2 états et 1 lettre dans l'alphabet
|
||||
lgraph *trans = create_lgraph_noedges(2, 1);
|
||||
|
||||
// Ajouter une transition de l'état 0 à l'état 1 avec la lettre theletter
|
||||
dequeue *transition = create_dequeue();
|
||||
rigins_dequeue(1, transition);
|
||||
trans->edges[0][0] = transition;
|
||||
|
||||
// Créer la liste des états initiaux (état 0)
|
||||
dequeue *initials = create_dequeue();
|
||||
rigins_dequeue(0, initials);
|
||||
|
||||
// Créer la liste des états finaux (état 1)
|
||||
dequeue *finals = create_dequeue();
|
||||
rigins_dequeue(1, finals);
|
||||
|
||||
// Allouer de la mémoire pour le nom de la lettre
|
||||
char *alpha_names = malloc(sizeof(char));
|
||||
CHECK(alpha_names);
|
||||
alpha_names[0] = theletter;
|
||||
|
||||
// Créer le NFA
|
||||
nfa *thenfa = malloc(sizeof(nfa));
|
||||
thenfa->trans = trans;
|
||||
thenfa->initials = initials;
|
||||
thenfa->finals = finals;
|
||||
thenfa->alpha_names = alpha_names;
|
||||
thenfa->state_names = NULL; // Pas de noms d'états
|
||||
return thenfa;
|
||||
}
|
||||
|
||||
void nfa_delete(nfa *thenfa) {
|
||||
printf("nfa_delete\n");
|
||||
// ne free pas le pointeur !
|
||||
nfa_reset_state_names(thenfa);
|
||||
delete_lgraph(thenfa->trans);
|
||||
delete_dequeue(thenfa->initials);
|
||||
delete_dequeue(thenfa->finals);
|
||||
free(thenfa->alpha_names);
|
||||
}
|
||||
|
||||
void nfa_overwrite(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_overwrite\n");
|
||||
nfa_delete(nfa1);
|
||||
*nfa1 = *nfa2;
|
||||
free(nfa2);
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
/* Opérations simples sur les NFAs */
|
||||
/***********************************/
|
||||
|
||||
nfa *nfa_copy(nfa *thenfa) {
|
||||
printf("nfa_copy\n");
|
||||
nfa *copy = malloc(sizeof(nfa));
|
||||
CHECK(copy);
|
||||
copy->initials = create_dequeue();
|
||||
copy->finals = create_dequeue();
|
||||
copy_dequeue_right(copy->initials, thenfa->initials, 0);
|
||||
copy_dequeue_right(copy->finals, thenfa->finals, 0);
|
||||
copy->alpha_names = nfa_copy_alpha(thenfa);
|
||||
copy->state_names = nfa_copy_all_names(thenfa);
|
||||
copy->trans = create_lgraph_noedges(thenfa->trans->size_graph,
|
||||
thenfa->trans->size_alpha);
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
for (uint j = 0; j < thenfa->trans->size_alpha; j++) {
|
||||
dequeue *edges = create_dequeue();
|
||||
copy_dequeue_right(edges, thenfa->trans->edges[i][j], 0);
|
||||
copy->trans->edges[i][j] = edges;
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
nfa *nfa_copy_exalpha(nfa *thenfa, const char *letters, const uchar tabsize) {
|
||||
nfa *copy = nfa_copy(thenfa);
|
||||
CHECK(copy);
|
||||
char *alpha = malloc(sizeof(char) * (copy->trans->size_alpha + tabsize));
|
||||
CHECK(alpha);
|
||||
for (uint l = 0; l < copy->trans->size_alpha; l++) {
|
||||
alpha[l] = copy->alpha_names[l];
|
||||
}
|
||||
for (uint l = 0; l < tabsize; l++) {
|
||||
alpha[l + copy->trans->size_alpha] = letters[l];
|
||||
}
|
||||
free(copy->alpha_names);
|
||||
copy->alpha_names = alpha;
|
||||
return copy;
|
||||
}
|
||||
|
||||
// Union disjointe de deux nfas
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
nfa *nfa_union(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_union\n");
|
||||
// nfa1 U nfa2 = nfa1 + nfa2 - (nfa1 ∩ nfa2)
|
||||
nfa *nfa_uni =
|
||||
nfa_copy_exalpha(nfa1, nfa2->alpha_names, nfa2->trans->size_alpha);
|
||||
|
||||
// On remplace les noms d'états
|
||||
nfa_reset_state_names(nfa_uni);
|
||||
|
||||
// On unie les états initiaux
|
||||
copy_dequeue_right(nfa_uni->initials, nfa2->initials,
|
||||
nfa1->trans->size_graph);
|
||||
|
||||
// On unie les états finaux
|
||||
copy_dequeue_right(nfa_uni->finals, nfa2->finals, nfa1->trans->size_graph);
|
||||
|
||||
// on crée le graphe
|
||||
lgraph *g =
|
||||
create_lgraph_noedges(nfa1->trans->size_graph + nfa2->trans->size_graph,
|
||||
nfa1->trans->size_alpha + nfa2->trans->size_alpha);
|
||||
|
||||
// on récupère le premier graphe
|
||||
for (uint sommet = 0; sommet < nfa1->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa1->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet][lettre],
|
||||
nfa1->trans->edges[sommet][lettre], 0);
|
||||
}
|
||||
}
|
||||
// on récupère le second graphe
|
||||
const uint d1 = nfa1->trans->size_graph;
|
||||
const uint d2 = nfa1->trans->size_alpha;
|
||||
for (uint sommet = 0; sommet < nfa2->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet + d1][lettre + d2],
|
||||
nfa2->trans->edges[sommet][lettre], d1);
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(nfa_uni->trans);
|
||||
nfa_uni->trans = g;
|
||||
return nfa_uni;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
nfa *nfa_concat(nfa *nfa1, nfa *nfa2) {
|
||||
printf("nfa_concat\n");
|
||||
// nfa1 . nfa2 <=> ε -> nfa1 -> nfa2 -> ε
|
||||
nfa *nfa_concaten =
|
||||
nfa_copy_exalpha(nfa1, nfa2->alpha_names, nfa2->trans->size_alpha);
|
||||
|
||||
// On remplace les noms d'états
|
||||
nfa_reset_state_names(nfa_concaten);
|
||||
|
||||
// on corrige les états finaux
|
||||
delete_dequeue(nfa_concaten->finals);
|
||||
nfa_concaten->finals = create_dequeue();
|
||||
copy_dequeue_right(nfa_concaten->finals, nfa2->finals,
|
||||
nfa1->trans->size_alpha);
|
||||
|
||||
// on crée le graphe
|
||||
const uint cumul = size_dequeue(nfa2->initials);
|
||||
lgraph *g = create_lgraph_noedges(
|
||||
nfa1->trans->size_graph + nfa2->trans->size_graph - cumul,
|
||||
nfa1->trans->size_alpha + nfa2->trans->size_alpha);
|
||||
|
||||
// on récupère le premier graphe
|
||||
for (uint sommet = 0; sommet < nfa1->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa1->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet][lettre],
|
||||
nfa1->trans->edges[sommet][lettre], 0);
|
||||
}
|
||||
}
|
||||
// on récupère le second graphe
|
||||
uint d1 = nfa1->trans->size_alpha;
|
||||
uint d2 = nfa1->trans->size_graph;
|
||||
for (uint sommet = 0; sommet < nfa2->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[sommet + d2 - cumul][lettre + d1],
|
||||
nfa2->trans->edges[sommet][lettre], d2 - cumul);
|
||||
}
|
||||
}
|
||||
|
||||
// on recupère les arrêtes de transition entre les deux graphes
|
||||
uint size = size_dequeue(nfa2->initials);
|
||||
uint size2 = size_dequeue(nfa1->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint depart = lefread_dequeue(nfa2->initials, i);
|
||||
for (uint j = 0; i < size2; i++) {
|
||||
const uint arrivee = lefread_dequeue(nfa1->finals, j);
|
||||
for (uint lettre = 0; lettre < nfa2->trans->size_alpha; lettre++) {
|
||||
copy_dequeue_right(g->edges[arrivee][lettre + nfa1->trans->size_alpha],
|
||||
nfa2->trans->edges[depart][lettre],
|
||||
nfa1->trans->size_alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(nfa_concaten->trans);
|
||||
nfa_concaten->trans = g;
|
||||
return nfa_concaten;
|
||||
}
|
||||
|
||||
// Étoile de Kleene d'un NFA
|
||||
nfa *nfa_star(nfa *thenfa) {
|
||||
printf("nfa_star\n");
|
||||
// final pointe chaque initial et on rajoute un epsilon
|
||||
// ajoute les epsilon
|
||||
nfa *kleene = nfa_copy(thenfa);
|
||||
bool eps = false;
|
||||
|
||||
// reconstitution du graphes avec un Epsilon
|
||||
lgraph *g = create_lgraph_noedges(kleene->trans->size_graph + 1,
|
||||
kleene->trans->size_alpha);
|
||||
for (uint sommet = 0; sommet < kleene->trans->size_graph; sommet++) {
|
||||
if (mem_dequeue(sommet, kleene->finals) &&
|
||||
mem_dequeue(sommet, kleene->initials)) { // ε
|
||||
eps = true;
|
||||
continue;
|
||||
}
|
||||
// on récupère nos arrêtes
|
||||
for (uint lettre = 0; lettre < kleene->trans->size_alpha; lettre++) {
|
||||
dequeue *edges = kleene->trans->edges[sommet][lettre];
|
||||
copy_dequeue_right(g->edges[sommet][lettre], edges, 0);
|
||||
// on ajoute les états initiaux à tout ce qui pointes sur un état
|
||||
// final
|
||||
uint size = size_dequeue(kleene->finals);
|
||||
for (uint s = 0; s < size; s++) {
|
||||
const uint sortie = lefread_dequeue(kleene->finals, s);
|
||||
// si on a une transition vers un état final, on ajoute les états
|
||||
// initiaux aux transitions
|
||||
if (mem_dequeue_sorted(sortie, edges)) {
|
||||
uint size2 = size_dequeue(kleene->initials);
|
||||
for (uint e = 0; e < size2; e++) {
|
||||
const uint entree = lefread_dequeue(kleene->initials, e);
|
||||
lefins_dequeue(entree, g->edges[sommet][lettre]);
|
||||
}
|
||||
sort_dequeue_norepeat(g->edges[sommet][lettre]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!eps) {
|
||||
insert_dequeue(kleene->initials, kleene->trans->size_graph);
|
||||
insert_dequeue(kleene->finals, kleene->trans->size_graph);
|
||||
} else {
|
||||
// on supprime l'état réservé pour l'epsilon
|
||||
g->size_graph--;
|
||||
for (uint lettre = 0; lettre < g->size_alpha; lettre++) {
|
||||
free(g->edges[g->size_graph][lettre]);
|
||||
}
|
||||
}
|
||||
|
||||
delete_lgraph(kleene->trans);
|
||||
kleene->trans = g;
|
||||
return kleene;
|
||||
}
|
||||
|
||||
// note les états accessibles depuis l'état donné
|
||||
// note les états depuis lesquels on peut atteindre un état final à partir
|
||||
// de l'état donné
|
||||
static bool trimer(nfa *thenfa, bool *reachable,
|
||||
bool *may_exit, // NOLINT(*-no-recursion)
|
||||
const uint sommet) {
|
||||
printf("trimer\n");
|
||||
if (reachable[sommet]) {
|
||||
// on a déjà visité cet état
|
||||
return may_exit[sommet];
|
||||
}
|
||||
reachable[sommet] = true;
|
||||
const lgraph *g = thenfa->trans;
|
||||
for (uint i = 0; i < g->size_alpha; i++) {
|
||||
dequeue *edges = g->edges[sommet][i];
|
||||
const uint size = size_dequeue(edges);
|
||||
for (uint j = 0; j < size; j++) {
|
||||
const uint etat = lefread_dequeue(edges, j);
|
||||
if (trimer(thenfa, reachable, may_exit, etat)) {
|
||||
may_exit[sommet] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mem_dequeue_sorted(sommet, thenfa->finals);
|
||||
}
|
||||
|
||||
// Élimination des états non-accessibles et non-co-accessibles
|
||||
// Le NFA produit n'est pas nécessairement complet
|
||||
nfa *nfa_trim(nfa *thenfa) {
|
||||
printf("nfa_trim\n");
|
||||
nfa *trimmed = nfa_copy(thenfa);
|
||||
bool reachable[trimmed->trans->size_graph];
|
||||
bool may_end[trimmed->trans->size_graph];
|
||||
for (uint i = 0; i < trimmed->trans->size_graph; i++) {
|
||||
reachable[i] = false;
|
||||
may_end[i] = false;
|
||||
}
|
||||
// on marque les états accessibles
|
||||
uint size = size_dequeue(trimmed->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(trimmed->initials, i);
|
||||
trimer(trimmed, reachable, may_end, etat);
|
||||
}
|
||||
// on compte les états accessibles
|
||||
int c = 0;
|
||||
for (uint i = 0; i < trimmed->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
// on crée un nouveau graphe
|
||||
lgraph *new_graph = create_lgraph_noedges(c, trimmed->trans->size_alpha);
|
||||
for (uint i = 0; i < new_graph->size_graph; i++) {
|
||||
for (uint j = 0; j < new_graph->size_alpha; j++) {
|
||||
// on récupère les arêtes accessibles
|
||||
dequeue *edges = new_graph->edges[i][j];
|
||||
dequeue *old_edges = trimmed->trans->edges[i][j];
|
||||
size = size_dequeue(old_edges);
|
||||
for (uint k = 0; k < size; k++) {
|
||||
const uint etat = lefread_dequeue(old_edges, k);
|
||||
if (reachable[etat] && may_end[etat]) {
|
||||
lefins_dequeue(etat, edges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// on remplace le graphe
|
||||
delete_lgraph(trimmed->trans);
|
||||
trimmed->trans = new_graph;
|
||||
|
||||
// on supprime les états finaux non accessibles
|
||||
size = size_dequeue(trimmed->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(trimmed->finals);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, trimmed->finals);
|
||||
}
|
||||
}
|
||||
// on supprime les états initiaux non accessibles
|
||||
size = size_dequeue(trimmed->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(trimmed->initials);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, trimmed->initials);
|
||||
}
|
||||
}
|
||||
|
||||
// on supprime les états non accessibles
|
||||
char **new_state_names = malloc(sizeof(char *) * c);
|
||||
CHECK(new_state_names);
|
||||
c = 0;
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
new_state_names[c] = nfa_copy_one_name(thenfa, i);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
free(trimmed->state_names);
|
||||
trimmed->state_names = new_state_names;
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
// Élimination des états non-accessibles (modifie le NFA originel)
|
||||
void nfa_trim_mod(nfa *thenfa) {
|
||||
printf("nfa_trim_mod\n");
|
||||
bool reachable[thenfa->trans->size_graph];
|
||||
bool may_end[thenfa->trans->size_graph];
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
reachable[i] = false;
|
||||
may_end[i] = false;
|
||||
}
|
||||
// on marque les états accessibles
|
||||
uint size = size_dequeue(thenfa->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(thenfa->initials, i);
|
||||
trimer(thenfa, reachable, may_end, etat);
|
||||
}
|
||||
// on compte les états accessibles
|
||||
int c = 0;
|
||||
for (uint i = 0; i < thenfa->trans->size_graph; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
// on crée un nouveau graphe
|
||||
lgraph *new_graph = create_lgraph_noedges(c, thenfa->trans->size_alpha);
|
||||
for (uint i = 0; i < new_graph->size_graph; i++) {
|
||||
for (uint j = 0; j < new_graph->size_alpha; j++) {
|
||||
// on récupère les arêtes accessibles
|
||||
dequeue *edges = new_graph->edges[i][j];
|
||||
dequeue *old_edges = thenfa->trans->edges[i][j];
|
||||
size = size_dequeue(old_edges);
|
||||
for (uint k = 0; k < size; k++) {
|
||||
const uint etat = lefread_dequeue(old_edges, k);
|
||||
if (reachable[etat] && may_end[etat]) {
|
||||
lefins_dequeue(etat, edges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// on remplace le graphe
|
||||
const uint saved_size = thenfa->trans->size_graph; // utile pour plus tard
|
||||
delete_lgraph(thenfa->trans);
|
||||
thenfa->trans = new_graph;
|
||||
|
||||
// on supprime les états finaux non accessibles
|
||||
size = size_dequeue(thenfa->finals);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(thenfa->finals);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, thenfa->finals);
|
||||
}
|
||||
}
|
||||
// on supprime les états initiaux non accessibles
|
||||
size = size_dequeue(thenfa->initials);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefpull_dequeue(thenfa->initials);
|
||||
if (reachable[etat]) {
|
||||
rigins_dequeue(etat, thenfa->initials);
|
||||
}
|
||||
}
|
||||
|
||||
// on supprime les états non accessibles
|
||||
char **new_state_names = malloc(sizeof(char *) * c);
|
||||
CHECK(new_state_names);
|
||||
c = 0;
|
||||
for (uint i = 0; i < saved_size; i++) {
|
||||
if (reachable[i] && may_end[i]) {
|
||||
new_state_names[c] = nfa_copy_one_name(thenfa, i);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
free(thenfa->state_names);
|
||||
thenfa->state_names = new_state_names;
|
||||
}
|
||||
|
||||
// Miroir
|
||||
nfa *nfa_mirror(nfa *thenfa) {
|
||||
printf("nfa_mirror\n");
|
||||
nfa *mirror = malloc(sizeof(nfa));
|
||||
CHECK(mirror);
|
||||
// on inverse les états initiaux et finaux
|
||||
mirror->initials = create_dequeue();
|
||||
copy_dequeue_right(mirror->initials, thenfa->finals, 0);
|
||||
mirror->finals = create_dequeue();
|
||||
copy_dequeue_right(mirror->finals, thenfa->initials, 0);
|
||||
// on copie les alphabets
|
||||
mirror->alpha_names = nfa_copy_alpha(thenfa);
|
||||
// on copie les noms d'états
|
||||
mirror->state_names = nfa_copy_all_names(thenfa);
|
||||
// on prépare le graphe
|
||||
lgraph *g = create_lgraph_noedges(thenfa->trans->size_graph,
|
||||
thenfa->trans->size_alpha);
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
dequeue *edge = thenfa->trans->edges[sommet][lettre];
|
||||
const uint size = size_dequeue(edge);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(edge, i);
|
||||
lefins_dequeue(sommet, g->edges[etat][lettre]);
|
||||
}
|
||||
}
|
||||
}
|
||||
mirror->trans = g;
|
||||
return mirror;
|
||||
}
|
||||
|
||||
/************************/
|
||||
/* Informations sur NFA */
|
||||
/************************/
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
int nfa_nb_trans(nfa *thenfa) {
|
||||
printf("nf_nb_trans\n");
|
||||
int nb_trans = 0;
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
nb_trans += (int)size_dequeue(thenfa->trans->edges[sommet][lettre]);
|
||||
}
|
||||
}
|
||||
return nb_trans;
|
||||
}
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
bool nfa_is_det(nfa *thenfa) {
|
||||
printf("nfa_is_det\n");
|
||||
printf("'ça va pas marcher mais chhhh...\n");
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
if (size_dequeue(thenfa->trans->edges[sommet][lettre]) > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nfa_is_comp(nfa *thenfa) {
|
||||
printf("nfa_is_comp\n");
|
||||
for (uint sommet = 0; sommet < thenfa->trans->size_graph; sommet++) {
|
||||
for (uint lettre = 0; lettre < thenfa->trans->size_alpha; lettre++) {
|
||||
if (size_dequeue(thenfa->trans->edges[sommet][lettre]) < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
bool nfa_is_empty(nfa *thenfa) {
|
||||
printf("nfa_is_empty\n");
|
||||
return thenfa->trans->size_alpha == 0 && thenfa->trans->size_graph == 0;
|
||||
}
|
||||
|
||||
bool nfa_accepts(nfa *thenfa, const char *theword) {
|
||||
printf("nfa_accepts\n");
|
||||
dequeue *runs = nfa_compute_runs(thenfa, theword);
|
||||
const uint size = size_dequeue(runs);
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(runs, i);
|
||||
if (mem_dequeue_sorted(etat, thenfa->finals)) {
|
||||
delete_dequeue(runs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete_dequeue(runs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calcule les états qui sont atteints par un mot dans un NFA.
|
||||
// ReSharper disable once CppParameterMayBeConstPtrOrRef
|
||||
dequeue *nfa_compute_runs(nfa *thenfa, const char *theword) {
|
||||
printf("nfa_compute_runs\n");
|
||||
dequeue *runs = create_dequeue();
|
||||
uint indice = 0;
|
||||
uint size = size_dequeue(thenfa->initials);
|
||||
while (indice < strlen(theword)) {
|
||||
dequeue *new_runs = create_dequeue();
|
||||
for (uint i = 0; i < size; i++) {
|
||||
const uint etat = lefread_dequeue(thenfa->initials, i);
|
||||
const uint lettre = (uint)theword[indice];
|
||||
merge_sorted_dequeue(new_runs, thenfa->trans->edges[etat][lettre]);
|
||||
}
|
||||
delete_dequeue(runs);
|
||||
runs = new_runs;
|
||||
size = size_dequeue(runs);
|
||||
indice++;
|
||||
}
|
||||
return runs;
|
||||
}
|
||||
246
Aloyse et Vincent/nfa_determi.c
Normal file
246
Aloyse et Vincent/nfa_determi.c
Normal 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;
|
||||
}
|
||||
145
Aloyse et Vincent/nfa_intersec.c
Normal file
145
Aloyse et Vincent/nfa_intersec.c
Normal 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;
|
||||
}
|
||||
127
Aloyse et Vincent/nfa_mccluskey.c
Normal file
127
Aloyse et Vincent/nfa_mccluskey.c
Normal 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;
|
||||
}
|
||||
29
Aloyse et Vincent/nfa_minimization.c
Normal file
29
Aloyse et Vincent/nfa_minimization.c
Normal 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;
|
||||
}
|
||||
9
Aloyse et Vincent/nfa_tocode.c
Normal file
9
Aloyse et Vincent/nfa_tocode.c
Normal 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;
|
||||
}
|
||||
1397
Aloyse et Vincent/parse_regexp.tab.c
Normal file
1397
Aloyse et Vincent/parse_regexp.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
1412
Aloyse et Vincent/parser.tab.c
Normal file
1412
Aloyse et Vincent/parser.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
302
Aloyse et Vincent/printing.c
Normal file
302
Aloyse et Vincent/printing.c
Normal 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
116
Aloyse et Vincent/regexp.c
Normal 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;
|
||||
}
|
||||
364
Aloyse et Vincent/regexp_tonfa.c
Normal file
364
Aloyse et Vincent/regexp_tonfa.c
Normal 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
2123
Aloyse et Vincent/scan.c
Normal file
File diff suppressed because it is too large
Load Diff
2172
Aloyse et Vincent/scan_regexp.c
Normal file
2172
Aloyse et Vincent/scan_regexp.c
Normal file
File diff suppressed because it is too large
Load Diff
1012
Aloyse et Vincent/shell_commands.c
Normal file
1012
Aloyse et Vincent/shell_commands.c
Normal file
File diff suppressed because it is too large
Load Diff
104
Aloyse et Vincent/shell_help.c
Normal file
104
Aloyse et Vincent/shell_help.c
Normal 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");
|
||||
}
|
||||
347
Aloyse et Vincent/shell_keywords.c
Normal file
347
Aloyse et Vincent/shell_keywords.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
353
Aloyse et Vincent/shell_languages.c
Normal file
353
Aloyse et Vincent/shell_languages.c
Normal 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;
|
||||
}
|
||||
401
Aloyse et Vincent/shell_test.c
Normal file
401
Aloyse et Vincent/shell_test.c
Normal 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);
|
||||
}
|
||||
}
|
||||
445
Aloyse et Vincent/shell_tools.c
Normal file
445
Aloyse et Vincent/shell_tools.c
Normal 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;
|
||||
}
|
||||
}
|
||||
77
Aloyse et Vincent/type_boolarray.c
Normal file
77
Aloyse et Vincent/type_boolarray.c
Normal 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;
|
||||
}
|
||||
386
Aloyse et Vincent/type_dequeue.c
Normal file
386
Aloyse et Vincent/type_dequeue.c
Normal 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;
|
||||
}
|
||||
73
Aloyse et Vincent/type_stack.c
Normal file
73
Aloyse et Vincent/type_stack.c
Normal 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;
|
||||
}
|
||||
84
Anna et Ethan/nfa_mccluskey.c
Normal file
84
Anna et Ethan/nfa_mccluskey.c
Normal 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
133
Anna et Ethan/regexp.c
Normal 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;
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user