diff --git a/CHANGELOG.md b/CHANGELOG.md index 4159b93d..43769ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,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 8998f01e..56477f22 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -28,7 +28,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`). @@ -37,9 +37,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 4a94b61a..fc56a5d8 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -347,14 +347,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 ); @@ -1479,8 +1483,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 @@ -1516,8 +1521,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), @@ -2753,9 +2759,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)?; @@ -2764,7 +2770,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 @@ -2772,7 +2778,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 => { @@ -2853,7 +2859,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 @@ -2896,7 +2902,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 b473babe..09d46b93 100644 --- a/src/token.rs +++ b/src/token.rs @@ -806,6 +806,7 @@ impl Token { match self { LexError(_) | SemiColon | // ; - is unary + Colon | // #{ foo: - is unary Comma | // ( ... , -expr ) - is unary //Period | LeftBrace | // { -expr } - is unary