parent
6dfe22152c
commit
0fd1c9980b
@ -0,0 +1,68 @@ |
||||
use std::{cmp, fmt}; |
||||
|
||||
/// The representation of an s-expression parse error.
|
||||
pub struct Error { |
||||
/// The error message.
|
||||
pub message: &'static str, |
||||
/// The line number on which the error occurred.
|
||||
pub line: usize, |
||||
/// The column number on which the error occurred.
|
||||
pub column: usize, |
||||
/// The index in the given string which caused the error.
|
||||
pub index: usize, |
||||
} |
||||
|
||||
/// Since errors are the uncommon case, they're boxed. This keeps the size of
|
||||
/// structs down, which helps performance in the common case.
|
||||
///
|
||||
/// For example, an `ERes<()>` becomes 8 bytes, instead of the 24 bytes it would
|
||||
/// be if `Err` were unboxed.
|
||||
type Err = Box<Error>; |
||||
|
||||
/// Helps clean up type signatures, but shouldn't be exposed to the outside
|
||||
/// world.
|
||||
pub(crate) type ERes<T> = Result<T, Err>; |
||||
|
||||
impl fmt::Display for Error { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
||||
write!(f, "{}:{}: {}", self.line, self.column, self.message) |
||||
} |
||||
} |
||||
|
||||
impl fmt::Debug for Error { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
||||
write!(f, "{}", self) |
||||
} |
||||
} |
||||
|
||||
impl std::error::Error for Error {} |
||||
|
||||
pub(crate) fn get_line_and_column(s: &str, pos: usize) -> (usize, usize) { |
||||
let mut line: usize = 1; |
||||
let mut col: isize = -1; |
||||
for c in s.chars().take(pos + 1) { |
||||
if c == '\n' { |
||||
line += 1; |
||||
col = -1; |
||||
} else { |
||||
col += 1; |
||||
} |
||||
} |
||||
(line, cmp::max(col, 0) as usize) |
||||
} |
||||
|
||||
#[cold] |
||||
fn err_impl(message: &'static str, s: &str, pos: &usize) -> Err { |
||||
let (line, column) = get_line_and_column(s, *pos); |
||||
Box::new(Error { |
||||
message: message, |
||||
line: line, |
||||
column: column, |
||||
index: *pos, |
||||
}) |
||||
} |
||||
|
||||
/// Build an error with span information
|
||||
pub(crate) fn err<T>(message: &'static str, s: &str, pos: &usize) -> ERes<T> { |
||||
Err(err_impl(message, s, pos)) |
||||
} |
Loading…
Reference in new issue