diff --git a/src/nfa/mcsheng_compile.cpp b/src/nfa/mcsheng_compile.cpp index 2d9658f2..2049fee0 100644 --- a/src/nfa/mcsheng_compile.cpp +++ b/src/nfa/mcsheng_compile.cpp @@ -617,7 +617,7 @@ void fill_in_succ_table_16(NFA *nfa, const dfa_info &info, #define MAX_SHERMAN_LIST_LEN 8 static -void addIfEarlier(set &dest, dstate_id_t candidate, +void addIfEarlier(flat_set &dest, dstate_id_t candidate, dstate_id_t max) { if (candidate < max) { dest.insert(candidate); @@ -625,13 +625,35 @@ void addIfEarlier(set &dest, dstate_id_t candidate, } static -void addSuccessors(set &dest, const dstate &source, +void addSuccessors(flat_set &dest, const dstate &source, u16 alphasize, dstate_id_t curr_id) { for (symbol_t s = 0; s < alphasize; s++) { addIfEarlier(dest, source.next[s], curr_id); } } +/* \brief Returns a set of states to search for a better daddy. */ +static +flat_set find_daddy_candidates(const dfa_info &info, + dstate_id_t curr_id) { + flat_set hinted; + + addIfEarlier(hinted, 0, curr_id); + addIfEarlier(hinted, info.raw.start_anchored, curr_id); + addIfEarlier(hinted, info.raw.start_floating, curr_id); + + // Add existing daddy and his successors, then search back one generation. + const u16 alphasize = info.impl_alpha_size; + dstate_id_t daddy = info.states[curr_id].daddy; + for (u32 level = 0; daddy && level < 2; level++) { + addIfEarlier(hinted, daddy, curr_id); + addSuccessors(hinted, info.states[daddy], alphasize, curr_id); + daddy = info.states[daddy].daddy; + } + + return hinted; +} + #define MAX_SHERMAN_SELF_LOOP 20 static @@ -671,22 +693,7 @@ void find_better_daddy(dfa_info &info, dstate_id_t curr_id, dstate_id_t best_daddy = 0; dstate &currState = info.states[curr_id]; - set hinted; /* set of states to search for a better daddy */ - addIfEarlier(hinted, 0, curr_id); - addIfEarlier(hinted, info.raw.start_anchored, curr_id); - addIfEarlier(hinted, info.raw.start_floating, curr_id); - - dstate_id_t mydaddy = currState.daddy; - if (mydaddy) { - addIfEarlier(hinted, mydaddy, curr_id); - addSuccessors(hinted, info.states[mydaddy], alphasize, curr_id); - dstate_id_t mygranddaddy = info.states[mydaddy].daddy; - if (mygranddaddy) { - addIfEarlier(hinted, mygranddaddy, curr_id); - addSuccessors(hinted, info.states[mygranddaddy], alphasize, - curr_id); - } - } + flat_set hinted = find_daddy_candidates(info, curr_id); for (const dstate_id_t &donor : hinted) { assert(donor < curr_id);