pest-parser / pest

The Elegant Parser
https://pest.rs
Apache License 2.0
4.67k stars 262 forks source link

Parsing not working as expected #914

Closed onlycs closed 1 year ago

onlycs commented 1 year ago

Describe the bug This is a very specific bug and I don't know exactly what is going on.

I have some rules:

base_expr       = { (ident | fn_call) | lparen ~ base_expr ~ rparen }
...
expr            = _{ base_expr | op_expr_recurse | op_expr } /* I will add the other rules if needed, they build off of base_expr using operators, i.e. && */
...
fn_call     = { ident ~ lparen ~ (expr ~ ("," ~ expr)*)? ~ rparen }
fn_def      = { fn_kwd ~ ident ~ lparen ~ fn_params? ~ rparen ~ fn_return? ~ block }
...
in_block         = _{ ((expr | stmt | var | break_kwd | continue_kwd | return_def) ~ semi) | if_def | while_def | for_def }
block       = { "{" ~ in_block* ~ "}" }
...
program     = { SOI ~ (fn_def)* ~ EOI }

(I will attach the entire file below)

This will fail:

fn main() {
    print("Hello, World");
}

Because

  |
  |     print("Hello, World");
  |          ^---
  |
  = expected semi

Which does match ident rule in expr, but ignores the fn_call rule next to it in the or operator

However, Using: jasmine.pest.txt With:

let thing: int = 32;

fn main() {
    print("Hello, World");
}

Works because in the base_expr rule, fn_call is the first to be checked in the or group. However, moving it to the end will fail because it tries to match the ident rule first/only.

Expected behavior I want the program to come back and try to match the rest of the or group before erroring.

Additional context Sorry for making this so specific, I don't know how to generalize this more.