Add allow_looping.
This commit is contained in:
parent
7cd76c6d18
commit
fd26654125
@ -17,7 +17,7 @@ Bug fixes
|
||||
New features
|
||||
------------
|
||||
|
||||
* New options for `Engine` which allows disabling `if`-expressions, `switch`-expressions, statement expressions and/or anonymous functions.
|
||||
* New options for `Engine` which allows disabling `if`-expressions, `switch`-expressions, statement expressions, anonymous functions and/or looping (i.e. `while`, `loop`, `do` and `for` statements).
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
|
@ -16,6 +16,8 @@ pub struct LanguageOptions {
|
||||
/// Is anonymous function allowed?
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub allow_anonymous_fn: bool,
|
||||
/// Is looping allowed?
|
||||
pub allow_loop: bool,
|
||||
}
|
||||
|
||||
impl LanguageOptions {
|
||||
@ -26,7 +28,9 @@ impl LanguageOptions {
|
||||
allow_if_expr: true,
|
||||
allow_switch_expr: true,
|
||||
allow_stmt_expr: true,
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
allow_anonymous_fn: true,
|
||||
allow_loop: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,4 +88,14 @@ impl Engine {
|
||||
pub fn set_allow_anonymous_fn(&mut self, enable: bool) {
|
||||
self.options.allow_anonymous_fn = enable;
|
||||
}
|
||||
/// Is looping allowed?
|
||||
#[inline(always)]
|
||||
pub fn allow_looping(&self) -> bool {
|
||||
self.options.allow_loop
|
||||
}
|
||||
/// Set whether looping is allowed.
|
||||
#[inline(always)]
|
||||
pub fn set_allow_looping(&mut self, enable: bool) {
|
||||
self.options.allow_loop = enable;
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,8 @@ struct ParseSettings {
|
||||
allow_switch_expr: bool,
|
||||
/// Is statement-expression allowed?
|
||||
allow_stmt_expr: bool,
|
||||
/// Is looping allowed?
|
||||
allow_loop: bool,
|
||||
/// Current expression nesting level.
|
||||
level: usize,
|
||||
}
|
||||
@ -1174,6 +1176,7 @@ fn parse_primary(
|
||||
allow_switch_expr: settings.default_options.allow_switch_expr,
|
||||
allow_stmt_expr: settings.default_options.allow_stmt_expr,
|
||||
allow_anonymous_fn: settings.default_options.allow_anonymous_fn,
|
||||
allow_loop: settings.default_options.allow_loop,
|
||||
is_global: false,
|
||||
is_function_scope: true,
|
||||
is_breakable: false,
|
||||
@ -2802,6 +2805,7 @@ fn parse_stmt(
|
||||
allow_switch_expr: settings.default_options.allow_switch_expr,
|
||||
allow_stmt_expr: settings.default_options.allow_stmt_expr,
|
||||
allow_anonymous_fn: settings.default_options.allow_anonymous_fn,
|
||||
allow_loop: settings.default_options.allow_loop,
|
||||
is_global: false,
|
||||
is_function_scope: true,
|
||||
is_breakable: false,
|
||||
@ -2846,19 +2850,23 @@ fn parse_stmt(
|
||||
|
||||
Token::If => parse_if(input, state, lib, settings.level_up()),
|
||||
Token::Switch => parse_switch(input, state, lib, settings.level_up()),
|
||||
Token::While | Token::Loop => parse_while_loop(input, state, lib, settings.level_up()),
|
||||
Token::Do => parse_do(input, state, lib, settings.level_up()),
|
||||
Token::For => parse_for(input, state, lib, settings.level_up()),
|
||||
Token::While | Token::Loop if settings.allow_loop => {
|
||||
parse_while_loop(input, state, lib, settings.level_up())
|
||||
}
|
||||
Token::Do if settings.allow_loop => parse_do(input, state, lib, settings.level_up()),
|
||||
Token::For if settings.allow_loop => parse_for(input, state, lib, settings.level_up()),
|
||||
|
||||
Token::Continue if settings.is_breakable => {
|
||||
Token::Continue if settings.allow_loop && settings.is_breakable => {
|
||||
let pos = eat_token(input, Token::Continue);
|
||||
Ok(Stmt::BreakLoop(AST_OPTION_NONE, pos))
|
||||
}
|
||||
Token::Break if settings.is_breakable => {
|
||||
Token::Break if settings.allow_loop && settings.is_breakable => {
|
||||
let pos = eat_token(input, Token::Break);
|
||||
Ok(Stmt::BreakLoop(AST_OPTION_BREAK_OUT, pos))
|
||||
}
|
||||
Token::Continue | Token::Break => Err(PERR::LoopBreak.into_err(token_pos)),
|
||||
Token::Continue | Token::Break if settings.allow_loop => {
|
||||
Err(PERR::LoopBreak.into_err(token_pos))
|
||||
}
|
||||
|
||||
Token::Return | Token::Throw => {
|
||||
let (return_type, token_pos) = input
|
||||
@ -3242,6 +3250,7 @@ impl Engine {
|
||||
allow_stmt_expr: false,
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
allow_anonymous_fn: false,
|
||||
allow_loop: false,
|
||||
is_global: true,
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
is_function_scope: false,
|
||||
@ -3299,6 +3308,7 @@ impl Engine {
|
||||
allow_stmt_expr: self.options.allow_stmt_expr,
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
allow_anonymous_fn: self.options.allow_anonymous_fn,
|
||||
allow_loop: self.options.allow_loop,
|
||||
is_global: true,
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
is_function_scope: false,
|
||||
|
@ -22,5 +22,11 @@ fn test_options() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
assert!(engine.compile("let x = || 42;").is_err());
|
||||
|
||||
engine.compile("while x > y { foo(z); }")?;
|
||||
|
||||
engine.set_allow_looping(false);
|
||||
|
||||
assert!(engine.compile("while x > y { foo(z); }").is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user