forked from MightyPork/crsn
sexp: move error defs to a module
This commit is contained in:
@@ -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))
|
||||||
|
}
|
||||||
@@ -9,14 +9,17 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cmp;
|
|
||||||
use std::error;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::{self, FromStr};
|
use std::str::{self, FromStr};
|
||||||
|
|
||||||
|
pub use error::Error;
|
||||||
|
use error::{ERes, err};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
|
||||||
/// A single data element in an s-expression. Floats are excluded to ensure
|
/// A single data element in an s-expression. Floats are excluded to ensure
|
||||||
/// atoms may be used as keys in ordered and hashed data structures.
|
/// atoms may be used as keys in ordered and hashed data structures.
|
||||||
///
|
///
|
||||||
@@ -38,75 +41,6 @@ pub enum Sexp {
|
|||||||
List(Vec<Sexp>),
|
List(Vec<Sexp>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for Error {
|
|
||||||
fn description(&self) -> &str { self.message }
|
|
||||||
fn cause(&self) -> Option<&dyn error::Error> { None }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn err<T>(message: &'static str, s: &str, pos: &usize) -> ERes<T> {
|
|
||||||
Err(err_impl(message, s, pos))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn atom_of_string(s: String) -> Atom {
|
fn atom_of_string(s: String) -> Atom {
|
||||||
match FromStr::from_str(&s) {
|
match FromStr::from_str(&s) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use super::error::get_line_and_column;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hello_world() {
|
fn test_hello_world() {
|
||||||
|
|||||||
Reference in New Issue
Block a user