2020-11-20 16:52:28 +08:00
|
|
|
//! Configuration settings for [`Engine`].
|
2020-07-23 18:40:42 +08:00
|
|
|
|
2020-12-26 23:21:09 +08:00
|
|
|
use crate::token::Token;
|
2020-12-22 23:45:14 +08:00
|
|
|
use crate::Engine;
|
2021-04-02 19:26:55 +08:00
|
|
|
use crate::{engine::Precedence, Identifier};
|
2021-04-17 15:15:54 +08:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
2020-07-26 15:53:22 +08:00
|
|
|
|
2021-01-06 18:22:45 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2021-04-17 15:15:54 +08:00
|
|
|
use std::num::{NonZeroU64, NonZeroUsize};
|
2020-07-13 19:38:50 +08:00
|
|
|
|
2020-07-05 15:23:51 +08:00
|
|
|
impl Engine {
|
2020-11-20 16:52:28 +08:00
|
|
|
/// Control whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
2020-07-05 15:23:51 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Not available under `no_optimize`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "no_optimize"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-11-16 16:28:04 +08:00
|
|
|
pub fn set_optimization_level(
|
|
|
|
&mut self,
|
|
|
|
optimization_level: crate::OptimizationLevel,
|
|
|
|
) -> &mut Self {
|
2020-07-12 11:46:53 +08:00
|
|
|
self.optimization_level = optimization_level;
|
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// The current optimization level.
|
2020-11-20 16:52:28 +08:00
|
|
|
/// It controls whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
2020-07-05 15:23:51 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Not available under `no_optimize`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "no_optimize"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-29 23:17:31 +08:00
|
|
|
pub const fn optimization_level(&self) -> crate::OptimizationLevel {
|
2020-07-05 15:23:51 +08:00
|
|
|
self.optimization_level
|
|
|
|
}
|
|
|
|
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
|
|
|
/// infinite recursion and stack overflows.
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_function`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-12-29 12:29:45 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_call_levels(&mut self, levels: usize) -> &mut Self {
|
2020-11-10 23:26:50 +08:00
|
|
|
self.limits.max_call_stack_depth = levels;
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// The maximum levels of function calls allowed for a script.
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_function`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-12-29 12:29:45 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_call_levels(&self) -> usize {
|
2020-11-10 23:26:50 +08:00
|
|
|
self.limits.max_call_stack_depth
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// Set the maximum number of operations allowed for a script to run to avoid
|
|
|
|
/// consuming too much resources (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_operations(&mut self, operations: u64) -> &mut Self {
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_operations = NonZeroU64::new(operations);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_operations(&self) -> u64 {
|
|
|
|
if let Some(n) = self.limits.max_operations {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_module`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-18 22:10:08 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_modules(&mut self, modules: usize) -> &mut Self {
|
2020-11-10 23:26:50 +08:00
|
|
|
self.limits.max_modules = modules;
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_module`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-18 22:10:08 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_modules(&self) -> usize {
|
2020-11-10 23:26:50 +08:00
|
|
|
self.limits.max_modules
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// Set the depth limits for expressions (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_expr_depths(
|
|
|
|
&mut self,
|
|
|
|
max_expr_depth: usize,
|
2020-10-18 17:02:17 +08:00
|
|
|
#[cfg(not(feature = "no_function"))] max_function_expr_depth: usize,
|
2020-07-12 11:46:53 +08:00
|
|
|
) -> &mut Self {
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_expr_depth = NonZeroUsize::new(max_expr_depth);
|
2020-10-18 17:02:17 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
{
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_function_expr_depth = NonZeroUsize::new(max_function_expr_depth);
|
2020-10-18 17:02:17 +08:00
|
|
|
}
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// The depth limit for expressions (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_expr_depth(&self) -> usize {
|
|
|
|
if let Some(n) = self.limits.max_expr_depth {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// The depth limit for expressions in functions (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_function`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-18 17:02:17 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_function_expr_depth(&self) -> usize {
|
|
|
|
if let Some(n) = self.limits.max_function_expr_depth {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self {
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_string_size = NonZeroUsize::new(max_size);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_string_size(&self) -> usize {
|
|
|
|
if let Some(n) = self.limits.max_string_size {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_index`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self {
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_array_size = NonZeroUsize::new(max_size);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-25 09:36:06 +08:00
|
|
|
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_index`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-29 23:17:31 +08:00
|
|
|
pub const fn max_array_size(&self) -> usize {
|
2021-06-28 18:06:05 +08:00
|
|
|
if let Some(n) = self.limits.max_array_size {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set the maximum size of [object maps][crate::Map] (0 for unlimited).
|
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_object`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self {
|
2021-01-06 13:46:53 +08:00
|
|
|
self.limits.max_map_size = NonZeroUsize::new(max_size);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2021-01-02 23:30:10 +08:00
|
|
|
/// The maximum size of [object maps][crate::Map] (0 for unlimited).
|
|
|
|
///
|
|
|
|
/// Not available under `unchecked` or `no_object`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn max_map_size(&self) -> usize {
|
|
|
|
if let Some(n) = self.limits.max_map_size {
|
|
|
|
n.get()
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
2020-11-20 16:52:28 +08:00
|
|
|
/// Set the module resolution service used by the [`Engine`].
|
2020-07-05 15:23:51 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Not available under `no_module`.
|
2020-07-05 15:23:51 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn set_module_resolver(
|
|
|
|
&mut self,
|
2020-12-26 13:05:57 +08:00
|
|
|
resolver: impl crate::ModuleResolver + 'static,
|
2020-07-12 11:46:53 +08:00
|
|
|
) -> &mut Self {
|
2021-05-29 18:33:29 +08:00
|
|
|
self.module_resolver = Some(Box::new(resolver));
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
/// Disable a particular keyword or operator in the language.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// The following will raise an error during parsing because the `if` keyword is disabled
|
2021-03-03 22:49:57 +08:00
|
|
|
/// and is recognized as a reserved symbol!
|
2020-07-05 15:23:51 +08:00
|
|
|
///
|
|
|
|
/// ```rust,should_panic
|
|
|
|
/// # fn main() -> Result<(), rhai::ParseError> {
|
|
|
|
/// use rhai::Engine;
|
|
|
|
///
|
|
|
|
/// let mut engine = Engine::new();
|
|
|
|
///
|
|
|
|
/// engine.disable_symbol("if"); // disable the 'if' keyword
|
|
|
|
///
|
|
|
|
/// engine.compile("let x = if true { 42 } else { 0 };")?;
|
2021-03-03 22:49:57 +08:00
|
|
|
/// // ^ 'if' is rejected as a reserved symbol
|
2020-07-05 15:23:51 +08:00
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The following will raise an error during parsing because the `+=` operator is disabled.
|
|
|
|
///
|
|
|
|
/// ```rust,should_panic
|
|
|
|
/// # fn main() -> Result<(), rhai::ParseError> {
|
|
|
|
/// use rhai::Engine;
|
|
|
|
///
|
|
|
|
/// let mut engine = Engine::new();
|
|
|
|
///
|
|
|
|
/// engine.disable_symbol("+="); // disable the '+=' operator
|
|
|
|
///
|
|
|
|
/// engine.compile("let x = 42; x += 1;")?;
|
|
|
|
/// // ^ unknown operator
|
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-04-02 19:26:55 +08:00
|
|
|
pub fn disable_symbol(&mut self, symbol: impl Into<Identifier>) -> &mut Self {
|
2020-10-25 21:57:18 +08:00
|
|
|
self.disabled_symbols.insert(symbol.into());
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-07-05 17:41:45 +08:00
|
|
|
}
|
2020-12-26 17:42:19 +08:00
|
|
|
/// Register a custom operator with a precedence into the language.
|
2020-07-05 17:41:45 +08:00
|
|
|
///
|
|
|
|
/// The operator must be a valid identifier (i.e. it cannot be a symbol).
|
|
|
|
///
|
2020-12-26 17:42:19 +08:00
|
|
|
/// The precedence cannot be zero.
|
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-07-05 17:41:45 +08:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
2021-03-15 11:36:30 +08:00
|
|
|
/// use rhai::Engine;
|
2020-07-05 17:41:45 +08:00
|
|
|
///
|
|
|
|
/// let mut engine = Engine::new();
|
|
|
|
///
|
|
|
|
/// // Register a custom operator called 'foo' and give it
|
2020-07-06 13:01:57 +08:00
|
|
|
/// // a precedence of 160 (i.e. between +|- and *|/).
|
2021-08-26 23:58:41 +08:00
|
|
|
/// engine.register_custom_operator("foo", 160).expect("should succeed");
|
2020-07-05 17:41:45 +08:00
|
|
|
///
|
|
|
|
/// // Register a binary function named 'foo'
|
|
|
|
/// engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));
|
|
|
|
///
|
|
|
|
/// assert_eq!(
|
|
|
|
/// engine.eval_expression::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?,
|
|
|
|
/// 15
|
|
|
|
/// );
|
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
|
|
|
pub fn register_custom_operator(
|
|
|
|
&mut self,
|
2021-04-02 19:26:55 +08:00
|
|
|
keyword: impl AsRef<str> + Into<Identifier>,
|
2020-07-05 17:41:45 +08:00
|
|
|
precedence: u8,
|
2020-07-12 11:46:53 +08:00
|
|
|
) -> Result<&mut Self, String> {
|
2021-03-14 10:47:29 +08:00
|
|
|
let precedence = Precedence::new(precedence);
|
2020-12-26 17:42:19 +08:00
|
|
|
|
|
|
|
if precedence.is_none() {
|
|
|
|
return Err("precedence cannot be zero".into());
|
|
|
|
}
|
2020-07-05 17:41:45 +08:00
|
|
|
|
2021-03-24 13:17:52 +08:00
|
|
|
match Token::lookup_from_syntax(keyword.as_ref()) {
|
2020-07-17 14:50:23 +08:00
|
|
|
// Standard identifiers, reserved keywords and custom keywords are OK
|
|
|
|
None | Some(Token::Reserved(_)) | Some(Token::Custom(_)) => (),
|
|
|
|
// Active standard keywords cannot be made custom
|
2020-12-26 23:21:09 +08:00
|
|
|
// Disabled keywords are OK
|
2021-07-10 15:50:31 +08:00
|
|
|
Some(token) if token.is_standard_keyword() => {
|
2020-12-26 23:21:09 +08:00
|
|
|
if !self.disabled_symbols.contains(token.syntax().as_ref()) {
|
2021-07-24 14:11:16 +08:00
|
|
|
return Err(format!("'{}' is a reserved keyword", keyword.as_ref()));
|
2020-12-26 23:21:09 +08:00
|
|
|
}
|
|
|
|
}
|
2021-02-10 12:41:27 +08:00
|
|
|
// Active standard symbols cannot be made custom
|
2021-07-10 15:50:31 +08:00
|
|
|
Some(token) if token.is_standard_symbol() => {
|
2020-12-26 23:21:09 +08:00
|
|
|
if !self.disabled_symbols.contains(token.syntax().as_ref()) {
|
2021-07-24 14:11:16 +08:00
|
|
|
return Err(format!("'{}' is a reserved operator", keyword.as_ref()));
|
2020-12-26 23:21:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Active standard symbols cannot be made custom
|
|
|
|
Some(token) if !self.disabled_symbols.contains(token.syntax().as_ref()) => {
|
2021-07-24 14:11:16 +08:00
|
|
|
return Err(format!("'{}' is a reserved symbol", keyword.as_ref()))
|
2020-12-26 23:21:09 +08:00
|
|
|
}
|
|
|
|
// Disabled symbols are OK
|
|
|
|
Some(_) => (),
|
2020-07-17 14:50:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add to custom keywords
|
2020-12-26 17:42:19 +08:00
|
|
|
self.custom_keywords.insert(keyword.into(), precedence);
|
2020-07-05 17:41:45 +08:00
|
|
|
|
2020-07-12 11:46:53 +08:00
|
|
|
Ok(self)
|
2020-07-05 15:23:51 +08:00
|
|
|
}
|
|
|
|
}
|