Help for recursive descent parser

trying to write a simple parser for python pgen grammar. using reset function for this code

/*
named_item:
    | NAME annotation? '=' item
    | item
    | '&''&'  atom
    | ('&' | '!') atom
    | '~'

item:
    | '[' alts ']'
    |  atom '?'
    |  atom '*'
    |  atom '+'
    |  atom '.' atom '+'
    |  atom

atom:
    | '(' alts ')'
    | NAME
    | STRING
*/
fn named_item(p: &mut Parser) {
    let mut m = p.start();
    match p.current() {
        NAME => {
            p.advance();
            if p.at(L_BRACK) {
                annotation(p);
            }
            if !p.eat(EQ) {
                m.reset(p);
                m = p.start();
            }
            item(p);
        }
        AMP if p.peek() == AMP => {
            p.advance();
            p.advance();
            atom(p);
        }
        AMP | BANG => {
            p.advance();
            atom(p);
        }
        TILDE => p.advance(),
        _ => item(p),
    }
    m.end(p, NAMED_ITEM);
}

is there a way to keep parsing without using reset function ?
grammar link i want to parse.
the parser is based on matklad tutorial.

The relevant flattened grammar looks like:

named_item:
  NAME annotation? '=' item
  NAME atom_suffix
  ...

atom_suffix: '?' | '*' | ...

But if you need to do more than recognize you're going to need a bit of shuffling.

I should note that most of the time, rewinding a parser by itself isn't terribly bad, it's only when you start getting into algorithmic issues like O(k^n) backtracking that's the real problem. It's more of an issue to consider for designing grammars to be simple than implementation of an existing one.

1 Like