Documentation
use super::{token::Token, Object, Result};
use logos::Lexer;

pub(super) fn parse<'a>(
    lexer: &mut Lexer<'a, Token<'a>>,
) -> Result<Vec<Object<'a>>> {
    let mut objects = Vec::new();

    let mut object_names: Vec<&'a str> = Vec::new();
    let mut awaiting_type = false;
    while let Some(token) = lexer.next() {
        match token {
            Ok(Token::Name(name)) => match awaiting_type {
                true => {
                    for object in object_names.iter() {
                        objects.push(Object {
                            name: object,
                            type_name: Some(name),
                        });
                    }
                    object_names.clear();
                    awaiting_type = false;
                }
                false => object_names.push(name),
            },
            Ok(Token::TypeSeparator) => awaiting_type = true,
            Ok(Token::RParen) => break,
            Ok(_) => return Err(("unexpected token", lexer.span())),
            Err(_) => return Err(("invalid token", lexer.span())),
        }
    }

    match awaiting_type {
        true => return Err(("erroneous type separator", lexer.span())),
        false => {
            for object in object_names.into_iter() {
                objects.push(Object {
                    name: object,
                    type_name: None,
                });
            }
        }
    }

    Ok(objects)
}

#[cfg(test)]
mod test {
    use super::{Object, Result, Token};
    use logos::Logos;
    use rstest::rstest;

    #[rstest]
    #[case(Ok(vec![Object { name: "a", type_name: None }]), "a)")]
    #[case(Ok(vec![Object { name: "a", type_name: Some("b") }]), "a - b)")]
    #[case(Ok(vec![
        Object { name: "a", type_name: Some("c") }, 
        Object { name: "b", type_name: Some("c") }
    ]), "a b - c)")]
    fn parse(#[case] expected: Result<Vec<Object>>, #[case] input: &str) {
        let mut lexer = Token::lexer(input);
        assert_eq!(expected, super::parse(&mut lexer));
    }
}