/* real recursion computation function */ void e_closure(struct nfa *nfa, struct set *stateset, struct accept **acp) { int state; if (!nfa) return; state = nfastate(nfa); /* greedy algorithm: accept as much states as possible */ if (!nfa->next[0]) { if (!nfa->accept) errexit("no accept action string"); if (acp) *acp = nfa->accept; } if (nfa->edge == EG_EPSILON) { /* next 0 */ if (nfa->next[0] && !test_add_set(stateset, nfastate(nfa->next[0]))) e_closure(nfa->next[0], stateset, acp); /* next 1 */ if (nfa->next[1] && !test_add_set(stateset, nfastate(nfa->next[1]))) e_closure(nfa->next[1], stateset, acp); } }
static int initial_e_closure(struct fsm *net) { struct fsm_state *fsm; int i,j; finals = xxcalloc(num_states, sizeof(_Bool)); num_start_states = 0; fsm = net->states; /* Create lookups for each state */ for (i=0,j=0; (fsm+i)->state_no != -1; i++) { if ((fsm+i)->final_state) { finals[(fsm+i)->state_no] = 1; } /* Add the start states as the initial set */ if ((op == SUBSET_TEST_STAR_FREE) || ((fsm+i)->start_state)) { if (*(e_table+((fsm+i)->state_no)) != mainloop) { num_start_states++; numss = (fsm+i)->state_no; *(e_table+((fsm+i)->state_no)) = mainloop; *(temp_move+j) = (fsm+i)->state_no; j++; } } } mainloop++; /* Memoize e-closure(u) */ if (epsilon_symbol != -1) { memoize_e_closure(fsm); } return(e_closure(j)); }
/* * recursion implemented computation for epsilon closure set from input * @dup if 1, output set realloced * otherwise, epsilon closure set is added into input * and return input * @accept accept state * @input start state for computing epsilon closure * * input only contains sstate */ struct set *epsilon_closure(struct set *input, struct accept **acp, int dup) { int start_state[MAXSTACKNFAS]; int state; struct set *output; /* * We cannot using e_closure(nfa, output), * because sstate is already in output. */ if (acp) *acp = NULL; if (!input) return NULL; /* set return value(epsilon closure set) */ output = dup ? dupset(input) : input; /* buffering start state int input */ for (startmember(input), state = 0; state < MAXSTACKNFAS; state++) { start_state[state] = nextmember(input); if (start_state[state] == -1) { state--; break; } } if (state >= MAXSTACKNFAS) errexit("state stack overflows"); /* computing epsilon closure of every start state in input set */ for (; state >= 0; state--) e_closure(statenfa(start_state[state]), output, acp); return output; }
static struct fsm *fsm_subset(struct fsm *net, int operation) { int T, U; if (net->is_deterministic == YES && operation != SUBSET_TEST_STAR_FREE) { return(net); } /* Export this var */ op = operation; fsm_count(net); num_states = net->statecount; deterministic = 1; init(net); nhash_init((num_states < 12) ? 6 : num_states/2); T = initial_e_closure(net); int_stack_clear(); if (deterministic == 1 && epsilon_symbol == -1 && num_start_states == 1 && numss == 0) { net->is_deterministic = YES; net->is_epsilon_free = YES; nhash_free(table, nhash_tablesize); xxfree(T_ptr); xxfree(e_table); xxfree(trans_list); xxfree(trans_array); xxfree(double_sigma_array); xxfree(single_sigma_array); xxfree(finals); xxfree(temp_move); xxfree(set_table); return(net); } if (operation == SUBSET_EPSILON_REMOVE && epsilon_symbol == -1) { net->is_epsilon_free = YES; nhash_free(table, nhash_tablesize); xxfree(T_ptr); xxfree(e_table); xxfree(trans_list); xxfree(trans_array); xxfree(double_sigma_array); xxfree(single_sigma_array); xxfree(finals); xxfree(temp_move); xxfree(set_table); return(net); } if (operation == SUBSET_TEST_STAR_FREE) { fsm_state_init(sigma_max(net->sigma)+1); star_free_mark = 0; } else { fsm_state_init(sigma_max(net->sigma)); xxfree(net->states); } /* init */ do { int i, j, tail, setsize, *theset, stateno, has_trans, minsym, next_minsym, trgt, symbol_in, symbol_out; struct trans_list *transitions; struct trans_array *tptr; fsm_state_set_current_state(T, (T_ptr+T)->finalstart, T == 0 ? 1 : 0); /* Prepare set */ setsize = (T_ptr+T)->size; theset = set_table+(T_ptr+T)->set_offset; minsym = INT_MAX; has_trans = 0; for (i = 0; i < setsize; i++) { stateno = *(theset+i); tptr = trans_array+stateno; tptr->tail = 0; if (tptr->size == 0) continue; if ((tptr->transitions)->inout < minsym) { minsym = (tptr->transitions)->inout; has_trans = 1; } } if (!has_trans) { /* close state */ fsm_state_end_state(); continue; } /* While set not empty */ for (next_minsym = INT_MAX; minsym != INT_MAX ; minsym = next_minsym, next_minsym = INT_MAX) { theset = set_table+(T_ptr+T)->set_offset; for (i = 0, j = 0 ; i < setsize; i++) { stateno = *(theset+i); tptr = trans_array+stateno; tail = tptr->tail; transitions = (tptr->transitions)+tail; while (tail < tptr->size && transitions->inout == minsym) { trgt = transitions->target; if (*(e_table+(trgt)) != mainloop) { *(e_table+(trgt)) = mainloop; *(temp_move+j) = trgt; j++; if (operation == SUBSET_EPSILON_REMOVE) { mainloop++; if ((U = e_closure(j)) != -1) { single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out); fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0); j = 0; } } } tail++; transitions++; } tptr->tail = tail; if (tail == tptr->size) continue; /* Check next minsym */ if (transitions->inout < next_minsym) { next_minsym = transitions->inout; } } if (operation == SUBSET_DETERMINIZE) { mainloop++; if ((U = e_closure(j)) != -1) { single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out); fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0); } } if (operation == SUBSET_TEST_STAR_FREE) { mainloop++; if ((U = e_closure(j)) != -1) { single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out); fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0); if (star_free_mark == 1) { //fsm_state_add_arc(T, maxsigma, maxsigma, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0); star_free_mark = 0; } } } } /* end state */ fsm_state_end_state(); } while ((T = next_unmarked()) != -1); /* wrapup() */ nhash_free(table, nhash_tablesize); xxfree(set_table); xxfree(T_ptr); xxfree(temp_move); xxfree(e_table); xxfree(trans_list); xxfree(trans_array); if (epsilon_symbol != -1) e_closure_free(); xxfree(double_sigma_array); xxfree(single_sigma_array); xxfree(finals); fsm_state_close(net); return(net); }