metrale_grammar/earley/
queue.rs1use std::collections::VecDeque;
9
10use ahash::AHashSet;
11
12use super::state::ParserState;
13
14#[derive(Debug, Default)]
23pub struct ProcessQueue {
24 queue: VecDeque<ParserState>,
25 visited: AHashSet<ParserState>,
26}
27
28impl ProcessQueue {
29 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn clear_visited(&mut self) {
37 self.visited.clear();
38 }
39
40 pub fn is_visited(&self, state: &ParserState) -> bool {
42 self.visited.contains(state)
43 }
44
45 pub fn enqueue(&mut self, state: ParserState) -> bool {
48 if self.visited.insert(state) {
49 self.queue.push_back(state);
50 true
51 } else {
52 false
53 }
54 }
55
56 pub fn mark_visited(&mut self, state: ParserState) -> bool {
61 self.visited.insert(state)
62 }
63
64 pub fn pop(&mut self) -> Option<ParserState> {
66 self.queue.pop_front()
67 }
68
69 pub fn is_empty(&self) -> bool {
71 self.queue.is_empty()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 fn st(id: i32) -> ParserState {
80 ParserState::new(id, 0, 0, 0, 0)
81 }
82
83 #[test]
84 fn enqueue_dedups() {
85 let mut q = ProcessQueue::new();
86 assert!(q.enqueue(st(1)));
87 assert!(!q.enqueue(st(1)));
88 assert!(q.enqueue(st(2)));
89 assert_eq!(q.pop(), Some(st(1)));
90 assert_eq!(q.pop(), Some(st(2)));
91 assert_eq!(q.pop(), None);
92 }
93
94 #[test]
95 fn fifo_order() {
96 let mut q = ProcessQueue::new();
97 for i in 0..5 {
98 q.enqueue(st(i));
99 }
100 for i in 0..5 {
101 assert_eq!(q.pop(), Some(st(i)));
102 }
103 }
104
105 #[test]
106 fn clear_visited_allows_reenqueue() {
107 let mut q = ProcessQueue::new();
108 q.enqueue(st(1));
109 q.pop();
110 assert!(!q.enqueue(st(1)));
111 q.clear_visited();
112 assert!(q.enqueue(st(1)));
113 }
114
115 #[test]
116 fn mark_visited_blocks_enqueue() {
117 let mut q = ProcessQueue::new();
118 assert!(q.mark_visited(st(7)));
119 assert!(!q.mark_visited(st(7)));
120 assert!(!q.enqueue(st(7)));
121 assert!(q.is_visited(&st(7)));
122 }
123}