【Rust】文字列の正規表現

一文字ずつ処理したい場合
matches!の場合は、Someと比較する

fn main() {
    let mut str = "hello world!";
    while matches!(str.chars().next(), Some(_x @ ('a'..='z' | 'A'..='Z'))) {
        let mut chars = str.chars();
        chars.next();
        str = chars.as_str();
        println!("{:?}", str);
    }
}

Running `target/debug/sample`
“ello world!”
“llo world!”
“lo world!”
“o world!”
” world!”

これを応用して、文字列をパースする

fn main() {
    let source = "123 world";
    println!(
        "source: {}, parsed: {:?}",
        source,
        ident(whitespace(number(source)))
    );
}

fn whitespace(mut input: &str) -> &str {
    while matches!(input.chars().next(), Some(' ')) {
        let mut chars = input.chars();
        chars.next();
        input = chars.as_str();
    }
    input
}

fn ident(mut input: &str) -> &str {
    if matches!(
        input.chars().next(),
        Some(_x @ ('a'..='z' | 'A'..='Z'))
    ) {
        while matches!(
            input.chars().next(),
            Some(_x @ ('a'..='z' | 'A'..='Z' | '0'..='9'))
        ) {
            let mut chars = input.chars();
            chars.next();
            input = chars.as_str();
        }
    }
    input
}

fn number(mut input: &str) -> &str {
    if matches!(
        input.chars().next(),
        Some(_x @ ('-'|'+'|'.'|'0'..='9'))
    ) {
        while matches!(
            input.chars().next(),
            Some(_x @ ('.'|'0'..='9'))
        ) {
            let mut chars = input.chars();
            chars.next();
            input = chars.as_str();
        }
    }
    input
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_whitespace() {
        assert_eq!(whitespace("    "), "");
    }

    #[test]
    fn test_indent() {
        assert_eq!(ident("Adam"), "");
    }

    #[test]
    fn test_number() {
        assert_eq!(number("123.45 "), " ");
    }
}