0 | ||| Utilities for the Knuth-Morris-Pratt string searching algorithm.
11 | %hide Data.Buffer.Core.get
12 | %hide Data.Buffer.Core.set
13 | %hide Data.ByteString.Search.DFA.Types.DFAStateSpace.states
14 | %hide Data.List.Elem.get
18 | ||| Mutable storage for the KMP border table.
19 | |||
20 | ||| The table contains one entry for every DFA state. Both table indices and
21 | ||| stored border values are represented by `DFAState`, so their bounds are
22 | ||| established once and carried as erased evidence.
23 | |||
24 | ||| The underlying storage is an Idris primitive array.
25 | |||
31 | ||| A constructed KMP border table together with the DFA state space to
32 | ||| which its indices and values belong.
33 | |||
34 | ||| Packaging the state space with the table allows `automaton` to reuse the
35 | ||| exact same state-space witness rather than independently reconstructing
36 | ||| and validating the pattern's state count.
37 | |||
44 | ||| Allocate an uninitialized KMP border table.
45 | |||
46 | ||| The table contains exactly one entry for each DFA state.
47 | |||
48 | export
55 | ||| Read a border value from the KMP border table.
56 | |||
57 | ||| The supplied index is already a valid `DFAState`, so no dynamic bounds
58 | ||| validation is required. The stored result is itself another valid DFA
59 | ||| state.
60 | |||
69 | ||| Write a border value to the KMP border table.
70 | |||
71 | ||| Both the destination index and stored border value are already bounded by
72 | ||| the same DFA state space, so no `Fin` conversion or runtime bounds check
73 | ||| is required.
74 | |||
84 | ||| Construct the successor of a DFA state during DFA preprocessing.
85 | |||
86 | ||| This check occurs only while constructing preprocessing tables. It is
87 | ||| never executed by the target-scanning DFA hot path.
88 | |||
96 | ||| Computes the suffix-oriented KMP border table for a given pattern.
97 | |||
98 | ||| Each entry associated with DFA state `i` stores the length of the longest
99 | ||| proper prefix of `pattern[0..i-1]` that is also a suffix.
100 | |||
101 | ||| Unlike the previous implementation, table indices and border values are
102 | ||| represented directly by bounded `DFAState` values rather than `Nat`
103 | ||| values indexed through `Fin`.
104 | |||
105 | ||| Consequently, accesses to the border table require no `tryNatToFin` or
106 | ||| equivalent dynamic table-bounds conversion.
107 | |||
108 | ||| The result packages the table together with its `DFAStateSpace`, allowing
109 | ||| construction of the DFA transition table to reuse exactly the same state
110 | ||| space.
111 | |||
112 | ||| Example: "ANPANMAN"
113 | |||
114 | ||| Indices: 0 1 2 3 4 5 6 7 8
115 | ||| Borders: 0 0 0 0 1 2 0 1 2
116 | |||
117 | export
132 | where
133 | mutual
134 | ||| Continue resolving the border for the current pattern position.
135 | |||
136 | ||| On a matching pattern byte, both the current pattern position and
137 | ||| border position advance by one. On a mismatch, the previous border
138 | ||| value is read directly from the bounded KMP border table.
139 | |||
172 | ||| Process the next pattern position while constructing the KMP border
173 | ||| table.
174 | |||
175 | ||| `i` and `j` are already valid DFA states, so border-table indexing
176 | ||| requires no dynamic conversion to `Fin`.
177 | |||