diff --git a/Aloyse et Vincent/a.c b/Aloyse et Vincent/a.c new file mode 100644 index 0000000..e4c5c68 --- /dev/null +++ b/Aloyse et Vincent/a.c @@ -0,0 +1,64 @@ +// Généré automatiquement à partir d'un automate reconnaissant le langage a. +// Ensemble des états : {0, 1, 2} +// État initiaux : {0} +// États finaux : {1} +// Transitions : +// 0 -a-> 1 +// 1 -a-> 2 +// 2 -a-> 2 +#include +#include + +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; + } + } + } +} diff --git a/Aloyse et Vincent/alloc.c b/Aloyse et Vincent/alloc.c new file mode 100644 index 0000000..ecfc57c --- /dev/null +++ b/Aloyse et Vincent/alloc.c @@ -0,0 +1,29 @@ +/** + * @file alloc.c + * @brief Fonctions d'allocation mémoire. + */ + +#include "alloc.h" + +void multiple_free(void *p, ...) { + va_list ap; + va_start(ap, p); + while (p != NULL) { + free(p); + p = va_arg(ap, void *); + } + va_end(ap); +} + +void check_null(const char *function, char *file, int line, int n, ...) { + va_list ap; + char *s; + + va_start(ap, n); + for (int i = 0; i < n; i++) { + void *p = va_arg(ap, void *); + s = va_arg(ap, char *); + if (p == NULL) + PRINT_ERROR(KO, "CRITICAL", function, file, line, "%s is NULL.", s); + } +} diff --git a/Aloyse et Vincent/extra.css b/Aloyse et Vincent/extra.css new file mode 100644 index 0000000..96a8279 --- /dev/null +++ b/Aloyse et Vincent/extra.css @@ -0,0 +1,7 @@ +div.image img[src="en_cours.png"]{ + width:350px; +} + +div.image img[src="moves.png"]{ + width:850px; +} diff --git a/Aloyse et Vincent/files.c b/Aloyse et Vincent/files.c new file mode 100644 index 0000000..2931adb --- /dev/null +++ b/Aloyse et Vincent/files.c @@ -0,0 +1,550 @@ +/***********************/ +/* Gestion de fichiers */ +/***********************/ + +#include "files.h" + +static void reg_to_string_aux(regexp *r, char *buffer) { + TRACE("reg_to_string_aux"); + + if (r == NULL) { + return; + } + + switch (r->op) { + case CHAR: { + char mess[2]; + mess[0] = r->letter; + mess[1] = '\0'; + strcat(buffer, mess); + } break; + case EMPTY: + strcat(buffer, "0"); + break; + case EPSILON: + strcat(buffer, "1"); + break; + case UNION: + strcat(buffer, "("); + reg_to_string_aux(r->left, buffer); + strcat(buffer, " + "); + reg_to_string_aux(r->right, buffer); + strcat(buffer, ")"); + break; + case INTER: + strcat(buffer, "("); + reg_to_string_aux(r->left, buffer); + strcat(buffer, " & "); + reg_to_string_aux(r->right, buffer); + strcat(buffer, ")"); + break; + case CONCAT: + strcat(buffer, "("); + reg_to_string_aux(r->left, buffer); + strcat(buffer, " "); + reg_to_string_aux(r->right, buffer); + strcat(buffer, ")"); + break; + case STAR: + strcat(buffer, "("); + reg_to_string_aux(r->left, buffer); + strcat(buffer, ")*"); + break; + case COMPLEMENT: + strcat(buffer, "!("); + reg_to_string_aux(r->left, buffer); + strcat(buffer, ")"); + break; + default: + CRITICAL("Unknown regexp operator (%d)", r->op); + break; + } +} + +void reg_to_string(regexp *r, char *buffer) { + TRACE("reg_to_string"); + + if (!r) { + return; + } + reg_to_string_aux(r, buffer); +} + +unsigned short autocount = 0; + +/***********************************************/ +/* Manipulation de structures JSON - Automates */ +/***********************************************/ + +json_object *files_auto_to_json(automata *theauto) { + // Création de l'objet json + json_object *root = json_object_new_object(); + if (!root) { + fprintf(stderr, "Failed to create the JSON object.\n"); + return NULL; + } + + json_object_object_add(root, "TYPE", json_object_new_string("AUTO")); + nfa *A = theauto->nfa; + + // Taille de l'alphabet + json_object_object_add(root, "N_ALPH", + json_object_new_int(A->trans->size_alpha)); + + // Taille de l'automate (nombre d'états) + json_object_object_add(root, "N_SIZE", + json_object_new_int(A->trans->size_graph)); + + // Alphabet + char *alphabet; + MALLOC(alphabet, A->trans->size_alpha + 1); + for (uint i = 0; i < A->trans->size_alpha; i++) { + alphabet[i] = A->alpha_names[i]; + } + alphabet[A->trans->size_alpha] = '\0'; + + json_object_object_add(root, "L_ALPH", json_object_new_string(alphabet)); + free(alphabet); + + // Liste des transitions (on commence par compter le nombre de transitions) + uint num_trans = 0; + for (uint q = 0; q < A->trans->size_graph; q++) { + for (uint a = 0; a < A->trans->size_alpha; a++) { + num_trans = num_trans + size_dequeue(A->trans->edges[q][a]); + } + } + + json_object *trans = json_object_new_array_ext(num_trans); + for (uint q = 0; q < A->trans->size_graph; q++) { + for (uint a = 0; a < A->trans->size_alpha; a++) { + for (uint i = 0; i < size_dequeue(A->trans->edges[q][a]); i++) { + json_object *onetrans = json_object_new_array_ext(3); + json_object_array_add(onetrans, json_object_new_int(q)); + json_object_array_add(onetrans, json_object_new_int(a)); + json_object_array_add(onetrans, json_object_new_int(lefread_dequeue( + A->trans->edges[q][a], i))); + json_object_array_add(trans, onetrans); + } + } + } + json_object_object_add(root, "L_TRAN", trans); + + // Liste des états initiaux + json_object *initials = json_object_new_array_ext(size_dequeue(A->initials)); + for (uint i = 0; i < size_dequeue(A->initials); i++) { + json_object_array_add(initials, + json_object_new_int(lefread_dequeue(A->initials, i))); + } + + json_object_object_add(root, "L_INIT", initials); + + // Liste des états finaux + json_object *finals = json_object_new_array_ext(size_dequeue(A->finals)); + for (uint i = 0; i < size_dequeue(A->finals); i++) { + json_object_array_add(finals, + json_object_new_int(lefread_dequeue(A->finals, i))); + } + json_object_object_add(root, "L_FINA", finals); + + return root; +} + +json_object *files_lang_to_json(language *thelang) { + json_object *root = json_object_new_object(); + if (!root) { + fprintf(stderr, "Failed to create the JSON object.\n"); + return NULL; + } + json_object_object_add(root, "TYPE", json_object_new_string("LANG")); + if (thelang->type == SPE_REG) { + json_object_object_add(root, "SPEC", json_object_new_string("REXP")); + char *newexp; + MALLOC(newexp, EXPSIZE); + newexp[0] = 0; + reg_to_string(thelang->reg, newexp); + json_object_object_add(root, "REXP", json_object_new_string(newexp)); + free(newexp); + } + if (thelang->type == SPE_NFA) { + json_object_object_add(root, "SPEC", json_object_new_string("AUTO")); + json_object_object_add(root, "AUTO", + files_auto_to_json(objects[thelang->nfa]->aut)); + } + return root; +} + +nfa *files_json_to_nfa(json_object *root) { + // Récupération de la taille de l'automate + json_object *jsize_graph; + if (!json_object_object_get_ex(root, "N_SIZE", &jsize_graph) || + json_object_get_type(jsize_graph) != json_type_int) { + fprintf(stderr, "Error: cannot read the size of the automaton.\n"); + return NULL; + } + uint size_graph = json_object_get_int(jsize_graph); + + // Récupération de la taille de l'alphabet + json_object *jsize_alpha; + if (!json_object_object_get_ex(root, "N_ALPH", &jsize_alpha) || + json_object_get_type(jsize_alpha) != json_type_int) { + fprintf(stderr, "Error: cannot read the size of the alphabet.\n"); + return NULL; + } + uint size_alpha = json_object_get_int(jsize_alpha); + + // Création du NFA + nfa *A; + MALLOC(A, 1); + MALLOC(A->alpha_names, size_alpha); + A->trans = create_lgraph_noedges(size_graph, size_alpha); + if (A->trans == NULL) { + fprintf(stderr, "Error: cannot create the transitions\nPlease implement " + "the function create_lgraph_noedges\n"); + free(A->alpha_names); + free(A); + return NULL; + } + A->initials = create_dequeue(); + if (A->initials == NULL) { + fprintf(stderr, "Error: cannot create the initials\nPlease implement the " + "function create_dequeue\n"); + free(A->alpha_names); + free(A); + return NULL; + } + A->finals = create_dequeue(); + A->state_names = NULL; + + // Récupération de l'alphabet + json_object *jalph; + if (!json_object_object_get_ex(root, "L_ALPH", &jalph) || + json_object_get_type(jalph) != json_type_string) { + fprintf(stderr, "Error: cannot read the alphabet.\n"); + nfa_delete(A); + return NULL; + } + const char *alphabet = json_object_get_string(jalph); + for (uint i = 0; i < size_alpha; i++) { + A->alpha_names[i] = alphabet[i]; + } + + // Récupération du graphe des transitions + json_object *jtrans; + if (!json_object_object_get_ex(root, "L_TRAN", &jtrans) || + json_object_get_type(jtrans) != json_type_array) { + fprintf(stderr, "Error: cannot read the list of transitions.\n"); + nfa_delete(A); + return NULL; + } + uint len = json_object_array_length(jtrans); + + for (uint i = 0; i < len; i++) { + json_object *onetrans = json_object_array_get_idx(jtrans, i); + if (json_object_get_type(onetrans) != json_type_array || + json_object_array_length(onetrans) != 3) { + fprintf(stderr, "Error: cannot read the list of transitions.\n"); + nfa_delete(A); + return NULL; + } + json_object *jq = json_object_array_get_idx(onetrans, 0); + json_object *ja = json_object_array_get_idx(onetrans, 1); + json_object *jr = json_object_array_get_idx(onetrans, 2); + if (json_object_get_type(jq) != json_type_int || + json_object_get_type(jr) != json_type_int) { + fprintf(stderr, "Error: cannot read the list of transitions.\n"); + nfa_delete(A); + return NULL; + } + uint q = json_object_get_int(jq); + uint r = json_object_get_int(jr); + uint a; + if (json_object_get_type(ja) == json_type_int) { + a = json_object_get_int(ja); + } else if (json_object_get_type(ja) == json_type_string && + json_object_get_string_len(ja) == 1) { + const char *sa = json_object_get_string(ja); + a = sa[0]; + int id = -1; + for (uint j = 0; j < size_alpha; j++) { + if (a == (uint)A->alpha_names[j]) { + id = j; + } + } + if (id >= 0) { + a = (uint)id; + } else { + fprintf(stderr, "Error: incorrect letter used in the transitions.\n"); + nfa_delete(A); + return NULL; + } + } else { + fprintf(stderr, "Error: cannot read the list of transitions.\n"); + nfa_delete(A); + return NULL; + } + + if (q < size_graph && r < size_graph && a < size_alpha) { + rigins_dequeue(r, A->trans->edges[q][a]); + } else { + fprintf(stderr, + "Error: incorrect letter or state used in the transitions.\n"); + nfa_delete(A); + return NULL; + } + } + + for (uint q = 0; q < size_graph; q++) { + for (uint a = 0; a < size_alpha; a++) { + sort_dequeue_norepeat(A->trans->edges[q][a]); + } + } + + // Récupération de la liste des états initiaux + A->initials = create_dequeue(); + json_object *jini; + if (!json_object_object_get_ex(root, "L_INIT", &jini) || + json_object_get_type(jini) != json_type_array) { + fprintf(stderr, "Error: cannot read the list of initial states.\n"); + nfa_delete(A); + return NULL; + } + len = json_object_array_length(jini); + for (uint i = 0; i < len; i++) { + json_object *jq = json_object_array_get_idx(jini, i); + if (json_object_get_type(jq) != json_type_int) { + fprintf(stderr, "Error: cannot read the list of final states.\n"); + nfa_delete(A); + return NULL; + } + uint q = json_object_get_int(jq); + if (q < size_graph) { + rigins_dequeue(q, A->initials); + } else { + fprintf(stderr, + "Error: incorrect state in the list of initial states.\n"); + nfa_delete(A); + return NULL; + } + } + sort_dequeue_norepeat(A->initials); + + // Récupération de la liste des états finaux + A->finals = create_dequeue(); + json_object *jfin; + if (!json_object_object_get_ex(root, "L_FINA", &jfin) || + json_object_get_type(jfin) != json_type_array) { + fprintf(stderr, "Error: cannot read the list of final states.\n"); + nfa_delete(A); + return NULL; + } + len = json_object_array_length(jfin); + for (uint i = 0; i < len; i++) { + json_object *jq = json_object_array_get_idx(jfin, i); + if (json_object_get_type(jq) != json_type_int) { + fprintf(stderr, "Error: cannot read the list of final states.\n"); + nfa_delete(A); + return NULL; + } + uint q = json_object_get_int(jq); + if (q < size_graph) { + rigins_dequeue(q, A->finals); + } else { + fprintf(stderr, "Error: incorrect state in the list of final states.\n"); + nfa_delete(A); + return NULL; + } + } + sort_dequeue_norepeat(A->finals); + + return A; +} + +/************************************/ +/* Lecture/écriture dans un fichier */ +/************************************/ + +void files_save_object(object *theobj, char *filename) { + json_object *root = NULL; + switch (theobj->type) { + case LANGUAGE: + root = files_lang_to_json(theobj->lan); + break; + case AUTOMATON: + root = files_auto_to_json(theobj->aut); + break; + default: + return; + break; + } + // Sauvegarde + if (json_object_to_file(filename, root)) { + fprintf(stderr, "Error: failed to save %s.\n", filename); + } else { + printf("%s saved.\n", filename); + } + + // Libération du JSON + json_object_put(root); +} + +static void files_read_object_aux(json_object *root, char *varname) { + json_object *obj_type; + if (!json_object_object_get_ex(root, "TYPE", &obj_type) || + json_object_get_type(obj_type) != json_type_string) { + fprintf(stderr, "Error: cannot read the type of the object.\n"); + return; + } + const char *thetype = json_object_get_string(obj_type); + if (strcmp(thetype, "AUTO") == 0) { + fprintf(stdout, "Reading an automaton.\n"); + nfa *A = files_json_to_nfa(root); + object_add_automata(varname, A); + return; + } + + if (strcmp(thetype, "LANG") == 0) { + fprintf(stdout, "Reading a language.\n"); + json_object *lang_spe; + if (!json_object_object_get_ex(root, "SPEC", &lang_spe) || + json_object_get_type(lang_spe) != json_type_string) { + fprintf(stderr, + "Error: cannot read the specification type of the language.\n"); + return; + } + const char *thespec = json_object_get_string(lang_spe); + if (strcmp(thespec, "REXP") == 0) { + json_object *theregexp; + if (!json_object_object_get_ex(root, "REXP", &theregexp) || + json_object_get_type(theregexp) != json_type_string) { + fprintf(stderr, "Error: cannot read the regular expression specifying " + "the language.\n"); + return; + } + const char *exp = json_object_get_string(theregexp); + regexp *myexp = parse_string_regexp(exp); + if (myexp == NULL) { + return; + } + reg_print(myexp); + object_add_language_reg(varname, myexp); + } + if (strcmp(thespec, "AUTO") == 0) { + json_object *theauto; + if (!json_object_object_get_ex(root, "AUTO", &theauto) || + json_object_get_type(theauto) != json_type_object) { + fprintf(stderr, + "Error: cannot read the automaton specifying the language.\n"); + return; + } + nfa *A = files_json_to_nfa(theauto); + char *newname; + MALLOC(newname, 20); + sprintf(newname, "SYSAUTO%04d", autocount++); + int j = object_add_automata(newname, A); + object_add_language_nfa(varname, j); + return; + } + return; + } +} + +void files_read_object(char *filename, char *varname) { + json_object *root = json_object_from_file(filename); + if (!root) { + fprintf(stderr, "Failed to read the file.\n"); + return; + } + files_read_object_aux(root, varname); + json_object_put(root); + + return; +} + +void files_save_session(char *filename) { + // Création de l'objet json + json_object *root = json_object_new_object(); + if (!root) { + fprintf(stderr, "Failed to create the JSON object.\n"); + return; + } + json_object_object_add(root, "TYPE", json_object_new_string("SESSION")); + uint size = 0; + for (int i = 0; i < nb_objects; i++) { + { + if (objects[i]->parent == -1) { + size++; + } + } + } + + json_object *thetable = json_object_new_array_ext(size); + for (int i = 0; i < nb_objects; i++) { + if (objects[i]->parent == -1) { + json_object *oneobj = json_object_new_array_ext(2); + json_object_array_add(oneobj, json_object_new_string(objects[i]->name)); + if (objects[i]->type == LANGUAGE) { + json_object_array_add(oneobj, files_lang_to_json(objects[i]->lan)); + } + if (objects[i]->type == AUTOMATON) { + json_object_array_add(oneobj, files_auto_to_json(objects[i]->aut)); + } + json_object_array_add(thetable, oneobj); + } + } + json_object_object_add(root, "OBJS", thetable); + // Sauvegarde + if (json_object_to_file(filename, root)) { + fprintf(stderr, "Error: failed to save %s.\n", filename); + } else { + printf("%s saved.\n", filename); + } + + // Libération du JSON + json_object_put(root); +} + +void files_load_session(char *filename) { + json_object *root = json_object_from_file(filename); + if (!root) { + fprintf(stderr, "Failed to read the file.\n"); + return; + } + // Récupération du type + json_object *obj_type; + if (!json_object_object_get_ex(root, "TYPE", &obj_type) || + json_object_get_type(obj_type) != json_type_string) { + fprintf(stderr, "Error: cannot read the type of the object.\n"); + return; + } + + const char *thetype = json_object_get_string(obj_type); + if (strcmp(thetype, "SESSION") != 0) { + fprintf(stderr, "Error: not a session file.\n"); + return; + } + + // Récupération des objets + json_object *jobjs; + if (!json_object_object_get_ex(root, "OBJS", &jobjs) || + json_object_get_type(jobjs) != json_type_array) { + fprintf(stderr, "Error: cannot read the list of objects.\n"); + return; + } + uint len = json_object_array_length(jobjs); + + for (uint i = 0; i < len; i++) { + json_object *oneobj = json_object_array_get_idx(jobjs, i); + if (json_object_get_type(oneobj) != json_type_array || + json_object_array_length(oneobj) != 2) { + fprintf(stderr, "Error: cannot read the list of objects.\n"); + return; + } + json_object *varname = json_object_array_get_idx(oneobj, 0); + json_object *theobje = json_object_array_get_idx(oneobj, 1); + + const char *thename = json_object_get_string(varname); + files_read_object_aux(theobje, strdup(thename)); + } + + json_object_put(root); +} diff --git a/Aloyse et Vincent/graphs.c b/Aloyse et Vincent/graphs.c new file mode 100644 index 0000000..374faf2 --- /dev/null +++ b/Aloyse et Vincent/graphs.c @@ -0,0 +1,127 @@ +/********************************************/ +/* Structures pour stocker les machines */ +/* Ensuite spécialisées pour NFA,DFA,Cayley */ +/********************************************/ + +#include "graphs.h" + +/*****************************/ +/*+ Création et suppression +*/ +/*****************************/ + +lgraph *create_lgraph_noedges(const uint nb_vertices, const uint size_alpha) { + lgraph *graph = malloc(sizeof(lgraph)); + if(graph == NULL){ + fprintf(stderr, "Erreur d'allocation de mémoire\n"); + exit(EXIT_FAILURE); + } + graph->size_graph = nb_vertices; + graph->size_alpha = size_alpha; + if(nb_vertices == 0 || size_alpha == 0) { + graph->edges = NULL; + return graph; + } + graph->edges = malloc(nb_vertices * sizeof(dequeue **)); + if(graph->edges == NULL){ + fprintf(stderr, "Erreur d'allocation de mémoire\n"); + exit(EXIT_FAILURE); + } + for(uint i = 0; i < nb_vertices; i++){ + graph->edges[i] = malloc(size_alpha * sizeof(dequeue *)); + if(graph->edges[i] == NULL){ + fprintf(stderr, "Erreur d'allocation de mémoire\n"); + exit(EXIT_FAILURE); + } + for(uint j = 0; j < size_alpha; j++){ + graph->edges[i][j] = create_dequeue(); + } + } + return graph; +} + + +void delete_lgraph(lgraph *thegraph) { + free(thegraph->edges); + free(thegraph); +} + +/**************************************/ +/*+ Fusion disjointe de deux graphes +*/ +/**************************************/ + +// ReSharper disable twice CppParameterMayBeConstPtrOrRef +lgraph *merge_lgraphs(lgraph *graph1, lgraph *graph2) { + if(graph1->size_alpha != graph2->size_alpha){ + return NULL; + } + lgraph *merge = create_lgraph_noedges(graph1->size_graph + graph2->size_graph, graph1->size_alpha); + for(uint i = 0; i < graph1->size_graph; i++){ + // ReSharper disable once CppDFANullDereference + merge->edges[i] = graph1->edges[i]; + } + const uint l = graph1->size_graph; + for(uint i = 0; i < graph2->size_graph; i++){ + // ReSharper disable once CppDFANullDereference + merge->edges[i + l] = graph2->edges[i]; + } + return merge; +} + +/*****************************************************************/ +/*+ Récupération des sommets adjacents à un ensemble de sommets +*/ +/*****************************************************************/ + +dequeue *lgraph_reachable(lgraph *g, dequeue *deq, const uint letter) { + dequeue *reach = create_dequeue(); + //on stocke la taille de la liste pour éviter de la recalculer + const uint s = size_dequeue(deq); + for(uint i = 0; i < s; i++) { + dequeue *temp = g->edges[lefread_dequeue(deq, i)][letter]; + //on insère (trié) les sommets atteignables dans la liste + merge_sorted_dequeue(reach, temp); + delete_dequeue(temp); + } + return reach; +} + +/********************************************************/ +/*+ Récupération d'une liste d'arêtes pour l'affichage +*/ +/********************************************************/ + +stack *lgraph_to_multi_edges(lgraph *thegraph){ + multi_edge *tab[thegraph->size_graph * thegraph->size_graph]; + //on va créer une multi_edge pour chaque couple de sommet + for(uint i = 0; i < thegraph->size_graph; i++) { + for(uint j = 0; j < thegraph->size_graph; j++) { + multi_edge *edges = malloc(sizeof(multi_edge)); + edges->in = i; + edges->out = j; + edges->lab = create_dequeue(); + tab[i * thegraph->size_graph + j] = edges; + } + } + //on remplit les labels des milti_edges + for(uint i = 0; i < thegraph->size_graph; i++) { //on parcourt les sommets + for(uint j = 0; j < thegraph->size_alpha; j++) { //on parcourt les lettres + dequeue *temp = thegraph->edges[i][j]; + const uint s = size_dequeue(temp); + for(uint k = 0; k < s; k++) { //on parcourt les sommets atteignables + insert_dequeue(tab[i * thegraph->size_graph + lefread_dequeue(temp, k)]->lab, j); + } + } + } + //on réccupère les multi_edges non vides et on libère les autres + stack *result = create_stack(); + for(uint i = 0; i < thegraph->size_graph; i++) { + for(uint j = 0; j < thegraph->size_graph; j++) { + dequeue *temp = tab[i * thegraph->size_graph + j]->lab; //on récupère le multi_edge de chaque couple + if(!isempty_dequeue(temp)){ + push(tab[i * thegraph->size_graph + j], result); + } + else { + delete_dequeue(temp); + } + } + } + return result; +} \ No newline at end of file diff --git a/Aloyse et Vincent/main.c b/Aloyse et Vincent/main.c new file mode 100644 index 0000000..bc57fa9 --- /dev/null +++ b/Aloyse et Vincent/main.c @@ -0,0 +1,94 @@ +#include "main.h" +#include "regexp.h" +#include "nfa.h" +#include "printing.h" +#include "alloc.h" +#include "shell_tools.h" +#include "string.h" +#include "time.h" +#include "shell_keywords.h" +#include "files.h" + +#include +#include + +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; +} diff --git a/Aloyse et Vincent/nfa.c b/Aloyse et Vincent/nfa.c new file mode 100644 index 0000000..4cb2359 --- /dev/null +++ b/Aloyse et Vincent/nfa.c @@ -0,0 +1,677 @@ +/***************************/ +/* Implémentation des NFAs */ +/***************************/ + +#include "nfa.h" +#include "error.h" +#include "graphs.h" +#include "type_dequeue.h" +#include +#include +#include + +#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; +} diff --git a/Aloyse et Vincent/nfa_determi.c b/Aloyse et Vincent/nfa_determi.c new file mode 100644 index 0000000..cd841d1 --- /dev/null +++ b/Aloyse et Vincent/nfa_determi.c @@ -0,0 +1,246 @@ +/********************************************/ +/* Determinisation et Minimisation des NFAs */ +/********************************************/ + +#include "nfa_determi.h" +#include "nfa.h" + +/************************/ +/* Procédure principale */ +/************************/ + +// Fonction auxiliaire pour convertir une file d'états en une représentation +// entière unique +static uint dequeue_to_uint(dequeue *states) { + uint result = 0; + for (uint i = 0; i < size_dequeue(states); ++i) { + result |= (1 << lefread_dequeue(states, i)); + } + return result; +} + +// Fonction auxiliaire pour vérifier si un ensemble d'états est final +static bool is_final_state(dequeue *states, dequeue *finals) { + for (uint i = 0; i < size_dequeue(states); ++i) { + if (mem_dequeue(lefread_dequeue(states, i), finals)) { + return true; + } + } + return false; +} + +// Procédure de déterminisation. Le Booléen names indique si les noms des +// nouveaux états (des ensembles d'états de l'ancien NFA) doivent être +// sauvegardés dans le DFA. +nfa *nfa_determinize(nfa *thenfa, bool recording) { + printf("Déterminisation de l'automate1\n"); + fflush(stdout); + // Créer un nouvel automate pour représenter le DFA + nfa *dfa = (nfa *)malloc(sizeof(nfa)); + // Créer un graphe avec la taille de l'alphabet de l'automate initial + dfa->trans = create_lgraph_noedges(0, thenfa->trans->size_alpha); + dfa->initials = create_dequeue(); + dfa->finals = create_dequeue(); + // Copier les noms des lettres de l'alphabet; + dfa->alpha_names = nfa_copy_alpha(thenfa); + // Initialiser les noms des états si nécessaire + if (recording) { + dfa->state_names = (char **)malloc(sizeof(char *)); + } else { + dfa->state_names = NULL; + } + + // Initialiser l'état initial du DFA + // recopier les états initiaux de l'automate initial + dequeue *initial_set = create_dequeue(); + copy_dequeue_right(initial_set, thenfa->initials, 0); + // on les transforme en binaires + uint initial_state = dequeue_to_uint(initial_set); + // On ajoute l'état initial du DFA en decimal à la file des états initiaux du + // DFA + lefins_dequeue(initial_state, dfa->initials); + + // Utiliser une file pour gérer les ensembles d'états à explorer + dequeue *queue = create_dequeue(); + // Ajouter l'état initial à la file + lefins_dequeue(initial_state, queue); + + // tableau de booléens pour marquer les états visités de taille 2^size_graph + barray *visited = create_barray(1 << thenfa->trans->size_graph); + // Marquer l'état initial comme visité + settrue_barray(visited, initial_state); + + // Carte pour stocker les ensembles d'états réels + dequeue **state_sets = + (dequeue **)malloc((1 << thenfa->trans->size_graph) * sizeof(dequeue *)); + // on int + state_sets[initial_state] = initial_set; + + // Traiter chaque ensemble d'états + while (!isempty_dequeue(queue)) { + uint current_state = lefpull_dequeue(queue); + // stocke cet ensemble d'états initiaux dans le tableau `state_sets` à + // l'indice `initial_state` + dequeue *current_set = state_sets[current_state]; + + // Vérifier si l'état actuel est un état final + if (is_final_state(current_set, thenfa->finals)) { + lefins_dequeue(current_state, dfa->finals); + } + + // Traiter chaque lettre de l'alphabet + for (uint letter = 0; letter < thenfa->trans->size_alpha; ++letter) { + dequeue *next_set = create_dequeue(); + + // Calculer l'ensemble des états atteignables par la lettre actuelle + for (uint i = 0; i < size_dequeue(current_set); ++i) { + uint state = lefread_dequeue(current_set, i); + dequeue *transitions = thenfa->trans->edges[state][letter]; + for (uint j = 0; j < size_dequeue(transitions); ++j) { + uint next_state = lefread_dequeue(transitions, j); + + if (!mem_dequeue(next_state, next_set)) { + lefins_dequeue(next_state, next_set); + } + } + } + + // Convertir le prochain ensemble en une représentation entière unique + uint next_state = dequeue_to_uint(next_set); + + // Si le prochain état n'a pas été visité, l'ajouter à la file et le + // marquer comme visité + if (!getval_barray(visited, next_state)) { + settrue_barray(visited, next_state); + lefins_dequeue(next_state, queue); + state_sets[next_state] = next_set; + } else { + delete_dequeue(next_set); + } + + // Ajouter la transition au DFA + if (dfa->trans->size_graph <= current_state) { + dfa->trans->size_graph = current_state + 1; + dfa->trans->edges = (dequeue ***)realloc( + dfa->trans->edges, dfa->trans->size_graph * sizeof(dequeue **)); + for (uint k = 0; k < dfa->trans->size_graph; ++k) { + dfa->trans->edges[k] = + (dequeue **)malloc(dfa->trans->size_alpha * sizeof(dequeue *)); + for (uint l = 0; l < dfa->trans->size_alpha; ++l) { + dfa->trans->edges[k][l] = create_dequeue(); + } + } + } + lefins_dequeue(next_state, dfa->trans->edges[current_state][letter]); + } + + // Enregistrer le nom de l'état si nécessaire + if (recording) { + char *state_name = (char *)malloc(256 * sizeof(char)); + sprintf(state_name, "{"); + for (uint i = 0; i < size_dequeue(current_set); ++i) { + if (i > 0) { + strcat(state_name, ","); + } + char buffer[10]; + sprintf(buffer, "%u", lefread_dequeue(current_set, i)); + strcat(state_name, buffer); + } + strcat(state_name, "}"); + dfa->state_names[current_state] = state_name; + } + + delete_dequeue(current_set); + } + + // Nettoyage + delete_dequeue(queue); + delete_barray(visited); + free(state_sets); + + printf("Fin de la déterminisation1\n"); + fflush(stdout); + return dfa; +} + +// Complementation +nfa *nfa_complement(nfa *thenfa) { + printf("Complémentation de l'automate\n"); + fflush(stdout); + // Déterminiser l'automate + nfa *det_nfa = nfa_determinize(thenfa, false); + + // Compléter l'automate déterminisé + uint num_states = det_nfa->trans->size_graph; + uint num_letters = det_nfa->trans->size_alpha; + printf("Complémentation de l'automate1\n"); + fflush(stdout); + + // Créer un nouvel état de puits + uint sink_state = num_states; + lgraph *new_trans = create_lgraph_noedges(num_states + 1, num_letters); + printf("Complémentation de l'automate2\n"); + fflush(stdout); + // Copier les transitions existantes + for (uint state = 0; state < num_states; state++) { + for (uint letter = 0; letter < num_letters; letter++) { + printf("Complémentation de l'automate3\n"); + fflush(stdout); + dequeue *transitions = det_nfa->trans->edges[state][letter]; + if (transitions != NULL) { + printf("Complémentation de l'automate4\n"); + fflush(stdout); + new_trans->edges[state][letter] = transitions; + } else { + printf("Complémentation de l'automate5\n"); + fflush(stdout); + new_trans->edges[state][letter] = create_dequeue(); + printf("Complémentation de l'automate6\n"); + fflush(stdout); + rigins_dequeue(sink_state, new_trans->edges[state][letter]); + printf("Complémentation de l'automate7\n"); + fflush(stdout); + } + } + } + + // Ajouter des transitions vers l'état de puits pour les transitions + // manquantes + for (uint letter = 0; letter < num_letters; letter++) { + new_trans->edges[sink_state][letter] = create_dequeue(); + rigins_dequeue(sink_state, new_trans->edges[sink_state][letter]); + } + + printf("Complémentation de l'automate8\n"); + fflush(stdout); + // Créer le nouvel automate avec les transitions complétées + nfa *comp_nfa = (nfa *)malloc(sizeof(nfa)); + comp_nfa->trans = new_trans; + comp_nfa->initials = det_nfa->initials; + comp_nfa->alpha_names = nfa_copy_alpha(det_nfa); + comp_nfa->state_names = nfa_copy_all_names(det_nfa); + + // Inverser les états finaux et non finaux + barray *finals_barray = create_barray(num_states + 1); + for (uint state = 0; state < num_states; state++) { + if (!mem_dequeue(state, det_nfa->finals)) { + settrue_barray(finals_barray, state); + } + } + settrue_barray(finals_barray, sink_state); + + // Créer la liste des états finaux + comp_nfa->finals = create_dequeue(); + for (uint state = 0; state <= num_states; state++) { + if (getval_barray(finals_barray, state)) { + rigins_dequeue(state, comp_nfa->finals); + } + } + printf("Complémentation de l'automate9\n"); + fflush(stdout); + // Libérer la mémoire + delete_barray(finals_barray); + nfa_delete(det_nfa); + + return comp_nfa; +} diff --git a/Aloyse et Vincent/nfa_intersec.c b/Aloyse et Vincent/nfa_intersec.c new file mode 100644 index 0000000..a547466 --- /dev/null +++ b/Aloyse et Vincent/nfa_intersec.c @@ -0,0 +1,145 @@ +/************************/ +/* Intersection of NFAs */ +/************************/ + +#include "nfa_intersec.h" + +/************************************************************************************************/ +/* Construction classique: calcul de l'automate produit en ne gardant que les + * états accessibles */ +/************************************************************************************************/ + +// Intersection +nfa *nfa_intersect(nfa *nfa1, nfa *nfa2, bool nom) { + printf("Intersection de l'automate\n"); + fflush(stdout); + // Vérifier que les alphabets des deux automates sont identiques + if (nfa1->trans->size_alpha != nfa2->trans->size_alpha) { + fprintf(stderr, + "Les alphabets des deux automates doivent être identiques.\n"); + return NULL; + } + + // Créer un nouveau NFA pour l'automate produit + nfa *result = (nfa *)malloc(sizeof(nfa)); + if (!result) { + perror("Erreur d'allocation de mémoire pour l'automate produit"); + return NULL; + } + + // Initialiser les champs de l'automate produit + result->trans = + create_lgraph_noedges(nfa1->trans->size_graph * nfa2->trans->size_graph, + nfa1->trans->size_alpha); + result->initials = create_dequeue(); + result->finals = create_dequeue(); + result->alpha_names = nfa_copy_alpha(nfa1); + result->state_names = + nom ? (char **)malloc(result->trans->size_graph * sizeof(char *)) : NULL; + + // Ajouter les états initiaux + for (uint i = 0; i < size_dequeue(nfa1->initials); i++) { + for (uint j = 0; j < size_dequeue(nfa2->initials); j++) { + // Récupérer les états initiaux des deux automates + uint state1 = lefread_dequeue(nfa1->initials, i); + uint state2 = lefread_dequeue(nfa2->initials, j); + // Calcule de l'indice du nouvel état initial dans l'automate produit + uint new_state = state1 * nfa2->trans->size_graph + state2; + // Ajouter le nouvel état initial à la liste des états initiaux de + // l'automate produit + insert_dequeue(result->initials, new_state); + } + } + printf("Intersection de l'automate1\n"); + fflush(stdout); + // Ajouter les états finaux + for (uint i = 0; i < size_dequeue(nfa1->finals); i++) { + for (uint j = 0; j < size_dequeue(nfa2->finals); j++) { + // Récupérer les états finaux des deux automates + uint state1 = lefread_dequeue(nfa1->finals, i); + uint state2 = lefread_dequeue(nfa2->finals, j); + // Calcule de l'indice du nouvel état final dans l'automate produit + uint new_state = state1 * nfa2->trans->size_graph + state2; + // Ajouter le nouvel état final à la liste des états finaux de l'automate + // produit + insert_dequeue(result->finals, new_state); + } + } + printf("Intersection de l'automate2\n"); + fflush(stdout); + // Ajouter les transitions + for (uint state1 = 0; state1 < nfa1->trans->size_graph; state1++) { + for (uint state2 = 0; state2 < nfa2->trans->size_graph; state2++) { + // Calcule de l'indice du nouvel dans l'automate produit + uint new_state = state1 * nfa2->trans->size_graph + state2; + for (uint letter = 0; letter < nfa1->trans->size_alpha; letter++) { + // Récupérer les états atteignables depuis state1 et state2 avec la + // lettre courante + // tuyau de tout les états atteignables depuis state1 avec la lettre + dequeue *reachable1 = nfa1->trans->edges[state1][letter]; + // tuyau de tout les états atteignables depuis state2 avec la lettre + dequeue *reachable2 = nfa2->trans->edges[state2][letter]; + // pour toute les combinaisons d'états atteignables depuis state1 et + // state2 avec la lettre + for (uint i = 0; i < size_dequeue(reachable1); i++) { + for (uint j = 0; j < size_dequeue(reachable2); j++) { + // Récupérer les états atteignables + uint next_state1 = lefread_dequeue(reachable1, i); + uint next_state2 = lefread_dequeue(reachable2, j); + // Calculer le nouvel état atteignable dans l'automate produit + uint new_next_state = + next_state1 * nfa2->trans->size_graph + next_state2; + // Ajouter la transition dans l'automate produit + rigins_dequeue(new_next_state, + result->trans->edges[new_state][letter]); + } + } + } + } + } + printf("Intersection de l'automate3\n"); + fflush(stdout); + + // Enregistrer les noms des états si nécessaire + if (nom) { + for (uint state1 = 0; state1 < nfa1->trans->size_graph; state1++) { + for (uint state2 = 0; state2 < nfa2->trans->size_graph; state2++) { + // Calculer le nouvel état dans l'automate produit + uint new_state = state1 * nfa2->trans->size_graph + state2; + // Récupérer les noms des états des deux automates + printf("c'est pas ici\n"); + fflush(stdout); + char *name1 = nfa_copy_one_name(nfa1, state1); + char *name2 = nfa_copy_one_name(nfa2, state2); + // Calculer la longueur des noms + printf("vincent c'est un genie\n"); + fflush(stdout); + size_t len1 = name1 ? strlen(name1) : 0; + size_t len2 = name2 ? strlen(name2) : 0; + // Allouer de la mémoire pour le nom du nouvel état + result->state_names[new_state] = + (char *)malloc((len1 + len2 + 4) * sizeof(char)); + printf("blem de malloc\n"); + fflush(stdout); + // Copier le nom du premier état + if (name1) { + strcpy(result->state_names[new_state], name1); + free(name1); + } + printf("truc bizzar de copilot\n"); + fflush(stdout); + // Ajouter une virgule pour séparer les noms + strcat(result->state_names[new_state], ","); + // Copier le nom du second état + if (name2) { + strcat(result->state_names[new_state], name2); + free(name2); + } + } + } + } + printf("fin Intersection de l'automate\n"); + fflush(stdout); + // Retourner l'automate produit + return result; +} diff --git a/Aloyse et Vincent/nfa_mccluskey.c b/Aloyse et Vincent/nfa_mccluskey.c new file mode 100644 index 0000000..61330ad --- /dev/null +++ b/Aloyse et Vincent/nfa_mccluskey.c @@ -0,0 +1,127 @@ +#include "nfa_mccluskey.h" +#include "regexp.h" +#include + +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; +} diff --git a/Aloyse et Vincent/nfa_minimization.c b/Aloyse et Vincent/nfa_minimization.c new file mode 100644 index 0000000..87003df --- /dev/null +++ b/Aloyse et Vincent/nfa_minimization.c @@ -0,0 +1,29 @@ +#include "nfa_minimization.h" + +/******************************/ +/*+ Algorithme de Brzozowski +*/ +/******************************/ + +nfa *nfa_brzozowski(nfa *) { + return NULL; +} + +/****************************/ +/*+ Algorithme de Hopcroft +*/ +/****************************/ + +hopcroft_partition *nfa_hopcroft_initial(uint, dequeue *) { + return NULL; +} + +nfa *nfa_hopcroft_genauto(nfa *, hopcroft_partition *) { + return NULL; +} + +void nfa_hopcroft_free(hopcroft_partition *) { + return; +} + +nfa *nfa_hopcroft(nfa *) { + return NULL; +} diff --git a/Aloyse et Vincent/nfa_tocode.c b/Aloyse et Vincent/nfa_tocode.c new file mode 100644 index 0000000..9a921be --- /dev/null +++ b/Aloyse et Vincent/nfa_tocode.c @@ -0,0 +1,9 @@ +#include "nfa_tocode.h" +#include "nfa_determi.h" +#include "printing.h" +#include "error.h" +#include + +void nfa2code(nfa *, char *) { + return; +} diff --git a/Aloyse et Vincent/parse_regexp.tab.c b/Aloyse et Vincent/parse_regexp.tab.c new file mode 100644 index 0000000..c8a3a82 --- /dev/null +++ b/Aloyse et Vincent/parse_regexp.tab.c @@ -0,0 +1,1397 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 + +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + +/* Substitute the variable and function names. */ +#define yyparse regexp_parse +#define yylex regexp_lex +#define yyerror regexp_error +#define yydebug regexp_debug +#define yynerrs regexp_nerrs +#define yylval regexp_lval +#define yychar regexp_char + +/* First part of user prologue. */ +#line 1 "parse_regexp.y" + +#include "parse_regexp.h" + +#line 82 "parse_regexp.tab.c" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +#include "parse_regexp.tab.h" +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_VARIABLE = 3, /* VARIABLE */ + YYSYMBOL_LETTER = 4, /* LETTER */ + YYSYMBOL_EPSILON_TOK = 5, /* EPSILON_TOK */ + YYSYMBOL_EMPTY_TOK = 6, /* EMPTY_TOK */ + YYSYMBOL_OPEN_TOK = 7, /* OPEN_TOK */ + YYSYMBOL_CLOSE_TOK = 8, /* CLOSE_TOK */ + YYSYMBOL_PLUS_TOK = 9, /* PLUS_TOK */ + YYSYMBOL_INTER_TOK = 10, /* INTER_TOK */ + YYSYMBOL_CONCAT_TOK = 11, /* CONCAT_TOK */ + YYSYMBOL_STAR_TOK = 12, /* STAR_TOK */ + YYSYMBOL_COMPL_TOK = 13, /* COMPL_TOK */ + YYSYMBOL_YYACCEPT = 14, /* $accept */ + YYSYMBOL_s = 15, /* s */ + YYSYMBOL_e = 16 /* e */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + +/* Unqualified %code blocks. */ +#line 7 "parse_regexp.y" + +void regexp_error(regexp**, char *s){ + if (s) + fprintf(stderr, "Syntax error in restricted regexp.\n"); +} + +#line 140 "parse_regexp.tab.c" + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int8 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 12 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 76 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 14 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 3 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 13 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 20 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 268 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13 +}; + +#if YYDEBUG +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int8 yyrline[] = +{ + 0, 31, 31, 32, 35, 37, 39, 41, 43, 45, + 47, 49, 51, 53 +}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "VARIABLE", "LETTER", + "EPSILON_TOK", "EMPTY_TOK", "OPEN_TOK", "CLOSE_TOK", "PLUS_TOK", + "INTER_TOK", "CONCAT_TOK", "STAR_TOK", "COMPL_TOK", "$accept", "s", "e", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#define YYPACT_NINF (-3) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ + ((Yyn) == YYTABLE_NINF) + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + 14, -3, -3, -3, -3, -3, 58, 58, 9, 36, + 25, 63, -3, 58, 58, -3, 47, -3, -2, 47 +}; + +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int8 yydefact[] = +{ + 0, 2, 13, 10, 11, 12, 0, 0, 0, 3, + 0, 7, 1, 0, 0, 6, 5, 9, 4, 8 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -3, -3, 0 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + 0, 8, 16 +}; + +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + 9, 2, 3, 4, 5, 6, 10, 11, 14, 12, + 15, 7, 0, 18, 19, 1, 0, 2, 3, 4, + 5, 6, 0, 0, 0, 0, 0, 7, 2, 3, + 4, 5, 6, 17, 13, 14, 0, 15, 7, 2, + 3, 4, 5, 6, 0, 13, 14, 0, 15, 7, + 2, 3, 4, 5, 6, 0, 0, 0, 0, 15, + 7, 2, 3, 4, 5, 6, 2, 3, 4, 5, + 6, 7, 0, 0, 0, 0, -1 +}; + +static const yytype_int8 yycheck[] = +{ + 0, 3, 4, 5, 6, 7, 6, 7, 10, 0, + 12, 13, -1, 13, 14, 1, -1, 3, 4, 5, + 6, 7, -1, -1, -1, -1, -1, 13, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 3, + 4, 5, 6, 7, -1, 9, 10, -1, 12, 13, + 3, 4, 5, 6, 7, -1, -1, -1, -1, 12, + 13, 3, 4, 5, 6, 7, 3, 4, 5, 6, + 7, 13, -1, -1, -1, -1, 13 +}; + +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int8 yystos[] = +{ + 0, 1, 3, 4, 5, 6, 7, 13, 15, 16, + 16, 16, 0, 9, 10, 12, 16, 8, 16, 16 +}; + +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr1[] = +{ + 0, 14, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16 +}; + +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 1, 1, 3, 2, 2, 2, 3, 3, + 1, 1, 1, 1 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (thereg, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value, thereg); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, regexp** thereg) +{ + FILE *yyoutput = yyo; + YY_USE (yyoutput); + YY_USE (thereg); + if (!yyvaluep) + return; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, regexp** thereg) +{ + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + + yy_symbol_value_print (yyo, yykind, yyvaluep, thereg); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule, regexp** thereg) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], thereg); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, thereg); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + + + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep, regexp** thereg) +{ + YY_USE (yyvaluep); + YY_USE (thereg); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/* Lookahead token kind. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (regexp** thereg) +{ + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + YYNOMEM; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + YYNOMEM; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: /* s: error */ +#line 31 "parse_regexp.y" + { *thereg = NULL;} +#line 1104 "parse_regexp.tab.c" + break; + + case 3: /* s: e */ +#line 32 "parse_regexp.y" + { *thereg = (yyvsp[0].regexp); } +#line 1110 "parse_regexp.tab.c" + break; + + case 4: /* e: e PLUS_TOK e */ +#line 35 "parse_regexp.y" + { (yyval.regexp) = reg_union((yyvsp[-2].regexp), (yyvsp[0].regexp)); } +#line 1116 "parse_regexp.tab.c" + break; + + case 5: /* e: e e */ +#line 37 "parse_regexp.y" + { (yyval.regexp) = reg_concat((yyvsp[-1].regexp), (yyvsp[0].regexp)); } +#line 1122 "parse_regexp.tab.c" + break; + + case 6: /* e: e STAR_TOK */ +#line 39 "parse_regexp.y" + { (yyval.regexp) = reg_star((yyvsp[-1].regexp)); } +#line 1128 "parse_regexp.tab.c" + break; + + case 7: /* e: COMPL_TOK e */ +#line 41 "parse_regexp.y" + { (yyval.regexp) = reg_complement((yyvsp[0].regexp)); } +#line 1134 "parse_regexp.tab.c" + break; + + case 8: /* e: e INTER_TOK e */ +#line 43 "parse_regexp.y" + { (yyval.regexp) = reg_inter((yyvsp[-2].regexp), (yyvsp[0].regexp)); } +#line 1140 "parse_regexp.tab.c" + break; + + case 9: /* e: OPEN_TOK e CLOSE_TOK */ +#line 45 "parse_regexp.y" + { (yyval.regexp) = (yyvsp[-1].regexp); } +#line 1146 "parse_regexp.tab.c" + break; + + case 10: /* e: LETTER */ +#line 47 "parse_regexp.y" + { (yyval.regexp) = reg_letter((yyvsp[0].carac)); } +#line 1152 "parse_regexp.tab.c" + break; + + case 11: /* e: EPSILON_TOK */ +#line 49 "parse_regexp.y" + { (yyval.regexp) = reg_epsilon(); } +#line 1158 "parse_regexp.tab.c" + break; + + case 12: /* e: EMPTY_TOK */ +#line 51 "parse_regexp.y" + { (yyval.regexp) = reg_empty(); } +#line 1164 "parse_regexp.tab.c" + break; + + case 13: /* e: VARIABLE */ +#line 53 "parse_regexp.y" + { + DEBUG("RVALUE %s", (yyvsp[0].name)); + int i = object_get_from_name((yyvsp[0].name)); + if (i == -1 || objects[i]->type != LANGUAGE) { + fprintf(stderr,"Error: %s is not a valid language variable.\n",(yyvsp[0].name)); + (yyval.regexp) = NULL; + } + else if (objects[i]->lan->type != SPE_REG) { + fprintf(stderr,"Error: %s is specified by an automaton.\n",(yyvsp[0].name)); + (yyval.regexp) = NULL; + } + else { + DEBUG("Language found"); + (yyval.regexp) = reg_copy(objects[i]->lan->reg); + } +} +#line 1185 "parse_regexp.tab.c" + break; + + +#line 1189 "parse_regexp.tab.c" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror (thereg, YY_("syntax error")); + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, thereg); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp, thereg); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturnlab; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturnlab; + + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ +yyexhaustedlab: + yyerror (thereg, YY_("memory exhausted")); + yyresult = 2; + goto yyreturnlab; + + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, thereg); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, thereg); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + + return yyresult; +} + +#line 71 "parse_regexp.y" + + +/* Declarations */ + +void set_input_string(const char* in); +void end_lexical_scan(void); + + +/* This function parses a string */ +regexp* parse_string_regexp(const char* in){ + set_input_string(in); + regexp* res; + regexp_parse(&res); + end_lexical_scan(); + return res; +} diff --git a/Aloyse et Vincent/parser.tab.c b/Aloyse et Vincent/parser.tab.c new file mode 100644 index 0000000..6445858 --- /dev/null +++ b/Aloyse et Vincent/parser.tab.c @@ -0,0 +1,1412 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 + +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + +/* Substitute the variable and function names. */ +#define yyparse shell_parse +#define yylex shell_lex +#define yyerror shell_error +#define yydebug shell_debug +#define yynerrs shell_nerrs +#define yylval shell_lval +#define yychar shell_char + +/* First part of user prologue. */ +#line 1 "parser.y" + +#include "parser.h" + +#line 82 "parser.tab.c" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +#include "parser.tab.h" +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_COMMAND = 3, /* COMMAND */ + YYSYMBOL_FILENAME = 4, /* FILENAME */ + YYSYMBOL_EXP = 5, /* EXP */ + YYSYMBOL_LANGUAGES = 6, /* LANGUAGES */ + YYSYMBOL_AUTOS = 7, /* AUTOS */ + YYSYMBOL_MORPHISMS = 8, /* MORPHISMS */ + YYSYMBOL_HELP = 9, /* HELP */ + YYSYMBOL_ALPHABET = 10, /* ALPHABET */ + YYSYMBOL_TEST = 11, /* TEST */ + YYSYMBOL_EXIT = 12, /* EXIT */ + YYSYMBOL_LEXICAL_ERROR = 13, /* LEXICAL_ERROR */ + YYSYMBOL_14_ = 14, /* '=' */ + YYSYMBOL_15_ = 15, /* ';' */ + YYSYMBOL_16_ = 16, /* ')' */ + YYSYMBOL_17_ = 17, /* ',' */ + YYSYMBOL_18_ = 18, /* '.' */ + YYSYMBOL_19_ = 19, /* '(' */ + YYSYMBOL_YYACCEPT = 20, /* $accept */ + YYSYMBOL_s = 21, /* s */ + YYSYMBOL_cp = 22, /* cp */ + YYSYMBOL_cc = 23 /* cc */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + +/* Unqualified %code blocks. */ +#line 5 "parser.y" + +void yyerror(char *s){ + if (s) fprintf(stderr, "Syntax error in command\n"); +} + + +#line 147 "parser.tab.c" + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int8 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 27 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 20 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 4 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 18 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 29 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 268 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 19, 16, 2, 2, 17, 2, 18, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, + 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13 +}; + +#if YYDEBUG +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int8 yyrline[] = +{ + 0, 32, 32, 34, 36, 38, 40, 42, 44, 50, + 55, 59, 63, 66, 68, 71, 73, 75, 77 +}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "COMMAND", "FILENAME", + "EXP", "LANGUAGES", "AUTOS", "MORPHISMS", "HELP", "ALPHABET", "TEST", + "EXIT", "LEXICAL_ERROR", "'='", "';'", "')'", "','", "'.'", "'('", + "$accept", "s", "cp", "cc", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#define YYPACT_NINF (-11) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ + 0 + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -11, 0, -11, -10, 4, -11, -11, -11, -11, -11, + -11, -7, -11, -5, -11, 16, 16, 16, -11, -11, + 6, -1, -11, -11, 10, -11, -11, 16, -11 +}; + +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int8 yydefact[] = +{ + 12, 0, 1, 0, 17, 18, 3, 4, 6, 5, + 7, 0, 2, 0, 11, 0, 0, 0, 10, 9, + 17, 0, 15, 16, 0, 8, 13, 0, 14 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -11, -11, -6, 1 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + 0, 1, 23, 24 +}; + +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + 2, 3, 13, 4, 5, 14, 6, 7, 18, 8, + 19, 9, 10, 11, 25, 12, 21, 22, 15, 20, + 5, 28, 16, 17, 16, 17, 26, 27 +}; + +static const yytype_int8 yycheck[] = +{ + 0, 1, 1, 3, 4, 15, 6, 7, 15, 9, + 15, 11, 12, 13, 15, 15, 15, 16, 14, 3, + 4, 27, 18, 19, 18, 19, 16, 17 +}; + +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int8 yystos[] = +{ + 0, 21, 0, 1, 3, 4, 6, 7, 9, 11, + 12, 13, 15, 23, 15, 14, 18, 19, 15, 15, + 3, 23, 23, 22, 23, 15, 16, 17, 22 +}; + +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr1[] = +{ + 0, 20, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 22, 22, 23, 23, 23, 23 +}; + +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 5, 3, + 3, 3, 0, 2, 3, 3, 3, 1, 1 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) +{ + FILE *yyoutput = yyo; + YY_USE (yyoutput); + if (!yyvaluep) + return; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + + yy_symbol_value_print (yyo, yykind, yyvaluep); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)]); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + + + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep) +{ + YY_USE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/* Lookahead token kind. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + YYNOMEM; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + YYNOMEM; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: /* s: s ';' */ +#line 32 "parser.y" + {} +#line 1103 "parser.tab.c" + break; + + case 3: /* s: s LANGUAGES */ +#line 34 "parser.y" + { object_print_langs(); } +#line 1109 "parser.tab.c" + break; + + case 4: /* s: s AUTOS */ +#line 36 "parser.y" + { object_print_autos(); } +#line 1115 "parser.tab.c" + break; + + case 5: /* s: s TEST */ +#line 38 "parser.y" + { test(); } +#line 1121 "parser.tab.c" + break; + + case 6: /* s: s HELP */ +#line 40 "parser.y" + { help(); } +#line 1127 "parser.tab.c" + break; + + case 7: /* s: s EXIT */ +#line 42 "parser.y" + { return 0; } +#line 1133 "parser.tab.c" + break; + + case 8: /* s: s COMMAND '=' cc ';' */ +#line 44 "parser.y" + { + com_apply_link_command((yyvsp[-3].name), (yyvsp[-1].com_command)); + com_free_command((yyvsp[-1].com_command)); + free((yyvsp[-3].name)); +} +#line 1143 "parser.tab.c" + break; + + case 9: /* s: s cc ';' */ +#line 50 "parser.y" + { + com_apply_command((yyvsp[-1].com_command)); + com_free_command((yyvsp[-1].com_command)); +} +#line 1152 "parser.tab.c" + break; + + case 10: /* s: s LEXICAL_ERROR ';' */ +#line 55 "parser.y" + { + yyerrok; +} +#line 1160 "parser.tab.c" + break; + + case 11: /* s: s error ';' */ +#line 59 "parser.y" + { + yyerrok; +} +#line 1168 "parser.tab.c" + break; + + case 12: /* s: %empty */ +#line 63 "parser.y" + {} +#line 1174 "parser.tab.c" + break; + + case 13: /* cp: cc ')' */ +#line 66 "parser.y" + { (yyval.com_parameters) = com_make_parameters((yyvsp[-1].com_command), NULL);} +#line 1180 "parser.tab.c" + break; + + case 14: /* cp: cc ',' cp */ +#line 68 "parser.y" + { (yyval.com_parameters) = com_make_parameters((yyvsp[-2].com_command), (yyvsp[0].com_parameters));} +#line 1186 "parser.tab.c" + break; + + case 15: /* cc: COMMAND '.' cc */ +#line 71 "parser.y" + { (yyval.com_command) = com_make_command((yyvsp[-2].name), (yyvsp[0].com_command)); } +#line 1192 "parser.tab.c" + break; + + case 16: /* cc: COMMAND '(' cp */ +#line 73 "parser.y" + { (yyval.com_command) = com_init_command((yyvsp[-2].name),(yyvsp[0].com_parameters));} +#line 1198 "parser.tab.c" + break; + + case 17: /* cc: COMMAND */ +#line 75 "parser.y" + { (yyval.com_command) = com_init_command((yyvsp[0].name),NULL);} +#line 1204 "parser.tab.c" + break; + + case 18: /* cc: FILENAME */ +#line 77 "parser.y" + { (yyval.com_command) = com_init_rawcommand((yyvsp[0].name));} +#line 1210 "parser.tab.c" + break; + + +#line 1214 "parser.tab.c" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror (YY_("syntax error")); + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturnlab; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturnlab; + + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + goto yyreturnlab; + + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + + return yyresult; +} + +#line 80 "parser.y" + + +/* Local Variables: */ +/* apheleia-mode: nil */ +/* apheleia-inhibit: t */ +/* End: */ diff --git a/Aloyse et Vincent/printing.c b/Aloyse et Vincent/printing.c new file mode 100644 index 0000000..604ce22 --- /dev/null +++ b/Aloyse et Vincent/printing.c @@ -0,0 +1,302 @@ +#include "printing.h" +#include + +#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"); +} diff --git a/Aloyse et Vincent/regexp.c b/Aloyse et Vincent/regexp.c new file mode 100644 index 0000000..2fb3545 --- /dev/null +++ b/Aloyse et Vincent/regexp.c @@ -0,0 +1,116 @@ +#include "regexp.h" + +bool reg_issimple(regexp *expr) { + // cas de base epression vide + if (expr == NULL) { + return true; + } + + // test si l'expression contient une intersection ou un complement + if (expr->op == INTER || expr->op == COMPLEMENT) { + return false; + } + + // on teste les sous expressions + return reg_issimple(expr->left) && reg_issimple(expr->right); +} + +void reg_free(regexp *expr) { + if (expr == NULL) { + return; + } + // Libérer récursivement les sous-expressions gauche et droite + reg_free(expr->left); + reg_free(expr->right); + free(expr); +} + +regexp *reg_copy(regexp *expr) { + // cas de base + if (expr == NULL) { + return NULL; + } + + regexp *new_expr = malloc(sizeof(regexp)); + + // on complète les champs + new_expr->op = expr->op; + new_expr->letter = expr->letter; + new_expr->left = reg_copy(expr->left); + new_expr->right = reg_copy(expr->right); + + return new_expr; +} + +regexp *reg_empty(void) { + regexp *void_expr = malloc(sizeof(regexp)); + void_expr->op = EMPTY; + void_expr->left = NULL; + void_expr->right = NULL; + void_expr->letter = '\0'; + return void_expr; +} + +regexp *reg_epsilon(void) { + regexp *epsilon = malloc(sizeof(regexp)); + epsilon->op = EPSILON; + epsilon->left = NULL; + epsilon->right = NULL; + epsilon->letter = '\0'; + return epsilon; +} + +regexp *reg_letter(char c) { + regexp *lettre = malloc(sizeof(regexp)); + lettre->op = CHAR; + lettre->left = NULL; + lettre->right = NULL; + // la lettre de l'expression + lettre->letter = c; + return lettre; +} + +regexp *reg_union(regexp *expr_left, regexp *expr_right) { + regexp *uni = malloc(sizeof(regexp)); + uni->op = UNION; + uni->left = expr_left; + uni->right = expr_right; + uni->letter = '\0'; + return uni; +} + +regexp *reg_inter(regexp *expr_left, regexp *expr_right) { + regexp *inter = malloc(sizeof(regexp)); + inter->op = INTER; + inter->left = expr_left; + inter->right = expr_right; + inter->letter = '\0'; + return inter; +} + +regexp *reg_concat(regexp *expr_left, regexp *expr_right) { + regexp *concat = malloc(sizeof(regexp)); + concat->op = CONCAT; + concat->left = expr_left; + concat->right = expr_right; + concat->letter = '\0'; + return concat; +} + +regexp *reg_star(regexp *expr) { + regexp *star = malloc(sizeof(regexp)); + star->op = STAR; + star->left = expr; + star->right = NULL; + star->letter = '\0'; + return star; +} + +regexp *reg_complement(regexp *expr) { + regexp *compl = malloc(sizeof(regexp)); + compl->op = COMPLEMENT; + compl->left = expr; + compl->right = NULL; + compl->letter = '\0'; + return compl; +} diff --git a/Aloyse et Vincent/regexp_tonfa.c b/Aloyse et Vincent/regexp_tonfa.c new file mode 100644 index 0000000..767cb62 --- /dev/null +++ b/Aloyse et Vincent/regexp_tonfa.c @@ -0,0 +1,364 @@ + +#include "regexp_tonfa.h" +#include "error.h" +#include "nfa.h" +#include "regexp.h" +#include "type_boolarray.h" +#include "type_dequeue.h" +#include +#include + +/****************************/ +/*+ 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; + } +} diff --git a/Aloyse et Vincent/scan.c b/Aloyse et Vincent/scan.c new file mode 100644 index 0000000..c8717ff --- /dev/null +++ b/Aloyse et Vincent/scan.c @@ -0,0 +1,2123 @@ + +#line 3 "" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer shell__create_buffer +#define yy_delete_buffer shell__delete_buffer +#define yy_scan_buffer shell__scan_buffer +#define yy_scan_string shell__scan_string +#define yy_scan_bytes shell__scan_bytes +#define yy_init_buffer shell__init_buffer +#define yy_flush_buffer shell__flush_buffer +#define yy_load_buffer_state shell__load_buffer_state +#define yy_switch_to_buffer shell__switch_to_buffer +#define yypush_buffer_state shell_push_buffer_state +#define yypop_buffer_state shell_pop_buffer_state +#define yyensure_buffer_stack shell_ensure_buffer_stack +#define yy_flex_debug shell__flex_debug +#define yyin shell_in +#define yyleng shell_leng +#define yylex shell_lex +#define yylineno shell_lineno +#define yyout shell_out +#define yyrestart shell_restart +#define yytext shell_text +#define yywrap shell_wrap +#define yyalloc shell_alloc +#define yyrealloc shell_realloc +#define yyfree shell_free + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define shell__create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer shell__create_buffer +#endif + +#ifdef yy_delete_buffer +#define shell__delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer shell__delete_buffer +#endif + +#ifdef yy_scan_buffer +#define shell__scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer shell__scan_buffer +#endif + +#ifdef yy_scan_string +#define shell__scan_string_ALREADY_DEFINED +#else +#define yy_scan_string shell__scan_string +#endif + +#ifdef yy_scan_bytes +#define shell__scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes shell__scan_bytes +#endif + +#ifdef yy_init_buffer +#define shell__init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer shell__init_buffer +#endif + +#ifdef yy_flush_buffer +#define shell__flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer shell__flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define shell__load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state shell__load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define shell__switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer shell__switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define shell_push_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state shell_push_buffer_state +#endif + +#ifdef yypop_buffer_state +#define shell_pop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state shell_pop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define shell_ensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack shell_ensure_buffer_stack +#endif + +#ifdef yylex +#define shell_lex_ALREADY_DEFINED +#else +#define yylex shell_lex +#endif + +#ifdef yyrestart +#define shell_restart_ALREADY_DEFINED +#else +#define yyrestart shell_restart +#endif + +#ifdef yylex_init +#define shell_lex_init_ALREADY_DEFINED +#else +#define yylex_init shell_lex_init +#endif + +#ifdef yylex_init_extra +#define shell_lex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra shell_lex_init_extra +#endif + +#ifdef yylex_destroy +#define shell_lex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy shell_lex_destroy +#endif + +#ifdef yyget_debug +#define shell_get_debug_ALREADY_DEFINED +#else +#define yyget_debug shell_get_debug +#endif + +#ifdef yyset_debug +#define shell_set_debug_ALREADY_DEFINED +#else +#define yyset_debug shell_set_debug +#endif + +#ifdef yyget_extra +#define shell_get_extra_ALREADY_DEFINED +#else +#define yyget_extra shell_get_extra +#endif + +#ifdef yyset_extra +#define shell_set_extra_ALREADY_DEFINED +#else +#define yyset_extra shell_set_extra +#endif + +#ifdef yyget_in +#define shell_get_in_ALREADY_DEFINED +#else +#define yyget_in shell_get_in +#endif + +#ifdef yyset_in +#define shell_set_in_ALREADY_DEFINED +#else +#define yyset_in shell_set_in +#endif + +#ifdef yyget_out +#define shell_get_out_ALREADY_DEFINED +#else +#define yyget_out shell_get_out +#endif + +#ifdef yyset_out +#define shell_set_out_ALREADY_DEFINED +#else +#define yyset_out shell_set_out +#endif + +#ifdef yyget_leng +#define shell_get_leng_ALREADY_DEFINED +#else +#define yyget_leng shell_get_leng +#endif + +#ifdef yyget_text +#define shell_get_text_ALREADY_DEFINED +#else +#define yyget_text shell_get_text +#endif + +#ifdef yyget_lineno +#define shell_get_lineno_ALREADY_DEFINED +#else +#define yyget_lineno shell_get_lineno +#endif + +#ifdef yyset_lineno +#define shell_set_lineno_ALREADY_DEFINED +#else +#define yyset_lineno shell_set_lineno +#endif + +#ifdef yywrap +#define shell_wrap_ALREADY_DEFINED +#else +#define yywrap shell_wrap +#endif + +#ifdef yyalloc +#define shell_alloc_ALREADY_DEFINED +#else +#define yyalloc shell_alloc +#endif + +#ifdef yyrealloc +#define shell_realloc_ALREADY_DEFINED +#else +#define yyrealloc shell_realloc +#endif + +#ifdef yyfree +#define shell_free_ALREADY_DEFINED +#else +#define yyfree shell_free +#endif + +#ifdef yytext +#define shell_text_ALREADY_DEFINED +#else +#define yytext shell_text +#endif + +#ifdef yyleng +#define shell_leng_ALREADY_DEFINED +#else +#define yyleng shell_leng +#endif + +#ifdef yyin +#define shell_in_ALREADY_DEFINED +#else +#define yyin shell_in +#endif + +#ifdef yyout +#define shell_out_ALREADY_DEFINED +#else +#define yyout shell_out +#endif + +#ifdef yy_flex_debug +#define shell__flex_debug_ALREADY_DEFINED +#else +#define yy_flex_debug shell__flex_debug +#endif + +#ifdef yylineno +#define shell_lineno_ALREADY_DEFINED +#else +#define yylineno shell_lineno +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = NULL; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart ( FILE *input_file ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); +void yy_delete_buffer ( YY_BUFFER_STATE b ); +void yy_flush_buffer ( YY_BUFFER_STATE b ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state ( void ); + +static void yyensure_buffer_stack ( void ); +static void yy_load_buffer_state ( void ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); + +void *yyalloc ( yy_size_t ); +void *yyrealloc ( void *, yy_size_t ); +void yyfree ( void * ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define shell_wrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +FILE *yyin = NULL, *yyout = NULL; + +typedef int yy_state_type; + +extern int yylineno; +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state ( void ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); +static int yy_get_next_buffer ( void ); +static void yynoreturn yy_fatal_error ( const char* msg ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; +#define YY_NUM_RULES 14 +#define YY_END_OF_BUFFER 15 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[49] = + { 0, + 0, 0, 0, 0, 15, 10, 8, 7, 9, 6, + 6, 6, 6, 6, 6, 12, 11, 13, 11, 12, + 6, 6, 6, 6, 6, 6, 12, 12, 6, 6, + 6, 6, 6, 6, 2, 1, 6, 5, 6, 6, + 6, 6, 6, 6, 4, 6, 3, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 1, 6, 1, + 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 7, 1, 1, 8, 1, 9, 5, 5, 5, + + 10, 5, 11, 12, 13, 5, 5, 14, 15, 16, + 17, 18, 5, 5, 19, 20, 21, 5, 5, 22, + 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[23] = + { 0, + 1, 1, 2, 2, 3, 1, 1, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3 + } ; + +static const flex_int16_t yy_base[52] = + { 0, + 0, 0, 20, 25, 68, 69, 69, 69, 69, 0, + 46, 44, 55, 55, 53, 55, 69, 69, 54, 26, + 0, 40, 46, 44, 41, 37, 48, 30, 37, 33, + 34, 40, 30, 34, 0, 0, 27, 0, 38, 37, + 25, 33, 33, 26, 0, 16, 0, 69, 37, 22, + 40 + } ; + +static const flex_int16_t yy_def[52] = + { 0, + 48, 1, 49, 49, 48, 48, 48, 48, 48, 50, + 50, 50, 50, 50, 50, 51, 48, 48, 51, 51, + 50, 50, 50, 50, 50, 50, 51, 51, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 48, 48, + 48 + } ; + +static const flex_int16_t yy_nxt[92] = + { 0, + 6, 7, 8, 9, 10, 6, 6, 6, 11, 12, + 10, 13, 10, 14, 10, 10, 10, 10, 10, 15, + 10, 10, 17, 18, 21, 19, 20, 17, 18, 27, + 19, 20, 28, 27, 47, 46, 28, 16, 16, 16, + 27, 45, 27, 44, 43, 42, 41, 40, 39, 38, + 37, 36, 35, 34, 28, 33, 32, 31, 30, 29, + 28, 28, 26, 25, 24, 23, 22, 48, 5, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48 + + } ; + +static const flex_int16_t yy_chk[92] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 50, 3, 3, 4, 4, 20, + 4, 4, 20, 28, 46, 44, 28, 49, 49, 49, + 51, 43, 51, 42, 41, 40, 39, 37, 34, 33, + 32, 31, 30, 29, 27, 26, 25, 24, 23, 22, + 19, 16, 15, 14, 13, 12, 11, 5, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48 + + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scan.l" +#line 2 "scan.l" +#include +#include + +#include "main.h" +#include "error.h" +#include "alloc.h" +#include "regexp.h" +#include "shell_commands.h" + +#include +#include + +#include "parser.tab.h" + +#define PROMPT ">>> " + +#define YY_INPUT(buf, result, max_size) result = mygetinput(buf, max_size); + +enum modes {START_LINE, AFTER_EQ, AFTER_DOT}; + +enum modes mode = START_LINE; + +static int mygetinput(char *buf, unsigned int size) { + char *line; + if (feof(yyin)) + return YY_NULL; + line = readline(PROMPT); + if(!line) + return YY_NULL; + if(strlen(line) + 2 > size){ + fprintf(stderr,"input line too long\n"); + return YY_NULL; + } + sprintf(buf,"%s\n",line); + add_history(line); + free(line); + return strlen(buf); +} + +void yyerror(char *); +#line 780 "" +#define YY_NO_INPUT 1 + +#line 783 "" + +#define INITIAL 0 +#define IN_STRING 1 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals ( void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( void ); + +int yyget_debug ( void ); + +void yyset_debug ( int debug_flag ); + +YY_EXTRA_TYPE yyget_extra ( void ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in ( void ); + +void yyset_in ( FILE * _in_str ); + +FILE *yyget_out ( void ); + +void yyset_out ( FILE * _out_str ); + + int yyget_leng ( void ); + +char *yyget_text ( void ); + +int yyget_lineno ( void ); + +void yyset_lineno ( int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( void ); +#else +extern int yywrap ( void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * ); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( void ); +#else +static int input ( void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 52 "scan.l" + + +#line 1002 "" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 49 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 69 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 54 "scan.l" +{ + return HELP; +} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 58 "scan.l" +{ + return EXIT; +} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 62 "scan.l" +{ + return LANGUAGES; +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 66 "scan.l" +{ + return AUTOS; +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 70 "scan.l" +{ + return TEST; +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 74 "scan.l" +{ + shell_lval.name = strdup(yytext); + return COMMAND; +} + YY_BREAK +case 7: +/* rule 7 can match eol */ +YY_RULE_SETUP +#line 79 "scan.l" +return ';'; + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +#line 81 "scan.l" +; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 83 "scan.l" +BEGIN IN_STRING; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 85 "scan.l" +return yytext[0]; + YY_BREAK +case 11: +/* rule 11 can match eol */ +YY_RULE_SETUP +#line 87 "scan.l" +{ + BEGIN INITIAL; + return ';'; +} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 92 "scan.l" +{ + shell_lval.name = strdup(yytext); + return FILENAME; +} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 97 "scan.l" +{ + BEGIN INITIAL; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 100 "scan.l" +ECHO; + YY_BREAK +#line 1152 "" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(IN_STRING): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 49 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 49 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 48); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return 0; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf ); + + yyfree( (void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr ) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg ) +{ + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = NULL; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = NULL; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 100 "scan.l" + + + diff --git a/Aloyse et Vincent/scan_regexp.c b/Aloyse et Vincent/scan_regexp.c new file mode 100644 index 0000000..3fe7642 --- /dev/null +++ b/Aloyse et Vincent/scan_regexp.c @@ -0,0 +1,2172 @@ + +#line 3 "" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer regexp__create_buffer +#define yy_delete_buffer regexp__delete_buffer +#define yy_scan_buffer regexp__scan_buffer +#define yy_scan_string regexp__scan_string +#define yy_scan_bytes regexp__scan_bytes +#define yy_init_buffer regexp__init_buffer +#define yy_flush_buffer regexp__flush_buffer +#define yy_load_buffer_state regexp__load_buffer_state +#define yy_switch_to_buffer regexp__switch_to_buffer +#define yypush_buffer_state regexp_push_buffer_state +#define yypop_buffer_state regexp_pop_buffer_state +#define yyensure_buffer_stack regexp_ensure_buffer_stack +#define yy_flex_debug regexp__flex_debug +#define yyin regexp_in +#define yyleng regexp_leng +#define yylex regexp_lex +#define yylineno regexp_lineno +#define yyout regexp_out +#define yyrestart regexp_restart +#define yytext regexp_text +#define yywrap regexp_wrap +#define yyalloc regexp_alloc +#define yyrealloc regexp_realloc +#define yyfree regexp_free + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define regexp__create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer regexp__create_buffer +#endif + +#ifdef yy_delete_buffer +#define regexp__delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer regexp__delete_buffer +#endif + +#ifdef yy_scan_buffer +#define regexp__scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer regexp__scan_buffer +#endif + +#ifdef yy_scan_string +#define regexp__scan_string_ALREADY_DEFINED +#else +#define yy_scan_string regexp__scan_string +#endif + +#ifdef yy_scan_bytes +#define regexp__scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes regexp__scan_bytes +#endif + +#ifdef yy_init_buffer +#define regexp__init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer regexp__init_buffer +#endif + +#ifdef yy_flush_buffer +#define regexp__flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer regexp__flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define regexp__load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state regexp__load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define regexp__switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer regexp__switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define regexp_push_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state regexp_push_buffer_state +#endif + +#ifdef yypop_buffer_state +#define regexp_pop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state regexp_pop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define regexp_ensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack regexp_ensure_buffer_stack +#endif + +#ifdef yylex +#define regexp_lex_ALREADY_DEFINED +#else +#define yylex regexp_lex +#endif + +#ifdef yyrestart +#define regexp_restart_ALREADY_DEFINED +#else +#define yyrestart regexp_restart +#endif + +#ifdef yylex_init +#define regexp_lex_init_ALREADY_DEFINED +#else +#define yylex_init regexp_lex_init +#endif + +#ifdef yylex_init_extra +#define regexp_lex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra regexp_lex_init_extra +#endif + +#ifdef yylex_destroy +#define regexp_lex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy regexp_lex_destroy +#endif + +#ifdef yyget_debug +#define regexp_get_debug_ALREADY_DEFINED +#else +#define yyget_debug regexp_get_debug +#endif + +#ifdef yyset_debug +#define regexp_set_debug_ALREADY_DEFINED +#else +#define yyset_debug regexp_set_debug +#endif + +#ifdef yyget_extra +#define regexp_get_extra_ALREADY_DEFINED +#else +#define yyget_extra regexp_get_extra +#endif + +#ifdef yyset_extra +#define regexp_set_extra_ALREADY_DEFINED +#else +#define yyset_extra regexp_set_extra +#endif + +#ifdef yyget_in +#define regexp_get_in_ALREADY_DEFINED +#else +#define yyget_in regexp_get_in +#endif + +#ifdef yyset_in +#define regexp_set_in_ALREADY_DEFINED +#else +#define yyset_in regexp_set_in +#endif + +#ifdef yyget_out +#define regexp_get_out_ALREADY_DEFINED +#else +#define yyget_out regexp_get_out +#endif + +#ifdef yyset_out +#define regexp_set_out_ALREADY_DEFINED +#else +#define yyset_out regexp_set_out +#endif + +#ifdef yyget_leng +#define regexp_get_leng_ALREADY_DEFINED +#else +#define yyget_leng regexp_get_leng +#endif + +#ifdef yyget_text +#define regexp_get_text_ALREADY_DEFINED +#else +#define yyget_text regexp_get_text +#endif + +#ifdef yyget_lineno +#define regexp_get_lineno_ALREADY_DEFINED +#else +#define yyget_lineno regexp_get_lineno +#endif + +#ifdef yyset_lineno +#define regexp_set_lineno_ALREADY_DEFINED +#else +#define yyset_lineno regexp_set_lineno +#endif + +#ifdef yywrap +#define regexp_wrap_ALREADY_DEFINED +#else +#define yywrap regexp_wrap +#endif + +#ifdef yyalloc +#define regexp_alloc_ALREADY_DEFINED +#else +#define yyalloc regexp_alloc +#endif + +#ifdef yyrealloc +#define regexp_realloc_ALREADY_DEFINED +#else +#define yyrealloc regexp_realloc +#endif + +#ifdef yyfree +#define regexp_free_ALREADY_DEFINED +#else +#define yyfree regexp_free +#endif + +#ifdef yytext +#define regexp_text_ALREADY_DEFINED +#else +#define yytext regexp_text +#endif + +#ifdef yyleng +#define regexp_leng_ALREADY_DEFINED +#else +#define yyleng regexp_leng +#endif + +#ifdef yyin +#define regexp_in_ALREADY_DEFINED +#else +#define yyin regexp_in +#endif + +#ifdef yyout +#define regexp_out_ALREADY_DEFINED +#else +#define yyout regexp_out +#endif + +#ifdef yy_flex_debug +#define regexp__flex_debug_ALREADY_DEFINED +#else +#define yy_flex_debug regexp__flex_debug +#endif + +#ifdef yylineno +#define regexp_lineno_ALREADY_DEFINED +#else +#define yylineno regexp_lineno +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = NULL; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart ( FILE *input_file ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); +void yy_delete_buffer ( YY_BUFFER_STATE b ); +void yy_flush_buffer ( YY_BUFFER_STATE b ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state ( void ); + +static void yyensure_buffer_stack ( void ); +static void yy_load_buffer_state ( void ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); + +void *yyalloc ( yy_size_t ); +void *yyrealloc ( void *, yy_size_t ); +void yyfree ( void * ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define regexp_wrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +FILE *yyin = NULL, *yyout = NULL; + +typedef int yy_state_type; + +extern int yylineno; +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state ( void ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); +static int yy_get_next_buffer ( void ); +static void yynoreturn yy_fatal_error ( const char* msg ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; +#define YY_NUM_RULES 23 +#define YY_END_OF_BUFFER 24 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[31] = + { 0, + 0, 0, 24, 22, 2, 1, 7, 9, 13, 15, + 11, 5, 22, 22, 4, 8, 3, 10, 14, 16, + 12, 6, 18, 17, 20, 21, 0, 0, 19, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 1, 1, 1, 7, 1, 8, + 9, 10, 11, 1, 1, 1, 1, 12, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 1, 1, 1, + 1, 1, 1, 1, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 1, 16, 1, 1, 14, 1, 14, 14, 14, 14, + + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 17, 1, 18, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[19] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 1, 1, 2 + } ; + +static const flex_int16_t yy_base[32] = + { 0, + 0, 0, 35, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 15, 19, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 13, 12, 36, 36, + 27 + } ; + +static const flex_int16_t yy_def[32] = + { 0, + 30, 1, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 31, 31, 30, 0, + 30 + } ; + +static const flex_int16_t yy_nxt[55] = + { 0, + 4, 5, 6, 5, 7, 4, 8, 9, 10, 11, + 12, 4, 4, 4, 4, 13, 14, 4, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 28, 29, + 29, 25, 26, 27, 30, 3, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30 + } ; + +static const flex_int16_t yy_chk[55] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 31, 28, + 27, 13, 13, 14, 3, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scan_regexp.l" +#line 2 "scan_regexp.l" +#include +#include + +#include "main.h" +#include "error.h" +#include "alloc.h" +#include "regexp.h" +#include "shell_commands.h" + +#include +#include + +#include "parse_regexp.tab.h" + +void lex_error(char *s); + +void lex_error(char *s){ + fprintf(stderr,"Lexical error in restricted regexp, token %s ignored\n", s); +} + +#line 743 "" +#define YY_NO_INPUT 1 +#line 745 "" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals ( void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( void ); + +int yyget_debug ( void ); + +void yyset_debug ( int debug_flag ); + +YY_EXTRA_TYPE yyget_extra ( void ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in ( void ); + +void yyset_in ( FILE * _in_str ); + +FILE *yyget_out ( void ); + +void yyset_out ( FILE * _out_str ); + + int yyget_leng ( void ); + +char *yyget_text ( void ); + +int yyget_lineno ( void ); + +void yyset_lineno ( int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( void ); +#else +extern int yywrap ( void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * ); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( void ); +#else +static int input ( void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 30 "scan_regexp.l" + + + +#line 964 "" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 31 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 36 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +#line 33 "scan_regexp.l" +return ';'; + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 35 "scan_regexp.l" +; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 37 "scan_regexp.l" +{ + regexp_lval.carac = '\"'; + return LETTER; +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 42 "scan_regexp.l" +{ + regexp_lval.carac = ' '; + return LETTER; +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 47 "scan_regexp.l" +{ + return PLUS_TOK; +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 51 "scan_regexp.l" +{ + regexp_lval.carac = '+'; + return LETTER; +} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 56 "scan_regexp.l" +{ + return COMPL_TOK; +} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 60 "scan_regexp.l" +{ + regexp_lval.carac = '!'; + return LETTER; +} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 65 "scan_regexp.l" +{ + return INTER_TOK; +} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 69 "scan_regexp.l" +{ + regexp_lval.carac = '&'; + return LETTER; +} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 75 "scan_regexp.l" +{ + return STAR_TOK; +} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 79 "scan_regexp.l" +{ + regexp_lval.carac = '*'; + return LETTER; +} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 84 "scan_regexp.l" +{ + return OPEN_TOK; +} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 88 "scan_regexp.l" +{ + regexp_lval.carac = '('; + return LETTER; +} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 93 "scan_regexp.l" +{ + return CLOSE_TOK; +} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 97 "scan_regexp.l" +{ + regexp_lval.carac = ')'; + return LETTER; +} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 102 "scan_regexp.l" +{ + return EPSILON_TOK; +} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 106 "scan_regexp.l" +{ + return EMPTY_TOK; +} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 110 "scan_regexp.l" +{ + regexp_text[regexp_leng-1] = 0; + regexp_lval.name = strdup(regexp_text + 1); + return VARIABLE; +} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 116 "scan_regexp.l" +{ + regexp_lval.carac = '{'; + return LETTER; +} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 121 "scan_regexp.l" +{ + regexp_lval.carac = '}'; + return LETTER; +} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 127 "scan_regexp.l" +{ + regexp_lval.carac = regexp_text[0]; + return LETTER; +} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 132 "scan_regexp.l" +ECHO; + YY_BREAK +#line 1191 "" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 31 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 31 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 30); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return 0; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf ); + + yyfree( (void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr ) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg ) +{ + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = NULL; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = NULL; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 132 "scan_regexp.l" + + +void set_input_string(const char* in); + +void end_lexical_scan(void); + +void set_input_string(const char * in){ + regexp__scan_string(in); +} + +void end_lexical_scan(void){ + regexp_lex_destroy(); +} + diff --git a/Aloyse et Vincent/shell_commands.c b/Aloyse et Vincent/shell_commands.c new file mode 100644 index 0000000..012d35c --- /dev/null +++ b/Aloyse et Vincent/shell_commands.c @@ -0,0 +1,1012 @@ +/*****************************/ +/* 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; +} diff --git a/Aloyse et Vincent/shell_help.c b/Aloyse et Vincent/shell_help.c new file mode 100644 index 0000000..06ae386 --- /dev/null +++ b/Aloyse et Vincent/shell_help.c @@ -0,0 +1,104 @@ +#include "shell_help.h" + +#define PAD1 30 +#define PAD2 33 +#define PADC 8 + +void help(void) { + FILE *p = stdout; + + print_dtitle_box(100, true, p, 1, "Bienvenue dans l'aide du programme LEA !"); + print_title_box(100, true, p, 1, "Commandes de base"); + fprintf(p, "%4s%-*sAffiche cette aide.\n", "", PAD1, "help"); + fprintf(p, "%4s%-*sQuitte le programme.\n", "", PAD1, "quit ou exit ou Ctrl-D"); + fprintf(p, "%4s%-*sAffiche les langages définis.\n", "", PAD1, "languages"); + fprintf(p, "%4s%-*sAffiche les automates définis.\n", "", PAD1, "automata"); + fprintf(p, "%4s%-*sTrie tous les objets par leur nom.\n", "", PAD1, "sort"); + fprintf(p, "%4s%-*sSupprime un objet (langage ou automate).\n", "", PAD1, + "delete()"); + fprintf(p, "%4s%-*sSauve tous les objets définis dans un fichier.\n", "", PAD1, + "savesession(\"\")"); + fprintf(p, "%4s%-*sCharge tous les objets définis dans un fichier.\n", "", PAD1, + "loadsession(\"\")"); + 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 = \"\"\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 | {}\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 = link()\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"); +} diff --git a/Aloyse et Vincent/shell_keywords.c b/Aloyse et Vincent/shell_keywords.c new file mode 100644 index 0000000..9949080 --- /dev/null +++ b/Aloyse et Vincent/shell_keywords.c @@ -0,0 +1,347 @@ +#include "shell_keywords.h" +#include + +/************************/ +/* 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); + } +} + +// diff --git a/Aloyse et Vincent/shell_languages.c b/Aloyse et Vincent/shell_languages.c new file mode 100644 index 0000000..2354975 --- /dev/null +++ b/Aloyse et Vincent/shell_languages.c @@ -0,0 +1,353 @@ +#include "shell_languages.h" + +#include "error.h" +#include "shell_languages.h" +#include "nfa.h" +#include "regexp.h" + +// #define MAX_LANGUAGES 2048 +// language* languages[MAX_LANGUAGES]; +// int nb_languages = 0; + +#define MAX_OBJECTS 2048 +object* objects[MAX_OBJECTS]; +int nb_objects = 0; + +unsigned short minicount = 0; +unsigned short syntcount = 0; + +/************************/ +/* Création/Suppression */ +/************************/ + +object* object_language_new_reg(char* name, regexp* theregexp) { + object* theobject; + MALLOC(theobject, 1); + theobject->name = strdup(name); + theobject->type = LANGUAGE; + theobject->parent = -1; + language* lang; + MALLOC(lang, 1); + lang->type = SPE_REG; + lang->reg = theregexp; + lang->minauto = -1; + theobject->lan = lang; + return theobject; +} + +object* object_language_new_nfa(char* name, int i) { + if (objects[i]->type != AUTOMATON) { + fprintf(stderr, "Error: this is not an automata variable.\n"); + return NULL; + } + object* theobject; + MALLOC(theobject, 1); + theobject->name = strdup(name); + theobject->type = LANGUAGE; + theobject->parent = -1; + language* lang; + MALLOC(lang, 1); + lang->type = SPE_NFA; + lang->nfa = i; + lang->minauto = -1; + theobject->lan = lang; + return theobject; +} + +object* object_automata_new(char* name, nfa* A) { + object* theobject; + MALLOC(theobject, 1); + theobject->name = strdup(name); + theobject->type = AUTOMATON; + theobject->parent = -1; + automata* aut; + MALLOC(aut, 1); + aut->nfa = A; + theobject->aut = aut; + return theobject; +} + +void object_free(object* theobject) { + if (theobject == NULL) { + return; + } + // Libération du nom + free(theobject->name); + + switch (theobject->type) { + case AUTOMATON: + if (theobject->aut == NULL) { + free(theobject); + return; + } + nfa_delete(theobject->aut->nfa); + free(theobject->aut); + break; + case LANGUAGE: + if (theobject->lan == NULL) { + free(theobject); + return; + } + // Si le langage est spécifié par une expression, + // on la libère. + if (theobject->lan->type == SPE_REG) { + if (theobject->lan->reg) { + reg_free(theobject->lan->reg); + } + } + // Si le langage est spécifié par un NFA, on enlève + // le flag qui protège ce NFA. + else if (theobject->lan->type == SPE_NFA) { + objects[theobject->lan->nfa]->parent = -1; + } + // Si le langage est associèe à un minimal, on enlève + // le flag qui protège ce minimal. + if (theobject->lan->minauto != -1) { + objects[theobject->lan->minauto]->parent = -1; + } + free(theobject->lan); + break; + + default: + break; + } + free(theobject); +} + +/*************************************/ +/* Récupération/insertion d'un objet */ +/*************************************/ + +int object_get_from_name(char* name) { + for (int i = 0; i < nb_objects; i++) { + if (objects[i] && strcmp(objects[i]->name, name) == 0) { + return i; + } + } + return -1; +} + +int object_delete_from_name(char* name) { + int i = object_get_from_name(name); + if (i == -1) { + fprintf(stderr, "Error: unknown variable.\n"); + return -1; + } + else if (objects[i] && objects[i]->parent != -1) { + fprintf(stderr, "Error: this is a protected variable.\n"); + return -1; + } + else { + object_free(objects[i]); + nb_objects--; + if (nb_objects > 0) { + objects[i] = objects[nb_objects]; + } + return i; + } +} + +int object_add_language_reg(char* name, regexp* theregexp) { + if (theregexp == NULL) { + return -1; + } + + if (nb_objects == MAX_OBJECTS) { + ERROR("Error: too many objects are already stored in memory.\n"); + return -1; + } + + int i = object_get_from_name(name); + + if (i != -1 && objects[i]->parent == -1) { + // Si il y a déjà un objet à ce nom et qu'il n'est pas protégé + DEBUG("Warning: an object with name %s already exists\n", name); + object_free(objects[i]); + objects[i] = object_language_new_reg(name, theregexp); + return i; + } + else if (i != -1 && objects[i]->parent != -1) { + fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n"); + reg_free(theregexp); + return -1; + } + else { + objects[nb_objects++] = object_language_new_reg(name, theregexp); + return nb_objects - 1; + } +} + +int object_add_language_nfa(char* name, int j) { + if (j == -1 || objects[j]->type != AUTOMATON) { + return -1; + } + + if (nb_objects == MAX_OBJECTS) { + ERROR("Error: too many objects are already stored in memory.\n"); + return -1; + } + int i = object_get_from_name(name); + + if (i != -1 && objects[i]->parent == -1) { + // Si il y a déjà un objet à ce nom et qu'il n'est pas protégé + DEBUG("Warning: an object with name %s already exists\n", name); + object_free(objects[i]); + objects[i] = object_language_new_nfa(name, j); + objects[j]->parent = i; + return i; + } + else if (i != -1 && objects[i]->parent != -1) { + fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n"); + return -1; + } + else { + objects[nb_objects++] = object_language_new_nfa(name, j); + objects[j]->parent = nb_objects - 1; + return nb_objects - 1; + } +} + +int object_add_automata(char* name, nfa* A) { + if (A == NULL) { + return -1; + } + + if (nb_objects == MAX_OBJECTS) { + ERROR("Error: too many objects are already stored in memory.\n"); + return -1; + } + + int i = object_get_from_name(name); + + // Si il y a déjà un objet à ce nom + if (i != -1 && objects[i]->parent == -1) { + DEBUG("Warning: an object with name %s already exists\n", name); + object_free(objects[i]); + objects[i] = object_automata_new(name, A); + return i; + } + else if (i != -1 && objects[i]->parent != -1) { + fprintf(stderr, "Error: cannot assign a new object to a protected variable.\n"); + nfa_delete(A); + return -1; + } + else { + objects[nb_objects++] = object_automata_new(name, A); + return nb_objects - 1; + } +} + +static int object_compare(const void* pob1, const void* pob2) { + object* ob1 = *(object* const*)pob1; + object* ob2 = *(object* const*)pob2; + if (ob1 == NULL) { + if (ob2 == NULL) { + return 0; + } + return -1; + } + if (ob2 == NULL) { + return 1; + } + return strcmp(ob1->name, ob2->name); +} + +void object_sort_array(void) { + qsort(objects, nb_objects, sizeof(object*), &object_compare); +} + +/****************************/ +/* Affichage d'informations */ +/****************************/ + +void object_print_langs(void) { + // Calcul du nombre de langages + ushort count = 0; + for (int i = 0; i < nb_objects; i++) { + if (objects[i]->type == LANGUAGE) { + count++; + } + } + + printf("#### There are %d language(s) in memory:\n\n", count); + + if (count > 0) { + count = 1; + } + for (int i = 0; i < nb_objects; i++) { + if (objects[i]->type == LANGUAGE) { + printf("#### %d: %s\n", count, objects[i]->name); + if (objects[i]->lan->type == SPE_REG) { + printf(" Specified by a regular expression\n"); + printf(" Regexp: "); + reg_print(objects[i]->lan->reg); + } + else if (objects[i]->lan->type == SPE_NFA) { + printf(" Specified by an automaton.\n"); + } + printf("\n"); + count++; + } + } +} + +void object_print_autos(void) { + // Calcul du nombre d'automates' + ushort count = 0; + for (int i = 0; i < nb_objects; i++) { + if (objects[i]->type == AUTOMATON) { + count++; + } + } + + printf("#### There are %d automata in memory:\n\n", count); + + if (count > 0) { + count = 1; + } + for (int i = 0; i < nb_objects; i++) { + if (objects[i]->type == AUTOMATON) { + printf("#### %d: %s\n", count, objects[i]->name); + if (objects[i]->parent != -1 && objects[objects[i]->parent]->type == LANGUAGE) { + printf(" Protected: tied to the language %s.\n", + objects[objects[i]->parent]->name); + } + printf("\n"); + count++; + } + } +} + +/************************************************/ +/* Calculs d'informations sur un objet existant */ +/************************************************/ + +// Calcul du DFA minimal d'un langage +int shell_compute_minimal(int i) { + if (objects[i]->type != LANGUAGE) { + fprintf(stderr, "Should be a language.\n"); + return -1; + } + language* lang = objects[i]->lan; + if (lang->minauto == -1) { + DEBUG("Computing the minimal automaton of a language"); + nfa* A; + if (lang->type == SPE_REG) { + A = reg_thompson(lang->reg); + } + else { + A = objects[lang->nfa]->aut->nfa; + } + + char* newname; + MALLOC(newname, 20); + sprintf(newname, "SYSMINI%04d", minicount++); + lang->minauto = object_add_automata(newname, nfa_brzozowski(A)); + free(newname); + // On protège le NFA minimal qu'on a créé + objects[lang->minauto]->parent = i; + + nfa_delete(A); + } + return lang->minauto; +} diff --git a/Aloyse et Vincent/shell_test.c b/Aloyse et Vincent/shell_test.c new file mode 100644 index 0000000..d123e87 --- /dev/null +++ b/Aloyse et Vincent/shell_test.c @@ -0,0 +1,401 @@ +#include "shell_test.h" + +#include +#include + +#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); + } +} diff --git a/Aloyse et Vincent/shell_tools.c b/Aloyse et Vincent/shell_tools.c new file mode 100644 index 0000000..71a1fa1 --- /dev/null +++ b/Aloyse et Vincent/shell_tools.c @@ -0,0 +1,445 @@ +#include "shell_tools.h" + + +static uint num_length_aux(uint n) { + if (n == 0) { + return 0; + } + else { + return num_length_aux(n / 10) + 1; + } +} + + +uint num_length(uint n) { + if (n == 0) { + return 1; + } + else { + return num_length_aux(n); + } +} + + +char* multiple_strcat(char* s, ...) { + va_list ap; + char* t = s; + size_t len = 0; + + va_start(ap, s); + do + { + len += strlen(t); + } while ((t = va_arg(ap, char*))); + va_end(ap); + + char* ret; + CALLOC(ret, len + 1); + + t = s; + va_start(ap, s); + do + { + strcat(ret, t); + } while ((t = va_arg(ap, char*))); + va_end(ap); + + return ret; +} + +void print_top_line(uint length, FILE* out) { + fprintf(out, "┌"); + for (uint i = 0; i < length; i++) { + fprintf(out, "─"); + } + fprintf(out, "┐\n"); +} + +void print_mid_line(uint length, FILE* out) { + fprintf(out, "├"); + for (uint i = 0; i < length; i++) { + fprintf(out, "─"); + } + fprintf(out, "┤\n"); +} + +void print_bot_line(uint length, FILE* out) { + fprintf(out, "└"); + for (uint i = 0; i < length; i++) { + fprintf(out, "─"); + } + fprintf(out, "┘\n"); +} + +void print_sep_line(uint length, FILE* out) { + print_top_line(length, out); + print_bot_line(length, out); +} + +void print_dtop_line(uint length, FILE* out) { + fprintf(out, "╔"); + for (uint i = 0; i < length; i++) { + fprintf(out, "═"); + } + fprintf(out, "╗\n"); +} + +void print_dmid_line(uint length, FILE* out) { + fprintf(out, "╠"); + for (uint i = 0; i < length; i++) { + fprintf(out, "═"); + } + fprintf(out, "╣\n"); +} + +void print_dbot_line(uint length, FILE* out) { + fprintf(out, "╚"); + for (uint i = 0; i < length; i++) { + fprintf(out, "═"); + } + fprintf(out, "╝\n"); +} + +void print_spaces(uint number, FILE* out) { + for (uint i = 0; i < number; i++) { + fprintf(out, " "); + } +} + +void print_char(uint number, char* c, FILE* out) { + for (uint i = 0; i < number; i++) { + fprintf(out, "%s", c); + } +} + +uint count_utf8_code_points(const char* s) { + uint count = 0; + while (*s) { + count += (*s++ & 0xC0) != 0x80; + } + return count; +} + +// Affichage d'un titre dans une boite. +// La taille minimale autorisée est 100 (le max de length et 100 est utilisé) +void print_title_box(uint length, bool closed, FILE* out, uint nlines, ...) { + // La taille minimale est 100 + length = max(length, 100); + + // Récupération des lignes à écrire + va_list list; + va_start(list, nlines); + char* input[nlines]; + for (uint i = 0; i < nlines; i++) { + input[i] = va_arg(list, char*); + if (count_utf8_code_points(input[i]) > length) { + printf("Printing error, the title is too long for the chosen length\n"); + return; + } + if (strchr(input[i], '\n') != NULL) { + printf("Printing error, the title should not contain \"newline\"\n"); + return; + } + } + // Si tout s'est bien passé, on passe à la phase d'écriture + print_top_line(length, out); + + for (uint i = 0; i < nlines; i++) { + uint titlelen = count_utf8_code_points(input[i]); + fprintf(out, "│"); + uint pad = length - titlelen; + print_spaces(pad / 2, out); + fprintf(out, "%s", input[i]); + print_spaces((pad / 2) + (pad % 2), out); + fprintf(out, "│\n"); + } + + if (closed) { + print_bot_line(length, out); + } + else { + print_mid_line(length, out); + } +} + +void print_title_box_shift(uint length, uint shiftl, uint shiftr, bool closed, FILE* out, + uint nlines, ...) { + // La taille minimale est 100 + length = max(length, 100); + + // Récupération des lignes à écrire + va_list list; + va_start(list, nlines); + char* input[nlines]; + for (uint i = 0; i < nlines; i++) { + input[i] = va_arg(list, char*); + if (count_utf8_code_points(input[i]) > length) { + printf("Printing error, the title is too long for the chosen length\n"); + return; + } + if (strchr(input[i], '\n') != NULL) { + printf("Printing error, the title should not contain \"newline\"\n"); + return; + } + } + // Si tout s'est bien passé, on passe à la phase d'écriture + print_top_line(length, out); + + for (uint i = 0; i < nlines; i++) { + uint titlelen = count_utf8_code_points(input[i]); + fprintf(out, "│"); + uint pad = length - titlelen; + print_spaces(pad / 2 - shiftl, out); + fprintf(out, "%s", input[i]); + print_spaces((pad / 2) + (pad % 2) - shiftr, out); + fprintf(out, "│\n"); + } + + if (closed) { + print_bot_line(length, out); + } + else { + print_mid_line(length, out); + } +} + +void print_dtitle_box(uint length, bool closed, FILE* out, uint nlines, ...) { + // La taille minimale est 100 + length = max(length, 100); + + // Récupération des lignes à écrire + va_list list; + va_start(list, nlines); + char* input[nlines]; + for (uint i = 0; i < nlines; i++) { + input[i] = va_arg(list, char*); + if (count_utf8_code_points(input[i]) > length) { + printf("Printing error, the title is too long for the chosen length\n"); + return; + } + if (strchr(input[i], '\n') != NULL) { + printf("Printing error, the title should not contain \"newline\"\n"); + return; + } + } + + // Si tout s'est bien passé, on passe à la phase d'écriture + print_dtop_line(length, out); + + for (uint i = 0; i < nlines; i++) { + uint titlelen = count_utf8_code_points(input[i]); + fprintf(out, "║"); + uint pad = length - titlelen; + print_spaces(pad / 2, out); + fprintf(out, "%s", input[i]); + print_spaces((pad / 2) + (pad % 2), out); + fprintf(out, "║\n"); + } + + if (closed) { + print_dbot_line(length, out); + } + else { + print_dmid_line(length, out); + } +} + +void print_line_box(uint length, FILE* out, char* s) { + // La taille minimale est 100 + length = max(length, 100); + uint linelen = count_utf8_code_points(s); + // Récupération des lignes à écrire + if (linelen > length) { + printf("Printing error, the line is too long for the chosen length\n"); + return; + } + if (strchr(s, '\n') != NULL) { + printf("Printing error, the line should not contain \"newline\"\n"); + return; + } + + // Si tout s'est bien passé, on passe à la phase d'écriture + fprintf(out, "│"); + uint pad = length - linelen; + fprintf(out, "%s", s); + print_spaces(pad, out); + fprintf(out, "│\n"); +} + +void print_dline_box(uint length, FILE* out, char* s) { + // La taille minimale est 100 + length = max(length, 100); + uint linelen = count_utf8_code_points(s); + // Récupération des lignes à écrire + if (linelen > length) { + printf("Printing error, the line is too long for the chosen length\n"); + return; + } + if (strchr(s, '\n') != NULL) { + printf("Printing error, the line should not contain \"newline\"\n"); + return; + } + + // Si tout s'est bien passé, on passe à la phase d'écriture + fprintf(out, "║"); + uint pad = length - linelen; + fprintf(out, "%s", s); + print_spaces(pad, out); + fprintf(out, "║\n"); +} + +void print_booltab_alph(bool* alph_array, uint alph_size, FILE* out) { + uint a = 0; + while (a < alph_size && !alph_array[a]) { + a++; + } + if (a == alph_size) { + fprintf(out, "∅.\n"); + } + else { + fprintf(out, "{%c", a + 'a'); + a++; + while (a < alph_size) { + if (alph_array[a]) { + fprintf(out, ",%c", a + 'a'); + } + + a++; + } + fprintf(out, "}.\n"); + } +} + +void append_power(uint n, char* name) { + if (n != 0) { + uint d = n % 10; + append_power(n / 10, name); + switch (d) { + case 0: + strcat(name, "⁰"); + break; + case 1: + strcat(name, "¹"); + break; + case 2: + strcat(name, "²"); + break; + case 3: + strcat(name, "³"); + break; + case 4: + strcat(name, "⁴"); + break; + case 5: + strcat(name, "⁵"); + break; + case 6: + strcat(name, "⁶"); + break; + case 7: + strcat(name, "⁷"); + break; + case 8: + strcat(name, "⁸"); + break; + case 9: + strcat(name, "⁹"); + break; + default: + break; + } + } +} + +void print_power(uint n, FILE* out) { + if (n != 0) { + uint d = n % 10; + print_power(n / 10, out); + switch (d) { + case 0: + fprintf(out, "⁰"); + break; + case 1: + fprintf(out, "¹"); + break; + case 2: + fprintf(out, "²"); + break; + case 3: + fprintf(out, "³"); + break; + case 4: + fprintf(out, "⁴"); + break; + case 5: + fprintf(out, "⁵"); + break; + case 6: + fprintf(out, "⁶"); + break; + case 7: + fprintf(out, "⁷"); + break; + case 8: + fprintf(out, "⁸"); + break; + case 9: + fprintf(out, "⁹"); + break; + default: + break; + } + } +} + +void print_facto_word(char* word, FILE* out) { + uint len = strlen(word); + if (len == 0) { + printf("ε"); + } + else { + uint n = 1; + fprintf(out, "%c", word[0]); + for (uint i = 1; i < len; i++) { + if (word[i] != word[i - 1]) { + if (n > 1) { + print_power(n, out); + } + fprintf(out, "%c", word[i]); + n = 1; + } + else { + n++; + } + } + if (n > 1) { + print_power(n, out); + } + } +} + +void print_color(char* s, color col, FILE* out) { + switch (col) { + case RED: + fprintf(out, "\033[0;31m%s\033[0m", s); + break; + case GREEN: + fprintf(out, "\033[0;32m%s\033[0m", s); + break; + case YELLOW: + fprintf(out, "\033[0;33m%s\033[0m", s); + break; + case BLUE: + fprintf(out, "\033[0;34m%s\033[0m", s); + break; + case PURPLE: + fprintf(out, "\033[0;35m%s\033[0m", s); + break; + case CYAN: + fprintf(out, "\033[0;36m%s\033[0m", s); + break; + case WHITE: + fprintf(out, "\033[0;37m%s\033[0m", s); + break; + } +} diff --git a/Aloyse et Vincent/type_boolarray.c b/Aloyse et Vincent/type_boolarray.c new file mode 100644 index 0000000..3700512 --- /dev/null +++ b/Aloyse et Vincent/type_boolarray.c @@ -0,0 +1,77 @@ +#include "type_boolarray.h" + +barray *create_barray(const uint size) { + barray *b = malloc(sizeof(barray)); + if (b == NULL) { + fprintf(stderr, "Erreur d'allocation de mémoire\n"); + exit(EXIT_FAILURE); + } + b->size = size; + if (size % 8 == 0) { + b->size_array = size / 8; + } else { + b->size_array = size / 8 + 1; + } + b->array = calloc(b->size_array, sizeof(uchar)); + if (b->array == NULL) { + fprintf(stderr, "Erreur d'allocation de mémoire\n"); + exit(EXIT_FAILURE); + } + return b; +} + +uint getsize_barray(barray *thearray) { return thearray->size; } + +void delete_barray(barray *thearray) { + free(thearray->array); + free(thearray); +} + +void settrue_barray(barray *thearray, const uint thecell) { + thearray->array[thecell / 8] |= (1 << thecell % 8); +} + +void setfalse_barray(barray *thearray, const uint thecell) { + thearray->array[thecell / 8] &= ~(1 << thecell % 8); +} + +bool getval_barray(barray *thearray, const uint thecell) { + return thearray->array[thecell / 8] & (1 << thecell % 8); +} + +void print_array(barray *ptr) { + for (uint i = 0; i < getsize_barray(ptr); i++) { + printf("%d ", getval_barray(ptr, i)); + } + printf("\n"); +} + +barray *or_barray(barray *array1, barray *array2) { + if (array1->size != array2->size) { + return NULL; + } + barray *b = create_barray(array1->size); + for (uint i = 0; i < b->size_array; i++) { + b->array[i] = array1->array[i] | array2->array[i]; + } + return b; +} + +barray *and_barray(barray *array1, barray *array2) { + if (array1->size != array2->size) { + return NULL; + } + barray *b = create_barray(array1->size); + for (uint i = 0; i < b->size_array; i++) { + b->array[i] = array1->array[i] & array2->array[i]; + } + return b; +} + +barray *copy_barray(barray *thearray) { + barray *b = create_barray(thearray->size); + for (uint i = 0; i < b->size_array; i++) { + b->array[i] = thearray->array[i]; + } + return b; +} diff --git a/Aloyse et Vincent/type_dequeue.c b/Aloyse et Vincent/type_dequeue.c new file mode 100644 index 0000000..2fc59bc --- /dev/null +++ b/Aloyse et Vincent/type_dequeue.c @@ -0,0 +1,386 @@ + +/*****************************************/ +/* Implémentations des listes de sommets */ +/* Utilisation d'un tuyau par liste */ +/*****************************************/ + +#include "type_dequeue.h" + +#include +#include +#include + +#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; +} diff --git a/Aloyse et Vincent/type_stack.c b/Aloyse et Vincent/type_stack.c new file mode 100644 index 0000000..603dad8 --- /dev/null +++ b/Aloyse et Vincent/type_stack.c @@ -0,0 +1,73 @@ + +#include "type_stack.h" + +/************************/ +/* Fonctions primitives */ +/************************/ + +static void grow_stack(stack *thestack) { + thestack->array = + realloc(thestack->array, 2 * thestack->size_array * sizeof(void *)); + if (thestack->array == NULL) { + ERROR("Erreur d'allocation mémoire"); + } + thestack->size_array = 2 * thestack->size_array; +} + +static void shrink_stack(stack *thestack) { + thestack->array = + realloc(thestack->array, thestack->size_array * sizeof(void *) / 2); + if (thestack->array == NULL) { + ERROR("Erreur d'allocation mémoire"); + } + thestack->size_array = thestack->size_array / 2; +} + +/* Création */ +stack *create_stack(void) { + stack *thestack = malloc(sizeof(stack)); + thestack->size_array = 1; + thestack->size_stack = 0; + thestack->array = malloc(sizeof(void *)); + return thestack; +} + +/* Suppression */ +void delete_stack(stack *thestack) { + free(thestack->array); + free(thestack); +} + +/* Test du vide */ +bool isempty_stack(stack *thestack) { + return thestack->size_stack == 0; +} + +/* Taille*/ +uint size_stack(stack *thestack) { return thestack->size_stack; } + +/* Lecture */ +void *read_stack(stack *thestack, const uint index) { return thestack->array[index]; } + +/* Dépiler */ +void *pop(stack *thestack) { + if (isempty_stack(thestack)) { + ERROR("La pile est vide."); + } + void *v = thestack->array[(thestack->size_stack) - 1]; + thestack->size_stack -= 1; + if (thestack->size_stack <= thestack->size_array / 4 && + thestack->size_array > 1) { + shrink_stack(thestack); + } + return v; +} + +/* Empiler */ +void push(void *val, stack *thestack) { + if (thestack->size_array <= thestack->size_stack) { + grow_stack(thestack); + } + thestack->size_stack += 1; + thestack->array[thestack->size_stack - 1] = val; +}