changement dossier

This commit is contained in:
Aloyse ARNAUD
2024-12-16 02:49:02 +01:00
parent b06c2fcc82
commit 1bd783c958
28 changed files with 0 additions and 13188 deletions
-64
View File
@@ -1,64 +0,0 @@
// 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
View File
@@ -1,29 +0,0 @@
/**
* @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
View File
@@ -1,7 +0,0 @@
div.image img[src="en_cours.png"]{
width:350px;
}
div.image img[src="moves.png"]{
width:850px;
}
-550
View File
@@ -1,550 +0,0 @@
/***********************/
/* 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
View File
@@ -1,127 +0,0 @@
/********************************************/
/* 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
View File
@@ -1,94 +0,0 @@
#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
View File
@@ -1,677 +0,0 @@
/***************************/
/* 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
View File
@@ -1,246 +0,0 @@
/********************************************/
/* 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
View File
@@ -1,145 +0,0 @@
/************************/
/* 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
View File
@@ -1,127 +0,0 @@
#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
View File
@@ -1,29 +0,0 @@
#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
View File
@@ -1,9 +0,0 @@
#include "nfa_tocode.h"
#include "nfa_determi.h"
#include "printing.h"
#include "error.h"
#include <stdio.h>
void nfa2code(nfa *, char *) {
return;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-302
View File
@@ -1,302 +0,0 @@
#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
View File
@@ -1,116 +0,0 @@
#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
View File
@@ -1,364 +0,0 @@
#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;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-104
View File
@@ -1,104 +0,0 @@
#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
View File
@@ -1,347 +0,0 @@
#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
View File
@@ -1,353 +0,0 @@
#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
View File
@@ -1,401 +0,0 @@
#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
View File
@@ -1,445 +0,0 @@
#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
View File
@@ -1,77 +0,0 @@
#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
View File
@@ -1,386 +0,0 @@
/*****************************************/
/* 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
View File
@@ -1,73 +0,0 @@
#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;
}