diff --git a/regex/priorityQueue.go b/regex/priorityQueue.go new file mode 100644 index 0000000..59592a9 --- /dev/null +++ b/regex/priorityQueue.go @@ -0,0 +1,76 @@ +package regex + +import "container/heap" + +// Implement a priority queue using container/heap + +const ( + min_priority int = iota + zerostate_priority + alternation_priority + kleene_priority + char_priority + max_priority +) + +func getPriority(state *nfaState) int { + if state.isKleene { + return kleene_priority + } else if state.isQuestion || state.isAlternation { + return alternation_priority + } else { + if state.isEmpty { + return zerostate_priority + } else { + return char_priority + } + } +} + +type priorQueueItem struct { + state *nfaState + priority int + index int +} + +type priorityQueue []*priorQueueItem + +func (pq priorityQueue) Len() int { + return len(pq) +} + +func (pq priorityQueue) Less(i, j int) bool { + if pq[i].priority == pq[j].priority { + return pq[i].index > pq[j].index + } + return pq[i].priority > pq[j].priority // We want max-heap, so we use greater-than +} + +func (pq priorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *priorityQueue) Push(x any) { + length := len(*pq) + item := x.(*priorQueueItem) + item.index = length + *pq = append(*pq, item) +} + +func (pq *priorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil + item.index = -1 + *pq = old[0 : n-1] + return item +} + +func (pq *priorityQueue) update(item *priorQueueItem, value *nfaState, priority int) { + item.state = value + item.priority = priority + heap.Fix(pq, item.index) +}