ptx-parser 0.1.5

parser for ptx files
Documentation
use nom::{
    bytes::complete::take_while1,
    IResult,
    sequence::delimited,
    character::complete::char,
};

pub(crate) mod token;
pub(crate) mod preamble;
pub(crate) mod comment;
pub(crate) mod function;
pub(crate) mod global;
pub(crate) mod ptx_file;
pub(crate) mod body;

#[derive(Debug, PartialEq)]
pub(crate) struct PtxFile<'a> {
    preamble: Preamble<'a>,
    body: Option<&'a str>,
}

#[derive(Debug, PartialEq)]
pub(crate) enum Comment<'a> {
    Line(&'a str),
    Block(&'a str),
}

#[derive(Debug, PartialEq)]
pub(crate) struct Preamble<'a> {
    version: preamble::Version<'a>,
    target: preamble::Target<'a>,
    address_size: preamble::AddressSize<'a>,
}

#[derive(Debug, PartialEq)]
pub(crate) struct Function<'a> {
    signature: function::FunctionSignature<'a>,
    body: Option<body::FunctionBody<'a>>,
}

#[derive(Debug, PartialEq)]
pub(crate) struct Global<'a> {
    raw_string: &'a str,
}

fn is_special(c: char) -> bool {
    ['.', '/', '(', ')', '[', ']', '{', '}', ',', ';', ':', '%']
    .contains(&c)
}

pub(crate) fn parse_name(input: &str) -> IResult<&str, &str> {
    take_while1(|c: char| !c.is_whitespace() && !is_special(c))
    (input)
}

pub(crate) fn parse_parenthesized_naive(input: &str) -> IResult<&str, &str> {
    delimited(
        char('('),
        take_while1(|c: char| c != ')'),
        char(')')
    )(input)
}

pub(crate) fn parse_braced_naive(input: &str) -> IResult<&str, &str> {
    delimited(
        char('{'),
        take_while1(|c: char| c != '}'),
        char('}')
    )(input)
}

pub(crate) fn parse_braced_balanced(input: &str) -> IResult<&str, &str> {
    let mut chars = input.chars().enumerate();
    let (mut depth, mut end) = match chars.next() {
        Some((_, '{')) => (1, None),
        _ => return Err(nom::Err::Error(
            nom::error::Error::new(input, nom::error::ErrorKind::Char)
        )),
    };

    for (i, c) in chars {
        match c {
            '{' => depth += 1,
            '}' => {
                depth -= 1;
                if depth == 0 {
                    end = Some(i);
                    break;
                }
            },
            _ => (),
        }
    }
    if let Some(end) = end {
        Ok((&input[end+1..], &input[1..end]))
    } else {
        Err(nom::Err::Error(
            nom::error::Error::new(input, nom::error::ErrorKind::Eof)
        ))
    }
}

#[cfg(test)]
mod test_parse_parenthesized {
    
    use super::parse_parenthesized_naive;
    
    #[test]
    fn no_newline() {
        let input = "(hello)";
        let expected = Ok(("", "hello"));
        assert_eq!(parse_parenthesized_naive(input), expected)
    }

    #[test]
    fn newline() {
        let input = "(hello\n)";
        let expected = Ok(("", "hello\n"));
        assert_eq!(parse_parenthesized_naive(input), expected)
    }

    #[test]
    fn one_left_parenthesis() {
        let input = "(hello";
        assert!(
            parse_parenthesized_naive(input).is_err()
        )
    }

    #[test]
    fn two_left_one_right() {
        let input = "((hello)";
        assert_eq!(
            parse_parenthesized_naive(input),
            Ok(("", "(hello")),
        )
    }
}

#[cfg(test)]
mod test_parse_braced {
    
    use super::parse_braced_naive;
    
    #[test]
    fn no_newline() {
        let input = "{hello}";
        let expected = Ok(("", "hello"));
        assert_eq!(parse_braced_naive(input), expected)
    }

    #[test]
    fn newline() {
        let input = "{hello\n}";
        let expected = Ok(("", "hello\n"));
        assert_eq!(parse_braced_naive(input), expected)
    }

    #[test]
    fn one_left_brace() {
        let input = "{hello";
        assert!(
            parse_braced_naive(input).is_err()
        )
    }

    #[test]
    fn two_left_one_right() {
        let input = "{{hello}";
        assert_eq!(
            parse_braced_naive(input),
            Ok(("", "{hello")),
        )
    }

    #[test]
    fn mock_function_body() {
        let input = "{.reg .b32 %r<3>}";
        let expected = Ok(("", ".reg .b32 %r<3>"));
        assert_eq!(parse_braced_naive(input), expected)
    }
}

#[cfg(test)]
mod test_parse_braced_balanced {
    
    use super::parse_braced_balanced;
    
    #[test]
    fn one_pair() {
        let input = "{hello}";
        let expected = Ok(("", "hello"));
        assert_eq!(parse_braced_balanced(input), expected)
    }

    #[test]
    fn two_pairs() {
        let input = "{hello}{world}";
        let expected = Ok(("{world}", "hello"));
        assert_eq!(parse_braced_balanced(input), expected)
    }

    #[test]
    fn nested_pair() {
        let input = "{hello{world}}";
        let expected = Ok(("", "hello{world}"));
        assert_eq!(parse_braced_balanced(input), expected)
    }

    #[test]
    fn imbalanced() {
        let input = "{hello{world}";
        assert!(
            parse_braced_balanced(input).is_err()
        )
    }
}