summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nom/src/whitespace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/nom/src/whitespace.rs')
-rw-r--r--third_party/rust/nom/src/whitespace.rs1077
1 files changed, 1077 insertions, 0 deletions
diff --git a/third_party/rust/nom/src/whitespace.rs b/third_party/rust/nom/src/whitespace.rs
new file mode 100644
index 0000000000..9ed3f55aad
--- /dev/null
+++ b/third_party/rust/nom/src/whitespace.rs
@@ -0,0 +1,1077 @@
+//! Support for whitespace delimited formats
+//!
+//! a lot of textual formats allows spaces and other
+//! types of separators between tokens. Handling it
+//! manually with nom means wrapping all parsers
+//! like this:
+//!
+//! ```ignore
+//! named!(token, delimited!(space, tk, space));
+//! ```
+//!
+//! To ease the development of such parsers, you
+//! can use the whitespace parsing facility, which works
+//! as follows:
+//!
+//! ```
+//! # #[macro_use] extern crate nom;
+//! # fn main() {
+//! named!(tuple<&[u8], (&[u8], &[u8]) >,
+//! ws!(tuple!( take!(3), tag!("de") ))
+//! );
+//!
+//! assert_eq!(
+//! tuple(&b" \t abc de fg"[..]),
+//! Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
+//! );
+//! # }
+//! ```
+//!
+//! The `ws!` combinator will modify the parser to
+//! intersperse space parsers everywhere. By default,
+//! it will consume the following characters: `" \t\r\n"`.
+//!
+//! If you want to modify that behaviour, you can make
+//! your own whitespace wrapper. As an example, if
+//! you don't want to consume ends of lines, only
+//! spaces and tabs, you can do it like this:
+//!
+//! ```
+//! # #[macro_use] extern crate nom;
+//! named!(pub space, eat_separator!(&b" \t"[..]));
+//!
+//! #[macro_export]
+//! macro_rules! sp (
+//! ($i:expr, $($args:tt)*) => (
+//! {
+//! use nom::Err;
+//!
+//! match sep!($i, space, $($args)*) {
+//! Err(e) => Err(e),
+//! Ok((i1,o)) => {
+//! match space(i1) {
+//! Err(e) => Err(Err::convert(e)),
+//! Ok((i2,_)) => Ok((i2, o))
+//! }
+//! }
+//! }
+//! }
+//! )
+//! );
+//!
+//! # fn main() {
+//! named!(tuple<&[u8], (&[u8], &[u8]) >,
+//! sp!(tuple!( take!(3), tag!("de") ))
+//! );
+//!
+//! assert_eq!(
+//! tuple(&b" \t abc de fg"[..]),
+//! Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
+//! );
+//! # }
+//! ```
+//!
+//! This combinator works by replacing each combinator with
+//! a version that supports wrapping with separator parsers.
+//! It will not support the combinators you wrote in your
+//! own code. You can still manually wrap them with the separator
+//! you want, or you can copy the macros defined in src/whitespace.rs
+//! and modify them to support a new combinator:
+//!
+//! * copy the combinator's code here, add the _sep suffix
+//! * add the `$separator:expr` as second argument
+//! * wrap any sub parsers with sep!($separator, $submac!($($args)*))
+//! * reference it in the definition of `sep!` as follows:
+//!
+//! ```ignore
+//! ($i:expr, $separator:path, my_combinator ! ($($rest:tt)*) ) => {
+//! wrap_sep!($i,
+//! $separator,
+//! my_combinator_sep!($separator, $($rest)*)
+//! )
+//! };
+//! ```
+//!
+
+/// applies the separator parser before the other parser
+#[macro_export(local_inner_macros)]
+macro_rules! wrap_sep (
+ ($i:expr, $separator:expr, $submac:ident!( $($args:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+ use $crate::{Err,IResult};
+
+ fn unify_types<I,O,P,E>(_: &IResult<I,O,E>, _: &IResult<I,P,E>) {}
+
+ let sep_res = ($separator)($i);
+ match sep_res {
+ Ok((i1,_)) => {
+ let res = $submac!(i1, $($args)*);
+ unify_types(&sep_res, &res);
+ res
+ },
+ Err(e) => Err(Err::convert(e)),
+ }
+ });
+ ($i:expr, $separator:expr, $f:expr) => (
+ wrap_sep!($i, $separator, call!($f))
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! pair_sep (
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
+ tuple!(
+ $i,
+ sep!($separator, $submac!($($args)*)),
+ sep!($separator, $submac2!($($args2)*))
+ )
+ );
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
+ pair_sep!($i, $separator, $submac!($($args)*), call!($g));
+ );
+ ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
+ pair_sep!($i, $separator, call!($f), $submac!($($args)*));
+ );
+ ($i:expr, $separator:path, $f:expr, $g:expr) => (
+ pair_sep!($i, $separator, call!($f), call!($g));
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! delimited_sep (
+ ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)+) {
+ Err(e) => Err(e),
+ Ok((remaining, (_,o,_))) => {
+ Ok((remaining, o))
+ }
+ }
+ });
+ ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
+ delimited_sep!($i, $separator, call!($f), $($rest)+);
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! separated_pair_sep (
+ ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)+) {
+ Err(e) => Err(e),
+ Ok((remaining, (o1,_,o2))) => {
+ Ok((remaining, (o1,o2)))
+ }
+ }
+ });
+ ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
+ separated_pair_sep!($i, $separator, call!($f), $($rest)+);
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! preceded_sep (
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
+ Err(e) => Err(e),
+ Ok((remaining, (_,o))) => {
+ Ok((remaining, o))
+ }
+ }
+ });
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
+ preceded_sep!($i, $separator, $submac!($($args)*), call!($g));
+ );
+ ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
+ preceded_sep!($i, $separator, call!($f), $submac!($($args)*));
+ );
+ ($i:expr, $separator:path, $f:expr, $g:expr) => (
+ preceded_sep!($i, $separator, call!($f), call!($g));
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! terminated_sep (
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
+ Err(e) => Err(e),
+ Ok((remaining, (o,_))) => {
+ Ok((remaining, o))
+ }
+ }
+ });
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
+ terminated_sep!($i, $separator, $submac!($($args)*), call!($g));
+ );
+ ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
+ terminated_sep!($i, $separator, call!($f), $submac!($($args)*));
+ );
+ ($i:expr, $separator:path, $f:expr, $g:expr) => (
+ terminated_sep!($i, $separator, call!($f), call!($g));
+ );
+);
+
+/// Internal parser, do not use directly
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! tuple_sep (
+ ($i:expr, $separator:path, ($($parsed:tt),*), $e:path, $($rest:tt)*) => (
+ tuple_sep!($i, $separator, ($($parsed),*), call!($e), $($rest)*);
+ );
+ ($i:expr, $separator:path, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ tuple_sep!(i, $separator, (o), $($rest)*)
+ }
+ }
+ }
+ );
+ ($i:expr, $separator:path, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ tuple_sep!(i, $separator, ($($parsed)* , o), $($rest)*)
+ }
+ }
+ }
+ );
+ ($i:expr, $separator:path, ($($parsed:tt),*), $e:path) => (
+ tuple_sep!($i, $separator, ($($parsed),*), call!($e));
+ );
+ ($i:expr, $separator:path, (), $submac:ident!( $($args:tt)* )) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ Ok((i, (o)))
+ }
+ }
+ }
+ );
+ ($i:expr, $separator:path, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ Ok((i, ($($parsed),* , o)))
+ }
+ }
+ }
+ );
+ ($i:expr, $separator:path, ($($parsed:expr),*)) => (
+ {
+ ::sts::result::Result::Ok(($i, ($($parsed),*)))
+ }
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! do_parse_sep (
+ (__impl $i:expr, $separator:path, ( $($rest:expr),* )) => (
+ $crate::lib::std::result::Result::Ok(($i, ( $($rest),* )))
+ );
+
+ (__impl $i:expr, $separator:path, $e:ident >> $($rest:tt)*) => (
+ do_parse_sep!(__impl $i, $separator, call!($e) >> $($rest)*);
+ );
+ (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,_)) => {
+ do_parse_sep!(__impl i, $separator, $($rest)*)
+ },
+ }
+ }
+ );
+
+ (__impl $i:expr, $separator:path, $field:ident : $e:ident >> $($rest:tt)*) => (
+ do_parse_sep!(__impl $i, $separator, $field: call!($e) >> $($rest)*);
+ );
+
+ (__impl $i:expr, $separator:path, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ let $field = o;
+ do_parse_sep!(__impl i, $separator, $($rest)*)
+ },
+ }
+ }
+ );
+
+ // ending the chain
+ (__impl $i:expr, $separator:path, $e:ident >> ( $($rest:tt)* )) => (
+ do_parse_sep!(__impl $i, $separator, call!($e) >> ( $($rest)* ));
+ );
+
+ (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,_)) => {
+ Ok((i, ( $($rest)* )))
+ },
+ }
+ });
+
+ (__impl $i:expr, $separator:path, $field:ident : $e:ident >> ( $($rest:tt)* )) => (
+ do_parse_sep!(__impl $i, $separator, $field: call!($e) >> ( $($rest)* ) );
+ );
+
+ (__impl $i:expr, $separator:path, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(e) => Err(e),
+ Ok((i,o)) => {
+ let $field = o;
+ Ok((i, ( $($rest)* )))
+ },
+ }
+ });
+
+ ($i:expr, $separator:path, $($rest:tt)*) => (
+ {
+ do_parse_sep!(__impl $i, $separator, $($rest)*)
+ }
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! permutation_sep (
+ ($i:expr, $separator:path, $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::lib::std::option::Option::*;
+ use $crate::{Err,error::ErrorKind};
+
+ let mut res = permutation_init!((), $($rest)*);
+ let mut input = $i;
+ let mut error = None;
+ let mut needed = None;
+
+ loop {
+ let mut all_done = true;
+ permutation_iterator_sep!(0, input, $separator, all_done, needed, res, $($rest)*);
+
+ //if we reach that part, it means none of the parsers were able to read anything
+ if !all_done {
+ //FIXME: should wrap the error returned by the child parser
+ error = Option::Some(error_position!(input, ErrorKind::Permutation));
+ }
+ break;
+ }
+
+ if let Some(need) = needed {
+ Err(Err::convert(need))
+ } else {
+ if let Some(unwrapped_res) = { permutation_unwrap!(0, (), res, $($rest)*) } {
+ Ok((input, unwrapped_res))
+ } else {
+ if let Some(e) = error {
+ Err(Err::Error(error_node_position!($i, ErrorKind::Permutation, e)))
+ } else {
+ Err(Err::Error(error_position!($i, ErrorKind::Permutation)))
+ }
+ }
+ }
+ }
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! permutation_iterator_sep (
+ ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident?, $($rest:tt)*) => (
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, call!($e), $($rest)*);
+ );
+ ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident, $($rest:tt)*) => (
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, call!($e), $($rest)*);
+ );
+
+ ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => ({
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, $submac!($($args)*), $($rest)*);
+ });
+ ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ if $res.$it == $crate::lib::std::option::Option::None {
+ match {sep!($i, $separator, $submac!($($args)*))} {
+ Ok((i,o)) => {
+ $i = i;
+ $res.$it = $crate::lib::std::option::Option::Some(o);
+ continue;
+ },
+ Err(Err::Error(_)) => {
+ $all_done = false;
+ },
+ Err(e) => {
+ $needed = $crate::lib::std::option::Option::Some(e);
+ break;
+ }
+ };
+ }
+ succ!($it, permutation_iterator_sep!($i, $separator, $all_done, $needed, $res, $($rest)*));
+ });
+
+ ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident?) => (
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $res, call!($e));
+ );
+ ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident) => (
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $res, call!($e));
+ );
+
+ ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?) => ({
+ permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, $submac!($($args)*));
+ });
+ ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )) => ({
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ if $res.$it == $crate::lib::std::option::Option::None {
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Ok((i,o)) => {
+ $i = i;
+ $res.$it = $crate::lib::std::option::Option::Some(o);
+ continue;
+ },
+ Err(Err::Error(_)) => {
+ $all_done = false;
+ },
+ Err(e) => {
+ $needed = $crate::lib::std::option::Option::Some(e);
+ break;
+ }
+ };
+ }
+ });
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! alt_sep (
+ (__impl $i:expr, $separator:path, $e:path | $($rest:tt)*) => (
+ alt_sep!(__impl $i, $separator, call!($e) | $($rest)*);
+ );
+
+ (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ let res = sep!($i, $separator, $subrule!($($args)*));
+ match res {
+ Ok((_,_)) => res,
+ Err(Err::Error(_)) => alt_sep!(__impl $i, $separator, $($rest)*),
+ Err(e) => Err(e),
+ }
+ }
+ );
+
+ (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ match sep!($i, $separator, $subrule!( $($args)* )) {
+ Ok((i,o)) => Ok((i,$gen(o))),
+ Err(Err::Error(_)) => {
+ alt_sep!(__impl $i, $separator, $($rest)+)
+ },
+ Err(e) => Err(e),
+ }
+ }
+ );
+
+ (__impl $i:expr, $separator:path, $e:path => { $gen:expr } | $($rest:tt)*) => (
+ alt_sep!(__impl $i, $separator, call!($e) => { $gen } | $($rest)*);
+ );
+
+ (__impl $i:expr, $separator:path, $e:path => { $gen:expr }) => (
+ alt_sep!(__impl $i, $separator, call!($e) => { $gen });
+ );
+
+ (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ match sep!($i, $separator, $subrule!( $($args)* )) {
+ Ok((i,o)) => Ok((i,$gen(o))),
+ Err(Err::Error(e)) => {
+ fn unify_types<T>(_: &T, _: &T) {}
+ let e2 = error_position!($i, $crate::error::ErrorKind::Alt);
+ unify_types(&e, &e2);
+ Err(Err::Error(e2))
+ },
+ Err(e) => Err(e),
+ }
+ }
+ );
+
+ (__impl $i:expr, $separator:path, $e:path) => (
+ alt_sep!(__impl $i, $separator, call!($e));
+ );
+
+ (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)*)) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ match sep!($i, $separator, $subrule!( $($args)* )) {
+ Ok((i,o)) => Ok((i,o)),
+ Err(Err::Error(e)) => {
+ fn unify_types<T>(_: &T, _: &T) {}
+ let e2 = error_position!($i, $crate::error::ErrorKind::Alt);
+ unify_types(&e, &e2);
+ Err(Err::Error(e2))
+ },
+ Err(e) => Err(e),
+ }
+ }
+ );
+
+ (__impl $i:expr) => ({
+ use $crate::lib::std::result::Result::*;
+ use $crate::{Err,Needed,IResult};
+
+ Err(Err::Error(error_position!($i, $crate::error::ErrorKind::Alt)))
+ });
+
+ (__impl $i:expr, $separator:path) => ({
+ use $crate::lib::std::result::Result::*;
+ use $crate::{Err,Needed,IResult};
+
+ Err(Err::Error(error_position!($i, $crate::error::ErrorKind::Alt)))
+ });
+
+ ($i:expr, $separator:path, $($rest:tt)*) => (
+ {
+ alt_sep!(__impl $i, $separator, $($rest)*)
+ }
+ );
+);
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! switch_sep (
+ (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => (
+ {
+ use $crate::lib::std::result::Result::*;
+ use $crate::Err;
+
+ match sep!($i, $separator, $submac!($($args)*)) {
+ Err(Err::Error(e)) => Err(Err::Error(error_node_position!(
+ $i, $crate::error::ErrorKind::Switch, e
+ ))),
+ Err(Err::Failure(e)) => Err(Err::Failure(
+ error_node_position!($i, $crate::error::ErrorKind::Switch, e))),
+ Err(e) => Err(e),
+ Ok((i, o)) => {
+ match o {
+ $($p => match sep!(i, $separator, $subrule!($($args2)*)) {
+ Err(Err::Error(e)) => Err(Err::Error(error_node_position!(
+ $i, $crate::error::ErrorKind::Switch, e
+ ))),
+ Err(Err::Failure(e)) => Err(Err::Failure(
+ error_node_position!($i, $crate::error::ErrorKind::Switch, e))),
+ a => a,
+ }),*,
+ _ => Err(Err::Error(error_position!($i, $crate::error::ErrorKind::Switch)))
+ }
+ }
+ }
+ }
+ );
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)*), $($rest:tt)*) => (
+ {
+ switch_sep!(__impl $i, $separator, $submac!($($args)*), $($rest)*)
+ }
+ );
+ ($i:expr, $separator:path, $e:path, $($rest:tt)*) => (
+ {
+ switch_sep!(__impl $i, $separator, call!($e), $($rest)*)
+ }
+ );
+);
+
+#[doc(hidden)]
+#[cfg(feature = "alloc")]
+#[macro_export(local_inner_macros)]
+macro_rules! separated_list_sep (
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
+ separated_list!(
+ $i,
+ sep!($separator, $submac!($($args)*)),
+ sep!($separator, $submac2!($($args2)*))
+ )
+ );
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
+ separated_list_sep!($i, $separator, $submac!($($args)*), call!($g));
+ );
+ ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
+ separated_list_sep!($i, $separator, call!($f), $submac!($($args)*));
+ );
+ ($i:expr, $separator:path, $f:expr, $g:expr) => (
+ separated_list_sep!($i, $separator, call!($f), call!($g));
+ );
+);
+
+/// helper macros to build a separator parser
+///
+/// ```
+/// # #[macro_use] extern crate nom;
+/// named!(pub space, eat_separator!(&b" \t"[..]));
+/// # fn main() {}
+/// ```
+#[macro_export(local_inner_macros)]
+macro_rules! eat_separator (
+ ($i:expr, $arr:expr) => (
+ {
+ use $crate::{FindToken, InputTakeAtPosition};
+ let input = $i;
+ input.split_at_position(|c| !$arr.find_token(c))
+ }
+ );
+);
+
+/// sep is the parser rewriting macro for whitespace separated formats
+///
+/// it takes as argument a space eating function and a parser tree,
+/// and will intersperse the space parser everywhere
+///
+/// ```ignore
+/// #[macro_export(local_inner_macros)]
+/// macro_rules! ws (
+/// ($i:expr, $($args:tt)*) => (
+/// {
+/// use sp;
+/// sep!($i, sp, $($args)*)
+/// }
+/// )
+/// );
+/// ```
+#[macro_export(local_inner_macros)]
+macro_rules! sep (
+ ($i:expr, $separator:path, tuple ! ($($rest:tt)*) ) => {
+ tuple_sep!($i, $separator, (), $($rest)*)
+ };
+ ($i:expr, $separator:path, pair ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ pair_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, delimited ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ delimited_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, separated_pair ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ separated_pair_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, preceded ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ preceded_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, terminated ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ terminated_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, do_parse ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ do_parse_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, permutation ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ permutation_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, alt ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ alt_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, switch ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ switch_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, separated_list ! ($($rest:tt)*) ) => {
+ wrap_sep!($i,
+ $separator,
+ separated_list_sep!($separator, $($rest)*)
+ )
+ };
+ ($i:expr, $separator:path, many0 ! ($($rest:tt)*) ) => {
+ many0!($i, wrap_sep!($separator, $($rest)*))
+ };
+ ($i:expr, $separator:path, many1 ! ($($rest:tt)*) ) => {
+ many1!($i, wrap_sep!($separator, $($rest)*))
+ };
+ ($i:expr, $separator:path, return_error!( $($args:tt)* )) => {
+ return_error!($i, wrap_sep!($separator, $($args)*))
+ };
+//FIXME: missing separated_nonempty_list,
+// many_till, many_m_n, count, count_fixed, fold_many0, fold_many1,
+// fold_many_m_n
+ ($i:expr, $separator:path, $submac:ident!( $($args:tt)* )) => {
+ wrap_sep!($i, $separator, $submac!($($args)*))
+ };
+ ($i:expr, $separator:path, $f:expr) => {
+ wrap_sep!($i, $separator, call!($f))
+ };
+);
+
+/// `ws!(I -> IResult<I,O>) => I -> IResult<I, O>`
+///
+/// transforms a parser to automatically consume
+/// whitespace between each token. By default,
+/// it takes the following characters: `" \t\r\n"`.
+///
+/// If you need a whitespace parser consuming a
+/// different set of characters, you can make
+/// your own by reusing the `sep!` combinator.
+///
+/// To use `ws!`, pass your parser as argument:
+///
+/// ```
+/// # #[macro_use] extern crate nom;
+/// # fn main() {
+/// named!(tuple<&[u8], (&[u8], &[u8]) >,
+/// ws!(tuple!( take!(3), tag!("de") ))
+/// );
+///
+/// assert_eq!(
+/// tuple(&b" \t abc de fg"[..]),
+/// Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
+/// );
+/// # }
+/// ```
+///
+#[macro_export(local_inner_macros)]
+#[deprecated(since = "5.0.0", note = "whitespace parsing only works with macros and will not be updated anymore")]
+macro_rules! ws (
+ ($i:expr, $($args:tt)*) => (
+ {
+ use $crate::Err;
+ use $crate::lib::std::result::Result::*;
+ use $crate::character::complete::multispace0;
+
+ match sep!($i, multispace0, $($args)*) {
+ Err(e) => Err(e),
+ Ok((i1,o)) => {
+ match (multispace0)(i1) {
+ Err(e) => Err(Err::convert(e)),
+ Ok((i2,_)) => Ok((i2, o))
+ }
+ }
+ }
+ }
+ )
+);
+
+#[cfg(test)]
+#[allow(dead_code)]
+mod tests {
+ #[cfg(feature = "alloc")]
+ use crate::{
+ error::ParseError,
+ lib::std::{
+ string::{String, ToString},
+ fmt::Debug
+ }
+ };
+ use crate::internal::{Err, IResult, Needed};
+ use crate::character::complete::multispace0 as sp;
+ use crate::error::ErrorKind;
+
+ #[test]
+ fn spaaaaace() {
+ assert_eq!(sp::<_,(_,ErrorKind)>(&b" \t abc "[..]), Ok((&b"abc "[..], &b" \t "[..])));
+ }
+
+ #[test]
+ fn tag() {
+ named!(abc, ws!(tag!("abc")));
+
+ assert_eq!(abc(&b" \t abc def"[..]), Ok((&b"def"[..], &b"abc"[..])));
+ }
+
+ #[test]
+ fn pair() {
+ named!(pair_2<&[u8], (&[u8], &[u8]) >,
+ ws!(pair!( take!(3), tag!("de") ))
+ );
+
+ assert_eq!(
+ pair_2(&b" \t abc de fg"[..]),
+ Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
+ );
+ }
+
+ #[test]
+ fn preceded() {
+ named!(prec<&[u8], &[u8] >,
+ ws!(preceded!( take!(3), tag!("de") ))
+ );
+
+ assert_eq!(prec(&b" \t abc de fg"[..]), Ok((&b"fg"[..], &b"de"[..])));
+ }
+
+ #[test]
+ fn terminated() {
+ named!(term<&[u8], &[u8] >,
+ ws!(terminated!( take!(3), tag!("de") ))
+ );
+
+ assert_eq!(term(&b" \t abc de fg"[..]), Ok((&b"fg"[..], &b"abc"[..])));
+ }
+
+ #[test]
+ fn tuple() {
+ //trace_macros!(true);
+ named!(tuple_2<&[u8], (&[u8], &[u8]) >,
+ ws!(tuple!( take!(3), tag!("de") ))
+ );
+ //trace_macros!(false);
+
+ assert_eq!(
+ tuple_2(&b" \t abc de fg"[..]),
+ Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
+ );
+ }
+
+ #[test]
+ fn levels() {
+ //trace_macros!(true);
+ named!(level_2<&[u8], (&[u8], (&[u8], &[u8])) >,
+ ws!(pair!(take!(3), tuple!( tag!("de"), tag!("fg ") )))
+ );
+ //trace_macros!(false);
+
+ assert_eq!(
+ level_2(&b" \t abc de fg \t hi "[..]),
+ Ok((&b"hi "[..], (&b"abc"[..], (&b"de"[..], &b"fg "[..]))))
+ );
+ }
+
+ #[test]
+ fn do_parse() {
+ fn ret_int1(i: &[u8]) -> IResult<&[u8], u8> {
+ Ok((i, 1))
+ };
+ fn ret_int2(i: &[u8]) -> IResult<&[u8], u8> {
+ Ok((i, 2))
+ };
+
+ //trace_macros!(true);
+ named!(do_parser<&[u8], (u8, u8)>,
+ ws!(do_parse!(
+ tag!("abcd") >>
+ opt!(tag!("abcd")) >>
+ aa: ret_int1 >>
+ tag!("efgh") >>
+ bb: ret_int2 >>
+ tag!("efgh") >>
+ (aa, bb)
+ ))
+ );
+
+ //trace_macros!(false);
+
+ assert_eq!(
+ do_parser(&b"abcd abcd\tefghefghX"[..]),
+ Ok((&b"X"[..], (1, 2)))
+ );
+ assert_eq!(
+ do_parser(&b"abcd\tefgh efgh X"[..]),
+ Ok((&b"X"[..], (1, 2)))
+ );
+ assert_eq!(
+ do_parser(&b"abcd ab"[..]),
+ Err(Err::Incomplete(Needed::Size(4)))
+ );
+ assert_eq!(
+ do_parser(&b" abcd\tefgh\tef"[..]),
+ Err(Err::Incomplete(Needed::Size(4)))
+ );
+ }
+
+ #[test]
+ fn permutation() {
+ //trace_macros!(true);
+ named!(
+ perm<(&[u8], &[u8], &[u8])>,
+ ws!(permutation!(tag!("abcd"), tag!("efg"), tag!("hi")))
+ );
+ //trace_macros!(false);
+
+ let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
+
+ let a = &b"abcd\tefg \thijk"[..];
+ assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
+ let b = &b" efg \tabcdhi jk"[..];
+ assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
+ let c = &b" hi efg\tabcdjk"[..];
+ assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
+
+ let d = &b"efg xyzabcdefghi"[..];
+ assert_eq!(
+ perm(d),
+ Err(Err::Error(error_node_position!(
+ &b"efg xyzabcdefghi"[..],
+ ErrorKind::Permutation,
+ error_position!(&b" xyzabcdefghi"[..], ErrorKind::Permutation)
+ )))
+ );
+
+ let e = &b" efg \tabc"[..];
+ assert_eq!(perm(e), Err(Err::Incomplete(Needed::Size(4))));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct ErrorStr(String);
+
+ #[cfg(feature = "alloc")]
+ impl<'a> From<(&'a[u8], ErrorKind)> for ErrorStr {
+ fn from(i: (&'a[u8], ErrorKind)) -> Self {
+ ErrorStr(format!("custom error code: {:?}", i))
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl<'a> From<(&'a str, ErrorKind)> for ErrorStr {
+ fn from(i: (&'a str, ErrorKind)) -> Self {
+ ErrorStr(format!("custom error message: {:?}", i))
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl<I: Debug> ParseError<I> for ErrorStr {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
+ }
+
+ fn append(input: I, kind: ErrorKind, other: Self) -> Self {
+ ErrorStr(format!("custom error message: ({:?}, {:?}) - {:?}", input, kind, other))
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn alt() {
+ fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((&b""[..], input))
+ }
+
+ #[allow(unused_variables)]
+ fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Err(Err::Error(ErrorStr("abcd".to_string())))
+ }
+
+ fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((input, &b""[..]))
+ }
+
+ fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt!(i, dont_work | dont_work)
+ }
+ fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt!(i, dont_work | work)
+ }
+ fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt!(i, dont_work | dont_work | work2 | dont_work)
+ }
+
+ let a = &b"\tabcd"[..];
+ assert_eq!(
+ alt1(a),
+ Err(Err::Error(error_position!(a, ErrorKind::Alt)))
+ );
+ assert_eq!(alt2(a), Ok((&b""[..], a)));
+ assert_eq!(alt3(a), Ok((a, &b""[..])));
+
+ }
+
+ named!(str_parse(&str) -> &str, ws!(tag!("test")));
+ #[allow(unused_variables)]
+ #[test]
+ fn str_test() {
+ assert_eq!(str_parse(" \n test\t a\nb"), Ok(("a\nb", "test")));
+ }
+
+ // test whitespace parser generation for alt
+ named!(space, tag!(" "));
+ #[cfg(feature = "alloc")]
+ named!(pipeline_statement<&[u8], ()>,
+ ws!(
+ do_parse!(
+ tag!("pipeline") >>
+ attributes: delimited!(char!('{'),
+ separated_list!(char!(','), alt!(
+ space |
+ space
+ )),
+ char!('}')) >>
+
+ ({
+ let _ = attributes;
+ ()
+ })
+ )
+ )
+ );
+
+ #[cfg(feature = "alloc")]
+ named!(
+ fail<&[u8]>,
+ map!(many_till!(take!(1), ws!(tag!("."))), |(r, _)| r[0])
+ );
+}