Files
c-automates-giiiiive/Aloyse et Vincent/shell_commands.c
2024-12-16 02:48:28 +01:00

1013 lines
29 KiB
C

/*****************************/
/* Gestionnaire de commandes */
/*****************************/
#include "shell_commands.h"
/******************************************************************************/
/* Récupération des automates désignés par une commande */
/******************************************************************************/
genob *shell_genob_from_command(com_command *thecom) {
// Si la commande est mal formée
if (thecom == NULL || thecom->main == NULL) {
return NULL;
}
// On récupère l'objet correspondant au premier maillon
int i = object_get_from_name(thecom->main->string);
if (i == -1) {
return NULL;
}
// L'objet généralisé qu'on va retourner
genob *new = NULL;
// La chaîne complète
string_chain *thechain = thecom->main;
// Tant qu'il y a des maillons
while (thechain != NULL) {
// On prend le prochain maillon
thechain = thechain->next;
// On regarde le type de l'objet
switch (objects[i]->type) {
case LANGUAGE: {
// Si il n'y pas de maillon suivant et pas de paramètre
// La commande désigne simplement le langage
if (thechain == NULL && thecom->params == NULL) {
MALLOC(new, 1);
new->type = OG_LANG;
new->theob = objects[i]->lan;
return new;
}
// Sinon la commande continue pour désigner l'automate minimal.
com_keyword key = key_from_string_chain(thechain);
switch (key) {
case CM_MINI:
i = shell_compute_minimal(i);
break;
default:
return NULL;
break;
}
} break;
case AUTOMATON: {
// Pour l'instant seul le cas d'un automate simple est géré
if (thechain == NULL && thecom->params == NULL) {
MALLOC(new, 1);
new->type = OG_AUTO;
new->theob = objects[i]->aut->nfa;
return new;
}
else {
return NULL;
}
}
default:
break;
}
}
return NULL;
}
/******************************/
/* Application d'une commande */
/******************************/
static bool com_apply_command_rec(string_chain *thechain, com_parameters *pars,
int i) {
if (i == -1) {
shell_command_error();
return false;
}
switch (objects[i]->type) {
case LANGUAGE: {
language *thelang = objects[i]->lan;
if (thechain == NULL && pars == NULL) {
if (thelang->type == SPE_REG) {
fprintf(stdout,
"This language is specified by a regular expression:\n");
reg_print(thelang->reg);
}
else if (thelang->type == SPE_NFA) {
fprintf(stdout, "This language is specified by an automaton:\n");
nfa_view(objects[thelang->nfa]->aut->nfa);
}
return true;
}
com_keyword key = key_from_string_chain(thechain);
switch (key) {
case CM_MINI:
shell_compute_minimal(i);
return com_apply_command_rec(thechain->next, pars, thelang->minauto);
break;
default:
shell_command_error();
return false;
break;
}
} break;
case AUTOMATON: {
automata *theauto = objects[i]->aut;
if (thechain == NULL && pars == NULL) {
print_title_box(100, true, stdout, 1, "Automaton.");
nfa_view(theauto->nfa);
return true;
}
com_keyword key = key_from_string_chain_single(thechain);
switch (key) {
case CM_RUN:
shell_make_nfa_run(theauto, pars);
break;
default:
shell_command_error();
return false;
break;
}
} break;
default:
shell_command_error();
return false;
break;
}
return false;
}
bool com_apply_command(com_command *thecom) {
if (thecom == NULL || thecom->main == NULL) {
shell_command_error();
return false;
}
// On commence par regarder si le premier maillon de la commande correspond
// à
// une variable.
int i = object_get_from_name(thecom->main->string);
if (i != -1) {
// Si c'est le cas, la commande est récursive
return com_apply_command_rec(thecom->main->next, thecom->params, i);
}
// Sinon, le premier maillon doit être le seul et doit correspondre à un
// keyword
if (thecom->main->next) {
shell_command_error();
return false;
}
com_keyword key = string_to_keyword(thecom->main->string);
switch (key) {
case CM_SAVE:
return shell_save_to_file(thecom->params);
break;
case CM_CODE:
return shell_code_to_file(thecom->params);
break;
case CM_SAVESESSION:
return shell_save_session(thecom->params);
break;
case CM_LOADSESSION:
return shell_load_session(thecom->params);
break;
case CM_DELETE:
return shell_delete(thecom->params);
break;
case CM_RESET:
return shell_reset(thecom->params);
break;
case CM_SORT:
return shell_sort(thecom->params);
break;
case CM_BMCK:
return shell_mccluskey_reg(NULL, thecom->params);
break;
case CM_THOMPSON:
return shell_thompson_nfa(NULL, thecom->params);
break;
case CM_GLUSHKOV:
return shell_glushkov_nfa(NULL, thecom->params);
break;
case CM_HOPCROFT:
return shell_hopcroft_nfa(NULL, thecom->params);
break;
case CM_MIRROR:
return shell_mirror_nfa(NULL, thecom->params);
break;
case CM_TRIMNFA:
return shell_trim_nfa(NULL, thecom->params);
break;
case CM_KLEENE:
return shell_kleene_nfa(NULL, thecom->params);
break;
case CM_INTERSEC:
return shell_intersect_nfa(NULL, thecom->params);
break;
case CM_CONCAT:
return shell_concat_nfa(NULL, thecom->params);
break;
case CM_UNION:
return shell_union_nfa(NULL, thecom->params);
break;
case CM_DETERMIN:
return shell_determinize_nfa(NULL, thecom->params);
break;
case CM_MINI:
case CM_BRZOZO:
return shell_minimize_nfa(NULL, thecom->params);
break;
case CM_OPEN:
return shell_open_object(NULL, thecom->params);
break;
default:
shell_command_error();
return false;
break;
}
shell_command_error();
return false;
}
int com_apply_link_command(char *name, com_command *thecom) {
if (thecom == NULL || thecom->main == NULL) {
shell_command_error();
return -1;
}
if (!check_varname(name)) {
return -1;
}
// Premier cas: la commande est juste un texte à traiter comme une regexp
if (thecom->thetype == CMT_RAW) {
regexp *myexp;
myexp = parse_string_regexp(thecom->main->string);
if (myexp == NULL) {
return -1;
}
int i = object_add_language_reg(name, myexp);
reg_print(myexp);
return i;
}
// Si le premier maillon est un nom de variable, alors il s'agit juste de
// faire une copie
int i = index_from_string_chain(thecom->main);
if (i != -1 && thecom->params == NULL) {
object_copy_generic(i, name);
return true;
}
// On sait maintenant que le premier argument est un keyword
// Dans ce cas il ne peut pas y avoir de nesting.
com_keyword key = key_from_string_chain_single(thecom->main);
switch (key) {
case CM_BMCK:
return shell_mccluskey_reg(name, thecom->params);
break;
case CM_THOMPSON:
return shell_thompson_nfa(name, thecom->params);
break;
case CM_GLUSHKOV:
return shell_glushkov_nfa(name, thecom->params);
break;
case CM_HOPCROFT:
return shell_hopcroft_nfa(name, thecom->params);
break;
case CM_MIRROR:
return shell_mirror_nfa(name, thecom->params);
break;
case CM_TRIMNFA:
return shell_trim_nfa(name, thecom->params);
break;
case CM_KLEENE:
return shell_kleene_nfa(name, thecom->params);
break;
case CM_INTERSEC:
return shell_intersect_nfa(name, thecom->params);
break;
case CM_CONCAT:
return shell_concat_nfa(name, thecom->params);
break;
case CM_UNION:
return shell_union_nfa(name, thecom->params);
break;
case CM_DETERMIN:
return shell_determinize_nfa(name, thecom->params);
break;
case CM_MINI:
case CM_BRZOZO:
return shell_minimize_nfa(name, thecom->params);
break;
case CM_LINK:
return shell_linktolang_nfa(name, thecom->params);
break;
case CM_OPEN:
return shell_open_object(name, thecom->params);
break;
default:
shell_command_error();
return false;
break;
}
shell_command_error();
return false;
}
/******************************/
/* Calculs de nouveaux objets */
/******************************/
// Ajout d'un nouvel objet en copiant un objet déjà existant dans la table
int object_copy_generic(int i, char *newname) {
if (i == -1) {
fprintf(stderr, "Error: this is not a valid object to copy.\n");
return -1;
}
switch (objects[i]->type) {
case AUTOMATON:
return object_add_automata(newname, nfa_copy(objects[i]->aut->nfa));
break;
case LANGUAGE:
if (objects[i]->lan->type == SPE_REG) {
return object_add_language_reg(newname, reg_copy(objects[i]->lan->reg));
}
else {
int j = object_add_automata(
newname, nfa_copy(objects[objects[i]->lan->nfa]->aut->nfa));
return object_add_language_nfa(newname, j);
}
default:
return -1;
break;
}
}
// Calcule un nouveau NFA avec la méthode de Glushkov à partir d'un langage.
int shell_glushkov_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != LANGUAGE ||
objects[i]->lan->type != SPE_REG) {
fprintf(stderr, "Error: Glushkov's algorithm can only be applied to a "
"language specified by a regular expression.\n");
return -1;
}
DEBUG("Computing an automaton from a language");
nfa *automaton = reg_glushkov(objects[i]->lan->reg);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the Glushkov automaton.\n"
"Please implement reg_glushkov().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Calcule le miroir d'un nfa à partir d'un langage.
int shell_mirror_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: Can only make the mirror of a NFA.\n");
return -1;
}
DEBUG("Computing the mirror of an automaton");
nfa *automaton = nfa_mirror(objects[i]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the mirror automaton.\n"
"Please implement nfa_mirror().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
int shell_hopcroft_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: Can only minimize a NFA.\n");
return -1;
}
DEBUG("Minimizing with Hopcroft");
nfa *automaton = nfa_hopcroft(objects[i]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the Hopcroft automaton.\n"
"Please implement nfa_hopcroft().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
int shell_mccluskey_reg(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: Brzozowski and McCluskey's algorithm can only be "
"applied to a NFA.\n");
return -1;
}
DEBUG("Computing a regular expression from an automaton");
regexp *exp = nfa_mccluskey(objects[i]->aut->nfa);
if (exp == NULL) {
fprintf(stderr, "Error: unable to compute the regular expression.\n"
"Please implement nfa_mccluskey().\n");
return -1;
}
if (varname) {
return object_add_language_reg(varname, exp);
}
else {
reg_print(exp);
reg_free(exp);
return 1;
}
}
// Calcule un nouveau NFA avec la méthode de thompson à partir d'un langage.
int shell_thompson_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != LANGUAGE ||
objects[i]->lan->type != SPE_REG) {
fprintf(stderr, "Error: Thomson's algorithm can only be applied to a "
"language specified by a regular expression.\n");
return -1;
}
DEBUG("Computing an automaton from a language");
nfa *automaton = reg_thompson(objects[i]->lan->reg);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the Thompson automaton.\n"
"Please implement reg_thompson().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Union de deux NFAs
int shell_union_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 2) {
shell_arguments_error();
return -1;
}
int i1 = index_from_string_chain(pars->param->main);
int i2 = index_from_string_chain(pars->next->param->main);
if (i1 == -1 || i2 == -1) {
shell_variable_error();
return false;
}
if (i1 < 0 || i2 < 0 || objects[i1]->type != AUTOMATON ||
objects[i2]->type != AUTOMATON) {
fprintf(stderr,
"Error: The union algorithm requires two automata as input.\n");
return -1;
}
nfa *automaton = nfa_union(objects[i1]->aut->nfa, objects[i2]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the union.\n"
"Please implement nfa_union().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Concatène deux NFAs
int shell_concat_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 2) {
shell_arguments_error();
return -1;
}
int i1 = index_from_string_chain(pars->param->main);
int i2 = index_from_string_chain(pars->next->param->main);
if (i1 == -1 || i2 == -1) {
shell_variable_error();
return false;
}
if (i1 < 0 || i2 < 0 || objects[i1]->type != AUTOMATON ||
objects[i2]->type != AUTOMATON) {
fprintf(
stderr,
"Error: The concatenation algorithm requires two automata as input.\n");
return -1;
}
nfa *automaton = nfa_concat(objects[i1]->aut->nfa, objects[i2]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the concatenation.\n"
"Please implement nfa_concat().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Étoile de Kleene sur un NFA
int shell_kleene_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: The Kleene star algorithm can only be applied to "
"an automaton.\n");
return -1;
}
nfa *automaton = nfa_star(objects[i]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the Kleene star automaton.\n"
"Please implement nfa_star().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Calcule un nouveau NFA en supprimant tous les états non-accessibles ou non
// co-accessibles
int shell_trim_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: Can only trim an automaton.\n");
return -1;
}
nfa *automaton = nfa_trim(objects[i]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the trimmed automaton.\n"
"Please implement nfa_trim().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Calcule un nouveau NFA en réalisant l'intersection de deux NFAs existants
int shell_intersect_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 2) {
shell_arguments_error();
return -1;
}
int i1 = index_from_string_chain(pars->param->main);
int i2 = index_from_string_chain(pars->next->param->main);
if (i1 == -1 || i2 == -1) {
shell_variable_error();
return false;
}
if (i1 < 0 || i2 < 0 || objects[i1]->type != AUTOMATON ||
objects[i2]->type != AUTOMATON) {
fprintf(
stderr,
"Error: The intersection algorithm requires two automata as input.\n");
return -1;
}
nfa *automaton =
nfa_intersect(objects[i1]->aut->nfa, objects[i2]->aut->nfa, true);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the intersection automaton.\n"
"Please implement nfa_intersect().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Calcule un nouveau NFA déterministe complet en déterminisant un NFA déjà
// existant
int shell_determinize_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: The subset construction can only be applied to an "
"automaton.\n");
return -1;
}
nfa *automaton = nfa_determinize(objects[i]->aut->nfa, true);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the determinized automaton.\n"
"Please implement nfa_determinize().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Calcule un automate minimal à partir d'un NFA
int shell_minimize_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: the minimization algorithm can only be applied to "
"an automaton.\n");
return -1;
}
nfa *automaton = nfa_brzozowski(objects[i]->aut->nfa);
if (automaton == NULL) {
fprintf(stderr, "Error: unable to compute the minimal automaton by "
"Brzozowski's algorithm.\n"
"Please implement nfa_brzozowski().\n");
return -1;
}
if (varname) {
return object_add_automata(varname, automaton);
}
else {
nfa_view(automaton);
nfa_delete(automaton);
return 1;
}
}
// Links an existing nfa to a nex language
int shell_linktolang_nfa(char *varname, com_parameters *pars) {
if (com_nbparams(pars) != 1) {
shell_arguments_error();
return -1;
}
int i = index_from_string_chain(pars->param->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (i < 0 || objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: the argument should be an automata variable.\n");
return -1;
}
return object_add_language_nfa(varname, i);
}
// Sauvegarde d'un objet
bool shell_save_to_file(com_parameters *params) {
if (com_nbparams(params) != 2) {
shell_arguments_error();
return false;
}
com_command **pararray = com_getparamarray(params);
int i = index_from_string_chain(pararray[0]->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (!com_israw(pararray[1])) {
fprintf(stderr, "Error: cannot parse the filename\n");
return false;
}
char *filename = pararray[1]->main->string;
printf("saving %s in the file: \"%s\".\n", params->param->main->string,
filename);
files_save_object(objects[i], filename);
free(pararray);
return true;
}
// Sauvegarde sous forme de code d'un automate
bool shell_code_to_file(com_parameters *params) {
if (com_nbparams(params) != 2) {
shell_arguments_error();
return false;
}
com_command **pararray = com_getparamarray(params);
int i = index_from_string_chain(pararray[0]->main);
if (i == -1) {
shell_variable_error();
return false;
}
if (objects[i]->type != AUTOMATON) {
fprintf(stderr, "Error: code can only be applied to an automaton\n");
return false;
}
if (!com_israw(pararray[1])) {
fprintf(stderr, "Error: cannot parse the filename\n");
return false;
}
char *filename = pararray[1]->main->string;
printf("sending the code of %s in file \"%s\".\n",
params->param->main->string, filename);
nfa2code(objects[i]->aut->nfa, filename);
free(pararray);
return true;
}
// Sauvegarde d'une session complète
bool shell_save_session(com_parameters *params) {
if (com_nbparams(params) != 1) {
shell_arguments_error();
return false;
}
if (!com_israw(params->param)) {
fprintf(stderr, "Error: cannot parse the filename\n");
return false;
}
char *filename = params->param->main->string;
printf("saving the session in the file: \"%s\".\n", filename);
files_save_session(filename);
return false;
}
// Chargement d'une session à partir d'un fichier
bool shell_load_session(com_parameters *params) {
if (com_nbparams(params) != 1) {
shell_arguments_error();
return false;
}
if (!com_israw(params->param)) {
fprintf(stderr, "Error: cannot parse the filename\n");
return false;
}
char *filename = params->param->main->string;
printf("loading the session saved in the file: \"%s\".\n", filename);
files_load_session(filename);
return false;
}
// Suppression d'un objet
int shell_delete(com_parameters *params) {
if (com_nbparams(params) != 1 || !com_single(params->param)) {
shell_arguments_error();
return false;
}
return object_delete_from_name(params->param->main->string);
}
// Effacement des noms d'un automate
int shell_reset(com_parameters *params) {
if (com_nbparams(params) != 1 || !com_single(params->param)) {
shell_arguments_error();
return false;
}
int i = object_get_from_name(params->param->main->string);
if (i == -1) {
fprintf(stderr, "Error: unknown variable.\n");
return -1;
}
if (objects[i]->type != AUTOMATON || objects[i]->aut == NULL) {
shell_arguments_error();
return false;
}
nfa_reset_state_names(objects[i]->aut->nfa);
return true;
}
// Tri des objets
bool shell_sort(com_parameters *params) {
if (params != NULL) {
shell_arguments_error();
return false;
}
object_sort_array();
return true;
}
// Ouverture d'un objet
bool shell_open_object(char *varname, com_parameters *params) {
if (com_nbparams(params) != 1 || params->param->thetype != CMT_RAW ||
varname == NULL) {
shell_arguments_error();
return false;
}
files_read_object(params->param->main->string, varname);
return true;
}
// Calcul d'un NFA aléatoire
bool shell_random_nfa(char *, com_parameters *, bool) {
/* if (com_nbparams(params) != 3) {
shell_arguments_error();
return false;
}
com_command* arg1 = params->param;
com_command* arg2 = params->next->param;
com_command* arg3 = params->next->next->param;
if (!com_single(arg1) || !com_single(arg2) || !com_single(arg3)) {
shell_arguments_error();
return false;
}
char* end;
int nb1 = strtol(arg1->main->string, &end, 10);
if (*end != '\0') {
shell_arguments_error();
return false;
}
int nb2 = strtol(arg2->main->string, &end, 10);
if (*end != '\0') {
shell_arguments_error();
return false;
}
int nb3 = strtol(arg3->main->string, &end, 10);
if (*end != '\0') {
shell_arguments_error();
return false;
} */
return false;
/* if (det)
return object_add_automata(varname, dfa_random(nb1, nb2, nb3));
else
return object_add_automata(varname, nfa_random(nb1, nb2, nb3)); */
}
/********************************************************************/
/* Affichage - fonctions appellées par le gestionnaire de commandes */
/********************************************************************/
bool shell_make_nfa_run(automata *aut, com_parameters *pars) {
if (com_nbparams(pars) != 1 || !com_single(pars->param)) {
shell_arguments_error();
return false;
}
dequeue *states = nfa_compute_runs(aut->nfa, pars->param->main->string);
if (states == NULL) {
printf("Error: this is not a valid word for this automaton.\n");
return false;
}
printf("Set of states reached: ");
if (isempty_dequeue(states)) {
printf("∅.\n");
}
else {
printf("{");
for (uint i = 0; i < size_dequeue(states) - 1; i++) {
nfa_print_state(aut->nfa, lefread_dequeue(states, i), stdout);
printf(",");
}
nfa_print_state(aut->nfa, lefread_dequeue(states, size_dequeue(states) - 1),
stdout);
printf("}.\n");
}
// On teste si on a atteint un état final
uint i = 0;
uint j = 0;
while (i < size_dequeue(states) && j < size_dequeue(aut->nfa->finals)) {
if (lefread_dequeue(states, i) == lefread_dequeue(aut->nfa->finals, j)) {
printf("The word is accepted.\n");
return true;
}
else if (lefread_dequeue(states, i) <
lefread_dequeue(aut->nfa->finals, j)) {
i++;
}
else {
j++;
}
}
printf("The word is rejected.\n");
return true;
}