review comment: rework `parse_for_head` to reduce branching

This commit is contained in:
Esteban Küber 2023-11-06 23:55:40 +00:00
parent 147faa54d5
commit 1575e6e96e
1 changed files with 42 additions and 36 deletions

View File

@ -2610,28 +2610,42 @@ impl<'a> Parser<'a> {
} }
fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> { fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> {
let pat = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { let begin_paren = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) {
// Record whether we are about to parse `for (`. // Record whether we are about to parse `for (`.
// This is used below for recovery in case of `for ( $stuff ) $block` // This is used below for recovery in case of `for ( $stuff ) $block`
// in which case we will suggest `for $stuff $block`. // in which case we will suggest `for $stuff $block`.
let start_span = self.token.span; let start_span = self.token.span;
let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span)); let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
match self.parse_pat_allow_top_alt( Some((start_span, left))
} else {
None
};
// Try to parse the pattern `for ($PAT) in $EXPR`.
let pat = match (
self.parse_pat_allow_top_alt(
None, None,
RecoverComma::Yes, RecoverComma::Yes,
RecoverColon::Yes, RecoverColon::Yes,
CommaRecoveryMode::LikelyTuple, CommaRecoveryMode::LikelyTuple,
),
begin_paren,
) { ) {
Ok(pat) => pat, (Ok(pat), _) => pat, // Happy path.
Err(err) if self.eat_keyword(kw::In) => { (Err(err), Some((start_span, left))) if self.eat_keyword(kw::In) => {
// We know for sure we have seen `for ($SOMETHING in`. In the happy path this would
// happen right before the return of this method.
let expr = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None) { let expr = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None) {
Ok(expr) => expr, Ok(expr) => expr,
Err(expr_err) => { Err(expr_err) => {
// We don't know what followed the `in`, so cancel and bubble up the
// original error.
expr_err.cancel(); expr_err.cancel();
return Err(err); return Err(err);
} }
}; };
return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) { return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) {
// We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
// parser state and emit a targetted suggestion.
let span = vec![start_span, self.token.span]; let span = vec![start_span, self.token.span];
let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span)); let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
self.bump(); // ) self.bump(); // )
@ -2645,18 +2659,10 @@ impl<'a> Parser<'a> {
}); });
Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr)) Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr))
} else { } else {
Err(err) Err(err) // Some other error, bubble up.
}; };
} }
Err(err) => return Err(err), (Err(err), _) => return Err(err), // Some other error, bubble up.
}
} else {
self.parse_pat_allow_top_alt(
None,
RecoverComma::Yes,
RecoverColon::Yes,
CommaRecoveryMode::LikelyTuple,
)?
}; };
if !self.eat_keyword(kw::In) { if !self.eat_keyword(kw::In) {
self.error_missing_in_for_loop(); self.error_missing_in_for_loop();