-
Let's say I have rule like the following:
How can I write this with I understand that my grammar should be rewritten like so:
However I am not sure how to write the full let var = parse_id().map(ast::Lvalue::Var).labelled("variable");
let field = just(Token::Dot).ignore_then(parse_id()).labelled("field");
var.then(field.repeated())
.foldl(|var, field| ast::Lvalue::Field(Box::new(var), field))
.labelled("lvalue") |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The typical way to solve left recursion is to rewrite the pattern as a right-recursive one and then reverse the output. A technique I've used in my own lang is to use a helper enum to allow me to restate patterns like yours in an iterative manner, as if it were a chain of 'tails' following the original expression. let var = parse_id().map(ast::Lvalue::Var).labelled("variable");
enum Tail {
Field(...),
Call(...),
}
let tail =
// Field access
DOT.then(FIELD).map(Tail::Field)
// Call
.or(EXPR.separated_by(LBRACKET, RBRACKET)).map(Tail::Call);
let chain = var.then(tail.repeated()).foldl(|lhs, tail| {
match tail {
Tail::Field(field) => ast::LValue::Field(lhs, field),
Tail::Call(arg) => ast::LValue::Call(lhs, arg),
}
}); Here's how such a pattern would look for the syntax I presume you're going for. Additionally, the similar implementation I use for my own language is here. |
Beta Was this translation helpful? Give feedback.
The typical way to solve left recursion is to rewrite the pattern as a right-recursive one and then reverse the output.
A technique I've used in my own lang is to use a helper enum to allow me to restate patterns like yours in an iterative manner, as if it were a chain of 'tails' following the original expression.