-
Notifications
You must be signed in to change notification settings - Fork 499
/
token.rs
108 lines (102 loc) · 2.77 KB
/
token.rs
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
pub(crate) struct Token<'src> {
pub(crate) column: usize,
pub(crate) kind: TokenKind,
pub(crate) length: usize,
pub(crate) line: usize,
pub(crate) offset: usize,
pub(crate) path: &'src Path,
pub(crate) src: &'src str,
}
impl<'src> Token<'src> {
pub(crate) fn lexeme(&self) -> &'src str {
&self.src[self.offset..self.offset + self.length]
}
pub(crate) fn error(&self, kind: CompileErrorKind<'src>) -> CompileError<'src> {
CompileError::new(*self, kind)
}
}
impl ColorDisplay for Token<'_> {
fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
let width = if self.length == 0 { 1 } else { self.length };
let line_number = self.line.ordinal();
match self.src.lines().nth(self.line) {
Some(line) => {
let mut i = 0;
let mut space_column = 0;
let mut space_line = String::new();
let mut space_width = 0;
for c in line.chars() {
if c == '\t' {
space_line.push_str(" ");
if i < self.column {
space_column += 4;
}
if i >= self.column && i < self.column + width {
space_width += 4;
}
} else {
if i < self.column {
space_column += UnicodeWidthChar::width(c).unwrap_or(0);
}
if i >= self.column && i < self.column + width {
space_width += UnicodeWidthChar::width(c).unwrap_or(0);
}
space_line.push(c);
}
i += c.len_utf8();
}
let line_number_width = line_number.to_string().len();
writeln!(
f,
"{:width$}{} {}:{}:{}",
"",
color.context().paint("——▶"),
self.path.display(),
line_number,
self.column.ordinal(),
width = line_number_width
)?;
writeln!(
f,
"{:width$} {}",
"",
color.context().paint("│"),
width = line_number_width
)?;
writeln!(
f,
"{} {space_line}",
color.context().paint(&format!("{line_number} │"))
)?;
write!(
f,
"{:width$} {}",
"",
color.context().paint("│"),
width = line_number_width
)?;
write!(
f,
" {0:1$}{2}{3:^<4$}{5}",
"",
space_column,
color.prefix(),
"",
space_width.max(1),
color.suffix()
)?;
}
None => {
if self.offset != self.src.len() {
write!(
f,
"internal error: Error has invalid line number: {line_number}"
)?;
}
}
}
Ok(())
}
}