| 2866 | } |
| 2867 | |
| 2868 | void Pattern::encode_dfa(DFA::State *start) |
| 2869 | { |
| 2870 | nop_ = 0; |
| 2871 | for (DFA::State *state = start; state != NULL; state = state->next) |
| 2872 | { |
| 2873 | // clamp max accept |
| 2874 | if (state->accept > Const::AMAX) |
| 2875 | state->accept = Const::AMAX; |
| 2876 | state->first = state->index = nop_; |
| 2877 | #if WITH_COMPACT_DFA == -1 |
| 2878 | Char hi = 0x00; |
| 2879 | for (DFA::State::Edges::const_iterator i = state->edges.begin(); i != state->edges.end(); ++i) |
| 2880 | { |
| 2881 | Char lo = i->first; |
| 2882 | if (lo == hi) |
| 2883 | hi = i->second.first + 1; |
| 2884 | ++nop_; |
| 2885 | if (is_meta(lo)) |
| 2886 | nop_ += i->second.first - lo; |
| 2887 | } |
| 2888 | // add final dead state (HALT opcode) only when needed, i.e. skip dead state if all chars 0-255 are already covered |
| 2889 | if (hi <= 0xff) |
| 2890 | { |
| 2891 | state->edges[hi] = DFA::State::Edge(0xff, static_cast<DFA::State*>(NULL)); // cast to appease MSVC 2010 |
| 2892 | ++nop_; |
| 2893 | } |
| 2894 | #else |
| 2895 | Char lo = 0xff; |
| 2896 | bool covered = false; |
| 2897 | for (DFA::State::Edges::const_reverse_iterator i = state->edges.rbegin(); i != state->edges.rend(); ++i) |
| 2898 | { |
| 2899 | Char hi = i->first; |
| 2900 | if (lo == hi) |
| 2901 | { |
| 2902 | if (i->second.first == 0x00) |
| 2903 | covered = true; |
| 2904 | else |
| 2905 | lo = i->second.first - 1; |
| 2906 | } |
| 2907 | ++nop_; |
| 2908 | if (is_meta(lo)) |
| 2909 | nop_ += hi - i->second.first; |
| 2910 | } |
| 2911 | // add final dead state (HALT opcode) only when needed, i.e. skip dead state if all chars 0-255 are already covered |
| 2912 | if (!covered) |
| 2913 | { |
| 2914 | state->edges[lo] = DFA::State::Edge(0x00, static_cast<DFA::State*>(NULL)); // cast to appease MSVC 2010 |
| 2915 | ++nop_; |
| 2916 | } |
| 2917 | #endif |
| 2918 | nop_ += static_cast<Index>(state->heads.size() + state->tails.size() + (state->accept > 0 || state->redo)); |
| 2919 | if (!valid_goto_index(nop_)) |
| 2920 | error(regex_error::exceeds_limits, rex_.size()); |
| 2921 | } |
| 2922 | if (nop_ > Const::LONG) |
| 2923 | { |
| 2924 | // over 64K opcodes: use 64-bit GOTO LONG opcodes |
| 2925 | nop_ = 0; |