-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy patherror.rs
108 lines (86 loc) · 2.86 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
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 std::fmt;
/// Error type used by the tokenizer and the parser internally.
#[derive(Debug)]
pub enum Error {
UnexpectedEndOfProgram,
UnexpectedToken {
start: usize,
end: usize,
},
}
/// Error type returned by `parser::parse`. This error will include
/// owned `String` of the source code where the error occured, so
/// that a meaningful error can be printed out.
pub enum ParseError {
UnexpectedEndOfProgram,
UnexpectedToken {
source: String,
start: usize,
end: usize,
},
}
impl fmt::Debug for ParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl fmt::Display for ParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ParseError::UnexpectedEndOfProgram => {
write!(f, "Unexpected end of program")?
},
ParseError::UnexpectedToken {
ref source,
start,
end
} => {
let (lineno, line) = source[..start]
.lines()
.enumerate()
.last()
.unwrap_or((0, ""));
let colno = line.chars().count();
let token_len = source[start..end].chars().count();
writeln!(f, "Unexpected token at {}:{}\n", lineno + 1, colno + 1)?;
let iter = source
.lines()
.enumerate()
.skip_while(|&(index, _)| index < lineno.saturating_sub(2))
.take_while(|&(index, _)| index < lineno + 3);
let width = log10(lineno + 3);
for (index, line) in iter {
if index == lineno {
writeln!(f, "> {0:1$} | {2}", index+1, width, line)?;
for _ in 0..width {
write!(f, " ")?;
}
write!(f, " | ")?;
for _ in 0..colno {
write!(f, " ")?;
}
for _ in 0..token_len {
write!(f, "^")?;
}
write!(f, "\n")?;
} else {
writeln!(f, "{0:1$} | {2}", index+1, width+2, line)?;
}
}
},
}
Ok(())
}
}
fn log10(mut num: usize) -> usize {
let mut log = 0;
while num > 0 {
log += 1;
num /= 10;
}
log
}
pub type Result<T> = ::std::result::Result<T, Error>;
pub type ParseResult<T> = ::std::result::Result<T, ParseError>;