| 3855 | } |
| 3856 | |
| 3857 | void Pattern::analyze_dfa(DFA::State *start) |
| 3858 | { |
| 3859 | DBGLOG("BEGIN Pattern::analyze_dfa()"); |
| 3860 | cut_ = 0; |
| 3861 | lbk_ = 0; |
| 3862 | lbm_ = 0; |
| 3863 | cbk_.reset(); |
| 3864 | fst_.reset(); |
| 3865 | std::set<DFA::State*> start_states; |
| 3866 | if (start->accept == 0) |
| 3867 | { |
| 3868 | // Analyze DFA with a breadth-first search to produce a set of new starting states for more accurate match prediction. |
| 3869 | // A good starting state is one with few edges (chars); we want select a new set of starting states with few edges. |
| 3870 | // We make a DFA graph s-t cut with few edges from which to predict matches. |
| 3871 | // We also cut away edges to states that precede the new starting states, because these repetitions can be ignored. |
| 3872 | // Characters on removed edges are recorded so we can look back to find a full match with the regex matcher. |
| 3873 | // We name an edge a "backedge" when it points to a state before the new starting states, i.e. a loop, not necessarily a cycle. |
| 3874 | bool backedge = false; // if we found a loop backedge during breadth-first search |
| 3875 | bool has_backedge = false; // if we found a loop backedge after the last cut to a state after the cut, not before the cut |
| 3876 | uint16_t fin_depth = 0xffff; // shortest distance to a final state |
| 3877 | uint16_t fin_count = 0; // number of characters to the final states cut off that are not included in the current cut |
| 3878 | std::set<DFA::State*> states; // current set of breadth-first-search states |
| 3879 | std::set<DFA::State*> fin_states; // set of states to final states not included in the current cut |
| 3880 | reflex::ORanges<Char> chars; // set of characters on edges before the current cut, the lookback set |
| 3881 | // current cut |
| 3882 | bool cut_backedge = false; // if we found a loop backedge for the current cut |
| 3883 | uint16_t cut_depth = 0; // breadth-first search depth of the current cut |
| 3884 | uint16_t cut_fin_depth = 0; // shortest distance to a final state for the current cut |
| 3885 | uint16_t cut_fin_count = 0; // number of characters to the final states |
| 3886 | uint16_t cut_span = 0; // length of the current cut, from the cut to the last state searched |
| 3887 | uint16_t cut_count = 0xffff; // number of characters at the start of the current cut |
| 3888 | uint16_t min_count = 0xffff; // min count of characters over the span of the current cut |
| 3889 | uint16_t max_count = 0; // max of number of characters over the span of the current cut |
| 3890 | uint8_t max_freq = 0; // max character frequency over the span of the current cut |
| 3891 | std::set<DFA::State*> cut_states; // set of states positioned on the left of the cut |
| 3892 | std::set<DFA::State*> cut_fin_states; // set of states to final states not included in the current cut |
| 3893 | reflex::ORanges<Char> cut_chars; // set of characters on edges before the current cut, the lookback set |
| 3894 | // best cut saved |
| 3895 | bool best_cut_backedge = false; |
| 3896 | uint16_t best_cut_depth = 0; |
| 3897 | uint16_t best_cut_fin_depth = 0xffff; |
| 3898 | uint16_t best_cut_fin_count = 0; |
| 3899 | uint16_t best_cut_span = 0; |
| 3900 | uint16_t best_cut_count = 0xffff; |
| 3901 | uint16_t best_min_count = 0xffff; |
| 3902 | std::set<DFA::State*> best_cut_states; |
| 3903 | std::set<DFA::State*> best_cut_fin_states; |
| 3904 | reflex::ORanges<Char> best_cut_chars; |
| 3905 | // start analyzing the DFA from the start state using a breadth-first search following forward edges to non-visited states |
| 3906 | start->first = 1; |
| 3907 | states.insert(states.begin(), start); |
| 3908 | std::set<DFA::State*> next_states; |
| 3909 | reflex::ORanges<uint16_t> next_chars; |
| 3910 | bool searching = false; |
| 3911 | for (uint16_t depth = 0; depth < DFA::MAX_DEPTH; ++depth) |
| 3912 | { |
| 3913 | next_states.clear(); |
| 3914 | next_chars.clear(); |