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