rush_parser/
span.rs

1use std::fmt::Debug;
2
3#[derive(Clone, Copy, PartialEq, Eq)]
4pub struct Span<'src> {
5    pub start: Location<'src>,
6    pub end: Location<'src>,
7}
8
9impl<'src> Span<'src> {
10    pub fn new(start: Location<'src>, end: Location<'src>) -> Self {
11        Self { start, end }
12    }
13
14    pub fn dummy() -> Self {
15        Self {
16            start: Location::new(""),
17            end: Location::new(""),
18        }
19    }
20
21    pub fn is_empty(&self) -> bool {
22        self.start.byte_idx == self.end.byte_idx
23    }
24}
25
26impl Debug for Span<'_> {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match f.alternate() {
29            true => write!(
30                f,
31                "{}:{}..{}:{}",
32                self.start.line, self.start.column, self.end.line, self.end.column
33            ),
34            false => write!(f, "{}..{}", self.start.byte_idx, self.end.byte_idx),
35        }
36    }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct Location<'src> {
41    pub line: usize,
42    pub column: usize,
43    pub char_idx: usize,
44    pub byte_idx: usize,
45    pub path: &'src str,
46}
47
48impl<'src> Location<'src> {
49    pub fn new(path: &'src str) -> Self {
50        Self {
51            line: 1,
52            column: 1,
53            char_idx: 0,
54            byte_idx: 0,
55            path,
56        }
57    }
58}
59
60impl<'src> Location<'src> {
61    pub fn advance(&mut self, newline: bool, byte_idx_offset: usize) {
62        self.char_idx += 1;
63        self.byte_idx += byte_idx_offset;
64        if newline {
65            self.line += 1;
66            self.column = 1;
67        } else {
68            self.column += 1;
69        }
70    }
71
72    pub fn until(self, end: Location<'src>) -> Span {
73        Span { start: self, end }
74    }
75}