DOCS: Added a bunch of documentation.

This commit is contained in:
Jeremy Wall 2018-09-07 21:06:26 -05:00
parent 085b31b204
commit 832a43db14
3 changed files with 218 additions and 9 deletions

View File

@ -1,7 +1,23 @@
//! Contains combinators that can assemble other mathers or combinators into more complex grammars. //! Contains combinators that can assemble other matchers or combinators into more complex grammars.
/// Turns a matcher into it's inverse, only succeeding if the the matcher returns a Fail. /// 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 (). /// Does not consume it's input and only returns ().
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// # use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # use std::convert::From;
/// # fn main() {
/// # let iter: iter::SliceIter<u8> = "foo".into();
/// let tok = not!(iter, text_token!("bar"));
/// assert!(tok.is_complete());
/// if let Result::Complete(i, o) = tok {
/// assert_eq!(i.get_offset(), 0);
/// assert_eq!(o, ());
/// }
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! not { macro_rules! not {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{ ($i:expr, $f:ident!( $( $args:tt )* ) ) => {{
@ -24,7 +40,23 @@ macro_rules! not {
}; };
} }
/// Matches the provided /// Checks the given matcher without consuming the input.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// # use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # use std::convert::From;
/// # fn main() {
/// # let iter: iter::SliceIter<u8> = "foo".into();
/// let tok = peek!(iter, text_token!("foo"));
/// # assert!(tok.is_complete());
/// # if let Result::Complete(i, o) = tok {
/// # assert_eq!(i.get_offset(), 0);
/// # assert_eq!(o, "foo");
/// # }
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! peek { macro_rules! peek {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{ ($i:expr, $f:ident!( $( $args:tt )* ) ) => {{
@ -55,7 +87,25 @@ macro_rules! run {
}; };
} }
/// Turns Fails into Aborts. Allows you to turn any parse failure into a hard abort of the parser. /// Turns Fails into Aborts. 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<u8> = "foo".into();
///
/// let tok = must!(iter, text_token!("foo"));
/// # assert!(tok.is_complete());
///
/// let fail = must!(iter, text_token!("bar"));
/// # assert!(fail.is_abort());
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! must { macro_rules! must {
($i:expr, $f:ident!( $( $args:tt )* ) ) => { ($i:expr, $f:ident!( $( $args:tt )* ) ) => {
@ -95,7 +145,20 @@ macro_rules! wrap_err {
}; };
} }
/// Turns Aborts into fails allowing you to trap and then convert an Abort into a normal Fail. /// Turns Aborts into fails allowing you to trap and then convert an Abort into a
/// normal Fail.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "foo";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = trap!(iter, must!(text_token!("bar")));
/// # assert!(result.is_fail());
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! trap { macro_rules! trap {
($i:expr, $f:ident!( $( $args:tt )* ) ) => { ($i:expr, $f:ident!( $( $args:tt )* ) ) => {
@ -112,8 +175,19 @@ macro_rules! trap {
}; };
} }
/// Turns Fails and Incompletes into Aborts. It uses an error factory /// Turns Fails and Incompletes into Aborts. You must specify the error message
/// to construct the errors for the Incomplete case. /// to use in case the matcher is Incomplete.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "foo";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let mut result = must_complete!(iter, "AHHH".to_string(), text_token!("fooooo"));
/// # assert!(result.is_abort());
/// # }
#[macro_export] #[macro_export]
macro_rules! must_complete { macro_rules! must_complete {
($i:expr, $e:expr, $f:ident!( $( $args:tt )* ) ) => {{ ($i:expr, $e:expr, $f:ident!( $( $args:tt )* ) ) => {{
@ -132,6 +206,54 @@ macro_rules! must_complete {
} }
/// Captures a sequence of sub parsers output. /// Captures a sequence of sub parsers output.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "(foobar)";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = do_each!(iter,
/// _ => text_token!("("),
/// foo => text_token!("foo"),
/// bar => text_token!("bar"),
/// _ => text_token!(")"),
/// (foo, bar) // This expression will be the result of the parse
/// );
/// # assert!(result.is_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;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// # let input_str = "(foobar)";
/// # let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = do_each!(iter,
/// _ => text_token!("("),
/// foo => text_token!("foo"),
/// bar => text_token!("bar"),
/// _ => text_token!(")"),
/// (vec![foo, bar]) // Non tuple expression as a result.
/// );
/// # assert!(result.is_complete());
/// if let Result::Complete(_, o) = result {
/// assert_eq!(vec!["foo", "bar"], o);
/// }
/// # }
/// ```
///
/// The output from this combinator must be indicated by parentheses.
#[macro_export] #[macro_export]
macro_rules! do_each { macro_rules! do_each {
($i:expr, $val:ident => $f:ident) => { ($i:expr, $val:ident => $f:ident) => {
@ -185,6 +307,22 @@ macro_rules! do_each {
} }
/// Returns the output of the first sub parser to succeed. /// Returns the output of the first sub parser to succeed.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "foo";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = either!(iter, text_token!("bar"), text_token!("foo"));
/// # assert!(result.is_complete());
/// # if let Result::Complete(_, o) = result {
/// # assert_eq!("foo", o);
/// # } else {
/// # assert!(false, "either! did not complete");
/// # }
/// # }
#[macro_export] #[macro_export]
macro_rules! either { macro_rules! either {
// Initialization case. // Initialization case.
@ -271,6 +409,22 @@ macro_rules! either {
/// Treats a sub parser as optional. It returns Some(output) for a successful match /// Treats a sub parser as optional. It returns Some(output) for a successful match
/// and None for Fails. /// and None for Fails.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "foo";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = optional!(iter, text_token!("foo"));
/// # assert!(result.is_complete());
/// # if let Result::Complete(_, o) = result {
/// # assert_eq!("foo", o.unwrap());
/// # } else {
/// # assert!(false, "optional! did not complete");
/// # }
/// # }
#[macro_export] #[macro_export]
macro_rules! optional { macro_rules! optional {
($i:expr, $f:ident) => { ($i:expr, $f:ident) => {
@ -301,8 +455,25 @@ macro_rules! optional {
}}; }};
} }
/// Runs a single parser repeating 0 or mre times and returns a possibly empty /// Runs a single matcher repeating 0 or mre times and returns a possibly empty
/// vector of the parsed results. /// vector of the parsed results.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// # fn main() {
/// let input_str = "foofoo";
/// let iter = iter::SliceIter::new(input_str.as_bytes());
/// let result = repeat!(iter, text_token!("foo"));
/// # assert!(result.is_complete());
/// if let Result::Complete(_, o) = result {
/// assert_eq!(2, o.len());
/// assert_eq!("foo", o[0]);
/// assert_eq!("foo", o[1]);
/// }
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! repeat { macro_rules! repeat {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{ ($i:expr, $f:ident!( $( $args:tt )* ) ) => {{

View File

@ -1,6 +1,25 @@
//! Contains matchers for matching specific patterns or tokens. //! Contains matchers for matching specific patterns or tokens.
use super::{InputIter, Result, Error};
use std::fmt::{Debug, Display};
/// Convenience macro for looking for a specific text token in a byte input stream. /// Convenience macro for looking for a specific text token in a byte input stream.
///
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// use std::convert::From;
/// # fn main() {
/// let iter: iter::SliceIter<u8> = "foo bar".into();
/// let tok = text_token!(iter, "foo");
/// # assert!(tok.is_complete());
/// if let Result::Complete(i, o) = tok {
/// assert_eq!(i.get_offset(), 3);
/// assert_eq!(o, "foo");
/// }
/// # }
/// ```
#[macro_export] #[macro_export]
macro_rules! text_token { macro_rules! text_token {
($i:expr, $e:expr) => {{ ($i:expr, $e:expr) => {{
@ -28,6 +47,24 @@ macro_rules! text_token {
}}; }};
} }
/// Consumes an input until it reaches the term combinator matches.
///
/// If the term never matches then returns incomplete.
/// ```
/// # #[macro_use] extern crate abortable_parser;
/// use abortable_parser::iter;
/// # use abortable_parser::{Result, Offsetable};
/// use std::convert::From;
/// # fn main() {
/// let iter: iter::SliceIter<u8> = "foo;".into();
/// let tok = until!(iter, text_token!(";"));
/// # assert!(tok.is_complete());
/// if let Result::Complete(i, o) = tok {
/// assert_eq!(i.get_offset(), 3);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! until { macro_rules! until {
($i:expr, $term:ident!( $( $args:tt )* ) ) => {{ ($i:expr, $term:ident!( $( $args:tt )* ) ) => {{
use $crate::{Result, Offsetable}; use $crate::{Result, Offsetable};
@ -58,6 +95,7 @@ macro_rules! until {
}; };
} }
/// Maps a Result of type Vec<&u8> to a Result of type String.
pub fn must_string<'a, I, E>(matched: Result<I, Vec<&'a u8>, E>, msg: E) -> Result<I, String, E> pub fn must_string<'a, I, E>(matched: Result<I, Vec<&'a u8>, E>, msg: E) -> Result<I, String, E>
where where
I: InputIter<Item=&'a u8>, I: InputIter<Item=&'a u8>,

View File

@ -144,7 +144,7 @@ fn test_wrap_err_fail() {
assert!(result.is_fail()); assert!(result.is_fail());
if let Result::Fail(e) = result { if let Result::Fail(e) = result {
assert!(e.get_cause().is_some()); assert!(e.get_cause().is_some());
assert_eq!("AAAAHHH!!!", e.get_cause().unwrap().get_err()); assert_eq!("AAAAHHH!!!", e.get_cause().unwrap().get_msg());
} }
} }
@ -156,7 +156,7 @@ fn test_wrap_err_abort() {
assert!(result.is_abort()); assert!(result.is_abort());
if let Result::Abort(e) = result { if let Result::Abort(e) = result {
assert!(e.get_cause().is_some()); assert!(e.get_cause().is_some());
assert_eq!("AAAAHHH!!!", e.get_cause().unwrap().get_err()); assert_eq!("AAAAHHH!!!", e.get_cause().unwrap().get_msg());
} }
} }