diff --git a/Cargo.toml b/Cargo.toml index 28617d1..1ec391c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ include = [ ".travis.yml", "Cargo.toml", "src/*.rs", + "src/*/*.rs", "tests/*.rs", "build.rs" ] diff --git a/src/character.rs b/src/character/macros.rs similarity index 66% rename from src/character.rs rename to src/character/macros.rs index 7265ef5..ded6c03 100644 --- a/src/character.rs +++ b/src/character/macros.rs @@ -20,27 +20,7 @@ use traits::{need_more, AtEof}; /// ``` #[macro_export(local_inner_macros)] macro_rules! one_of ( - ($i:expr, $inp: expr) => ( - { - use $crate::lib::std::result::Result::*; - use $crate::lib::std::option::Option::*; - use $crate::{Err,Needed}; - - use $crate::Slice; - use $crate::AsChar; - use $crate::FindToken; - use $crate::InputIter; - - match ($i).iter_elements().next().map(|c| { - (c, $inp.find_token(c)) - }) { - None => $crate::need_more($i, Needed::Size(1)), - Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::))), - //the unwrap should be safe here - Some((c, true)) => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() )) - } - } - ); + ($i:expr, $inp: expr) => ( $crate::one_ofc($i, $inp) ); ); /// matches anything but the provided characters @@ -59,27 +39,7 @@ macro_rules! one_of ( /// ``` #[macro_export(local_inner_macros)] macro_rules! none_of ( - ($i:expr, $inp: expr) => ( - { - use $crate::lib::std::result::Result::*; - use $crate::lib::std::option::Option::*; - use $crate::{Err,Needed}; - - use $crate::Slice; - use $crate::AsChar; - use $crate::FindToken; - use $crate::InputIter; - - match ($i).iter_elements().next().map(|c| { - (c, !$inp.find_token(c)) - }) { - None => $crate::need_more($i, Needed::Size(1)), - Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::))), - //the unwrap should be safe here - Some((c, true)) => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() )) - } - } - ); + ($i:expr, $inp: expr) => ( $crate::none_ofc($i, $inp) ); ); /// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char> @@ -97,30 +57,7 @@ macro_rules! none_of ( /// ``` #[macro_export(local_inner_macros)] macro_rules! char ( - ($i:expr, $c: expr) => ( - { - use $crate::lib::std::result::Result::*; - use $crate::lib::std::option::Option::*; - use $crate::{Err,Needed}; - - use $crate::Slice; - use $crate::AsChar; - use $crate::InputIter; - - match ($i).iter_elements().next().map(|c| { - let b = c.as_char() == $c; - b - }) { - None => $crate::need_more($i, Needed::Size(1)), - Some(false) => { - let e: $crate::ErrorKind = $crate::ErrorKind::Char; - Err(Err::Error($crate::Context::Code($i, e))) - }, - //the unwrap should be safe here - Some(true) => Ok(( $i.slice($c.len()..), $i.iter_elements().next().unwrap().as_char() )) - } - } - ); + ($i:expr, $c: expr) => ( $crate::charc($i, $c) ); ); named!(#[doc="Matches a newline character '\\n'"], pub newline, char!('\n')); diff --git a/src/character/mod.rs b/src/character/mod.rs new file mode 100644 index 0000000..436daca --- /dev/null +++ b/src/character/mod.rs @@ -0,0 +1,84 @@ +#[macro_use] +mod macros; + +pub use self::macros::anychar; + +use internal::{Err,IResult,Needed}; +use util::ErrorKind; +use traits::{AtEof,Slice,AsChar,InputIter,InputLength,FindToken,need_more}; +use crate::Context; +use std::ops::RangeFrom; + +pub fn char(c: char) -> impl Fn(I) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar { + + move |i:I| { + match (i).iter_elements().next().map(|t| { + let b = t.as_char() == c; + (&c, b) + }) { + None => need_more(i, Needed::Size(1)), + Some((_, false)) => { + let e: ErrorKind = ErrorKind::Char; + Err(Err::Error(Context::Code(i, e))) + }, + Some((c, true)) => Ok(( i.slice(c.len()..), c.as_char() )) + } + } +} + +pub fn charc(input: I, c: char) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar { + + char(c)(input) +} + +pub fn one_of(list: T) -> impl Fn(I) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar+Copy, + T: FindToken<::Item> { + + move |i:I| { + match (i).iter_elements().next().map(|c| { + (c, list.find_token(c)) + }) { + None => need_more(i, Needed::Size(1)), + Some((_, false)) => Err(Err::Error(error_position!(i, ErrorKind::OneOf::))), + Some((c, true)) => Ok(( i.slice(c.len()..), c.as_char() )) + } + } +} + +pub fn one_ofc(input: I, list: T) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar+Copy, + T: FindToken<::Item> { + + one_of(list)(input) +} + +pub fn none_of(list: T) -> impl Fn(I) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar+Copy, + T: FindToken<::Item> { + + move |i:I| { + match (i).iter_elements().next().map(|c| { + (c, !list.find_token(c)) + }) { + None => need_more(i, Needed::Size(1)), + Some((_, false)) => Err(Err::Error(error_position!(i, ErrorKind::NoneOf::))), + Some((c, true)) => Ok(( i.slice(c.len()..), c.as_char() )) + } + } +} + +pub fn none_ofc(input: I, list: T) -> IResult + where I: Slice>+InputIter+AtEof, + ::Item: AsChar+Copy, + T: FindToken<::Item> { + + none_of(list)(input) +} diff --git a/src/multi.rs b/src/multi/macros.rs similarity index 95% rename from src/multi.rs rename to src/multi/macros.rs index 6802844..93990a6 100644 --- a/src/multi.rs +++ b/src/multi/macros.rs @@ -241,48 +241,10 @@ macro_rules! separated_nonempty_list_complete { #[macro_export(local_inner_macros)] macro_rules! many0( ($i:expr, $submac:ident!( $($args:tt)* )) => ( - { - use $crate::lib::std::result::Result::*; - use $crate::{Err,AtEof}; - - let ret; - let mut res = $crate::lib::std::vec::Vec::new(); - let mut input = $i.clone(); - - loop { - let input_ = input.clone(); - match $submac!(input_, $($args)*) { - Ok((i, o)) => { - // loop trip must always consume (otherwise infinite loops) - if i == input { - - if i.at_eof() { - ret = Ok((input, res)); - } else { - ret = Err(Err::Error(error_position!(input, $crate::ErrorKind::Many0))); - } - break; - } - res.push(o); - - input = i; - }, - Err(Err::Error(_)) => { - ret = Ok((input, res)); - break; - }, - Err(e) => { - ret = Err(e); - break; - }, - } - } - - ret - } + many0!($i, |i| $submac!(i, $($args)*)) ); ($i:expr, $f:expr) => ( - many0!($i, call!($f)); + $crate::many0c($i, $f) ); ); @@ -317,55 +279,10 @@ macro_rules! many0( #[macro_export(local_inner_macros)] macro_rules! many1( ($i:expr, $submac:ident!( $($args:tt)* )) => ( - { - use $crate::lib::std::result::Result::*; - use $crate::Err; - - use $crate::InputLength; - let i_ = $i.clone(); - match $submac!(i_, $($args)*) { - Err(Err::Error(_)) => Err(Err::Error( - error_position!(i_, $crate::ErrorKind::Many1) - )), - Err(Err::Failure(_)) => Err(Err::Failure( - error_position!(i_, $crate::ErrorKind::Many1) - )), - Err(i) => Err(i), - Ok((i1,o1)) => { - let mut res = $crate::lib::std::vec::Vec::with_capacity(4); - res.push(o1); - let mut input = i1; - let mut error = $crate::lib::std::option::Option::None; - loop { - let input_ = input.clone(); - match $submac!(input_, $($args)*) { - Err(Err::Error(_)) => { - break; - }, - Err(e) => { - error = $crate::lib::std::option::Option::Some(e); - break; - }, - Ok((i, o)) => { - if i.input_len() == input.input_len() { - break; - } - res.push(o); - input = i; - } - } - } - - match error { - $crate::lib::std::option::Option::Some(e) => Err(e), - $crate::lib::std::option::Option::None => Ok((input, res)) - } - } - } - } + many1!($i, |i| $submac!(i, $($args)*)) ); ($i:expr, $f:expr) => ( - many1!($i, call!($f)); + $crate::many1c($i, $f) ); ); @@ -1401,7 +1318,7 @@ mod tests { #[test] #[cfg(feature = "alloc")] fn many1() { - named!(multi<&[u8],Vec<&[u8]> >, many1!(tag!("abcd"))); + named!(multi<&[u8],Vec<&[u8]> >, many1!(dbg_dmp!(tag!("abcd")))); let a = &b"abcdef"[..]; let b = &b"abcdabcdefgh"[..]; diff --git a/src/multi/mod.rs b/src/multi/mod.rs new file mode 100644 index 0000000..79e4cc1 --- /dev/null +++ b/src/multi/mod.rs @@ -0,0 +1,113 @@ +#[macro_use] +mod macros; + +use internal::{Err,IResult}; +use util::ErrorKind; +use traits::{AtEof,InputLength}; + +pub fn many0c(mut input: I, mut f: F) -> IResult> + where F: FnMut(I) -> IResult { + + let mut acc = Vec::with_capacity(4); + + loop { + let input_ = input.clone(); + match f(input_) { + Err(Err::Error(_)) => return Ok((input, acc)), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(n)) => { + if input.at_eof() { + return Ok((input, acc)); + } else { + return Err(Err::Incomplete(n)); + } + } + Ok((i, o)) => { + if input.input_len() == i.input_len() { + return Err(Err::Error(error_position!(i, ErrorKind::Many0))) + } + + input = i; + acc.push(o); + } + } + } +} + +use std::fmt::Debug; +pub fn many1c(input: I, f: F) -> IResult> + where F: Fn(I) -> IResult { + let input_ = input.clone(); + match f(input_) { + Err(_) => { + return Err(Err::Error(error_position!(input, ErrorKind::Many1))) + }, + Ok((i2, o)) => { + let mut acc = Vec::with_capacity(4); + acc.push(o); + let mut input = i2; + + loop { + let input_ = input.clone(); + match f(input_) { + Err(Err::Error(_)) => return Ok((input, acc)), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(n)) => { + if input.at_eof() { + return Ok((input, acc)); + } else { + return Err(Err::Incomplete(n)); + } + } + Ok((i, o)) => { + if input.input_len() == i.input_len() { + return Err(Err::Error(error_position!(i, ErrorKind::Many1))) + } + + input = i; + acc.push(o); + } + } + } + } + } +} + +pub fn separated_list(input: I, mut sep: G, mut f: F) -> IResult> + where F: FnMut(I) -> IResult, + G: FnMut(I) -> IResult { + let mut acc = Vec::new(); + let (input, o) = f(input)?; + acc.push(o); + + let mut i = input; + + loop { + if i.input_len() == 0 { + return Ok((i, acc)); + } + + let i_ = i.clone(); + match sep(i_) { + Err(_) => return Ok((i, acc)), + Ok((i2, _)) => { + if i.input_len() == i2.input_len() { + return Err(Err::Error(error_position!(i, ErrorKind::Many0))) + } + + let i2_ = i2.clone(); + match f(i2_) { + Err(_) => return Ok((i, acc)), + Ok((i3, o)) => { + if i2.input_len() == i3.input_len() { + return Err(Err::Error(error_position!(i, ErrorKind::Many0))) + } + + i = i3; + acc.push(o); + } + } + } + } + } +} diff --git a/src/nom.rs b/src/nom.rs index 865bb91..a46766b 100644 --- a/src/nom.rs +++ b/src/nom.rs @@ -810,7 +810,7 @@ where T: Slice> + Slice> + Slice>, T: Clone + Offset, T: InputIter + AtEof, - ::Item: AsChar, + ::Item: AsChar+Copy, T: InputTakeAtPosition, ::Item: AsChar { @@ -839,7 +839,7 @@ where T: Slice> + Slice> + Slice>, T: Clone + Offset, T: InputIter + InputLength + ParseTo + AtEof, - ::Item: AsChar, + ::Item: AsChar+Copy, T: InputTakeAtPosition, ::Item: AsChar { @@ -854,7 +854,7 @@ where T: Slice> + Slice> + Slice>, T: Clone + Offset, T: InputIter + InputLength + ParseTo + AtEof, - ::Item: AsChar, + ::Item: AsChar+Copy, T: InputTakeAtPosition, ::Item: AsChar { @@ -868,7 +868,7 @@ where T: Slice> + Slice> + Slice>, T: Clone + Offset, T: InputIter + InputLength + ParseTo + AtEof, - ::Item: AsChar, + ::Item: AsChar+Copy, T: InputTakeAtPosition, ::Item: AsChar { @@ -883,7 +883,7 @@ where T: Slice> + Slice> + Slice>, T: Clone + Offset, T: InputIter + InputLength + ParseTo + AtEof, - ::Item: AsChar, + ::Item: AsChar+Copy, T: InputTakeAtPosition, ::Item: AsChar { diff --git a/src/sequence.rs b/src/sequence/macros.rs similarity index 93% rename from src/sequence.rs rename to src/sequence/macros.rs index f7e194d..5dd8733 100644 --- a/src/sequence.rs +++ b/src/sequence/macros.rs @@ -93,21 +93,19 @@ macro_rules! tuple_parser ( #[macro_export(local_inner_macros)] macro_rules! pair( ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ( - { - tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) - } + pair!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*)) ); ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => ( - pair!($i, $submac!($($args)*), call!($g)); + pair!($i, |i| $submac!(i, $($args)*), $g); ); ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => ( - pair!($i, call!($f), $submac!($($args)*)); + pair!($i, $f, |i| $submac!(i, $($args)*)); ); ($i:expr, $f:expr, $g:expr) => ( - pair!($i, call!($f), call!($g)); + $crate::pairc($i, $f, $g) ); ); @@ -115,21 +113,17 @@ macro_rules! pair( /// separated_pair(X,sep,Y) returns (x,y) #[macro_export(local_inner_macros)] macro_rules! separated_pair( - ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => ( - { - use $crate::lib::std::result::Result::*; - - match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { - Err(e) => Err(e), - Ok((i1, (o1, _, o2))) => { - Ok((i1, (o1, o2))) - } - } - } + ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ( + separated_pair!($i, |i| $submac!(i, $($args)*), $($rest)*) ); - - ($i:expr, $f:expr, $($rest:tt)+) => ( - separated_pair!($i, call!($f), $($rest)*); + ($i:expr, $f:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ( + separated_pair!($i, $f, |i| $submac!(i, $($args)*), $($rest)*) + ); + ($i:expr, $f:expr, $g:expr, $submac:ident!( $($args:tt)* )) => ( + separated_pair!($i, $f, $g, |i| $submac!(i, $($args)*)) + ); + ($i:expr, $f:expr, $g:expr, $h:expr) => ( + $crate::separated_pairc($i, $f, $g, $h) ); ); @@ -138,28 +132,19 @@ macro_rules! separated_pair( #[macro_export(local_inner_macros)] macro_rules! preceded( ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ( - { - use $crate::lib::std::result::Result::*; - - match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { - Err(e) => Err(e), - Ok((remaining, (_,o))) => { - Ok((remaining, o)) - } - } - } + preceded!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*)) ); ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => ( - preceded!($i, $submac!($($args)*), call!($g)); + preceded!($i, |i| $submac!(i, $($args)*), $g); ); ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => ( - preceded!($i, call!($f), $submac!($($args)*)); + preceded!($i, $f, |i| $submac!(i, $($args)*)); ); ($i:expr, $f:expr, $g:expr) => ( - preceded!($i, call!($f), call!($g)); + $crate::precededc($i, $f, $g) ); ); @@ -168,28 +153,19 @@ macro_rules! preceded( #[macro_export(local_inner_macros)] macro_rules! terminated( ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ( - { - use $crate::lib::std::result::Result::*; - - match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { - Err(e) => Err(e), - Ok((remaining, (o,_))) => { - Ok((remaining, o)) - } - } - } + terminated!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*)) ); ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => ( - terminated!($i, $submac!($($args)*), call!($g)); + terminated!($i, |i| $submac!(i, $($args)*), $g); ); ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => ( - terminated!($i, call!($f), $submac!($($args)*)); + terminated!($i, $f, |i| $submac!(i, $($args)*)); ); ($i:expr, $f:expr, $g:expr) => ( - terminated!($i, call!($f), call!($g)); + $crate::terminatedc($i, $f, $g) ); ); @@ -213,21 +189,17 @@ macro_rules! terminated( /// ``` #[macro_export(local_inner_macros)] macro_rules! delimited( - ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => ( - { - use $crate::lib::std::result::Result::*; - - match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { - Err(e) => Err(e), - Ok((i1, (_, o, _))) => { - Ok((i1, o)) - } - } - } + ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ( + delimited!($i, |i| $submac!(i, $($args)*), $($rest)*) ); - - ($i:expr, $f:expr, $($rest:tt)+) => ( - delimited!($i, call!($f), $($rest)*); + ($i:expr, $f:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ( + delimited!($i, $f, |i| $submac!(i, $($args)*), $($rest)*) + ); + ($i:expr, $f:expr, $g:expr, $submac:ident!( $($args:tt)* )) => ( + delimited!($i, $f, $g, |i| $submac!(i, $($args)*)) + ); + ($i:expr, $f:expr, $g:expr, $h:expr) => ( + $crate::delimitedc($i, $f, $g, $h) ); ); diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs new file mode 100644 index 0000000..3ac8a17 --- /dev/null +++ b/src/sequence/mod.rs @@ -0,0 +1,50 @@ +#[macro_use] +mod macros; + +use internal::IResult; + +pub fn pairc(input: I, first: F, second: G) -> IResult + where F: Fn(I) -> IResult, + G: Fn(I) -> IResult { + + let (input, o1) = first(input)?; + second(input).map(|(i, o2)| (i, (o1, o2))) +} + +pub fn precededc(input: I, first: F, second: G) -> IResult + where F: Fn(I) -> IResult, + G: Fn(I) -> IResult { + + let (input, _) = first(input)?; + second(input) +} + +pub fn terminatedc(input: I, first: F, second: G) -> IResult + where F: Fn(I) -> IResult, + G: Fn(I) -> IResult { + + let (input, o1) = first(input)?; + second(input).map(|(i, _)| (i, o1)) +} + +pub fn separated_pairc(input: I, first: F, sep: G, second: H) -> IResult + where F: Fn(I) -> IResult, + G: Fn(I) -> IResult, + H: Fn(I) -> IResult { + + let (input, o1) = first(input)?; + let (input, _) = sep(input)?; + second(input).map(|(i, o2)| (i, (o1, o2))) +} + +// needs FnMut because fold_many0 in tests/reborrow_fold.rs will not compile otherwise +pub fn delimitedc(input: I, mut first: F, mut sep: G, mut second: H) -> IResult + where F: FnMut(I) -> IResult, + G: FnMut(I) -> IResult, + H: FnMut(I) -> IResult { + + let (input, _) = first(input)?; + let (input, o2) = sep(input)?; + second(input).map(|(i, _)| (i, o2)) +} +