From 063ca377da8cedc7c2394a5762904d3ec37b3dd2 Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Wed, 14 Dec 2016 01:56:48 -0500 Subject: [PATCH] Add tests for parsing number and symbol Fix a bug in number parsing where it would accept invalid numbers like 123q. --- src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b8982f4..bd8aa71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,12 +74,22 @@ named!(string<&str, Atom>, named!(symbol<&str, Atom>, do_parse!( - peek!(not!(digit)) >> + opt!(multispace) >> + peek!(valid_ident_prefix) >> name: take_while1_s!(valid_ident_char) >> (Atom::Sym(name.into())) ) ); +fn valid_ident_prefix(ident: &str) -> IResult<&str, ()> { + match ident.chars().next() { + Some(c) if !c.is_digit(10) && valid_ident_char(c) => + IResult::Done(&ident[1..], ()), + None => IResult::Incomplete(nom::Needed::Unknown), + _ => IResult::Error(nom::ErrorKind::Custom(0)), + } +} + fn valid_ident_char(c: char) -> bool { !c.is_whitespace() && c != '"' && c != '(' && c != ')' } @@ -88,13 +98,36 @@ named!(number<&str, Atom>, do_parse!( opt!(multispace) >> integral: digit >> + peek!(not!(valid_ident_prefix)) >> (Atom::Int(integral.chars().fold(0, |i, c| i * 10 + c as i64 - '0' as i64))) ) ); #[cfg(test)] -mod tests { - #[test] - fn it_works() { - } +#[test] +fn test_parse_number() { + assert_eq!(number("0"), IResult::Done("", Atom::Int(0))); + assert_eq!(number("123"), IResult::Done("", Atom::Int(123))); + assert_eq!(number("0123456789"), IResult::Done("", Atom::Int(123456789))); + assert_eq!(number(" 42"), IResult::Done("", Atom::Int(42))); + + assert!(number(" 42a").is_err()); + assert_eq!(number("13()"), IResult::Done("()", Atom::Int(13))); + + assert!(number("abc").is_err()); + assert!(number("()").is_err()); + assert!(number("").is_incomplete()); +} + +#[cfg(test)] +#[test] +fn test_parse_ident() { + assert_eq!(symbol("+"), IResult::Done("", Atom::Sym("+".into()))); + assert_eq!(symbol(" nil?"), IResult::Done("", Atom::Sym("nil?".into()))); + assert_eq!(symbol(" ->socket"), IResult::Done("", Atom::Sym("->socket".into()))); + assert_eq!(symbol("fib("), IResult::Done("(", Atom::Sym("fib".into()))); + + assert!(symbol("0").is_err()); + assert!(symbol("()").is_err()); + assert!(symbol("").is_incomplete()); } -- 2.43.2