use nom::{IResult, branch::alt, bytes::complete::{tag, take_while1, take_until}, character::complete::{anychar, char, none_of}, combinator::{map, recognize}, multi::many0, sequence::{delimited, preceded}};
#[derive(Debug, PartialEq)]
pub enum Token {
Literal(char),
Dot,
Star,
Plus,
Question,
Custom(String),
}
fn custom_token(input: &str) -> IResult<&str, Token> {
map(
delimited(char('<'), take_until(">"), char('>')),
|s: &str| Token::Custom(s.to_string()),
)(input)
}
fn token(input: &str) -> IResult<&str, Token> {
alt((
map(char('.'), |_| Token::Dot),
map(char('*'), |_| Token::Star),
map(char('+'), |_| Token::Plus),
map(char('?'), |_| Token::Question),
custom_token,
map(none_of(".*+?<>"), |c| Token::Literal(c)),
))(input)
}
pub fn tokenize(input: &str) -> IResult<&str, Vec<Token>> {
many0(token)(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tokenize() {
let input = "a.b*<DIGIT>?";
let (_, tokens) = tokenize(input).unwrap();
assert_eq!(tokens, vec![
Token::Literal('a'),
Token::Dot,
Token::Literal('b'),
Token::Star,
Token::Custom("DIGIT".to_string()),
Token::Question,
]);
}
}