Skip to content

Add filter_map I think #896

@jnhyatt

Description

@jnhyatt

This might be a skill issue, but I'm trying to create a lexer/parser combo, my tokenizer sees 1234 and spits out Token::Number(BigUint). Then I want my parser to see '-'? Number and spit out a Ast::Literal(BigInt). What should my parser look like? My first instinct was something like:

just(Token::Neg).or_not()
    .then(any().filter(|tok| matches!(tok, Token::Number(_))))
    .map(|(neg, num)| {
        // Uh-oh, num is a Token::Number guaranteed, but I have to do something nasty like:
        let number = match num { Token::Number(x) => x, _ => unreachable!() };
        ...
    })

When I hit situations like this with Iterators, I reach for filter_map:

just(Token::Neg).or_not()
    .then(any().filter_map(|tok| match tok { Token::Number(x) => Some(x), _ => None }))
    .map(|(neg, num)| {
        // Yay, num is a BigUint!
        ...
    })

I can't find that particular combinator in chumsky. Am I missing it, or is it an oversight, or maybe it's not as simple as it looks? Or best of all, maybe there's a simpler way to do what I'm trying to do here? I suppose there's select...

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions