How to handle cyclic recursion, i.e. two parsers that depend on each other? #263
-
Hi! I'm trying to implement a grammar that looks something like this:
Basically, I want to implement array indexing using an expression. The problem I'm running into is that an Here's roughly what my code looks like (it's probably not 100% correct, I'm just simplifying it for demonstration's sake): enum Lval {
Ident(Ident),
Index(Box<Lval>, Box<Expr>)
}
enum Expr {
Int(u32),
Add(Box<Expr>, Box<Expr>),
Lval(Lval),
}
fn lval_parser() -> impl Parser<Lval> {
recursive(|lval| {
choice((
ident_parser().map(Lval::Ident),
lval.then(expr_parser().delimited_by(just('['), just(']'))) // expr_parser() called here
.map(|(lval, expr)| Lval::Index(lval, expr)),
))
})
}
fn expr_parser() -> impl Parser<Expr> {
recursive(|expr| {
let atom = choice((
int_parser().map(Expr::Int),
lval_parser().map(Expr::Lval), // lval_parser() called here
));
todo!()
})
} My guess is that I have to forward-declare the parsers somehow, but I'm unsure how to do it. Any help would be greatly appreciated. Thank you for the awesome library by the way! I'm having lots of fun tinkering with it and learning about compilers. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There's a method on Examplelet first = Recursive::declare();
let second = Recursive::declare();
first.define(
just('A').then(second.clone().or_not())
);
second.define(
just('B').then(first.clone().or_not())
}; |
Beta Was this translation helpful? Give feedback.
There's a method on
Recursive
,Recursive::declare
. It can be used to define as many parsers as you need in advance, then define them all later withRecursive::define
Example