From 8d7dc1ed5424494b01aef5ce3bf72fa96fd7873d Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Wed, 14 Dec 2016 02:06:23 -0500 Subject: [PATCH] Add parsing for characters --- src/lib.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bd8aa71..461a2e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ pub enum Atom { Sym(String), /// A value representing a string literal. Str(String), + /// A value representing a single character. + Char(char), /// A value representing an integer. Any number containing no decimal point /// will be parsed as an `Int`. Int(i64), @@ -59,7 +61,7 @@ named!(list<&str, Vec >, ) ); -named!(atom<&str, Atom>, alt!(string | symbol | number)); +named!(atom<&str, Atom>, alt!(string | symbol | number | character)); named!(string<&str, Atom>, do_parse!( @@ -83,7 +85,7 @@ named!(symbol<&str, Atom>, fn valid_ident_prefix(ident: &str) -> IResult<&str, ()> { match ident.chars().next() { - Some(c) if !c.is_digit(10) && valid_ident_char(c) => + Some(c) if c != '#' && !c.is_digit(10) && valid_ident_char(c) => IResult::Done(&ident[1..], ()), None => IResult::Incomplete(nom::Needed::Unknown), _ => IResult::Error(nom::ErrorKind::Custom(0)), @@ -103,6 +105,15 @@ named!(number<&str, Atom>, ) ); +named!(character<&str, Atom>, + do_parse!( + opt!(multispace) >> + tag_s!("#\\") >> + character: take_s!(1) >> + (Atom::Char(character.chars().next().unwrap())) + ) +); + #[cfg(test)] #[test] fn test_parse_number() { @@ -127,7 +138,21 @@ fn test_parse_ident() { assert_eq!(symbol(" ->socket"), IResult::Done("", Atom::Sym("->socket".into()))); assert_eq!(symbol("fib("), IResult::Done("(", Atom::Sym("fib".into()))); + // We reserve #foo for the implementation to do as it wishes + assert!(symbol("#hi").is_err()); + assert!(symbol("0").is_err()); assert!(symbol("()").is_err()); assert!(symbol("").is_incomplete()); } + +#[cfg(test)] +#[test] +fn test_parse_char() { + assert_eq!(character("#\\\""), IResult::Done("", Atom::Char('"'))); + assert_eq!(character("#\\ "), IResult::Done("", Atom::Char(' '))); + assert_eq!(character(" #\\\\"), IResult::Done("", Atom::Char('\\'))); + + assert!(character("#").is_incomplete()); + assert!(character("a").is_err()); +} -- 2.43.2