diff --git a/src/nom.rs b/src/nom.rs index b2c6261d3..babef1f16 100644 --- a/src/nom.rs +++ b/src/nom.rs @@ -91,7 +91,11 @@ use std::ops::{Index,Range,RangeFrom}; /// Recognizes lowercase and uppercase alphabetic characters: a-zA-Z pub fn alpha<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where T:Index, Output=T>+Index, Output=T>, - &'a T: IterIndices { + &'a T: IterIndices+InputLength { + if input.input_len() == 0 { + return Error(Position(ErrorKind::Alpha, input)) + } + for (idx, item) in input.iter_indices() { if ! item.is_alpha() { if idx == 0 { @@ -107,7 +111,11 @@ pub fn alpha<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where /// Recognizes numerical characters: 0-9 pub fn digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where T:Index, Output=T>+Index, Output=T>, - &'a T: IterIndices { + &'a T: IterIndices+InputLength { + if input.input_len() == 0 { + return Error(Position(ErrorKind::Digit, input)) + } + for (idx, item) in input.iter_indices() { if ! item.is_0_to_9() { if idx == 0 { @@ -123,7 +131,11 @@ pub fn digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where /// Recognizes numerical and alphabetic characters: 0-9a-zA-Z pub fn alphanumeric<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where T:Index, Output=T>+Index, Output=T>, - &'a T: IterIndices { + &'a T: IterIndices+InputLength { + if input.input_len() == 0 { + return Error(Position(ErrorKind::AlphaNumeric, input)); + } + for (idx, item) in input.iter_indices() { if ! item.is_alphanum() { if idx == 0 { @@ -139,7 +151,11 @@ pub fn alphanumeric<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where /// Recognizes spaces and tabs pub fn space<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where T:Index, Output=T>+Index, Output=T>, - &'a T: IterIndices { + &'a T: IterIndices+InputLength { + if input.input_len() == 0 { + return Error(Position(ErrorKind::Space, input)); + } + for (idx, item) in input.iter_indices() { let chr = item.as_char(); if ! (chr == ' ' || chr == '\t') { @@ -156,7 +172,11 @@ pub fn space<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where /// Recognizes spaces, tabs, carriage returns and line feeds pub fn multispace<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where T:Index, Output=T>+Index, Output=T>, - &'a T: IterIndices { + &'a T: IterIndices+InputLength { + if input.input_len() == 0 { + return Error(Position(ErrorKind::MultiSpace, input)); + } + for (idx, item) in input.iter_indices() { let chr = item.as_char(); if ! (chr == ' ' || chr == '\t' || chr == '\r' || chr == '\n') { diff --git a/tests/issues.rs b/tests/issues.rs index 92c95cb59..e8baefdff 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -1,7 +1,8 @@ #[macro_use] extern crate nom; -use nom::{IResult,Needed}; +use nom::{IResult,Needed,HexDisplay,space,digit}; +use std::str; #[allow(dead_code)] struct Range { @@ -63,3 +64,34 @@ fn issue_58() { } //trace_macros!(false); + +named!(parse_ints< Vec >, many0!(spaces_or_int)); + +fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32>{ + println!("{}", input.to_hex(8)); + chain!(input, + opt!(space) ~ + x: digit, + || { + println!("x: {:?}", x); + let result = str::from_utf8(x).unwrap(); + println!("Result: {}", result); + println!("int is empty?: {}", x.is_empty()); + match result.parse(){ + Ok(i) => i, + Err(_) => panic!("UH OH! NOT A DIGIT!") + } + } + ) +} + +#[test] +fn issue_142(){ + let subject = parse_ints(&b"12 34 5689"[..]); + let expected = IResult::Done(&b""[..], vec![12, 34, 5689]); + assert_eq!(subject, expected); + + let subject = parse_ints(&b"12 34 5689 "[..]); + let expected = IResult::Done(&b" "[..], vec![12, 34, 5689]); + assert_eq!(subject, expected) +}