diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e21e9b3..8c981e62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Bug fixes * Printing of integral floating-point numbers is fixed (used to only prints `0.0`). * `func!()` calls now work properly under `no_closure`. +* Fixed parsing of unary negation such that expressions like `if foo { ... } -x` parses correctly. Version 1.1.2 diff --git a/src/engine_api.rs b/src/engine_api.rs index 8cafcd26..d9d716da 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -27,7 +27,7 @@ impl Engine { pub(crate) fn global_namespace(&self) -> &Module { self.global_modules .first() - .expect("global_modules contains at least one module") + .expect("global_modules not empty") } /// Get a mutable reference to the global namespace module /// (which is the first module in `global_modules`). @@ -36,9 +36,9 @@ impl Engine { Shared::get_mut( self.global_modules .first_mut() - .expect("global_modules contains at least one module"), + .expect("global_modules not empty"), ) - .expect("global namespace module is never shared") + .expect("global namespace never shared") } /// Register a custom function with the [`Engine`]. /// diff --git a/src/parse.rs b/src/parse.rs index 4cf3b68e..4ea4d317 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -355,14 +355,18 @@ fn ensure_not_assignment(input: &mut TokenStream) -> Result<(), ParseError> { } /// Consume a particular [token][Token], checking that it is the expected one. +/// +/// # Panics +/// +/// Panics if the next token is not the expected one. #[inline] -fn eat_token(input: &mut TokenStream, token: Token) -> Position { +fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position { let (t, pos) = input.next().expect(NEVER_ENDS); - if t != token { + if t != expected_token { unreachable!( "expecting {} (found {}) at {}", - token.syntax(), + expected_token.syntax(), t.syntax(), pos ); @@ -1488,8 +1492,9 @@ fn parse_unary( match token { // -expr - Token::UnaryMinus => { - let pos = eat_token(input, Token::UnaryMinus); + Token::Minus | Token::UnaryMinus => { + let token = token.clone(); + let pos = eat_token(input, token); match parse_unary(input, state, lib, settings.level_up())? { // Negative integer @@ -1525,8 +1530,9 @@ fn parse_unary( } } // +expr - Token::UnaryPlus => { - let pos = eat_token(input, Token::UnaryPlus); + Token::Plus | Token::UnaryPlus => { + let token = token.clone(); + let pos = eat_token(input, token); match parse_unary(input, state, lib, settings.level_up())? { expr @ Expr::IntegerConstant(_, _) => Ok(expr), @@ -2769,9 +2775,9 @@ fn parse_stmt( let (token, token_pos) = match input.peek().expect(NEVER_ENDS) { (Token::EOF, pos) => return Ok(Stmt::Noop(*pos)), - x => x, + (x, pos) => (x, *pos), }; - settings.pos = *token_pos; + settings.pos = token_pos; #[cfg(not(feature = "unchecked"))] settings.ensure_level_within_max_limit(state.max_expr_depth)?; @@ -2780,7 +2786,7 @@ fn parse_stmt( // ; - empty statement Token::SemiColon => { eat_token(input, Token::SemiColon); - Ok(Stmt::Noop(settings.pos)) + Ok(Stmt::Noop(token_pos)) } // { - statements block @@ -2788,7 +2794,7 @@ fn parse_stmt( // fn ... #[cfg(not(feature = "no_function"))] - Token::Fn if !settings.is_global => Err(PERR::WrongFnDefinition.into_err(settings.pos)), + Token::Fn if !settings.is_global => Err(PERR::WrongFnDefinition.into_err(token_pos)), #[cfg(not(feature = "no_function"))] Token::Fn | Token::Private => { @@ -2869,7 +2875,7 @@ fn parse_stmt( let pos = eat_token(input, Token::Break); Ok(Stmt::BreakLoop(AST_OPTION_BREAK_OUT, pos)) } - Token::Continue | Token::Break => Err(PERR::LoopBreak.into_err(settings.pos)), + Token::Continue | Token::Break => Err(PERR::LoopBreak.into_err(token_pos)), Token::Return | Token::Throw => { let (return_type, token_pos) = input @@ -2912,7 +2918,7 @@ fn parse_stmt( Token::Import => parse_import(input, state, lib, settings.level_up()), #[cfg(not(feature = "no_module"))] - Token::Export if !settings.is_global => Err(PERR::WrongExport.into_err(settings.pos)), + Token::Export if !settings.is_global => Err(PERR::WrongExport.into_err(token_pos)), #[cfg(not(feature = "no_module"))] Token::Export => parse_export(input, state, lib, settings.level_up()), diff --git a/src/token.rs b/src/token.rs index 61c31bcb..122dd792 100644 --- a/src/token.rs +++ b/src/token.rs @@ -817,6 +817,7 @@ impl Token { match self { LexError(_) | SemiColon | // ; - is unary + Colon | // #{ foo: - is unary Comma | // ( ... , -expr ) - is unary //Period | LeftBrace | // { -expr } - is unary