asexp 0.1.2

Advanced S-expression-like format suitable for configuration and serialization
use super::Sexp;
use super::Atom;
use super::token::Token;

#[cfg(test)]
use super::token::Tokenizer;

#[derive(Debug, PartialEq)]
pub enum ParseError<'a> {
    UnexpectedToken(Token<'a>),
    UnexpectedEnd,
}

// Returns either the successfully parsed expression, or
// the invalid token which was not expected.
pub fn parse_sexp<'a, I>(tokenstream: &mut I) -> Result<Sexp, ParseError<'a>>
    where I: Iterator<Item = Token<'a>>
{
    match tokenstream.next() {
        None => Err(ParseError::UnexpectedEnd),
        Some(tok) => {
            match tok {
                Token::Str(s) => Ok(Sexp::from(s)),
                Token::QStr(s) => Ok(Sexp::from(s)),
                Token::UInt(u) => Ok(Sexp::from(Atom::UInt(u))),
                Token::SInt(s) => Ok(Sexp::from(Atom::SInt(s))),
                Token::Float(s) => Ok(Sexp::from(Atom::Float(s))),
                Token::OpenBrace => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBrace)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Tuple(exprs))
                }
                Token::OpenBracket => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBracket)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Array(exprs))
                }
                Token::OpenCurly => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(key) => {
                                match parse_sexp(tokenstream) {
                                    Ok(value) => {
                                        exprs.push((key, value));
                                    }
                                    Err(err) => return Err(err),
                                }
                            }
                            Err(ParseError::UnexpectedToken(Token::CloseCurly)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Map(exprs))
                }
                tok => Err(ParseError::UnexpectedToken(tok)),
            }
        }
    }
}

pub fn at_end<'a, I>(tokenstream: &mut I) -> bool
    where I: Iterator<Item = Token<'a>>
{
    tokenstream.next().is_none()
}

#[test]
fn test_parse_sexp() {
    let mut p = Tokenizer::new("123.45", true);
    assert_eq!(Ok(Sexp::from(123.45)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("123", true);
    assert_eq!(Ok(Sexp::from(123usize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("+123", true);
    assert_eq!(Ok(Sexp::from(123isize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));







    let mut p = Tokenizer::new("\"hal\\\"lo\"", true);
    assert_eq!(Ok(Sexp::from("hal\"lo")), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(123)", true);
    assert_eq!(Ok(Sexp::from((123usize,))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   ", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   123", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(false, at_end(&mut p));

    let mut p = Tokenizer::new("   ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc    ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc  }  ", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));

    let mut p = Tokenizer::new("[1 2 3]", true);
    assert_eq!(Ok(Sexp::Array(vec![Sexp::from(1usize), Sexp::from(2usize), Sexp::from(3usize)])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b 2}", true);
    assert_eq!(Ok(Sexp::Map(vec![(Sexp::from("a"), Sexp::from(1usize)),
                                 (Sexp::from("b"), Sexp::from(2usize))])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b }", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));
}