diff --git a/CHANGELOG.md b/CHANGELOG.md index 374f4f5c9..ccff89562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug fixes New features ------------ +* The `break`, `continue`, `return` and `throw` statements can now follow the `??` operator to short-circuit operations where the value is `()`. * A new symbol, `$func$`, is added to custom syntax to allow parsing of anonymous functions. diff --git a/src/parser.rs b/src/parser.rs index 048d44aa6..462b90057 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2265,20 +2265,31 @@ impl Engine { // Parse the RHS let rhs = match op_token { + Token::DoubleQuestion + if matches!( + state.input.peek().unwrap().0, + Token::Break | Token::Continue | Token::Return | Token::Throw + ) => + { + let stmt = self.parse_stmt(state, settings)?; + let block: StmtBlock = stmt.into(); + Expr::Stmt(block.into()) + } // [xxx..] | (xxx..) | {xxx..} | xxx.., | xxx..; | xxx.. => // [xxx..=] | (xxx..=) | {xxx..=} | xxx..=, | xxx..=; | xxx..= => - Token::ExclusiveRange | Token::InclusiveRange => { - let (next_op, next_pos) = state.input.peek().unwrap(); - - match next_op { + Token::ExclusiveRange | Token::InclusiveRange + if matches!( + state.input.peek().unwrap().0, Token::RightBracket - | Token::RightParen - | Token::RightBrace - | Token::Comma - | Token::SemiColon - | Token::DoubleArrow => Expr::Unit(*next_pos), - _ => self.parse_unary(state, settings)?, - } + | Token::RightParen + | Token::RightBrace + | Token::Comma + | Token::SemiColon + | Token::DoubleArrow + ) => + { + let (_, next_pos) = state.input.peek().unwrap(); + Expr::Unit(*next_pos) } _ => self.parse_unary(state, settings)?, }; diff --git a/tests/looping.rs b/tests/looping.rs index dc142ee8d..b891d67ba 100644 --- a/tests/looping.rs +++ b/tests/looping.rs @@ -28,6 +28,20 @@ fn test_loop() { 21 ); + assert_eq!( + engine + .eval::( + " + for n in 0..10 { + let x = if n <= 5 { n }; + x ?? break 42; + } + " + ) + .unwrap(), + 42 + ); + assert_eq!(*engine.compile("let x = 0; break;").unwrap_err().err_type(), ParseErrorType::LoopBreak); #[cfg(not(feature = "no_function"))]