cl-parser: Make break bodies actually optional

Note: This goes against the original plan to 'not give Semi a special meaning', but it should be syntactically unambiguous.
This commit is contained in:
John 2024-04-18 16:42:48 -05:00
parent 736fc37a81
commit 17a522b633

View File

@ -781,13 +781,6 @@ impl<'t> Parser<'t> {
let start = self.loc(); let start = self.loc();
Ok(Expr { kind: f(self)?, extents: Span(start, self.loc()) }) Ok(Expr { kind: f(self)?, extents: Span(start, self.loc()) })
} }
pub fn optional_expr(&mut self) -> PResult<Option<Expr>> {
match self.expr() {
Ok(v) => Ok(Some(v)),
Err(Error { reason: Nothing, .. }) => Ok(None),
Err(e) => Err(e),
}
}
/// Parses an [ExprKind] /// Parses an [ExprKind]
/// ///
@ -816,14 +809,8 @@ impl<'t> Parser<'t> {
TokenKind::While => ExprKind::While(self.parse_while()?), TokenKind::While => ExprKind::While(self.parse_while()?),
TokenKind::If => ExprKind::If(self.parse_if()?), TokenKind::If => ExprKind::If(self.parse_if()?),
TokenKind::For => ExprKind::For(self.parse_for()?), TokenKind::For => ExprKind::For(self.parse_for()?),
TokenKind::Break => { TokenKind::Break => ExprKind::Break(self.parse_break()?),
self.consume_peeked(); TokenKind::Return => ExprKind::Return(self.parse_return()?),
Break { body: self.optional_expr()?.map(Into::into) }.into()
}
TokenKind::Return => {
self.consume_peeked();
Return { body: self.optional_expr()?.map(Into::into) }.into()
}
TokenKind::Continue => { TokenKind::Continue => {
self.consume_peeked(); self.consume_peeked();
Continue.into() Continue.into()
@ -1014,6 +1001,24 @@ impl<'t> Parser<'t> {
} }
/// ## Control flow subexpressions /// ## Control flow subexpressions
impl<'t> Parser<'t> { impl<'t> Parser<'t> {
/// [Break] = `break` (*unconsumed* `;` | [Expr])
pub fn parse_break(&mut self) -> PResult<Break> {
self.consume_peeked();
Ok(Break { body: self.ret_body(Parsing::Break)? })
}
/// [Return] = `return` (*unconsumed* `;` | [Expr])
pub fn parse_return(&mut self) -> PResult<Return> {
self.consume_peeked();
Ok(Return { body: self.ret_body(Parsing::Return)? })
}
/// ret_body = (*unconsumed* `;` | [Expr])
fn ret_body(&mut self, while_parsing: Parsing) -> PResult<Option<Box<Expr>>> {
Ok(match self.peek_kind(while_parsing)? {
TokenKind::Punct(Punct::Semi) => None,
_ => Some(self.expr()?.into()),
})
}
/// [While] = `while` [Expr] [Block] [Else]? /// [While] = `while` [Expr] [Block] [Else]?
pub fn parse_while(&mut self) -> PResult<While> { pub fn parse_while(&mut self) -> PResult<While> {
self.match_type(TokenKind::While, Parsing::While)?; self.match_type(TokenKind::While, Parsing::While)?;