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}