ptx-parser 0.1.2

parser for ptx files
Documentation
use nom::{
    IResult,
    branch::alt,
    bytes::complete::{tag, take_while, take_while1},
    Parser,
    sequence::preceded,
    character::complete::{char, space0}};

use super::{Token, is_special};

#[cfg(feature = "std")]
use nom::multi::{many0, many1};


fn parse_token(input: &str) -> IResult<&str, Token> {
    preceded(space0,
    alt((
        char('.').map(|_| Token::Period),
        char('/').map(|_| Token::ForwardSlash),
        char('(').map(|_| Token::LeftParenthesis),
        char(')').map(|_| Token::RightParenthesis),
        char('[').map(|_| Token::LeftBracket),
        char(']').map(|_| Token::RightBracket),
        char('{').map(|_| Token::LeftBrace),
        char('}').map(|_| Token::RightBrace),
        char(',').map(|_| Token::Comma),
        char(';').map(|_| Token::Semicolon),
        char(':').map(|_| Token::Colon),
        char('%').map(|_| Token::Percent),
        take_while1(|c: char| !c.is_whitespace() && !is_special(c)).map(Token::String),
    )))(input)
}

#[cfg(feature = "std")]
fn parse_line(input: &str) -> IResult<&str, Vec<Token>> {
    many1(parse_token)(input.trim_start())
}

#[cfg(feature = "std")]
fn parse_file(input: &str) -> IResult<&str, Vec<Vec<Token>>> {
    many0(parse_line)(input)
}

#[cfg(test)]
mod token_tests {
    #[cfg(feature = "std")]
    use crate::ptx_files::_EXAMPLE_FILE;

    use super::*;

    #[test]
    fn test_parse_token_period() {
        assert_eq!(parse_token("."), Ok(("", Token::Period)));
    }

    #[test]
    fn test_parse_token_backslash() {
        assert_eq!(parse_token("/"), Ok(("", Token::ForwardSlash)));
    }

    #[test]
    fn test_parse_token_string() {
        assert_eq!(
            parse_token("Hello, world! "),
            Ok((", world! ", Token::String("Hello")))
        );
    }

    #[test]
    fn test_parse_token_empty() {
        assert!(parse_token("").is_err());
    }

    #[test]
    fn test_parse_token_whitespace() {
        assert!(parse_token(" ").is_err());
    }

    #[cfg(feature = "std")]
    #[test]
    fn test_tokens() {
        assert_eq!(
            parse_line(".version 7.5"),
            Ok((
                "",
                vec![
                    Token::Period,
                    Token::String("version"),
                    Token::String("7"),
                    Token::Period,
                    Token::String("5"),
                ]
            ))
        );
    }

    #[cfg(feature = "std")]
    #[test]
    fn test_parse_line() {
        match parse_line(_EXAMPLE_FILE) {
            Ok((input, tokens)) => {
                tokens.iter().for_each(|token|
                    println!("{token:?}")
                );
                println!("{input}");
            },
            Err(e) => {
                println!("{e:?}")
            }
        }   
    }

    #[cfg(feature = "std")]
    #[test]
    fn test_parse_file() {
        match parse_file(_EXAMPLE_FILE) {
            Ok((input, tokens)) => {
                tokens.iter().for_each(|token|
                    println!("{token:?}")
                );
                println!("{input}");
            },
            Err(e) => {
                println!("{e:?}")
            }
        }
    }
}