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
use lalrpop_util::ParseError;
use lalrpop_util::ParseError::*;
pub fn simplify_parse_error<'input>(
error: ParseError<usize, (usize, &'input str), ()>
) -> ParseError<usize, String, ()>
{
match error {
InvalidToken { location } => InvalidToken { location },
UnrecognizedToken { token, expected } => {
let token = token.map(|(start, (_, tok), end)| (start, tok.into(), end));
UnrecognizedToken {token, expected}
}
ExtraToken { token: (start, (_, tok), end) } => {
let token = (start, tok.into(), end);
ExtraToken { token }
},
User { error } => User { error },
}
}
fn code_error(code: &str, tok_pos: usize) {
let code = format!("\n\n{}", code);
let code = code.lines().collect::<Vec<_>>();
let mut pos: isize = 0;
for (i, lines) in (&code[..]).windows(3).enumerate() {
if pos + lines[2].len() as isize >= tok_pos as isize {
let arrow_len = (tok_pos as isize) - (pos - 6);
let omit_left = if arrow_len > 60 { arrow_len as usize - 60 } else { 0 };
let print_line = |n: usize, mut line: &str| {
if line.len() >= omit_left {
line = &line[omit_left..];
if line.len() > 70 {
line = &line[..70];
}
}
line = line.trim_right();
if !line.is_empty() {
println!("{:>3} | {}", n, line);
} else {
println!("{:>3} |", n);
}
};
if i > 1 {
print_line(i - 1, &lines[0]);
}
if i > 0 {
print_line(i, &lines[1]);
}
print_line(i + 1, &lines[2]);
if arrow_len > 0 {
let arrow_len = arrow_len as usize - omit_left;
println!("{}^", "~".repeat(arrow_len));
}
return;
}
pos += (lines[2].len() as isize) + 1;
}
}
pub fn print_parse_error(code: &str, err: &ParseError<usize, String, ()>) {
match *err {
ParseError::InvalidToken { location: loc } => {
println!("Error: Invalid token:");
code_error(code, loc);
}
ParseError::UnrecognizedToken {
token: Some((loc, ref tok, _)),
..
} => {
println!("Error: Unrecognized token `{}`:", tok);
code_error(code, loc);
}
ParseError::ExtraToken { token: (loc, ref tok, _) } => {
println!("Error: Extra token `{}`:", tok);
code_error(code, loc);
}
_ => (),
}
}