1
Fork 0

Refactor LhsExpr.

Combine `NotYetParsed` and `AttributesParsed` into a single variant,
because (a) that reflects the structure of the code that consumes
`LhsExpr`, and (b) because that variant will have the `Option` removed
in a later commit.
This commit is contained in:
Nicholas Nethercote 2024-06-18 20:40:27 +10:00
parent 42e47dfe82
commit 25523ba382
3 changed files with 38 additions and 42 deletions

View file

@ -70,9 +70,10 @@ macro_rules! maybe_whole_expr {
#[derive(Debug)] #[derive(Debug)]
pub(super) enum LhsExpr { pub(super) enum LhsExpr {
NotYetParsed, // Already parsed either (a) nothing or (b) just the outer attributes.
AttributesParsed(AttrWrapper), Unparsed { attrs: Option<AttrWrapper> },
AlreadyParsed { expr: P<Expr>, starts_statement: bool }, // Already parsed the expression.
Parsed { expr: P<Expr>, starts_statement: bool },
} }
#[derive(Debug)] #[derive(Debug)]
@ -133,9 +134,9 @@ impl<'a> Parser<'a> {
pub(super) fn parse_expr_res( pub(super) fn parse_expr_res(
&mut self, &mut self,
r: Restrictions, r: Restrictions,
already_parsed_attrs: Option<AttrWrapper>, attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs)) self.with_res(r, |this| this.parse_expr_assoc(attrs))
} }
/// Parses an associative expression. /// Parses an associative expression.
@ -143,15 +144,8 @@ impl<'a> Parser<'a> {
/// This parses an expression accounting for associativity and precedence of the operators in /// This parses an expression accounting for associativity and precedence of the operators in
/// the expression. /// the expression.
#[inline] #[inline]
fn parse_expr_assoc( fn parse_expr_assoc(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
&mut self, self.parse_expr_assoc_with(0, LhsExpr::Unparsed { attrs })
already_parsed_attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> {
let lhs = match already_parsed_attrs {
Some(attrs) => LhsExpr::AttributesParsed(attrs),
None => LhsExpr::NotYetParsed,
};
self.parse_expr_assoc_with(0, lhs)
} }
/// Parses an associative expression with operators of at least `min_prec` precedence. /// Parses an associative expression with operators of at least `min_prec` precedence.
@ -161,18 +155,17 @@ impl<'a> Parser<'a> {
lhs: LhsExpr, lhs: LhsExpr,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let mut starts_stmt = false; let mut starts_stmt = false;
let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs { let mut lhs = match lhs {
starts_stmt = starts_statement; LhsExpr::Parsed { expr, starts_statement } => {
expr starts_stmt = starts_statement;
} else { expr
let attrs = match lhs { }
LhsExpr::AttributesParsed(attrs) => Some(attrs), LhsExpr::Unparsed { attrs } => {
_ => None, if self.token.is_range_separator() {
}; return self.parse_expr_prefix_range(attrs);
if self.token.is_range_separator() { } else {
return self.parse_expr_prefix_range(attrs); self.parse_expr_prefix(attrs)?
} else { }
self.parse_expr_prefix(attrs)?
} }
}; };
@ -310,7 +303,10 @@ impl<'a> Parser<'a> {
Fixity::None => 1, Fixity::None => 1,
}; };
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed) this.parse_expr_assoc_with(
prec + prec_adjustment,
LhsExpr::Unparsed { attrs: None },
)
})?; })?;
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
@ -484,7 +480,7 @@ impl<'a> Parser<'a> {
let rhs = if self.is_at_start_of_range_notation_rhs() { let rhs = if self.is_at_start_of_range_notation_rhs() {
let maybe_lt = self.token.clone(); let maybe_lt = self.token.clone();
Some( Some(
self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed) self.parse_expr_assoc_with(prec + 1, LhsExpr::Unparsed { attrs: None })
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
) )
} else { } else {
@ -539,9 +535,12 @@ impl<'a> Parser<'a> {
this.bump(); this.bump();
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
// RHS must be parsed with more associativity than the dots. // RHS must be parsed with more associativity than the dots.
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) this.parse_expr_assoc_with(
.map(|x| (lo.to(x.span), Some(x))) op.unwrap().precedence() + 1,
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? LhsExpr::Unparsed { attrs: None },
)
.map(|x| (lo.to(x.span), Some(x)))
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
} else { } else {
(lo, None) (lo, None)
}; };
@ -2645,8 +2644,10 @@ impl<'a> Parser<'a> {
} else { } else {
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
} }
let expr = let expr = self.parse_expr_assoc_with(
self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), LhsExpr::NotYetParsed)?; 1 + prec_let_scrutinee_needs_par(),
LhsExpr::Unparsed { attrs: None },
)?;
let span = lo.to(expr.span); let span = lo.to(expr.span);
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
} }

View file

@ -398,7 +398,7 @@ impl<'a> Parser<'a> {
// Parse an associative expression such as `+ expr`, `% expr`, ... // Parse an associative expression such as `+ expr`, `% expr`, ...
// Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
let lhs = LhsExpr::AlreadyParsed { expr, starts_statement: false }; let lhs = LhsExpr::Parsed { expr, starts_statement: false };
if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) { if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) {
// We got a valid expression. // We got a valid expression.
self.restore_snapshot(snapshot); self.restore_snapshot(snapshot);

View file

@ -174,10 +174,7 @@ impl<'a> Parser<'a> {
// Perform this outside of the `collect_tokens_trailing_token` closure, // Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression // since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| { let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
this.parse_expr_assoc_with( this.parse_expr_assoc_with(0, LhsExpr::Parsed { expr, starts_statement: true })
0,
LhsExpr::AlreadyParsed { expr, starts_statement: true },
)
})?; })?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else { } else {
@ -210,10 +207,8 @@ impl<'a> Parser<'a> {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?; let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?;
let e = self.parse_expr_assoc_with( let e = self
0, .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?;
LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
)?;
StmtKind::Expr(e) StmtKind::Expr(e)
}; };
Ok(self.mk_stmt(lo.to(hi), kind)) Ok(self.mk_stmt(lo.to(hi), kind))