diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c889e006..090a8605 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,7 @@ jobs: - "--features no_float,serde,metadata,internals,debugging" - "--features f32_float,serde,metadata,internals,debugging" - "--features decimal,serde,metadata,internals,debugging" + - "--features no_custom_syntax,serde,metadata,internals,debugging" - "--features no_float,decimal" - "--tests --features only_i32,serde,metadata,internals,debugging" - "--features only_i64,serde,metadata,internals,debugging" @@ -36,8 +37,8 @@ jobs: - "--features no_module,serde,metadata,internals,debugging" - "--features no_closure,serde,metadata,internals,debugging" - "--features unicode-xid-ident,serde,metadata,internals,debugging" - - "--features sync,no_function,no_float,no_position,no_optimize,no_module,no_closure,metadata,serde,unchecked,debugging" - - "--features no_function,no_float,no_position,no_index,no_object,no_optimize,no_module,no_closure,unchecked" + - "--features sync,no_function,no_float,no_position,no_optimize,no_module,no_closure,no_custom_syntax,metadata,serde,unchecked,debugging" + - "--features no_function,no_float,no_position,no_index,no_object,no_optimize,no_module,no_closure,no_custom_syntax,unchecked" toolchain: [stable] experimental: [false] include: diff --git a/CHANGELOG.md b/CHANGELOG.md index bb039a1c..04c06ec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Rhai Release Notes Version 1.9.0 ============= +New features +------------ + +* A new feature, `no_custom_syntax`, is added to remove custom syntax support from Rhai for applications that do not require it (which should be most). + Enhancements ------------ diff --git a/Cargo.toml b/Cargo.toml index 0328b394..9c22483f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ no_object = [] # no custom objects no_function = ["no_closure"] # no script-defined functions (meaning no closures) no_closure = [] # no automatic sharing and capture of anonymous functions to external variables no_module = [] # no modules +no_custom_syntax = [] # no custom syntax or custom operators unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers. metadata = ["serde", "serde_json", "rhai_codegen/metadata", "smartstring/serde"] # enable exporting functions metadata internals = [] # expose internal data structures diff --git a/src/api/custom_syntax.rs b/src/api/custom_syntax.rs index 4aacf153..5f365f2b 100644 --- a/src/api/custom_syntax.rs +++ b/src/api/custom_syntax.rs @@ -1,4 +1,5 @@ //! Module implementing custom syntax for [`Engine`]. +#![cfg(not(feature = "no_custom_syntax"))] use crate::ast::Expr; use crate::func::SendSync; @@ -153,6 +154,8 @@ pub struct CustomSyntax { impl Engine { /// Register a custom syntax with the [`Engine`]. /// + /// Not available under `no_custom_syntax`. + /// /// * `symbols` holds a slice of strings that define the custom syntax. /// * `scope_may_be_changed` specifies variables _may_ be added/removed by this custom syntax. /// * `func` is the implementation function. @@ -296,6 +299,8 @@ impl Engine { } /// Register a custom syntax with the [`Engine`]. /// + /// Not available under `no_custom_syntax`. + /// /// # WARNING - Low Level API /// /// This function is very low level. diff --git a/src/api/deprecated.rs b/src/api/deprecated.rs index 01f9331f..49dfb94f 100644 --- a/src/api/deprecated.rs +++ b/src/api/deprecated.rs @@ -1,8 +1,8 @@ //! Module containing all deprecated API that will be removed in the next major version. use crate::{ - Dynamic, Engine, EvalAltResult, Expression, FnPtr, ImmutableString, NativeCallContext, - Position, RhaiResult, RhaiResultOf, Scope, AST, + Dynamic, Engine, EvalAltResult, FnPtr, ImmutableString, NativeCallContext, Position, + RhaiResult, RhaiResultOf, Scope, AST, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -312,7 +312,8 @@ impl FnPtr { } } -impl Expression<'_> { +#[cfg(not(feature = "no_custom_syntax"))] +impl crate::Expression<'_> { /// If this expression is a variable name, return it. Otherwise [`None`]. /// /// # Deprecated diff --git a/src/api/mod.rs b/src/api/mod.rs index 71a6527c..4f5e96e1 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -28,10 +28,11 @@ pub mod custom_syntax; pub mod deprecated; -use crate::engine::Precedence; -use crate::tokenizer::Token; use crate::{Dynamic, Engine, Identifier}; +#[cfg(not(feature = "no_custom_syntax"))] +use crate::{engine::Precedence, tokenizer::Token}; + #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -121,6 +122,8 @@ impl Engine { /// Register a custom operator with a precedence into the language. /// + /// Not available under `no_custom_syntax`. + /// /// The operator can be a valid identifier, a reserved symbol, a disabled operator or a disabled keyword. /// /// The precedence cannot be zero. @@ -147,6 +150,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` + #[cfg(not(feature = "no_custom_syntax"))] pub fn register_custom_operator( &mut self, keyword: impl AsRef, @@ -161,8 +165,11 @@ impl Engine { let keyword = keyword.as_ref(); match Token::lookup_from_syntax(keyword) { - // Standard identifiers, reserved keywords and custom keywords are OK - None | Some(Token::Reserved(..)) | Some(Token::Custom(..)) => (), + // Standard identifiers and reserved keywords are OK + None | Some(Token::Reserved(..)) => (), + // custom keywords are OK + #[cfg(not(feature = "no_custom_syntax"))] + Some(Token::Custom(..)) => (), // Active standard keywords cannot be made custom // Disabled keywords are OK Some(token) if token.is_standard_keyword() => { diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 6251dd0a..edb66068 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -48,6 +48,9 @@ impl From<(Expr, Expr)> for BinaryExpr { /// _(internals)_ A custom syntax expression. /// Exported under the `internals` feature only. +/// +/// Not available under `no_custom_syntax`. +#[cfg(not(feature = "no_custom_syntax"))] #[derive(Debug, Clone, Hash)] pub struct CustomExpr { /// List of keywords. @@ -61,6 +64,7 @@ pub struct CustomExpr { pub self_terminated: bool, } +#[cfg(not(feature = "no_custom_syntax"))] impl CustomExpr { /// Is this custom syntax self-terminated (i.e. no need for a semicolon terminator)? /// @@ -421,6 +425,7 @@ pub enum Expr { /// lhs `??` rhs Coalesce(Box, Position), /// Custom syntax + #[cfg(not(feature = "no_custom_syntax"))] Custom(Box, Position), } @@ -530,6 +535,7 @@ impl fmt::Debug for Expr { .field("rhs", &x.rhs) .finish() } + #[cfg(not(feature = "no_custom_syntax"))] Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(), }?; @@ -703,10 +709,12 @@ impl Expr { | Self::Coalesce(.., pos) | Self::Index(.., pos) | Self::Dot(.., pos) - | Self::Custom(.., pos) | Self::InterpolatedString(.., pos) | Self::Property(.., pos) => *pos, + #[cfg(not(feature = "no_custom_syntax"))] + Self::Custom(.., pos) => *pos, + Self::FnCall(x, ..) | Self::MethodCall(x, ..) => x.pos, Self::Stmt(x) => x.position(), @@ -761,10 +769,12 @@ impl Expr { | Self::Variable(.., pos) | Self::FnCall(.., pos) | Self::MethodCall(.., pos) - | Self::Custom(.., pos) | Self::InterpolatedString(.., pos) | Self::Property(.., pos) => *pos = new_pos, + #[cfg(not(feature = "no_custom_syntax"))] + Self::Custom(.., pos) => *pos = new_pos, + Self::Stmt(x) => x.set_position(new_pos, Position::NONE), } @@ -853,8 +863,10 @@ impl Expr { | Self::Dot(..) | Self::Index(..) | Self::Array(..) - | Self::Map(..) - | Self::Custom(..) => false, + | Self::Map(..) => false, + + #[cfg(not(feature = "no_custom_syntax"))] + Self::Custom(..) => false, Self::Variable(..) => match token { Token::LeftParen => true, @@ -925,6 +937,7 @@ impl Expr { } } } + #[cfg(not(feature = "no_custom_syntax"))] Self::Custom(x, ..) => { for e in &x.inputs { if !e.walk(path, on_node) { diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6dfb077b..cb525116 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -9,7 +9,9 @@ pub mod script_fn; pub mod stmt; pub use ast::{ASTNode, AST}; -pub use expr::{BinaryExpr, CustomExpr, Expr, FnCallExpr, FnCallHashes}; +#[cfg(not(feature = "no_custom_syntax"))] +pub use expr::CustomExpr; +pub use expr::{BinaryExpr, Expr, FnCallExpr, FnCallHashes}; pub use flags::{ASTFlags, FnAccess}; pub use ident::Ident; #[cfg(not(feature = "no_module"))] diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index d5c1069c..5acbd892 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -713,6 +713,7 @@ impl Stmt { Self::Noop(..) => false, Self::Expr(e) => match &**e { + #[cfg(not(feature = "no_custom_syntax"))] Expr::Custom(x, ..) if x.is_self_terminated() => true, _ => false, }, diff --git a/src/engine.rs b/src/engine.rs index 2af23bac..10a80417 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,6 +1,5 @@ //! Main module defining the script evaluation [`Engine`]. -use crate::api::custom_syntax::CustomSyntax; use crate::api::options::LangOptions; use crate::func::native::{ OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback, @@ -111,9 +110,11 @@ pub struct Engine { /// A set of symbols to disable. pub(crate) disabled_symbols: BTreeSet, /// A map containing custom keywords and precedence to recognize. + #[cfg(not(feature = "no_custom_syntax"))] pub(crate) custom_keywords: BTreeMap>, /// Custom syntax. - pub(crate) custom_syntax: BTreeMap, + #[cfg(not(feature = "no_custom_syntax"))] + pub(crate) custom_syntax: BTreeMap, /// Callback closure for filtering variable definition. pub(crate) def_var_filter: Option>, /// Callback closure for resolving variable access. @@ -160,17 +161,19 @@ impl fmt::Debug for Engine { #[cfg(not(feature = "no_module"))] f.field("global_sub_modules", &self.global_sub_modules); - f.field("disabled_symbols", &self.disabled_symbols) - .field("custom_keywords", &self.custom_keywords) - .field( - "custom_syntax", - &self - .custom_syntax - .keys() - .map(|s| s.as_str()) - .collect::(), - ) - .field("def_var_filter", &self.def_var_filter.is_some()) + f.field("disabled_symbols", &self.disabled_symbols); + + #[cfg(not(feature = "no_custom_syntax"))] + f.field("custom_keywords", &self.custom_keywords).field( + "custom_syntax", + &self + .custom_syntax + .keys() + .map(|s| s.as_str()) + .collect::(), + ); + + f.field("def_var_filter", &self.def_var_filter.is_some()) .field("resolve_var", &self.resolve_var.is_some()) .field("token_mapper", &self.token_mapper.is_some()); @@ -268,7 +271,9 @@ impl Engine { empty_string: ImmutableString::new(), disabled_symbols: BTreeSet::new(), + #[cfg(not(feature = "no_custom_syntax"))] custom_keywords: BTreeMap::new(), + #[cfg(not(feature = "no_custom_syntax"))] custom_syntax: BTreeMap::new(), def_var_filter: None, diff --git a/src/eval/eval_context.rs b/src/eval/eval_context.rs index 150b19e4..11245721 100644 --- a/src/eval/eval_context.rs +++ b/src/eval/eval_context.rs @@ -1,12 +1,12 @@ //! Evaluation context. use super::{Caches, GlobalRuntimeState}; -use crate::{Dynamic, Engine, Expression, Module, RhaiResult, Scope}; +use crate::{Dynamic, Engine, Module, Scope}; #[cfg(feature = "no_std")] use std::prelude::v1::*; /// Context of a script evaluation process. -#[derive(Debug)] +#[allow(dead_code)] pub struct EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> { /// The current [`Engine`]. engine: &'a Engine, @@ -142,13 +142,14 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, ' self.level } - /// Evaluate an [expression tree][Expression] within this [evaluation context][`EvalContext`]. + /// Evaluate an [expression tree][crate::Expression] within this [evaluation context][`EvalContext`]. /// /// # WARNING - Low Level API /// /// This function is very low level. It evaluates an expression from an [`AST`][crate::AST]. + #[cfg(not(feature = "no_custom_syntax"))] #[inline(always)] - pub fn eval_expression_tree(&mut self, expr: &Expression) -> RhaiResult { + pub fn eval_expression_tree(&mut self, expr: &crate::Expression) -> crate::RhaiResult { let mut new_caches = Caches::new(); let caches = match self.caches.as_mut() { diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 94da70e5..c4a0011f 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -4,7 +4,7 @@ use super::{Caches, EvalContext, GlobalRuntimeState, Target}; use crate::ast::{Expr, FnCallExpr, OpAssignment}; use crate::engine::{KEYWORD_THIS, OP_CONCAT}; use crate::types::dynamic::AccessMode; -use crate::{Dynamic, Engine, Module, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, ERR}; +use crate::{Dynamic, Engine, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR}; use std::num::NonZeroUsize; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -475,8 +475,10 @@ impl Engine { } } + #[cfg(not(feature = "no_custom_syntax"))] Expr::Custom(custom, pos) => { - let expressions: StaticVec<_> = custom.inputs.iter().map(Into::into).collect(); + let expressions: crate::StaticVec<_> = + custom.inputs.iter().map(Into::into).collect(); // The first token acts as the custom syntax's key let key_token = custom.tokens.first().unwrap(); // The key should exist, unless the AST is compiled in a different Engine diff --git a/src/lib.rs b/src/lib.rs index a6825ab0..c24ab2bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,6 @@ type ExclusiveRange = std::ops::Range; /// An inclusive integer range. type InclusiveRange = std::ops::RangeInclusive; -pub use api::custom_syntax::Expression; pub use api::events::VarDefInfo; pub use ast::{FnAccess, AST}; pub use engine::{Engine, OP_CONTAINS, OP_EQUALS}; @@ -179,6 +178,9 @@ pub use types::{ Dynamic, EvalAltResult, FnPtr, ImmutableString, LexError, ParseError, ParseErrorType, Scope, }; +#[cfg(not(feature = "no_custom_syntax"))] +pub use api::custom_syntax::Expression; + /// _(debugging)_ Module containing types for debugging. /// Exported under the `debugging` feature only. #[cfg(feature = "debugging")] @@ -282,11 +284,14 @@ pub use parser::ParseState; #[cfg(feature = "internals")] pub use ast::{ - ASTFlags, ASTNode, BinaryExpr, ConditionalStmtBlock, CustomExpr, Expr, FnCallExpr, - FnCallHashes, Ident, OpAssignment, RangeCase, ScriptFnDef, Stmt, StmtBlock, SwitchCases, - TryCatchBlock, + ASTFlags, ASTNode, BinaryExpr, ConditionalStmtBlock, Expr, FnCallExpr, FnCallHashes, Ident, + OpAssignment, RangeCase, ScriptFnDef, Stmt, StmtBlock, SwitchCases, TryCatchBlock, }; +#[cfg(feature = "internals")] +#[cfg(not(feature = "no_custom_syntax"))] +pub use ast::CustomExpr; + #[cfg(feature = "internals")] #[cfg(not(feature = "no_module"))] pub use ast::Namespace; diff --git a/src/optimizer.rs b/src/optimizer.rs index 8e540cf7..c1399f10 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -1231,6 +1231,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) { } // Custom syntax + #[cfg(not(feature = "no_custom_syntax"))] Expr::Custom(x, ..) => { if x.scope_may_be_changed { state.propagate_constants = false; diff --git a/src/parser.rs b/src/parser.rs index 3c8e6c9f..119f207d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,10 +1,9 @@ //! Main module defining the lexer and parser. -use crate::api::custom_syntax::{markers::*, CustomSyntax}; use crate::api::events::VarDefInfo; use crate::api::options::LangOptions; use crate::ast::{ - ASTFlags, BinaryExpr, ConditionalStmtBlock, CustomExpr, Expr, FnCallExpr, FnCallHashes, Ident, + ASTFlags, BinaryExpr, ConditionalStmtBlock, Expr, FnCallExpr, FnCallHashes, Ident, OpAssignment, RangeCase, ScriptFnDef, Stmt, StmtBlockContainer, SwitchCases, TryCatchBlock, }; use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS}; @@ -428,6 +427,7 @@ fn parse_var_name(input: &mut TokenStream) -> ParseResult<(SmartString, Position } /// Parse a symbol. +#[cfg(not(feature = "no_custom_syntax"))] #[inline] fn parse_symbol(input: &mut TokenStream) -> ParseResult<(SmartString, Position)> { match input.next().expect(NEVER_ENDS) { @@ -1449,6 +1449,7 @@ impl Engine { Token::MapStart => self.parse_map_literal(input, state, lib, settings.level_up())?, // Custom syntax. + #[cfg(not(feature = "no_custom_syntax"))] Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key) if !self.custom_syntax.is_empty() && self.custom_syntax.contains_key(&**key) => { @@ -2184,6 +2185,7 @@ impl Engine { } let precedence = match current_op { + #[cfg(not(feature = "no_custom_syntax"))] Token::Custom(c) => self .custom_keywords .get(c) @@ -2208,6 +2210,7 @@ impl Engine { let (next_op, next_pos) = input.peek().expect(NEVER_ENDS); let next_precedence = match next_op { + #[cfg(not(feature = "no_custom_syntax"))] Token::Custom(c) => self .custom_keywords .get(c) @@ -2317,6 +2320,7 @@ impl Engine { .into_fn_call_expr(pos) } + #[cfg(not(feature = "no_custom_syntax"))] Token::Custom(s) if self .custom_keywords @@ -2347,6 +2351,7 @@ impl Engine { } /// Parse a custom syntax. + #[cfg(not(feature = "no_custom_syntax"))] fn parse_custom_syntax( &self, input: &mut TokenStream, @@ -2354,9 +2359,11 @@ impl Engine { lib: &mut FnLib, settings: ParseSettings, key: impl Into, - syntax: &CustomSyntax, + syntax: &crate::api::custom_syntax::CustomSyntax, pos: Position, ) -> ParseResult { + use crate::api::custom_syntax::markers::*; + let mut settings = settings; let mut inputs = StaticVec::::new(); let mut segments = StaticVec::new_const(); @@ -2520,7 +2527,7 @@ impl Engine { }; Ok(Expr::Custom( - CustomExpr { + crate::ast::CustomExpr { inputs, tokens, scope_may_be_changed: syntax.scope_may_be_changed, diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 39bd7627..d7031e4d 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -562,6 +562,9 @@ pub enum Token { /// A reserved symbol. Reserved(SmartString), /// A custom keyword. + /// + /// Not available under the `no_custom_syntax` feature. + #[cfg(not(feature = "no_custom_syntax"))] Custom(SmartString), /// End of the input stream. EOF, @@ -682,6 +685,7 @@ impl Token { CharConstant(c) => c.to_string().into(), Identifier(s) => s.to_string().into(), Reserved(s) => s.to_string().into(), + #[cfg(not(feature = "no_custom_syntax"))] Custom(s) => s.to_string().into(), LexError(err) => err.to_string().into(), Comment(s) => s.to_string().into(), @@ -1069,12 +1073,15 @@ impl Token { #[inline] pub(crate) fn into_function_name_for_override(self) -> Result { match self { - Self::Custom(s) | Self::Identifier(s) if is_valid_function_name(&s) => Ok(s), + #[cfg(not(feature = "no_custom_syntax"))] + Self::Custom(s) if is_valid_function_name(&s) => Ok(s), + Self::Identifier(s) if is_valid_function_name(&s) => Ok(s), _ => Err(self), } } /// Is this token a custom keyword? + #[cfg(not(feature = "no_custom_syntax"))] #[inline(always)] #[must_use] pub const fn is_custom(&self) -> bool { @@ -2329,7 +2336,12 @@ impl<'a> Iterator for TokenIterator<'a> { } // Reserved keyword/symbol Some((Token::Reserved(s), pos)) => (match - (&*s, !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s)) + (&*s, + #[cfg(not(feature = "no_custom_syntax"))] + (!self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s)), + #[cfg(feature = "no_custom_syntax")] + false + ) { ("===", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), "'===' is not a valid operator. This is not JavaScript! Should it be '=='?".to_string(), @@ -2358,7 +2370,10 @@ impl<'a> Iterator for TokenIterator<'a> { "'#' is not a valid symbol. Should it be '#{'?".to_string(), ).into()), // Reserved keyword/operator that is custom. + #[cfg(not(feature = "no_custom_syntax"))] (.., true) => Token::Custom(s), + #[cfg(feature = "no_custom_syntax")] + (.., true) => unreachable!("no custom operators"), // Reserved keyword that is not custom and disabled. (token, false) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token) => { let msg = format!("reserved {} '{}' is disabled", if is_valid_identifier(token.chars()) { "keyword"} else {"symbol"}, token); @@ -2368,10 +2383,12 @@ impl<'a> Iterator for TokenIterator<'a> { (.., false) => Token::Reserved(s), }, pos), // Custom keyword + #[cfg(not(feature = "no_custom_syntax"))] Some((Token::Identifier(s), pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s) => { (Token::Custom(s), pos) } // Custom keyword/symbol - must be disabled + #[cfg(not(feature = "no_custom_syntax"))] Some((token, pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(token.literal_syntax()) => { if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) { // Disabled standard keyword/symbol diff --git a/tests/custom_syntax.rs b/tests/custom_syntax.rs index 26cc2ae1..fbd24a93 100644 --- a/tests/custom_syntax.rs +++ b/tests/custom_syntax.rs @@ -1,3 +1,5 @@ +#![cfg(not(feature = "no_custom_syntax"))] + use rhai::{ Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseErrorType, Position, Scope, INT, }; diff --git a/tests/tokens.rs b/tests/tokens.rs index 392f8953..1b9cb71a 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -30,6 +30,7 @@ fn test_tokens_disabled() { )); } +#[cfg(not(feature = "no_custom_syntax"))] #[test] fn test_tokens_custom_operator_identifiers() -> Result<(), Box> { let mut engine = Engine::new(); @@ -60,6 +61,7 @@ fn test_tokens_custom_operator_identifiers() -> Result<(), Box> { Ok(()) } +#[cfg(not(feature = "no_custom_syntax"))] #[test] fn test_tokens_custom_operator_symbol() -> Result<(), Box> { let mut engine = Engine::new();