diff --git a/src/combinators.rs b/src/combinators.rs index fff0c4e..a6455d5 100644 --- a/src/combinators.rs +++ b/src/combinators.rs @@ -1,29 +1,32 @@ //! Contains combinators that can assemble other matchers or combinators into more complex grammars. -use super::{InputIter, Error, Result}; +use super::{Error, InputIter, Result}; /// Turns a `Result` to it's inverse. -/// +/// /// `Result::Fail` becomes `Result::Complete` and `Result::Complete` becomes `Result::Fail`. /// You must pass in an iterator at the appropriate spot for the next combinator /// to start at. -/// +/// /// The `not!` macro provides syntactic sugar for using this combinator properly. -pub fn not(i: I, result: Result) -> Result +pub fn not(i: I, result: Result) -> Result where I: InputIter, { - match result { - Result::Complete(i, _) => Result::Fail(Error::new("Matched on input when we shouldn't have.".to_string(), &i)), - Result::Abort(e) => Result::Abort(e), - Result::Incomplete(offset) => Result::Incomplete(offset), - Result::Fail(_) => Result::Complete(i, ()), - } + match result { + Result::Complete(i, _) => Result::Fail(Error::new( + "Matched on input when we shouldn't have.".to_string(), + &i, + )), + Result::Abort(e) => Result::Abort(e), + Result::Incomplete(offset) => Result::Incomplete(offset), + Result::Fail(_) => Result::Complete(i, ()), + } } /// Turns a matcher into it's inverse, only succeeding if the the matcher returns a Fail. /// Does not consume it's input and only returns (). -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// # use abortable_parser::iter; @@ -56,7 +59,7 @@ macro_rules! not { } /// Checks the given matcher without consuming the input. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// # use abortable_parser::iter; @@ -103,13 +106,13 @@ macro_rules! run { } /// Maps a `Result::Fail` to a `Result::Abort`. -/// +/// /// It leaves the rest of the Result variants untouched. -/// +/// /// The `must!` macro provided syntactice sugar for using this combinator. pub fn must(result: Result) -> Result where - I: InputIter + I: InputIter, { match result { Result::Complete(i, o) => Result::Complete(i, o), @@ -117,25 +120,24 @@ where Result::Fail(e) => Result::Abort(e), Result::Abort(e) => Result::Abort(e), } - } /// Turns `Result::Fail` into `Result::Abort`. -/// +/// /// Allows you to turn any parse failure into a hard abort of the parser. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; /// # use abortable_parser::Result; /// # use std::convert::From; /// # fn main() { -/// +/// /// let iter: iter::SliceIter = "foo".into(); -/// +/// /// let tok = must!(iter, text_token!("foo")); /// # assert!(tok.is_complete()); -/// +/// /// let fail = must!(iter, text_token!("bar")); /// # assert!(fail.is_abort()); /// # } @@ -175,25 +177,25 @@ macro_rules! wrap_err { } /// Traps a `Result::Abort` and converts it into a `Result::Fail`. -/// +/// /// This is the semantic inverse of `must`. /// /// The `trap!` macro provides syntactic sugar for using this combinator. pub fn trap(result: Result) -> Result where - I: InputIter + I: InputIter, { - match result { - Result::Complete(i, o) => Result::Complete(i, o), - Result::Incomplete(offset) => Result::Incomplete(offset), - Result::Fail(e) => Result::Fail(e), - Result::Abort(e) => Result::Fail(e), - } + match result { + Result::Complete(i, o) => Result::Complete(i, o), + Result::Incomplete(offset) => Result::Incomplete(offset), + Result::Fail(e) => Result::Fail(e), + Result::Abort(e) => Result::Fail(e), + } } /// Turns `Result::Abort` into `Result::Fail` allowing you to trap and then convert any `Result::Abort` /// into a normal Fail. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -217,9 +219,9 @@ macro_rules! trap { } /// Turns `Result::Fail` or `Result::Incomplete` into `Result::Abort`. -/// +/// /// You must specify the error message to use in case the matcher is incomplete. -/// +/// /// The must_complete! macro provides syntactic sugar for using this combinator. pub fn must_complete(result: Result, msg: M) -> Result where @@ -227,17 +229,17 @@ where M: Into, { match result { - Result::Complete(i, o) => Result::Complete(i, o), - Result::Incomplete(ref offset) => Result::Abort(Error::new(msg, offset)), - Result::Fail(e) => Result::Abort(e), - Result::Abort(e) => Result::Abort(e), - } + Result::Complete(i, o) => Result::Complete(i, o), + Result::Incomplete(ref offset) => Result::Abort(Error::new(msg, offset)), + Result::Fail(e) => Result::Abort(e), + Result::Abort(e) => Result::Abort(e), + } } /// Turns `Result::Fail` and `Result::Incomplete` into `Result::Abort`. -/// +/// /// You must specify the error message to use in case the matcher is incomplete. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -260,7 +262,7 @@ macro_rules! must_complete { } /// Captures a sequence of sub parsers output. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -279,13 +281,13 @@ macro_rules! must_complete { /// if let Result::Complete(_, o) = result { /// assert_eq!("foo", o.0); /// assert_eq!("bar", o.1); -/// } +/// } /// # } /// ``` /// /// Or alternatively rather than a tuple as the output you can return a single /// expression. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// # use abortable_parser::iter; @@ -306,7 +308,7 @@ macro_rules! must_complete { /// } /// # } /// ``` -/// +/// /// The output from this combinator must be indicated by parentheses. #[macro_export] macro_rules! do_each { @@ -361,7 +363,7 @@ macro_rules! do_each { } /// Returns the output of the first sub parser to succeed. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -462,11 +464,11 @@ macro_rules! either { } /// Maps a `Result` to be optional. -/// +/// /// `Result::Fail` maps to None and `Result::Complete` maps to Some. The rest of the /// `Result` variants are left untouched. You must pass in the iterator that the /// next matcher should use in the event of a fail. -/// +/// /// The `optional!` macro provides some syntactice sugar for using this combinator /// properly. pub fn optional(iter: I, result: Result) -> Result> @@ -474,25 +476,19 @@ where I: InputIter, { match result { - Result::Complete(i, o) => { - Result::Complete(i, Some(o)) - } - // Incomplete could still work possibly parse. - Result::Incomplete(i) => { - Result::Incomplete(i) - } - // Fail just means it didn't match. - Result::Fail(_) => { - Result::Complete(iter, None) - }, - // Aborts are hard failures that the parser can't recover from. - Result::Abort(e) => Result::Abort(e), - } + Result::Complete(i, o) => Result::Complete(i, Some(o)), + // Incomplete could still work possibly parse. + Result::Incomplete(i) => Result::Incomplete(i), + // Fail just means it didn't match. + Result::Fail(_) => Result::Complete(iter, None), + // Aborts are hard failures that the parser can't recover from. + Result::Abort(e) => Result::Abort(e), + } } /// Treats a sub parser as optional. It returns Some(output) for a successful match /// and None for failures. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -526,7 +522,7 @@ macro_rules! optional { /// Runs a single matcher repeating 0 or mre times and returns a possibly empty /// vector of the parsed results. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -585,7 +581,7 @@ macro_rules! repeat { } /// Convenience macro for looking for a specific text token in a byte input stream. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// use abortable_parser::iter; @@ -697,20 +693,16 @@ macro_rules! discard { } /// Matches and returns any ascii charactar whitespace byte. -pub fn ascii_ws<'a, I: InputIter>(mut i: I) -> Result { +pub fn ascii_ws<'a, I: InputIter>(mut i: I) -> Result { match i.next() { - Some(b) => { - match b { - b'\r' => Result::Complete(i, *b), - b'\n' => Result::Complete(i, *b), - b'\t' => Result::Complete(i, *b), - b' ' => Result::Complete(i, *b), - _ => Result::Fail(Error::new("Not whitespace", &i)), - } + Some(b) => match b { + b'\r' => Result::Complete(i, *b), + b'\n' => Result::Complete(i, *b), + b'\t' => Result::Complete(i, *b), + b' ' => Result::Complete(i, *b), + _ => Result::Fail(Error::new("Not whitespace", &i)), }, - None => { - Result::Fail(Error::new("Unexpected End Of Input", &i)) - } + None => Result::Fail(Error::new("Unexpected End Of Input", &i)), } } @@ -734,9 +726,9 @@ pub fn eoi(i: I) -> Result { /// text_token!("token") /// ); /// ``` -/// +/// /// You can also specify that the function is public if so desired. -/// +/// /// ``` /// # #[macro_use] extern crate abortable_parser; /// # use abortable_parser::iter::StrIter; @@ -766,4 +758,4 @@ macro_rules! make_fn { make_fn!(pub $name<$i, $o>, run!($rule)) }; -} \ No newline at end of file +} diff --git a/src/integration_tests.rs b/src/integration_tests.rs index 339769d..f76d454 100644 --- a/src/integration_tests.rs +++ b/src/integration_tests.rs @@ -1,7 +1,8 @@ - use iter::StrIter; - use super::{Result, eoi, ascii_ws}; - - make_fn!(proto, + +use super::{ascii_ws, eoi, Result}; +use iter::StrIter; + +make_fn!(proto, do_each!( proto => until!(text_token!("://")), _ => must!(text_token!("://")), @@ -9,18 +10,18 @@ ) ); - make_fn!(domain, +make_fn!(domain, until!(either!( discard!(text_token!("/")), discard!(ascii_ws), eoi)) ); - - make_fn!(path, + +make_fn!(path, until!(either!(discard!(ascii_ws), eoi)) ); - - make_fn!(pub url, Option<&str>, &str)>, + +make_fn!(pub url, Option<&str>, &str)>, do_each!( protocol => optional!(proto), domain => optional!(domain), @@ -39,4 +40,4 @@ fn test_url_parser() { assert!(domain.is_some()); assert_eq!(path, "/some/path"); } -} \ No newline at end of file +} diff --git a/src/iter.rs b/src/iter.rs index ff7c98d..b28edc1 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -55,10 +55,10 @@ impl<'a, T: Debug + 'a> InputIter for SliceIter<'a, T> {} impl<'a, T: Debug + 'a> Span<&'a [T]> for SliceIter<'a, T> { fn span(&self, idx: SpanRange) -> &'a [T] { match idx { - SpanRange::Range(r) => self.source.index(r), - SpanRange::RangeTo(r) => self.source.index(r), - SpanRange::RangeFrom(r) => self.source.index(r), - SpanRange::RangeFull(r) => self.source.index(r), + SpanRange::Range(r) => self.source.index(r), + SpanRange::RangeTo(r) => self.source.index(r), + SpanRange::RangeFrom(r) => self.source.index(r), + SpanRange::RangeFull(r) => self.source.index(r), } } } @@ -75,7 +75,7 @@ impl<'a, T: Debug> From<&'a [T]> for SliceIter<'a, T> { } } -impl <'a, T: Debug> From<&'a Vec> for SliceIter<'a, T> { +impl<'a, T: Debug> From<&'a Vec> for SliceIter<'a, T> { fn from(source: &'a Vec) -> Self { SliceIter::new(source.as_slice()) } @@ -140,10 +140,10 @@ use std::ops::Index; impl<'a> Span<&'a str> for StrIter<'a> { fn span(&self, idx: SpanRange) -> &'a str { match idx { - SpanRange::Range(r) => self.source.index(r), - SpanRange::RangeTo(r) => self.source.index(r), - SpanRange::RangeFrom(r) => self.source.index(r), - SpanRange::RangeFull(r) => self.source.index(r), + SpanRange::Range(r) => self.source.index(r), + SpanRange::RangeTo(r) => self.source.index(r), + SpanRange::RangeFrom(r) => self.source.index(r), + SpanRange::RangeFull(r) => self.source.index(r), } } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 87c62bf..b5fbc33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,13 @@ //! An opinionated parser combinator library with a focus on fully abortable parsing and error handling. -//! +//! //! # Example -//! +//! //! ``` //! #[macro_use] //! extern crate abortable_parser; //! use abortable_parser::iter::StrIter; //! use abortable_parser::{Result, eoi, ascii_ws}; -//! +//! //! make_fn!(proto, //! do_each!( //! proto => until!(text_token!("://")), @@ -22,11 +22,11 @@ //! discard!(ascii_ws), //! eoi)) //! ); -//! +//! //! make_fn!(path, //! until!(either!(discard!(ascii_ws), eoi)) //! ); -//! +//! //! make_fn!(url, Option<&str>, &str)>, //! do_each!( //! protocol => optional!(proto), @@ -35,7 +35,7 @@ //! (protocol, domain, path) //! ) //! ); -//! +//! //! # fn main() { //! let iter = StrIter::new("http://example.com/some/path "); //! let result = url(iter); @@ -88,10 +88,11 @@ pub struct Error { impl Error { /// Constructs a new Error with an offset and no cause. - pub fn new(msg: M, offset: &S) -> Self + pub fn new(msg: M, offset: &S) -> Self where S: Offsetable, - M: Into { + M: Into, + { Error { msg: msg.into(), offset: offset.get_offset(), @@ -103,8 +104,8 @@ impl Error { pub fn caused_by(msg: M, offset: &S, cause: Self) -> Self where S: Offsetable, - M: Into { - + M: Into, + { Error { msg: msg.into(), offset: offset.get_offset(), @@ -189,14 +190,14 @@ impl Result { } } -pub use iter::SliceIter; pub use combinators::*; +pub use iter::SliceIter; #[macro_use] pub mod combinators; pub mod iter; #[cfg(test)] -mod test; +mod integration_tests; #[cfg(test)] -mod integration_tests; \ No newline at end of file +mod test; diff --git a/src/test.rs b/src/test.rs index a7f1b6e..7e1b355 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,8 +1,8 @@ use std::fmt::{Debug, Display}; use super::{InputIter, Offsetable, Result}; -use iter::{StrIter, SliceIter}; use combinators::*; +use iter::{SliceIter, StrIter}; #[test] fn test_slice_iter() { @@ -361,7 +361,7 @@ fn test_until() { assert_eq!(i.get_offset(), 3); assert_eq!(o.len(), 3); assert_eq!(o, "foo"); - } + } } #[test] @@ -461,4 +461,4 @@ fn test_ascii_ws_carriage_return() { let iter = StrIter::new(input_str); let result = ascii_ws(iter); assert!(result.is_complete()); -} \ No newline at end of file +}