2018-09-02 22:10:11 -05:00
|
|
|
//! A parser combinator library with a focus on fully abortable parsing and error handling.
|
2018-09-03 00:05:32 -05:00
|
|
|
use std::fmt::Display;
|
2018-09-03 00:06:15 -05:00
|
|
|
use std::iter::Iterator;
|
2018-09-02 22:10:11 -05:00
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
/// A trait for types that can have an offset as a count of processed items.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub trait Offsetable {
|
2018-09-02 22:10:11 -05:00
|
|
|
fn get_offset(&self) -> usize;
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:05:32 -05:00
|
|
|
impl Offsetable for usize {
|
|
|
|
fn get_offset(&self) -> usize {
|
|
|
|
return *self;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A Cloneable Iterator that can report an offset as a count of processed Items.
|
|
|
|
pub trait InputIter: Iterator + Clone + Offsetable {}
|
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
/// The custom error type for use in `Result::{Fail, Abort}`.
|
|
|
|
/// Stores a wrapped err that must implement Display as well as an offset and
|
|
|
|
/// an optional cause.
|
2018-09-03 00:05:32 -05:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Error<E: Display> {
|
|
|
|
err: E,
|
|
|
|
offset: usize,
|
|
|
|
cause: Option<Box<Error<E>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Display> Error<E> {
|
2018-09-03 00:09:57 -05:00
|
|
|
/// Constructs a new Error with an offset and no cause.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub fn new<S: Offsetable>(err: E, offset: &S) -> Self {
|
2018-09-03 00:06:15 -05:00
|
|
|
Error {
|
2018-09-03 00:05:32 -05:00
|
|
|
err: err,
|
|
|
|
offset: offset.get_offset(),
|
|
|
|
cause: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
/// Constructs a new Error with an offset and a cause.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub fn caused_by<S: Offsetable>(err: E, offset: &S, cause: Self) -> Self {
|
2018-09-03 00:06:15 -05:00
|
|
|
Error {
|
2018-09-03 00:05:32 -05:00
|
|
|
err: err,
|
|
|
|
offset: offset.get_offset(),
|
|
|
|
cause: Some(Box::new(cause)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
/// Returns the contained err.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub fn get_err<'a>(&'a self) -> &'a E {
|
|
|
|
&self.err
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
/// Returns `Some(cause)` if there is one, None otherwise.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub fn get_cause<'a>(&'a self) -> Option<&'a Error<E>> {
|
|
|
|
match self.cause {
|
|
|
|
Some(ref cause) => Some(cause),
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:09:57 -05:00
|
|
|
// Returns the offset at which this Error happened.
|
2018-09-03 00:05:32 -05:00
|
|
|
pub fn get_offset(&self) -> usize {
|
|
|
|
self.offset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Display> Display for Error<E> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
|
|
|
|
try!(write!(f, "{}", self.err));
|
|
|
|
match self.cause {
|
|
|
|
Some(ref c) => write!(f, "\n\tCaused By:{}", c),
|
2018-09-03 00:06:15 -05:00
|
|
|
None => Ok(()),
|
2018-09-03 00:05:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-02 22:10:11 -05:00
|
|
|
/// The result of a parsing attempt.
|
|
|
|
#[derive(Debug)]
|
2018-09-03 00:05:32 -05:00
|
|
|
pub enum Result<I: InputIter, O, E: Display> {
|
2018-09-02 22:10:11 -05:00
|
|
|
/// Complete represents a successful match.
|
|
|
|
Complete(I, O),
|
|
|
|
/// Incomplete indicates input ended before a match could be completed.
|
|
|
|
/// It contains the offset at which the input ended before a match could be completed.
|
|
|
|
Incomplete(usize),
|
|
|
|
/// Fail represents a failed match.
|
2018-09-03 00:05:32 -05:00
|
|
|
Fail(Error<E>),
|
2018-09-02 22:10:11 -05:00
|
|
|
/// Abort represents a match failure that the parser cannot recover from.
|
2018-09-03 00:05:32 -05:00
|
|
|
Abort(Error<E>),
|
2018-09-02 22:10:11 -05:00
|
|
|
}
|
|
|
|
|
2018-09-03 00:05:32 -05:00
|
|
|
impl<I: InputIter, O, E: Display> Result<I, O, E> {
|
2018-09-02 22:10:11 -05:00
|
|
|
/// Returns true if the Result is Complete.
|
|
|
|
pub fn is_complete(&self) -> bool {
|
|
|
|
if let &Result::Complete(_, _) = self {
|
2018-09-03 00:06:15 -05:00
|
|
|
return true;
|
2018-09-02 22:10:11 -05:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-09-03 00:06:15 -05:00
|
|
|
/// Returns true if the Result is Incomoplete.
|
2018-09-02 22:10:11 -05:00
|
|
|
pub fn is_incomplete(&self) -> bool {
|
|
|
|
if let &Result::Incomplete(_) = self {
|
2018-09-03 00:06:15 -05:00
|
|
|
return true;
|
2018-09-02 22:10:11 -05:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-03 00:06:15 -05:00
|
|
|
|
|
|
|
/// Returns true if the Result is Fail.
|
2018-09-02 22:10:11 -05:00
|
|
|
pub fn is_fail(&self) -> bool {
|
|
|
|
if let &Result::Fail(_) = self {
|
2018-09-03 00:06:15 -05:00
|
|
|
return true;
|
2018-09-02 22:10:11 -05:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-03 00:06:15 -05:00
|
|
|
|
|
|
|
/// Returns true if the Result is Abort.
|
2018-09-02 22:10:11 -05:00
|
|
|
pub fn is_abort(&self) -> bool {
|
|
|
|
if let &Result::Abort(_) = self {
|
2018-09-03 00:06:15 -05:00
|
|
|
return true;
|
2018-09-02 22:10:11 -05:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub use iter::SliceIter;
|
|
|
|
|
|
|
|
#[macro_use]
|
|
|
|
pub mod macros;
|
|
|
|
pub mod iter;
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2018-09-03 00:06:15 -05:00
|
|
|
mod test;
|