-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherror.rs
79 lines (70 loc) · 2.61 KB
/
error.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
use std::path::PathBuf;
use chumsky::error::{Rich, RichReason};
use codesnake::{Block, CodeWidth, Label, LineIndex};
use yansi::Paint;
/// Take the errors output by the Chumsky parser and print them.
pub fn print_syntax_errors(errs: Vec<Rich<char>>, path: &PathBuf, src: &str) {
let idx = LineIndex::new(&src);
let errs = build_syntax_errors(errs, path, &idx);
errs.iter().for_each(|err| err.print());
}
fn build_syntax_errors<'src>(
errs: Vec<Rich<char>>,
path: &PathBuf,
idx: &'src LineIndex<'src>
) -> Vec<CompilerErr<'src>> {
let mut res = vec![];
for err in errs {
let reason = err.reason();
match reason {
RichReason::ExpectedFound { expected, found } => {
let msg = format!(
"[{:#?}]: invalid syntax, expected {}",
path.file_name().unwrap(),
expected.iter()
.fold(String::new(), |mut acc, e| {
acc.push_str(&e.to_string());
acc
})
);
let label = if let Some(token) = found {
Label::new(err.span().into_range())
.with_text(format!("found {}", token.into_inner()))
.with_style(|s| s.red().to_string())
} else {
Label::new(err.span().into_range())
.with_style(|s| s.red().to_string())
};
let block = Block::new(&idx, [label]).unwrap();
let block = block.map_code(|c| CodeWidth::new(c, c.len()));
res.push(CompilerErr { msg, block });
}
RichReason::Custom(msg) => {
let msg = format!(
"[{:#?}]: {}",
path.file_name().unwrap(),
msg
);
let label = Label::new(err.span().into_range())
.with_text("here".to_owned())
.with_style(|s| s.red().to_string());
let block = Block::new(&idx, [label]).unwrap();
let block = block.map_code(|c| CodeWidth::new(c, c.len()));
res.push(CompilerErr { msg, block });
}
RichReason::Many(_) => todo!(),
}
}
res
}
struct CompilerErr<'a> {
msg: String,
block: Block<CodeWidth<&'a str>, String>,
}
impl<'a> CompilerErr<'a> {
pub fn print(&self) {
eprintln!("{}{}", self.block.prologue(), self.msg);
eprint!("{}", self.block);
eprintln!("{}", self.block.epilogue());
}
}