struct fsm* ConditionMerger::union_trees(struct fsm* fst1, struct fsm* fst2) { struct fsm* ret = fsm_topsort( fsm_minimize( fsm_determinize( fsm_union( fsm_copy(fst1), fsm_copy(fst2))))); fsm_sort_arcs(ret, 1); return ret; }
struct fsm *flag_eliminate(struct fsm *net, char *name) { struct flags *flags, *f, *ff; struct fsm *filter, *succeed_flags, *fail_flags, *self, *newfilter, *newnet; int flag, fstatus, found; filter = NULL; flags = flag_extract(net); /* Check that flag actually exists in net */ if (name != NULL) { for (found = 0, f = flags; f != NULL; f = f->next) { if (strcmp(name,f->name) == 0) found = 1; } if (found == 0) { #ifdef ORIGINAL fprintf(stderr,"Flag attribute '%s' does not occur in the network.\n",name); #else // TODO: Handle this in some other way. #endif return(net); } } flag = 0; for (f = flags; f != NULL; f = f->next) { if ((name == NULL || strcmp(f->name,name) == 0) && (f->type | FLAG_UNIFY | FLAG_REQUIRE | FLAG_DISALLOW | FLAG_EQUAL)) { succeed_flags = fsm_empty_set(); fail_flags = fsm_empty_set(); self = flag_create_symbol(f->type, f->name, f->value); for (ff = flags, flag = 0; ff != NULL; ff = ff->next) { fstatus = flag_build(f->type, f->name, f->value, ff->type, ff->name, ff->value); if (fstatus == FAIL) { fail_flags = fsm_minimize(fsm_union(fail_flags, flag_create_symbol(ff->type, ff->name, ff->value))); flag = 1; } if (fstatus == SUCCEED) { succeed_flags = fsm_minimize(fsm_union(succeed_flags, flag_create_symbol(ff->type, ff->name, ff->value))); flag = 1; } } } if (flag) { if (f->type == FLAG_REQUIRE) { newfilter = fsm_complement(fsm_concat(fsm_optionality(fsm_concat(fsm_universal(), fail_flags)), fsm_concat(fsm_complement(fsm_contains(succeed_flags)), fsm_concat(self, fsm_universal())))); } else { newfilter = fsm_complement(fsm_contains(fsm_concat(fail_flags,fsm_concat(fsm_complement(fsm_contains(succeed_flags)),self)))); } filter = (filter == NULL) ? newfilter : fsm_intersect(filter, newfilter); } flag = 0; } if (filter != NULL) { extern int g_flag_is_epsilon; int old_g_flag_is_epsilon; old_g_flag_is_epsilon = g_flag_is_epsilon; g_flag_is_epsilon = 0; newnet = fsm_compose(fsm_copy(filter),fsm_compose(net,fsm_copy(filter))); g_flag_is_epsilon = old_g_flag_is_epsilon; } else { newnet = net; } flag_purge(newnet, name); newnet = fsm_minimize(newnet); sigma_cleanup(newnet,0); xxfree(flags); return(fsm_topsort(newnet)); }
struct fsm *flag_twosided(struct fsm *net) { struct fsm_state *fsm; struct sigma *sigma; int i, j, tail, *isflag, maxsigma, maxstate, newarcs, change; /* Enforces twosided flag diacritics */ /* Mark flag symbols */ maxsigma = sigma_max(net->sigma); isflag = xxcalloc(maxsigma+1, sizeof(int)); fsm = net->states; for (sigma = net->sigma ; sigma != NULL; sigma = sigma->next) { if (flag_check(sigma->symbol)) { *(isflag+sigma->number) = 1; } else { *(isflag+sigma->number) = 0; } } maxstate = 0; change = 0; for (i = 0, newarcs = 0; (fsm+i)->state_no != -1 ; i++) { maxstate = (fsm+i)->state_no > maxstate ? (fsm+i)->state_no : maxstate; if ((fsm+i)->target == -1) continue; if (*(isflag+(fsm+i)->in) && (fsm+i)->out == EPSILON) { change = 1; (fsm+i)->out = (fsm+i)->in; } else if (*(isflag+(fsm+i)->out) && (fsm+i)->in == EPSILON) { change = 1; (fsm+i)->in = (fsm+i)->out; } if ((*(isflag+(fsm+i)->in) || *(isflag+(fsm+i)->out)) && (fsm+i)->in != (fsm+i)->out) { newarcs++; } } if (newarcs == 0) { if (change == 1) { net->is_deterministic = UNK; net->is_minimized = UNK; net->is_pruned = UNK; return fsm_topsort(fsm_minimize(net)); } return net; } net->states = xxrealloc(net->states, sizeof(struct fsm)*(i+newarcs)); fsm = net->states; tail = j = i; maxstate++; for (i = 0; i < tail; i++) { if ((fsm+i)->target == -1) continue; if ((*(isflag+(fsm+i)->in) || *(isflag+(fsm+i)->out)) && (fsm+i)->in != (fsm+i)->out) { if (*(isflag+(fsm+i)->in) && !*(isflag+(fsm+i)->out)) { j = add_fsm_arc(fsm, j, maxstate, EPSILON, (fsm+i)->out, (fsm+i)->target, 0, 0); (fsm+i)->out = (fsm+i)->in; (fsm+i)->target = maxstate; maxstate++; } else if (*(isflag+(fsm+i)->out) && !*(isflag+(fsm+i)->in)) { j = add_fsm_arc(fsm, j, maxstate, (fsm+i)->out, (fsm+i)->out, (fsm+i)->target, 0, 0); (fsm+i)->out = EPSILON; (fsm+i)->target = maxstate; maxstate++; } else if (*(isflag+(fsm+i)->in) && *(isflag+(fsm+i)->out)) { j = add_fsm_arc(fsm, j, maxstate, (fsm+i)->out, (fsm+i)->out, (fsm+i)->target, 0, 0); (fsm+i)->out = (fsm+i)->in; (fsm+i)->target = maxstate; maxstate++; } } } /* Add sentinel */ add_fsm_arc(fsm, j, -1, -1, -1, -1, -1, -1); net->is_deterministic = UNK; net->is_minimized = UNK; return fsm_topsort(fsm_minimize(net)); }