summaryrefslogtreecommitdiff
path: root/src/locators/source.rs
blob: 20542e3816407f8ddd2845ca78ab00637d2ff1c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::path::PathBuf;


#[derive(Clone)]
pub struct SourceSpan {
    /// The source characters which this span represents.
    pub string: String,
    /// The location of this span in the merged source file.
    pub in_merged: SourceLocation,
    /// The location of this span in the original source file.
    pub in_source: Option<SourceLocation>,
}

impl SourceSpan {
    pub fn location(&self) -> &SourceLocation {
        self.in_source.as_ref().unwrap_or(&self.in_merged)
    }
}


#[derive(Clone)]
pub struct SourceLocation {
    /// File path the source was loaded from.
    pub path: Option<PathBuf>,
    /// Position of the first character of the string.
    pub start: Position,
    /// Position of the final character of the string.
    pub end: Position,
}

impl std::fmt::Display for SourceLocation {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let y = self.start.line + 1;
        let x = self.start.column + 1;
        match &self.path {
            Some(path) => write!(f, "{}:{y}:{x}", path.as_os_str().to_string_lossy()),
            None => write!(f, "<unknown>:{y}:{x}"),
        }
    }
}


#[derive(Clone, Copy)]
pub struct Position {
    /// The number of lines that precede this line in the file.
    pub line: usize,
    /// The number of characters that precede this character in the line.
    pub column: usize,
}

impl Position {
    pub fn to_next_char(&mut self) {
        self.column += 1;
    }

    pub fn to_next_line(&mut self) {
        self.line += 1;
        self.column = 0;
    }

    pub fn advance(&mut self, c: char) {
        match c {
            '\n' => self.to_next_line(),
            _ => self.to_next_char(),
        }
    }
}

impl std::fmt::Display for Position {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let y = self.line + 1;
        let x = self.column + 1;
        write!(f, "{y}:{x}")
    }
}