minimalist_grammar_parser/parsing/
trees.rs1use std::{borrow::Borrow, cmp::Ordering};
2
3use itertools::Itertools;
4use petgraph::graph::NodeIndex;
5
6use crate::Direction;
7use bitvec::prelude::*;
8use thin_vec::ThinVec;
9
10use super::RuleIndex;
11
12pub const N_CHUNKS: u32 = 128 / usize::BITS;
13type IndexArray = BitArray<[usize; N_CHUNKS as usize], Lsb0>;
14
15pub const MAX_STEPS: usize = (usize::BITS * N_CHUNKS) as usize;
17
18#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
22pub struct GornIndex {
23 index: IndexArray,
24 size: usize,
25}
26
27impl std::fmt::Debug for GornIndex {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 f.debug_list()
30 .entries(
31 self.index[..self.size]
32 .iter()
33 .map(|x| {
34 let x: bool = *x.as_ref();
35 let x: u8 = x.into();
36 x
37 })
38 .collect::<Vec<_>>(),
39 )
40 .finish()
41 }
42}
43
44impl std::fmt::Display for GornIndex {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(
47 f,
48 "{}",
49 self.index[..self.size]
50 .iter()
51 .map(|x| if *x { "1" } else { "0" })
52 .join("")
53 )
54 }
55}
56
57impl PartialOrd for GornIndex {
58 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63impl Ord for GornIndex {
64 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
65 self.index[..self.size].cmp(&other.index[..other.size])
66 }
67}
68
69impl Iterator for GornIterator {
70 type Item = Direction;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 if self.pos < self.gorn.size {
74 let d = self.gorn.index[self.pos];
75 self.pos += 1;
76 Some(d.into())
77 } else {
78 None
79 }
80 }
81}
82
83#[derive(Default, Clone, PartialEq, Eq, Hash)]
84pub struct GornIterator {
85 pos: usize,
86 gorn: GornIndex,
87}
88
89impl IntoIterator for GornIndex {
90 type Item = Direction;
91
92 type IntoIter = GornIterator;
93
94 fn into_iter(self) -> Self::IntoIter {
95 GornIterator { pos: 0, gorn: self }
96 }
97}
98
99impl<T> From<T> for GornIndex
100where
101 T: Borrow<[Direction]>,
102{
103 fn from(value: T) -> Self {
104 let value = value.borrow();
105 let size = value.len();
106 let mut index = IndexArray::default();
107 value
108 .iter()
109 .enumerate()
110 .for_each(|(i, &x)| index.set(i, x.into()));
111 GornIndex { index, size }
112 }
113}
114impl From<GornIndex> for Vec<Direction> {
115 fn from(value: GornIndex) -> Self {
116 value
117 .index
118 .into_iter()
119 .take(value.size)
120 .map(std::convert::Into::into)
121 .collect()
122 }
123}
124
125impl GornIndex {
126 #[inline]
128 #[must_use]
129 pub fn clone_push(&self, d: Direction) -> Self {
130 let mut v = *self;
131 v.index.set(v.size, d.into());
132 v.size += 1;
133 v
134 }
135
136 pub fn push(&mut self, d: Direction) {
138 self.index.set(self.size, d.into());
139 self.size += 1;
140 }
141
142 #[must_use]
145 pub fn new(d: Direction) -> Self {
146 let mut v = GornIndex {
147 size: 0,
148 index: IndexArray::default(),
149 };
150 v.index.set(v.size, d.into());
151 v.size += 1;
152 v
153 }
154
155 #[must_use]
157 pub fn depth(&self) -> usize {
158 self.size
159 }
160
161 #[must_use]
163 pub fn is_ancestor_of(&self, x: GornIndex) -> bool {
164 self.size < x.size && (self.into_iter().zip(x).all(|(x, y)| x == y))
165 }
166
167 #[must_use]
169 pub fn is_parent_of(&self, x: GornIndex) -> bool {
170 x.size > 0 && self.size == (x.size - 1) && (self.into_iter().zip(x).all(|(x, y)| x == y))
171 }
172
173 #[must_use]
175 pub fn comes_before(&self, x: &GornIndex) -> bool {
176 matches!(GornIndex::infix_order(self, x), Ordering::Less)
177 }
178
179 pub(crate) fn infix_order(x: &GornIndex, y: &GornIndex) -> Ordering {
180 for (a, b) in (*x).into_iter().zip(*y) {
181 match (a, b) {
182 (Direction::Left, Direction::Right) => return Ordering::Less,
183 (Direction::Right, Direction::Left) => return Ordering::Greater,
184 _ => (),
185 }
186 }
187 match x.size.cmp(&y.size) {
188 Ordering::Less => {
189 if y.index[x.size] {
190 Ordering::Less
193 } else {
194 Ordering::Greater
195 }
196 }
197 Ordering::Greater => {
198 if x.index[y.size] {
199 Ordering::Greater
200 } else {
201 Ordering::Less
202 }
203 }
204 Ordering::Equal => Ordering::Equal,
205 }
206 }
207
208 #[must_use]
216 pub fn len(&self) -> usize {
217 self.size
218 }
219
220 #[must_use]
222 pub fn is_empty(&self) -> bool {
223 self.size == 0
224 }
225}
226
227#[derive(Debug, Copy, Clone, PartialEq, Eq)]
228pub(crate) struct FutureTree {
229 pub node: NodeIndex,
230 pub index: GornIndex,
231 pub id: RuleIndex,
232}
233
234impl PartialOrd for FutureTree {
235 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
236 Some(self.cmp(other))
237 }
238}
239
240impl Ord for FutureTree {
241 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
242 match self.index.cmp(&other.index) {
243 core::cmp::Ordering::Equal => {}
244 ord => return ord,
245 }
246 self.node.cmp(&other.node)
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
251pub(crate) struct ParseMoment {
252 pub tree: FutureTree,
253 pub stolen_head: StolenHead,
254 pub movers: ThinVec<FutureTree>,
255}
256
257impl ParseMoment {
258 pub fn least_index(&self) -> &GornIndex {
259 let mut least = &self.tree.index;
260 for m in &self.movers {
261 if m.index < *least {
262 least = &m.index;
263 }
264 }
265 least
266 }
267
268 pub fn new(tree: FutureTree, movers: ThinVec<FutureTree>, stolen_head: StolenHead) -> Self {
269 ParseMoment {
270 tree,
271 stolen_head,
272 movers,
273 }
274 }
275
276 pub fn should_be_scanned(&self) -> bool {
277 self.movers.is_empty()
278 }
279}
280
281impl PartialOrd for ParseMoment {
282 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
283 Some(self.cmp(other))
284 }
285}
286
287impl Ord for ParseMoment {
288 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
289 self.stolen_head
290 .cmp(&other.stolen_head)
291 .then(self.least_index().cmp(other.least_index()))
292 }
293}
294
295#[derive(Debug, Copy, Clone, PartialEq, Eq)]
296pub enum StolenHead {
297 None,
298 Root(usize),
299 Affix {
300 rule: RuleIndex,
301 direction: Direction,
302 stealer_id: usize,
303 is_done: bool,
304 },
305}
306
307impl PartialOrd for StolenHead {
308 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
309 Some(self.cmp(other))
310 }
311}
312
313impl Ord for StolenHead {
314 fn cmp(&self, other: &Self) -> Ordering {
315 match (self, other) {
316 (StolenHead::Affix { .. }, StolenHead::None | StolenHead::Root(_)) => Ordering::Less,
317 (StolenHead::None | StolenHead::Root(_), StolenHead::Affix { .. }) => Ordering::Greater,
318 _ => Ordering::Equal,
319 }
320 }
321}
322
323impl StolenHead {
324 pub(crate) fn new_stolen(rule: RuleIndex, direction: Direction, stealer_id: usize) -> Self {
325 StolenHead::Affix {
326 rule,
327 direction,
328 stealer_id,
329 is_done: false,
330 }
331 }
332
333 pub(crate) fn with_done(self) -> Self {
334 match self {
335 StolenHead::None => StolenHead::None,
336 StolenHead::Root(x) => StolenHead::Root(x),
337 StolenHead::Affix {
338 rule,
339 direction,
340 stealer_id,
341 ..
342 } => StolenHead::Affix {
343 rule,
344 direction,
345 stealer_id,
346 is_done: true,
347 },
348 }
349 }
350
351 pub(crate) fn with_not_done(self) -> Self {
352 match self {
353 StolenHead::None | StolenHead::Root(_) => panic!("These can't be finished!"),
354 StolenHead::Affix {
355 rule,
356 direction,
357 stealer_id,
358 ..
359 } => StolenHead::Affix {
360 rule,
361 direction,
362 stealer_id,
363 is_done: false,
364 },
365 }
366 }
367}