Files
2024-12-16 02:48:28 +01:00

354 lines
9.5 KiB
C

#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;
}