Function chumsky::primitive::choice

source ·
pub fn choice<T, E>(parsers: T) -> Choice<T, E>
Expand description

Parse using a tuple or array of many parsers, producing the output of the first to successfully parse.

This primitive has a twofold improvement over a chain of Parser::or calls:

  • Rust’s trait solver seems to resolve the Parser impl for this type much faster, significantly reducing compilation times.

  • Parsing is likely a little faster in some cases because the resulting parser is ‘less careful’ about error routing, and doesn’t perform the same fine-grained error prioritisation that Parser::or does.

These qualities make this parser ideal for lexers.

The output type of this parser is the output type of the inner parsers.

Examples

#[derive(Clone, Debug, PartialEq)]
enum Token {
    If,
    For,
    While,
    Fn,
    Int(u64),
    Ident(String),
}

let tokens = choice::<_, Simple<char>>((
    text::keyword("if").to(Token::If),
    text::keyword("for").to(Token::For),
    text::keyword("while").to(Token::While),
    text::keyword("fn").to(Token::Fn),
    text::int(10).from_str().unwrapped().map(Token::Int),
    text::ident().map(Token::Ident),
))
    .padded()
    .repeated();

use Token::*;
assert_eq!(
    tokens.parse("if 56 for foo while 42 fn bar"),
    Ok(vec![If, Int(56), For, Ident("foo".to_string()), While, Int(42), Fn, Ident("bar".to_string())]),
);

If you have more than 26 choices, the array-form of choice will work for any length. The downside being that the contained parsers must all be of the same type.

#[derive(Clone, Debug, PartialEq)]
enum Token {
    If,
    For,
    While,
    Fn,
    Def,
}

let tokens = choice::<_, Simple<char>>([
    text::keyword("if").to(Token::If),
    text::keyword("for").to(Token::For),
    text::keyword("while").to(Token::While),
    text::keyword("fn").to(Token::Fn),
    text::keyword("def").to(Token::Def),
])
    .padded()
    .repeated();

use Token::*;
assert_eq!(
    tokens.parse("def fn while if for"),
    Ok(vec![Def, Fn, While, If, For]),
);