|
Hello, chumsky beginner here. My goal is to convert all the examples below into a Let Expression: but my rule (See below) currently expects an assignment (e.g. = 4;) in order to create a Let-Expression. I do want to make the assignment part optional but I do not know how to achieve this. I copied the "Let parsing" from the nano rust example and modified it to accept a comma separated list of identifiers like so: I did experiment with the or_not() modifier but when using or_not, the very last .map() expression does not accept the types any more and I am at a loss on how to fix the types. Maybe someone can point me to the canonical solution on how to deal with optional parts. Thank you very much. |
Replies: 1 comment 1 reply
|
Hey :) So, when trying to do transformations to existing parsers like this, the first thing to consider is: where to let let_ =
// Let Token (ignored)
just(Token::Let)
// list of identifiers
.ignore_then(
ident_items
.clone()
.map_with(|expr, e| (expr, e.span()))
)
// You want from here -- {
.then_ignore(just(Token::Op("=")))
// the assigned
.then(inline_expr.clone())
// -- } to here to be optional
// token semikolon (ignored)
.then_ignore(just(Token::Ctrl(';')))
// this is the next expression in the source code
.then(expr.clone())
.map(|((items, val), body)| Expr::Let(Box::new(items), Box::new(val), Box::new(body)));Step 1: Extract the optional bits: let assign_value = just(Token::Op("=")).ignore_then(inline_expr.clone());Because of how combinators work, the only transformation here was removing the Step 2: Insert it back to where we extracted the optional bits: Step 3: Apply Use let let_ =
just(Token::Let)
.ignore_then(
ident_items
.clone()
.map_with(|expr, e| (expr, e.span()))
)
// Now we make the `assign_value` optional
.then(assign_value.or_not())
// token semikolon (ignored)
.then_ignore(just(Token::Ctrl(';')))
// this is the next expression in the source code
.then(expr.clone())
// Also modify to map `Box::new` as opposed to boxing the optional value
.map(|((items, val), body)| Expr::Let(Box::new(items), val.map(Box::new), Box::new(body)));And there you go :) Your assignment now allow for optional expressions. |
Hey :) So, when trying to do transformations to existing parsers like this, the first thing to consider is: where to
.or_not(). Your intuition to use it is correct, though in the parsers current form that won't work. What you need to do is extract the optional part: