From 17a522b6338321eff679c138e8ab23bd81aa18c4 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 18 Apr 2024 16:42:48 -0500 Subject: [PATCH] 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. --- cl-parser/src/parser.rs | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/cl-parser/src/parser.rs b/cl-parser/src/parser.rs index e0aa23c..b078792 100644 --- a/cl-parser/src/parser.rs +++ b/cl-parser/src/parser.rs @@ -781,13 +781,6 @@ impl<'t> Parser<'t> { let start = self.loc(); Ok(Expr { kind: f(self)?, extents: Span(start, self.loc()) }) } - pub fn optional_expr(&mut self) -> PResult> { - match self.expr() { - Ok(v) => Ok(Some(v)), - Err(Error { reason: Nothing, .. }) => Ok(None), - Err(e) => Err(e), - } - } /// Parses an [ExprKind] /// @@ -816,14 +809,8 @@ impl<'t> Parser<'t> { TokenKind::While => ExprKind::While(self.parse_while()?), TokenKind::If => ExprKind::If(self.parse_if()?), TokenKind::For => ExprKind::For(self.parse_for()?), - TokenKind::Break => { - self.consume_peeked(); - Break { body: self.optional_expr()?.map(Into::into) }.into() - } - TokenKind::Return => { - self.consume_peeked(); - Return { body: self.optional_expr()?.map(Into::into) }.into() - } + TokenKind::Break => ExprKind::Break(self.parse_break()?), + TokenKind::Return => ExprKind::Return(self.parse_return()?), TokenKind::Continue => { self.consume_peeked(); Continue.into() @@ -1014,6 +1001,24 @@ impl<'t> Parser<'t> { } /// ## Control flow subexpressions impl<'t> Parser<'t> { + /// [Break] = `break` (*unconsumed* `;` | [Expr]) + pub fn parse_break(&mut self) -> PResult { + self.consume_peeked(); + Ok(Break { body: self.ret_body(Parsing::Break)? }) + } + /// [Return] = `return` (*unconsumed* `;` | [Expr]) + pub fn parse_return(&mut self) -> PResult { + self.consume_peeked(); + Ok(Return { body: self.ret_body(Parsing::Return)? }) + } + /// ret_body = (*unconsumed* `;` | [Expr]) + fn ret_body(&mut self, while_parsing: Parsing) -> PResult>> { + Ok(match self.peek_kind(while_parsing)? { + TokenKind::Punct(Punct::Semi) => None, + _ => Some(self.expr()?.into()), + }) + } + /// [While] = `while` [Expr] [Block] [Else]? pub fn parse_while(&mut self) -> PResult { self.match_type(TokenKind::While, Parsing::While)?;