Add no_custom_syntax.
This commit is contained in:
parent
b6528bd51d
commit
b4dbc7619a
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@ -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:
|
||||
|
@ -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
|
||||
------------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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<str>,
|
||||
@ -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() => {
|
||||
|
@ -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<BinaryExpr>, Position),
|
||||
/// Custom syntax
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
Custom(Box<CustomExpr>, 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) {
|
||||
|
@ -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"))]
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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<Identifier>,
|
||||
/// A map containing custom keywords and precedence to recognize.
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
pub(crate) custom_keywords: BTreeMap<Identifier, Option<Precedence>>,
|
||||
/// Custom syntax.
|
||||
pub(crate) custom_syntax: BTreeMap<Identifier, CustomSyntax>,
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
pub(crate) custom_syntax: BTreeMap<Identifier, crate::api::custom_syntax::CustomSyntax>,
|
||||
/// Callback closure for filtering variable definition.
|
||||
pub(crate) def_var_filter: Option<Box<OnDefVarCallback>>,
|
||||
/// 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::<String>(),
|
||||
)
|
||||
.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::<String>(),
|
||||
);
|
||||
|
||||
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,
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
13
src/lib.rs
13
src/lib.rs
@ -165,7 +165,6 @@ type ExclusiveRange = std::ops::Range<INT>;
|
||||
/// An inclusive integer range.
|
||||
type InclusiveRange = std::ops::RangeInclusive<INT>;
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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<ImmutableString>,
|
||||
syntax: &CustomSyntax,
|
||||
syntax: &crate::api::custom_syntax::CustomSyntax,
|
||||
pos: Position,
|
||||
) -> ParseResult<Expr> {
|
||||
use crate::api::custom_syntax::markers::*;
|
||||
|
||||
let mut settings = settings;
|
||||
let mut inputs = StaticVec::<Expr>::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,
|
||||
|
@ -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<SmartString, Self> {
|
||||
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
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![cfg(not(feature = "no_custom_syntax"))]
|
||||
|
||||
use rhai::{
|
||||
Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseErrorType, Position, Scope, INT,
|
||||
};
|
||||
|
@ -30,6 +30,7 @@ fn test_tokens_disabled() {
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
#[test]
|
||||
fn test_tokens_custom_operator_identifiers() -> Result<(), Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
@ -60,6 +61,7 @@ fn test_tokens_custom_operator_identifiers() -> Result<(), Box<EvalAltResult>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_custom_syntax"))]
|
||||
#[test]
|
||||
fn test_tokens_custom_operator_symbol() -> Result<(), Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
|
Loading…
Reference in New Issue
Block a user