Skip to content

Commit

Permalink
Merge pull request #1644 from dtolnay/ifelse
Browse files Browse the repository at this point in the history
Remove recursion from parsing of Expr::If
  • Loading branch information
dtolnay authored May 11, 2024
2 parents e9e6329 + 70777ce commit e2e7f2d
Showing 1 changed file with 45 additions and 31 deletions.
76 changes: 45 additions & 31 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2255,40 +2255,54 @@ pub(crate) mod parsing {
impl Parse for ExprIf {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
Ok(ExprIf {
attrs,
if_token: input.parse()?,
cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
then_branch: input.parse()?,
else_branch: {
if input.peek(Token![else]) {
Some(input.call(else_block)?)
} else {
None
}
},
})
}
}

#[cfg(feature = "full")]
fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
let else_token: Token![else] = input.parse()?;
let mut clauses = Vec::new();
let mut expr;
loop {
let if_token: Token![if] = input.parse()?;
let cond = input.call(Expr::parse_without_eager_brace)?;
let then_branch: Block = input.parse()?;

let lookahead = input.lookahead1();
let else_branch = if lookahead.peek(Token![if]) {
input.parse().map(Expr::If)?
} else if lookahead.peek(token::Brace) {
Expr::Block(ExprBlock {
attrs: Vec::new(),
label: None,
block: input.parse()?,
})
} else {
return Err(lookahead.error());
};
expr = ExprIf {
attrs: Vec::new(),
if_token,
cond: Box::new(cond),
then_branch,
else_branch: None,
};

if !input.peek(Token![else]) {
break;
}

let else_token: Token![else] = input.parse()?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![if]) {
expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
clauses.push(expr);
continue;
} else if lookahead.peek(token::Brace) {
expr.else_branch = Some((
else_token,
Box::new(Expr::Block(ExprBlock {
attrs: Vec::new(),
label: None,
block: input.parse()?,
})),
));
break;
} else {
return Err(lookahead.error());
}
}

Ok((else_token, Box::new(else_branch)))
while let Some(mut prev) = clauses.pop() {
*prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
expr = prev;
}
expr.attrs = attrs;
Ok(expr)
}
}

#[cfg(feature = "full")]
Expand Down

0 comments on commit e2e7f2d

Please sign in to comment.