/** * 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); } } } }
/** * If the state #q of the automaton A has a default transition, this function * adds all the explicit transitions that are equivalent to the default one. */ void explicit_default_transition(language_t* language,SingleGraph A,int q) { if (A->states[q]->default_state==-1) { /* Nothing to do if there is no default transition */ return; } /* We compute the set of symbols tagging transitions that outgo from q */ symbol_t* s=symbols_from_transs(A->states[q]->outgoing_transitions); /* and we take the complementary set */ symbol_t* all_but_s=minus_symbols(language,s); add_all_outgoing_transitions(A->states[q],all_but_s,A->states[q]->default_state); free_symbols(s); free_symbols(all_but_s); }
/** * Loads and returns an automaton from the given .fst2. * Returns NULL if there is no more automaton to load. */ Fst2Automaton* load_automaton(Elag_fst_file_in* fstf) { if (fstf->pos>=fstf->nb_automata) { return NULL; } Ustring* ustr=new_Ustring(); readline(ustr,fstf->f); const unichar* p=ustr->str; if (p[0]!='-') { fatal_error("load_automaton: %s: bad file format\n",fstf->name); } p++; int i=u_parse_int(p,&p); if (i!=fstf->pos+1) { /* We make sure that the automaton number is what it should be */ fatal_error("load_automaton: %s: parsing error with line '%S' ('-%d ...' expected)\n",fstf->name,ustr->str,fstf->pos+1); } /* Now p points on the automaton name */ p++; Fst2Automaton* A=new_Fst2Automaton(p); while (readline(ustr,fstf->f) && ustr->str[0]!='f') { /* If there is a state to read */ p=ustr->str; SingleGraphState state=add_state(A->automaton); if (*p=='t') { /* If necessary, we set the state final */ set_final_state(state); } /* We puts p on the first digit */ while (*p!='\0' && !u_is_digit(*p)) { p++; } while (*p!='\0') { /* If there is a transition to read */ int tag_number=u_parse_int(p,&p); if (fstf->renumber!=NULL) { tag_number=fstf->renumber[tag_number]; } while (*p==' ') { p++; } if (!u_is_digit(*p)) { fatal_error("load_automaton: %s: bad file format (line='%S')\n",fstf->name,ustr->str); } int state_number=u_parse_int(p,&p); symbol_t* tmp=(symbol_t*)fstf->symbols->value[tag_number]; if (tmp!=NULL) { /* If it is a good symbol (successfully loaded), we add transition(s) */ if (fstf->type!=FST_TEXT) { add_all_outgoing_transitions(state,tmp,state_number); } else { /* In a text automaton, we add one transition per element of * the symbol list. For instance, if we have: * * tmp = "{domestique,.N:fs}" => "{domestique,.N:ms}" => NULL * * then we add two transitions. */ add_all_outgoing_transitions(state,tmp,state_number); } } while (*p==' ') { p++; } } } if (*ustr->str=='\0') { fatal_error("load_automaton: unexpected end of file\n"); } if (A->automaton->number_of_states==0) { error("load_automaton: automaton with no state\n"); } else { set_initial_state(A->automaton->states[0]); } fstf->pos++; free_Ustring(ustr); return A; }