pub_just/
token.rs

1use super::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
4pub struct Token<'src> {
5  pub column: usize,
6  pub kind: TokenKind,
7  pub length: usize,
8  pub line: usize,
9  pub offset: usize,
10  pub path: &'src Path,
11  pub src: &'src str,
12}
13
14impl<'src> Token<'src> {
15  pub fn lexeme(&self) -> &'src str {
16    &self.src[self.offset..self.offset + self.length]
17  }
18
19  pub fn error(&self, kind: CompileErrorKind<'src>) -> CompileError<'src> {
20    CompileError::new(*self, kind)
21  }
22}
23
24impl<'src> ColorDisplay for Token<'src> {
25  fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
26    let width = if self.length == 0 { 1 } else { self.length };
27
28    let line_number = self.line.ordinal();
29    match self.src.lines().nth(self.line) {
30      Some(line) => {
31        let mut i = 0;
32        let mut space_column = 0;
33        let mut space_line = String::new();
34        let mut space_width = 0;
35        for c in line.chars() {
36          if c == '\t' {
37            space_line.push_str("    ");
38            if i < self.column {
39              space_column += 4;
40            }
41            if i >= self.column && i < self.column + width {
42              space_width += 4;
43            }
44          } else {
45            if i < self.column {
46              space_column += UnicodeWidthChar::width(c).unwrap_or(0);
47            }
48            if i >= self.column && i < self.column + width {
49              space_width += UnicodeWidthChar::width(c).unwrap_or(0);
50            }
51            space_line.push(c);
52          }
53          i += c.len_utf8();
54        }
55        let line_number_width = line_number.to_string().len();
56        writeln!(
57          f,
58          "{:width$}{} {}:{}:{}",
59          "",
60          color.context().paint("——▶"),
61          self.path.display(),
62          line_number,
63          self.column.ordinal(),
64          width = line_number_width
65        )?;
66        writeln!(
67          f,
68          "{:width$} {}",
69          "",
70          color.context().paint("│"),
71          width = line_number_width
72        )?;
73        writeln!(
74          f,
75          "{} {space_line}",
76          color.context().paint(&format!("{line_number} │"))
77        )?;
78        write!(
79          f,
80          "{:width$} {}",
81          "",
82          color.context().paint("│"),
83          width = line_number_width
84        )?;
85        write!(
86          f,
87          " {0:1$}{2}{3:^<4$}{5}",
88          "",
89          space_column,
90          color.prefix(),
91          "",
92          space_width.max(1),
93          color.suffix()
94        )?;
95      }
96      None => {
97        if self.offset != self.src.len() {
98          write!(
99            f,
100            "internal error: Error has invalid line number: {line_number}"
101          )?;
102        }
103      }
104    }
105
106    Ok(())
107  }
108}