Skip to main content

lady_deirdre/syntax/
captures.rs

1////////////////////////////////////////////////////////////////////////////////
2// This file is part of "Lady Deirdre", a compiler front-end foundation       //
3// technology.                                                                //
4//                                                                            //
5// This work is proprietary software with source-available code.              //
6//                                                                            //
7// To copy, use, distribute, or contribute to this work, you must agree to    //
8// the terms of the General License Agreement:                                //
9//                                                                            //
10// https://github.com/Eliah-Lakhin/lady-deirdre/blob/master/EULA.md           //
11//                                                                            //
12// The agreement grants a Basic Commercial License, allowing you to use       //
13// this work in non-commercial and limited commercial products with a total   //
14// gross revenue cap. To remove this commercial limit for one of your         //
15// products, you must acquire a Full Commercial License.                      //
16//                                                                            //
17// If you contribute to the source code, documentation, or related materials, //
18// you must grant me an exclusive license to these contributions.             //
19// Contributions are governed by the "Contributions" section of the General   //
20// License Agreement.                                                         //
21//                                                                            //
22// Copying the work in parts is strictly forbidden, except as permitted       //
23// under the General License Agreement.                                       //
24//                                                                            //
25// If you do not or cannot agree to the terms of this Agreement,              //
26// do not use this work.                                                      //
27//                                                                            //
28// This work is provided "as is", without any warranties, express or implied, //
29// except where such disclaimers are legally invalid.                         //
30//                                                                            //
31// Copyright (c) 2024 Ilya Lakhin (Илья Александрович Лахин).                 //
32// All rights reserved.                                                       //
33////////////////////////////////////////////////////////////////////////////////
34
35use std::{
36    fmt::{Display, Formatter},
37    iter::{Flatten, FusedIterator, Map},
38};
39
40use crate::{
41    lexis::{Site, SiteSpan, TokenRef},
42    syntax::{AbstractNode, NodeRef, PolyRef, RefKind},
43    units::CompilationUnit,
44};
45
46/// A polymorphic key that is either a string or a numeric key.
47#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
48pub enum Key<'a> {
49    /// A string key. Usually denotes the enum variant field name.
50    Name(&'a str),
51
52    /// A numeric key. Usually denotes the index of the variant field.
53    Index(usize),
54}
55
56impl<'a> Display for Key<'a> {
57    #[inline(always)]
58    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
59        match self {
60            Self::Name(key) => Display::fmt(key, formatter),
61            Self::Index(key) => Display::fmt(key, formatter),
62        }
63    }
64}
65
66impl<'a> From<&'a str> for Key<'a> {
67    #[inline(always)]
68    fn from(value: &'a str) -> Self {
69        Self::Name(value)
70    }
71}
72
73impl<'a> From<usize> for Key<'a> {
74    #[inline(always)]
75    fn from(value: usize) -> Self {
76        Self::Index(value)
77    }
78}
79
80/// A set of the node children grouped together.
81///
82/// During the syntax tree node parsing, the parser usually captures
83/// individual tokens and descends into other rules, capturing their node
84/// products.
85///
86/// The parser groups these objects' [TokenRef] and [NodeRef] references
87/// together, and puts these groups under the Node's enum variant fields.
88///
89/// Lady Deirdre refers to these groups as "captures".
90///
91/// The "Single*" variants of this enum represent captures when the parser
92/// captures exactly one child (`foo: bar`), or zero or one
93/// child (`foo: bar?`).
94///
95/// The "Many*" variants of this enum represent captures when the parser
96/// captures an array of children (`foo: bar*`).
97///
98/// Any captured references within this object could be
99/// [nil](PolyRef::is_nil) references, and the arrays of children could be empty
100/// arrays.
101#[derive(Clone, PartialEq, Eq, Hash, Debug)]
102pub enum Capture<'a> {
103    /// A single node capture.
104    ///
105    /// Represents zero or one node (`foo: Bar?`), or exactly one
106    /// node (`foo: Bar`).
107    ///
108    /// If the parsing rule didn't capture anything, the value is
109    /// [NodeRef::nil].
110    SingleNode(&'a NodeRef),
111
112    /// A capture of an array of nodes.
113    ///
114    /// Represents zero or many nodes (`foo: Bar*`), or one or many nodes
115    /// (`foo: Bar+`).
116    ManyNodes(&'a Vec<NodeRef>),
117
118    /// A single token capture.
119    ///
120    /// Represents zero or one token (`foo: $Bar?`), or exactly one
121    /// token (`foo: $Bar`).
122    ///
123    /// If the parsing rule didn't capture anything, the value is
124    /// [TokenRef::nil].
125    SingleToken(&'a TokenRef),
126
127    /// A capture of an array of tokens.
128    ///
129    /// Represents zero or many tokens (`foo: $Bar*`), or one or many tokens
130    /// (`foo: $Bar+`).
131    ManyTokens(&'a Vec<TokenRef>),
132}
133
134impl<'a> From<&'a NodeRef> for Capture<'a> {
135    #[inline(always)]
136    fn from(capture: &'a NodeRef) -> Self {
137        Self::SingleNode(capture)
138    }
139}
140
141impl<'a> From<&'a Vec<NodeRef>> for Capture<'a> {
142    #[inline(always)]
143    fn from(capture: &'a Vec<NodeRef>) -> Self {
144        Self::ManyNodes(capture)
145    }
146}
147
148impl<'a> From<&'a TokenRef> for Capture<'a> {
149    #[inline(always)]
150    fn from(capture: &'a TokenRef) -> Self {
151        Self::SingleToken(capture)
152    }
153}
154
155impl<'a> From<&'a Vec<TokenRef>> for Capture<'a> {
156    #[inline(always)]
157    fn from(capture: &'a Vec<TokenRef>) -> Self {
158        Self::ManyTokens(capture)
159    }
160}
161
162impl<'a> IntoIterator for Capture<'a> {
163    type Item = &'a dyn PolyRef;
164    type IntoIter = CaptureIntoIter<'a>;
165
166    #[inline(always)]
167    fn into_iter(self) -> Self::IntoIter {
168        CaptureIntoIter::new(self)
169    }
170}
171
172impl<'a> Capture<'a> {
173    /// Describes captured children kind.
174    #[inline(always)]
175    pub fn kind(&self) -> RefKind {
176        match self {
177            Capture::SingleNode(..) | Capture::ManyNodes(..) => RefKind::Node,
178            Capture::SingleToken(..) | Capture::ManyTokens(..) => RefKind::Token,
179        }
180    }
181
182    /// Returns true, if the Capture represents a "Single*" child.
183    #[inline(always)]
184    pub fn is_single(&self) -> bool {
185        match self {
186            Capture::SingleNode(..) | Capture::SingleToken(..) => true,
187            Capture::ManyTokens(..) | Capture::ManyNodes(..) => false,
188        }
189    }
190
191    /// Returns true, if the Capture represents "Many*" children.
192    #[inline(always)]
193    pub fn is_many(&self) -> bool {
194        !self.is_single()
195    }
196
197    /// Returns the total number of children in this Capture (including the
198    /// [nil](PolyRef::is_nil) entities).
199    #[inline(always)]
200    pub fn len(&self) -> usize {
201        match self {
202            Capture::SingleNode(..) | Capture::SingleToken(..) => 1,
203            Capture::ManyNodes(capture) => capture.len(),
204            Capture::ManyTokens(capture) => capture.len(),
205        }
206    }
207
208    /// Returns true, if `self.len() == 0`.
209    #[inline(always)]
210    pub fn is_empty(&self) -> bool {
211        match self {
212            Capture::SingleNode(..) | Capture::SingleToken(..) => false,
213            Capture::ManyNodes(capture) => capture.is_empty(),
214            Capture::ManyTokens(capture) => capture.is_empty(),
215        }
216    }
217
218    /// Returns a child within this Capture by `index`.
219    ///
220    /// If the child is inside the "Single*" capture, the only valid index is 0.
221    ///
222    /// Returns None if the index is out of bounds.
223    #[inline(always)]
224    pub fn get(&self, index: usize) -> Option<&'a dyn PolyRef> {
225        match self {
226            Capture::SingleNode(capture) if index == 0 => Some(*capture),
227            Capture::SingleToken(capture) if index == 0 => Some(*capture),
228            Capture::ManyNodes(capture) => capture.get(index).map(|capture| capture as _),
229            Capture::ManyTokens(capture) => capture.get(index).map(|capture| capture as _),
230            _ => None,
231        }
232    }
233
234    /// Returns the same as `self.get(0)`.
235    #[inline(always)]
236    pub fn first(&self) -> Option<&'a dyn PolyRef> {
237        match self {
238            Capture::SingleNode(capture) => Some(*capture),
239            Capture::ManyNodes(capture) => capture.first().map(|capture| capture as _),
240            Capture::SingleToken(capture) => Some(*capture),
241            Capture::ManyTokens(capture) => capture.first().map(|capture| capture as _),
242        }
243    }
244
245    /// Returns the same as `self.get(self.len() - 1)`
246    /// or None if the Capture is empty.
247    #[inline(always)]
248    pub fn last(&self) -> Option<&'a dyn PolyRef> {
249        match self {
250            Capture::SingleNode(capture) => Some(*capture),
251            Capture::ManyNodes(capture) => capture.last().map(|capture| capture as _),
252            Capture::SingleToken(capture) => Some(*capture),
253            Capture::ManyTokens(capture) => capture.last().map(|capture| capture as _),
254        }
255    }
256
257    /// Computes the [site span](SiteSpan) from the [first child](Self::first)
258    /// start site to the [last child](Self::last) end site.
259    ///
260    /// If the Capture is empty, or the corresponding child instance does not
261    /// exist in the `unit`, or the corresponding sites cannot be inferred
262    /// (e.g., if the Node's [span](AbstractNode::span) returns None),
263    /// the function returns None.
264    pub fn site_span(&self, unit: &impl CompilationUnit) -> Option<SiteSpan> {
265        let start_site = self.start(unit)?;
266        let end_site = self.end(unit)?;
267
268        Some(start_site..end_site)
269    }
270
271    /// Computes the start [site](Site) of the first child in this Capture.
272    ///
273    /// If the Capture is empty, or the corresponding child instance does not
274    /// exist in the `unit`, or the corresponding site cannot be inferred
275    /// (e.g., if the Node's [start](AbstractNode::start) returns None),
276    /// the function returns None.
277    pub fn start(&self, unit: &impl CompilationUnit) -> Option<Site> {
278        match self {
279            Capture::SingleNode(capture) => (*capture).deref(unit)?.start(unit),
280            Capture::ManyNodes(capture) => capture.first()?.deref(unit)?.start(unit),
281            Capture::SingleToken(capture) => Some(capture.chunk(unit)?.start()),
282            Capture::ManyTokens(capture) => Some(capture.first()?.chunk(unit)?.start()),
283        }
284    }
285
286    /// Computes the end [site](Site) of the last child in this Capture.
287    ///
288    /// If the Capture is empty, or the corresponding child instance does not
289    /// exist in the `unit`, or the corresponding site cannot be inferred
290    /// (e.g., if the Node's [end](AbstractNode::end) returns None),
291    /// the function returns None.
292    pub fn end(&self, unit: &impl CompilationUnit) -> Option<Site> {
293        match self {
294            Capture::SingleNode(capture) => (*capture).deref(unit)?.end(unit),
295            Capture::ManyNodes(capture) => capture.last()?.deref(unit)?.end(unit),
296            Capture::SingleToken(capture) => Some(capture.chunk(unit)?.end()),
297            Capture::ManyTokens(capture) => Some(capture.last()?.chunk(unit)?.end()),
298        }
299    }
300}
301
302/// An owned iterator over the [Capture] children.
303///
304/// This object is created by the `into_iter` function of the Capture.
305pub struct CaptureIntoIter<'a> {
306    front: usize,
307    back: usize,
308    capture: Capture<'a>,
309}
310
311impl<'a> Iterator for CaptureIntoIter<'a> {
312    type Item = &'a dyn PolyRef;
313
314    #[inline(always)]
315    fn next(&mut self) -> Option<Self::Item> {
316        if self.front == self.back {
317            return None;
318        }
319
320        let index = self.front;
321
322        self.front += 1;
323
324        self.capture.get(index)
325    }
326
327    #[inline(always)]
328    fn size_hint(&self) -> (usize, Option<usize>) {
329        let remaining = self.back - self.front;
330        (remaining, Some(remaining))
331    }
332}
333
334impl<'a> DoubleEndedIterator for CaptureIntoIter<'a> {
335    #[inline(always)]
336    fn next_back(&mut self) -> Option<Self::Item> {
337        if self.front == self.back {
338            return None;
339        }
340
341        self.back -= 1;
342
343        self.capture.get(self.back)
344    }
345}
346
347impl<'a> ExactSizeIterator for CaptureIntoIter<'a> {}
348
349impl<'a> FusedIterator for CaptureIntoIter<'a> {}
350
351impl<'a> CaptureIntoIter<'a> {
352    #[inline(always)]
353    fn new(capture: Capture<'a>) -> Self {
354        Self {
355            front: 0,
356            back: capture.len(),
357            capture,
358        }
359    }
360}
361
362/// An iterator over all [captures](Capture) of the [Node](crate::syntax::Node)
363/// interface.
364///
365/// This object is created by the [AbstractNode::captures_iter] function.
366pub struct CapturesIter<'a, N: AbstractNode + ?Sized> {
367    front: usize,
368    back: usize,
369    node: &'a N,
370}
371
372impl<'a, N: AbstractNode + ?Sized> Iterator for CapturesIter<'a, N> {
373    type Item = Capture<'a>;
374
375    #[inline(always)]
376    fn next(&mut self) -> Option<Self::Item> {
377        if self.front == self.back {
378            return None;
379        }
380
381        let index = self.front;
382
383        self.front += 1;
384
385        self.node.capture(Key::Index(index))
386    }
387
388    #[inline(always)]
389    fn size_hint(&self) -> (usize, Option<usize>) {
390        let remaining = self.back - self.front;
391        (remaining, Some(remaining))
392    }
393}
394
395impl<'a, N: AbstractNode + ?Sized> DoubleEndedIterator for CapturesIter<'a, N> {
396    #[inline(always)]
397    fn next_back(&mut self) -> Option<Self::Item> {
398        if self.front == self.back {
399            return None;
400        }
401
402        self.back -= 1;
403
404        self.node.capture(Key::Index(self.back))
405    }
406}
407
408impl<'a, N: AbstractNode + ?Sized> ExactSizeIterator for CapturesIter<'a, N> {}
409
410impl<'a, N: AbstractNode + ?Sized> FusedIterator for CapturesIter<'a, N> {}
411
412impl<'a, N: AbstractNode + ?Sized> CapturesIter<'a, N> {
413    #[inline(always)]
414    pub(super) fn new(node: &'a N) -> Self {
415        Self {
416            front: 0,
417            back: node.captures_len(),
418            node,
419        }
420    }
421}
422
423/// An iterator over all children of the [Node](crate::syntax::Node)
424/// interface.
425///
426/// This object is created by the [AbstractNode::children_iter] function.
427#[repr(transparent)]
428pub struct ChildrenIter<'a, N: AbstractNode + ?Sized> {
429    inner: Flatten<Map<CapturesIter<'a, N>, fn(Capture) -> CaptureIntoIter>>,
430}
431
432impl<'a, N: AbstractNode + ?Sized> Iterator for ChildrenIter<'a, N> {
433    type Item = &'a dyn PolyRef;
434
435    #[inline(always)]
436    fn next(&mut self) -> Option<Self::Item> {
437        self.inner.next()
438    }
439}
440
441impl<'a, N: AbstractNode + ?Sized> DoubleEndedIterator for ChildrenIter<'a, N> {
442    #[inline(always)]
443    fn next_back(&mut self) -> Option<Self::Item> {
444        self.inner.next_back()
445    }
446}
447
448impl<'a, N: AbstractNode + ?Sized> FusedIterator for ChildrenIter<'a, N> {}
449
450impl<'a, N: AbstractNode + ?Sized> ChildrenIter<'a, N> {
451    #[inline(always)]
452    pub(super) fn new(node: &'a N) -> Self {
453        fn capture_into_iter(capture: Capture) -> CaptureIntoIter {
454            capture.into_iter()
455        }
456
457        Self {
458            inner: CapturesIter::new(node)
459                .map(capture_into_iter as _)
460                .flatten(),
461        }
462    }
463}