diff --git a/CHANGELOG.md b/CHANGELOG.md index fc71773b..f7dac623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Breaking changes ---------------- * Negative index to an array or string yields the appropriate element/character counting from the _end_. +* The default `_` case of a `switch` statement now must be the last case, together with a new error variant `EvalAltResult::WrongSwitchDefaultCase`. * `ModuleResolver` trait methods take an additional parameter `source_path` that contains the path of the current environment. This is to facilitate loading other script files always from the current directory. * `FileModuleResolver` now resolves relative paths under the source path if there is no base path set. * `FileModuleResolver::base_path` now returns `Option<&str>` which is `None` if there is no base path set. diff --git a/src/parse_error.rs b/src/parse_error.rs index a0a62e00..bce23876 100644 --- a/src/parse_error.rs +++ b/src/parse_error.rs @@ -113,8 +113,10 @@ pub enum ParseErrorType { /// /// Never appears under the `no_object` feature. DuplicatedProperty(String), - /// A switch case is duplicated. + /// A `switch` case is duplicated. DuplicatedSwitchCase, + /// The default case of a `switch` statement is not the last. + WrongSwitchDefaultCase, /// Missing a property name for custom types and maps. /// /// Never appears under the `no_object` feature. @@ -195,6 +197,7 @@ impl ParseErrorType { Self::MalformedCapture(_) => "Invalid capturing", Self::DuplicatedProperty(_) => "Duplicated property in object map literal", Self::DuplicatedSwitchCase => "Duplicated switch case", + Self::WrongSwitchDefaultCase => "Default switch case is not the last", Self::PropertyExpected => "Expecting name of a property", Self::VariableExpected => "Expecting name of a variable", Self::Reserved(_) => "Invalid use of reserved keyword", diff --git a/src/parser.rs b/src/parser.rs index 18de1c75..ab7902dd 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -809,6 +809,7 @@ fn parse_switch( } let mut table = BTreeMap::>::new(); + let mut def_pos = Position::NONE; let mut def_stmt = None; loop { @@ -825,11 +826,13 @@ fn parse_switch( .into_err(*pos), ) } - (Token::Underscore, _) if def_stmt.is_none() => { + (Token::Underscore, pos) if def_stmt.is_none() => { + def_pos = *pos; eat_token(input, Token::Underscore); None } (Token::Underscore, pos) => return Err(PERR::DuplicatedSwitchCase.into_err(*pos)), + _ if def_stmt.is_some() => return Err(PERR::WrongSwitchDefaultCase.into_err(def_pos)), _ => Some(parse_expr(input, state, lib, settings.level_up())?), };