chumsky icon indicating copy to clipboard operation
chumsky copied to clipboard

Add a combinator `then_or_not` to optionally run a parser after another

Open 91khr opened this issue 10 months ago • 2 comments

Closes #630, which first mentioned something like this.

This can be used in syntaxes like Rust's let statement, which has an optional type notation:

let a = 0;
let b: i32 = 0;

.then(...).or_not() doesn't work well in such cases, because when there's a parse error in the type, or_not would just suppress it and return None, leaving the following parsers confusing, or even worse, mistakenly starting parsing from the wrong position. In this particular example, when the type has an error, the parser may complain something like expected '=', got ':', rather than pointing out the error in the type.

With then_or_not, Rust's let statement can roughly be parsed with:

let let_stmt = group((
        just("let").padded(),
        pattern,
        just(':').padded().then_or_not(rust_type),
        just('=').padded().then_or_not(expr),
    ))
    .map(|(_, pat, ty, val)| Stmt::Let(pat, ty.map(|t| t.1), val.map(|v| v.1)));

And this would correctly report the errors in rust_type and expr.

91khr avatar Feb 21 '25 15:02 91khr

.then(...).or_not() doesn't work well in such cases, because when there's a parse error in the type, or_not would just suppress it and return None, leaving the following parsers confusing, or even worse, mistakenly starting parsing from the wrong position

I'm not sure I follow this logic. Optional type annotations can be expressed perfectly well (I've been doing so in my own lang for years) with the following

let pat = ... ; // Pattern
let ty = ... ;// Type annotation

text::keyword("let").padded()
    .ignore_then(pat)
    .then(just(":").padded().ignore_then(ty).or_not())
    .then_ignore(just("=").padded())
    .then(...)

Chumsky doesn't get confused by this, and the fact that the error is suppressed when parsing fails is not a problem: chumsky will still remember that the error could have been hit and will make use of that information when generating the final syntax error.

zesterer avatar Feb 23 '25 23:02 zesterer

Is this still an API hole for you, or is my suggested solution sufficient?

zesterer avatar Apr 06 '25 20:04 zesterer