Skip to main content

parol_runtime/lexer/
rng.rs

1use std::ops::{Add, Deref, Range};
2
3/// This trait should be implemented by generated AST data types
4pub trait ToSpan {
5    /// Calculates the span of the implementing item
6    fn span(&self) -> Span;
7}
8
9/// The Span type is a customized Range that can handle extension of ranges.
10/// Span and std::ops::Range are convertible into each other.
11#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
12pub struct Span(Range<usize>);
13
14impl Span {
15    /// Returns a new Span instance with the given start end end indices
16    pub fn new(start: usize, end: usize) -> Span {
17        Span(Range { start, end })
18    }
19
20    /// Generates a union of both ranges.
21    /// It handles the special empty range.
22    /// Empty ranges are null elements for `extend` operations:
23    ///
24    /// R1 + Empty = R1
25    /// Empty + R1 = R1
26    /// Empty + Empty = Empty
27    ///
28    pub fn extend(&self, right: &Span) -> Span {
29        if self.is_empty() {
30            right.clone()
31        } else if right.is_empty() {
32            self.clone()
33        } else {
34            Span::new(self.start, right.end)
35        }
36    }
37
38    /// Same as [Span::extend] but consuming RHS
39    pub fn extend_to(&self, right: Span) -> Span {
40        if self.is_empty() {
41            right
42        } else if right.is_empty() {
43            self.clone()
44        } else {
45            Span::new(self.start, right.end)
46        }
47    }
48
49    // pub fn from_slice<'a, T>(slc: &'a [T]) -> Self
50    // where
51    //     &'a T: Into<Span>,
52    // {
53    //     if slc.is_empty() {
54    //         Span::default()
55    //     } else {
56    //         let first: &T = slc.first().unwrap();
57    //         let rng: Span = first.into();
58    //         let last: &T = slc.last().unwrap();
59    //         let span = last.into();
60    //         rng.extend(&span)
61    //     }
62    // }
63}
64
65impl Deref for Span {
66    type Target = Range<usize>;
67
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}
72
73impl Add for Span {
74    type Output = Self;
75
76    /// Same as [Span::extend] but consuming LHS and RHS
77    fn add(self, rhs: Self) -> Self::Output {
78        if self.is_empty() {
79            rhs
80        } else if rhs.is_empty() {
81            self
82        } else {
83            // Addition is commutative, so the order is irrelevant for the result
84            Span::new(
85                std::cmp::min(self.start, rhs.start),
86                std::cmp::max(self.end, rhs.end),
87            )
88        }
89    }
90}
91
92impl From<Span> for Range<usize> {
93    fn from(val: Span) -> Range<usize> {
94        val.0
95    }
96}
97
98impl From<&Span> for Range<usize> {
99    fn from(val: &Span) -> Range<usize> {
100        val.0.clone()
101    }
102}
103
104impl From<Range<usize>> for Span {
105    fn from(val: Range<usize>) -> Span {
106        Span(val)
107    }
108}
109
110impl From<&Range<usize>> for Span {
111    fn from(val: &Range<usize>) -> Span {
112        Span(val.clone())
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119    use std::ops::Range;
120
121    #[test]
122    fn test_extend() {
123        let rng1 = Span::new(0, 5);
124        let rng2 = Span::new(12, 15);
125        let extended_rng = Span::new(0, 15);
126        assert_eq!(extended_rng, rng1.extend_to(rng2));
127        let empty_rng = Span::default();
128        assert!(empty_rng.is_empty());
129        assert_eq!(empty_rng, empty_rng.extend(&empty_rng));
130        assert_eq!(rng1, empty_rng.extend(&rng1));
131        assert_eq!(rng1, rng1.extend(&empty_rng));
132    }
133
134    #[test]
135    fn test_add() {
136        // With non-overlapping ranges
137        assert_eq!(Span::new(0, 15), Span::new(0, 5) + Span::new(12, 15));
138        assert_eq!(Span::new(0, 15), Span::new(12, 15) + Span::new(0, 5));
139
140        // With overlapping ranges
141        assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(3, 7));
142        assert_eq!(Span::new(0, 7), Span::new(3, 7) + Span::new(0, 5));
143
144        // With smallest overlapping ranges
145        assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(4, 7));
146        assert_eq!(Span::new(0, 7), Span::new(4, 7) + Span::new(0, 5));
147
148        // With adjoining ranges
149        assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(5, 7));
150        assert_eq!(Span::new(0, 7), Span::new(5, 7) + Span::new(0, 5));
151
152        // With empty ranges
153        assert_eq!(Span::default(), Span::default() + Span::default());
154        assert_eq!(Span::new(0, 5), Span::default() + Span::new(0, 5));
155        assert_eq!(Span::new(0, 5), Span::new(0, 5) + Span::default());
156    }
157
158    #[test]
159    fn test_conversions() {
160        let span: Span = Range { start: 1, end: 2 }.into();
161        assert_eq!(Span::new(1, 2), span);
162        let span: Span = (&Range { start: 2, end: 3 }).into();
163        assert_eq!(Span::new(2, 3), span);
164
165        let range: Range<usize> = Span::new(1, 2).into();
166        assert_eq!(Range { start: 1, end: 2 }, range);
167        let range: Range<usize> = (&Span::new(2, 3)).into();
168        assert_eq!(Range { start: 2, end: 3 }, range);
169    }
170
171    #[test]
172    fn test_string_application() {
173        let s = "Löwe 老虎 Léopard";
174        // Bytes:
175        // 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
176        // 4c c3 b6 77 65 20 e8 80 81 e8 99 8e 20 4c c3 a9 6f 70 61 72 64
177        // Chars:
178        // 0  1     2  3  4  5        6        7  8  9     10 11 12 13 14
179        // L  ö     w  e  _  老       虎       _  L  é     o  p  a  r  d
180        assert_eq!(21, s.len());
181        // for (i, b) in s.bytes().enumerate() {
182        //     print!("{i}: 0x{b:x}");
183        // }
184        assert_eq!(15, s.chars().count());
185        // for (i, c) in s.chars().enumerate() {
186        //     println!("{i}: {c}");
187        // }
188        assert_eq!("老", &s[6..9]);
189        assert_eq!("虎", &s[9..12]);
190        assert_eq!("L", &s[13..14]);
191
192        assert_eq!("老", &s[Range { start: 6, end: 9 }]);
193        assert_eq!("虎", &s[Into::<Range<usize>>::into(Span::new(9, 12))]);
194        assert_eq!("L", &s[Into::<Range<usize>>::into(Span::new(13, 14))]);
195    }
196}