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