/** * Replaces the given automaton by its complement one. */ void elag_complementation(language_t* language,SingleGraph A) { int sink_state_index=A->number_of_states; SingleGraphState sink_state=add_state(A); /* The sink state is not final (because finalities will be reversed * below), and its default transition loops back on itself */ sink_state->default_state=sink_state_index; for (int q=0;q<A->number_of_states;q++) { /* We reverse the finality of each state */ if (is_final_state(A->states[q])) { unset_final_state(A->states[q]); } else { set_final_state(A->states[q]); } if (A->states[q]->default_state==-1) { /* If there is no default transition, we create one that is * tagged by anything but the non default ones */ symbol_t* s=LEXIC_minus_transitions(language,A->states[q]->outgoing_transitions); if (s!=NULL) { add_all_outgoing_transitions(A->states[q],s,sink_state_index); /* We have added a single transition tagged by a symbol list. Now * we replace it by a list of transitions, each one of them * tagged with a single symbol */ flatten_transition(A->states[q]->outgoing_transitions); /* Important to use free_symbols and not free_symbol, because * s represents a symbol list */ free_symbols(s); } } } }
/** * This function concatenates B at the end of A. A is modified. */ void elag_concat(language_t* language,SingleGraph A,SingleGraph B) { int oldnb=A->number_of_states; int* renumber=(int*)malloc(B->number_of_states*sizeof(int)); if (renumber==NULL) { fatal_alloc_error("elag_concat"); } int q; /* We copy the states of B into A */ for (q=0;q<B->number_of_states;q++) { renumber[q]=A->number_of_states; add_state(A); } for (q=0;q<B->number_of_states;q++) { A->states[renumber[q]]->outgoing_transitions=clone_transition_list(B->states[q]->outgoing_transitions,renumber,dup_symbol); A->states[renumber[q]]->default_state=(B->states[q]->default_state!=-1)?renumber[B->states[q]->default_state]:-1; if (is_final_state(B->states[q])) { set_final_state(A->states[renumber[q]]); } } /* Then, we concatenate A and B. * 1) We replace default transitions that outgo from B's initial states * by explicit transitions */ struct list_int* initials=get_initial_states(B); for (struct list_int* tmp=initials;tmp!=NULL;tmp=tmp->next) { explicit_default_transition(language,A,renumber[tmp->n]); } for (q=0;q<oldnb;q++) { if (is_final_state(A->states[q])) { /* Each final state of A becomes non final. Moreover, we have * to explicit its default transition, because if not, the concatenation * algorithm will modify the recognized language. */ unset_final_state(A->states[q]); explicit_default_transition(language,A,q); for (struct list_int* tmp=initials;tmp!=NULL;tmp=tmp->next) { concat(&(A->states[q]->outgoing_transitions),clone_transition_list(A->states[renumber[tmp->n]]->outgoing_transitions,NULL,dup_symbol)); if (is_final_state(A->states[renumber[tmp->n]])) { set_final_state(A->states[q]); } } } } free(renumber); free_list_int(initials); }