Use SmartString for buffers and literal_syntax can panic.
This commit is contained in:
parent
05c7d00a8e
commit
d911327242
@ -163,25 +163,18 @@ impl Engine {
|
|||||||
// Active standard keywords cannot be made custom
|
// Active standard keywords cannot be made custom
|
||||||
// Disabled keywords are OK
|
// Disabled keywords are OK
|
||||||
Some(token) if token.is_standard_keyword() => {
|
Some(token) if token.is_standard_keyword() => {
|
||||||
if self.disabled_symbols.is_empty()
|
if !self.disabled_symbols.contains(token.literal_syntax()) {
|
||||||
|| !self.disabled_symbols.contains(&*token.syntax())
|
|
||||||
{
|
|
||||||
return Err(format!("'{keyword}' is a reserved keyword"));
|
return Err(format!("'{keyword}' is a reserved keyword"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Active standard symbols cannot be made custom
|
// Active standard symbols cannot be made custom
|
||||||
Some(token) if token.is_standard_symbol() => {
|
Some(token) if token.is_standard_symbol() => {
|
||||||
if self.disabled_symbols.is_empty()
|
if !self.disabled_symbols.contains(token.literal_syntax()) {
|
||||||
|| !self.disabled_symbols.contains(&*token.syntax())
|
|
||||||
{
|
|
||||||
return Err(format!("'{keyword}' is a reserved operator"));
|
return Err(format!("'{keyword}' is a reserved operator"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Active standard symbols cannot be made custom
|
// Active standard symbols cannot be made custom
|
||||||
Some(token)
|
Some(token) if !self.disabled_symbols.contains(token.literal_syntax()) => {
|
||||||
if self.disabled_symbols.is_empty()
|
|
||||||
|| !self.disabled_symbols.contains(&*token.syntax()) =>
|
|
||||||
{
|
|
||||||
return Err(format!("'{keyword}' is a reserved symbol"))
|
return Err(format!("'{keyword}' is a reserved symbol"))
|
||||||
}
|
}
|
||||||
// Disabled symbols are OK
|
// Disabled symbols are OK
|
||||||
|
@ -688,8 +688,7 @@ impl Engine {
|
|||||||
name: &str,
|
name: &str,
|
||||||
module: SharedModule,
|
module: SharedModule,
|
||||||
) {
|
) {
|
||||||
let separator = crate::tokenizer::Token::DoubleColon.syntax();
|
let separator = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
||||||
let separator = separator.as_ref();
|
|
||||||
|
|
||||||
if name.contains(separator) {
|
if name.contains(separator) {
|
||||||
let mut iter = name.splitn(2, separator);
|
let mut iter = name.splitn(2, separator);
|
||||||
|
@ -361,7 +361,7 @@ impl fmt::Debug for Expr {
|
|||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut display_pos = format!(" @ {:?}", self.start_position());
|
let mut display_pos = self.start_position();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::DynamicConstant(value, ..) => write!(f, "{value:?}"),
|
Self::DynamicConstant(value, ..) => write!(f, "{value:?}"),
|
||||||
@ -395,7 +395,7 @@ impl fmt::Debug for Expr {
|
|||||||
write!(f, "{}{}", x.1, Token::DoubleColon.literal_syntax())?;
|
write!(f, "{}{}", x.1, Token::DoubleColon.literal_syntax())?;
|
||||||
let pos = x.1.position();
|
let pos = x.1.position();
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = format!(" @ {pos:?}");
|
display_pos = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.write_str(&x.3)?;
|
f.write_str(&x.3)?;
|
||||||
@ -413,7 +413,7 @@ impl fmt::Debug for Expr {
|
|||||||
Self::Stmt(x) => {
|
Self::Stmt(x) => {
|
||||||
let pos = x.span();
|
let pos = x.span();
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = format!(" @ {pos:?}");
|
display_pos = pos.start();
|
||||||
}
|
}
|
||||||
f.write_str("ExprStmtBlock")?;
|
f.write_str("ExprStmtBlock")?;
|
||||||
f.debug_list().entries(x.iter()).finish()
|
f.debug_list().entries(x.iter()).finish()
|
||||||
@ -421,7 +421,7 @@ impl fmt::Debug for Expr {
|
|||||||
Self::FnCall(x, ..) => fmt::Debug::fmt(x, f),
|
Self::FnCall(x, ..) => fmt::Debug::fmt(x, f),
|
||||||
Self::Index(x, options, pos) => {
|
Self::Index(x, options, pos) => {
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = format!(" @ {pos:?}");
|
display_pos = *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut f = f.debug_struct("Index");
|
let mut f = f.debug_struct("Index");
|
||||||
@ -434,7 +434,7 @@ impl fmt::Debug for Expr {
|
|||||||
}
|
}
|
||||||
Self::Dot(x, options, pos) => {
|
Self::Dot(x, options, pos) => {
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = format!(" @ {pos:?}");
|
display_pos = *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut f = f.debug_struct("Dot");
|
let mut f = f.debug_struct("Dot");
|
||||||
@ -454,7 +454,7 @@ impl fmt::Debug for Expr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = format!(" @ {pos:?}");
|
display_pos = *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.debug_struct(op_name)
|
f.debug_struct(op_name)
|
||||||
@ -466,7 +466,7 @@ impl fmt::Debug for Expr {
|
|||||||
Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(),
|
Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
f.write_str(&display_pos)
|
write!(f, " @ {display_pos:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Dynamic,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
new_val: Option<(Dynamic, &OpAssignment)>,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let chain_type = ChainType::from(expr);
|
let chain_type = ChainType::from(expr);
|
||||||
|
|
||||||
@ -507,7 +507,7 @@ impl Engine {
|
|||||||
target: &mut Target,
|
target: &mut Target,
|
||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
idx_values: &mut FnArgsVec<Dynamic>,
|
idx_values: &mut FnArgsVec<Dynamic>,
|
||||||
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
new_val: Option<(Dynamic, &OpAssignment)>,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
let is_ref_mut = target.is_ref();
|
let is_ref_mut = target.is_ref();
|
||||||
let op_pos = parent.position();
|
let op_pos = parent.position();
|
||||||
@ -576,7 +576,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr, parent)?;
|
self.run_debugger(global, caches, scope, this_ptr, parent)?;
|
||||||
|
|
||||||
let (new_val, op_info) = new_val.take().expect("`Some`");
|
let (new_val, op_info) = new_val.expect("`Some`");
|
||||||
let idx_val = &mut idx_values.pop().unwrap();
|
let idx_val = &mut idx_values.pop().unwrap();
|
||||||
let idx = &mut idx_val.clone();
|
let idx = &mut idx_val.clone();
|
||||||
|
|
||||||
@ -686,12 +686,12 @@ impl Engine {
|
|||||||
unreachable!("function call in dot chain should not be namespace-qualified")
|
unreachable!("function call in dot chain should not be namespace-qualified")
|
||||||
}
|
}
|
||||||
// {xxx:map}.id op= ???
|
// {xxx:map}.id op= ???
|
||||||
Expr::Property(x, pos) if target.is_map() && new_val.is_some() => {
|
Expr::Property(x, pos) if new_val.is_some() && target.is_map() => {
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr, rhs)?;
|
self.run_debugger(global, caches, scope, this_ptr, rhs)?;
|
||||||
|
|
||||||
let index = &mut x.2.clone().into();
|
let index = &mut x.2.clone().into();
|
||||||
let (new_val, op_info) = new_val.take().expect("`Some`");
|
let (new_val, op_info) = new_val.expect("`Some`");
|
||||||
{
|
{
|
||||||
let val_target = &mut self.get_indexed_mut(
|
let val_target = &mut self.get_indexed_mut(
|
||||||
global, caches, target, index, *pos, op_pos, true, false,
|
global, caches, target, index, *pos, op_pos, true, false,
|
||||||
@ -720,7 +720,7 @@ impl Engine {
|
|||||||
self.run_debugger(global, caches, scope, this_ptr, rhs)?;
|
self.run_debugger(global, caches, scope, this_ptr, rhs)?;
|
||||||
|
|
||||||
let ((getter, hash_get), (setter, hash_set), name) = &**x;
|
let ((getter, hash_get), (setter, hash_set), name) = &**x;
|
||||||
let (mut new_val, op_info) = new_val.take().expect("`Some`");
|
let (mut new_val, op_info) = new_val.expect("`Some`");
|
||||||
|
|
||||||
if op_info.is_op_assignment() {
|
if op_info.is_op_assignment() {
|
||||||
let args = &mut [target.as_mut()];
|
let args = &mut [target.as_mut()];
|
||||||
|
@ -8,7 +8,7 @@ use std::borrow::Borrow;
|
|||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
impl Engine {
|
impl Dynamic {
|
||||||
/// Recursively calculate the sizes of a value.
|
/// Recursively calculate the sizes of a value.
|
||||||
///
|
///
|
||||||
/// Sizes returned are `(` [`Array`][crate::Array], [`Map`][crate::Map] and [`String`] `)`.
|
/// Sizes returned are `(` [`Array`][crate::Array], [`Map`][crate::Map] and [`String`] `)`.
|
||||||
@ -16,20 +16,20 @@ impl Engine {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if any interior data is shared (should never happen).
|
/// Panics if any interior data is shared (should never happen).
|
||||||
pub(crate) fn calc_data_sizes(value: &Dynamic, _top: bool) -> (usize, usize, usize) {
|
pub(crate) fn calc_data_sizes(&self, _top: bool) -> (usize, usize, usize) {
|
||||||
match value.0 {
|
match self.0 {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(ref arr, ..) => {
|
Union::Array(ref arr, ..) => {
|
||||||
arr.iter()
|
arr.iter()
|
||||||
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
||||||
Union::Array(..) => {
|
Union::Array(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = value.calc_data_sizes(false);
|
||||||
(ax + a + 1, mx + m, sx + s)
|
(ax + a + 1, mx + m, sx + s)
|
||||||
}
|
}
|
||||||
Union::Blob(ref a, ..) => (ax + 1 + a.len(), mx, sx),
|
Union::Blob(ref a, ..) => (ax + 1 + a.len(), mx, sx),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(..) => {
|
Union::Map(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = value.calc_data_sizes(false);
|
||||||
(ax + a + 1, mx + m, sx + s)
|
(ax + a + 1, mx + m, sx + s)
|
||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (ax + 1, mx, sx + s.len()),
|
Union::Str(ref s, ..) => (ax + 1, mx, sx + s.len()),
|
||||||
@ -44,13 +44,13 @@ impl Engine {
|
|||||||
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(..) => {
|
Union::Array(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = value.calc_data_sizes(false);
|
||||||
(ax + a, mx + m + 1, sx + s)
|
(ax + a, mx + m + 1, sx + s)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Blob(ref a, ..) => (ax + a.len(), mx, sx),
|
Union::Blob(ref a, ..) => (ax + a.len(), mx, sx),
|
||||||
Union::Map(..) => {
|
Union::Map(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = value.calc_data_sizes(false);
|
||||||
(ax + a, mx + m + 1, sx + s)
|
(ax + a, mx + m + 1, sx + s)
|
||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (ax, mx + 1, sx + s.len()),
|
Union::Str(ref s, ..) => (ax, mx + 1, sx + s.len()),
|
||||||
@ -59,17 +59,17 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (0, 0, s.len()),
|
Union::Str(ref s, ..) => (0, 0, s.len()),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) if _top => {
|
Union::Shared(..) if _top => self.read_lock::<Dynamic>().unwrap().calc_data_sizes(true),
|
||||||
Self::calc_data_sizes(&*value.read_lock::<Dynamic>().unwrap(), true)
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => {
|
Union::Shared(..) => {
|
||||||
unreachable!("shared values discovered within data: {}", value)
|
unreachable!("shared values discovered within data: {}", self)
|
||||||
}
|
}
|
||||||
_ => (0, 0, 0),
|
_ => (0, 0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Engine {
|
||||||
/// Raise an error if any data size exceeds limit.
|
/// Raise an error if any data size exceeds limit.
|
||||||
///
|
///
|
||||||
/// [`Position`] in [`EvalAltResult`][crate::EvalAltResult] is always [`NONE`][Position::NONE]
|
/// [`Position`] in [`EvalAltResult`][crate::EvalAltResult] is always [`NONE`][Position::NONE]
|
||||||
@ -125,7 +125,7 @@ impl Engine {
|
|||||||
return Ok(value);
|
return Ok(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sizes = Self::calc_data_sizes(value.borrow(), true);
|
let sizes = value.borrow().calc_data_sizes(true);
|
||||||
|
|
||||||
self.raise_err_if_over_data_size_limit(sizes)
|
self.raise_err_if_over_data_size_limit(sizes)
|
||||||
.map(|_| value)
|
.map(|_| value)
|
||||||
|
@ -307,7 +307,7 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if self.has_data_size_limit() {
|
if self.has_data_size_limit() {
|
||||||
let val_sizes = Self::calc_data_sizes(&value, true);
|
let val_sizes = value.calc_data_sizes(true);
|
||||||
|
|
||||||
total_data_sizes = (
|
total_data_sizes = (
|
||||||
total_data_sizes.0 + val_sizes.0,
|
total_data_sizes.0 + val_sizes.0,
|
||||||
@ -339,7 +339,7 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if self.has_data_size_limit() {
|
if self.has_data_size_limit() {
|
||||||
let delta = Self::calc_data_sizes(&value, true);
|
let delta = value.calc_data_sizes(true);
|
||||||
total_data_sizes = (
|
total_data_sizes = (
|
||||||
total_data_sizes.0 + delta.0,
|
total_data_sizes.0 + delta.0,
|
||||||
total_data_sizes.1 + delta.1,
|
total_data_sizes.1 + delta.1,
|
||||||
@ -411,13 +411,11 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(..) => {
|
Expr::Index(..) => {
|
||||||
self.eval_dot_index_chain(global, caches, scope, this_ptr, expr, &mut None)
|
self.eval_dot_index_chain(global, caches, scope, this_ptr, expr, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(..) => {
|
Expr::Dot(..) => self.eval_dot_index_chain(global, caches, scope, this_ptr, expr, None),
|
||||||
self.eval_dot_index_chain(global, caches, scope, this_ptr, expr, &mut None)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,9 @@ pub use eval_context::EvalContext;
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub use global_state::GlobalConstants;
|
pub use global_state::GlobalConstants;
|
||||||
pub use global_state::GlobalRuntimeState;
|
pub use global_state::GlobalRuntimeState;
|
||||||
pub use target::{calc_index, calc_offset_len, Target};
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
pub use target::calc_offset_len;
|
||||||
|
pub use target::{calc_index, Target};
|
||||||
|
|
||||||
#[cfg(feature = "unchecked")]
|
#[cfg(feature = "unchecked")]
|
||||||
mod unchecked {
|
mod unchecked {
|
||||||
|
@ -258,7 +258,7 @@ impl Engine {
|
|||||||
rhs_val = self.get_interned_string(value).into();
|
rhs_val = self.get_interned_string(value).into();
|
||||||
}
|
}
|
||||||
|
|
||||||
let _new_val = &mut Some((rhs_val, op_info));
|
let _new_val = Some((rhs_val, op_info));
|
||||||
|
|
||||||
// Must be either `var[index] op= val` or `var.prop op= val`
|
// Must be either `var[index] op= val` or `var.prop op= val`
|
||||||
match lhs {
|
match lhs {
|
||||||
|
@ -13,8 +13,8 @@ use std::{
|
|||||||
/// Negative starting positions count from the end.
|
/// Negative starting positions count from the end.
|
||||||
///
|
///
|
||||||
/// Values going over bounds are limited to the actual length.
|
/// Values going over bounds are limited to the actual length.
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn calc_offset_len(length: usize, start: crate::INT, len: crate::INT) -> (usize, usize) {
|
pub fn calc_offset_len(length: usize, start: crate::INT, len: crate::INT) -> (usize, usize) {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
let abs_start = start.unsigned_abs();
|
let abs_start = start.unsigned_abs();
|
||||||
|
@ -4,11 +4,12 @@ use super::call::FnCallArgs;
|
|||||||
use super::native::FnBuiltin;
|
use super::native::FnBuiltin;
|
||||||
use crate::tokenizer::{Token, Token::*};
|
use crate::tokenizer::{Token, Token::*};
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, ExclusiveRange, ImmutableString, InclusiveRange, NativeCallContext, RhaiResult, INT,
|
Dynamic, ExclusiveRange, ImmutableString, InclusiveRange, NativeCallContext, RhaiResult,
|
||||||
|
SmartString, INT,
|
||||||
};
|
};
|
||||||
use std::any::TypeId;
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
use std::{any::TypeId, fmt::Write};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
@ -241,7 +242,9 @@ pub fn get_builtin_binary_op_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Option<
|
|||||||
let x = args[0].as_char().expect(BUILTIN);
|
let x = args[0].as_char().expect(BUILTIN);
|
||||||
let y = args[1].as_char().expect(BUILTIN);
|
let y = args[1].as_char().expect(BUILTIN);
|
||||||
|
|
||||||
let result = format!("{x}{y}");
|
let mut result = SmartString::new_const();
|
||||||
|
result.push(x);
|
||||||
|
result.push(y);
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
_ctx.engine()
|
_ctx.engine()
|
||||||
@ -399,7 +402,10 @@ pub fn get_builtin_binary_op_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Option<
|
|||||||
Plus => Some(|_ctx, args| {
|
Plus => Some(|_ctx, args| {
|
||||||
let x = args[0].as_char().expect(BUILTIN);
|
let x = args[0].as_char().expect(BUILTIN);
|
||||||
let y = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN);
|
let y = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
let result = format!("{x}{y}");
|
|
||||||
|
let mut result = SmartString::new_const();
|
||||||
|
result.push(x);
|
||||||
|
result.push_str(y);
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
_ctx.engine()
|
_ctx.engine()
|
||||||
@ -679,7 +685,12 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
PlusAssign => Some(|_, args| {
|
PlusAssign => Some(|_, args| {
|
||||||
let y = args[1].as_char().expect(BUILTIN);
|
let y = args[1].as_char().expect(BUILTIN);
|
||||||
let x = &mut *args[0].write_lock::<Dynamic>().expect(BUILTIN);
|
let x = &mut *args[0].write_lock::<Dynamic>().expect(BUILTIN);
|
||||||
Ok((*x = format!("{x}{y}").into()).into())
|
|
||||||
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{y}").unwrap();
|
||||||
|
buf.push(y);
|
||||||
|
|
||||||
|
Ok((*x = buf.into()).into())
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -247,8 +247,8 @@ pub mod array_functions {
|
|||||||
let mut arr_len = array.len();
|
let mut arr_len = array.len();
|
||||||
let mut arr = Dynamic::from_array(mem::take(array));
|
let mut arr = Dynamic::from_array(mem::take(array));
|
||||||
|
|
||||||
let (mut a1, mut m1, mut s1) = crate::Engine::calc_data_sizes(&arr, true);
|
let (mut a1, mut m1, mut s1) = arr.calc_data_sizes(true);
|
||||||
let (a2, m2, s2) = crate::Engine::calc_data_sizes(&item, true);
|
let (a2, m2, s2) = item.calc_data_sizes(true);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = arr.write_lock::<Array>().unwrap();
|
let mut guard = arr.write_lock::<Array>().unwrap();
|
||||||
|
@ -269,9 +269,13 @@ fn collect_fn_metadata(
|
|||||||
.iter_script_fn()
|
.iter_script_fn()
|
||||||
.filter(|(s, a, n, p, f)| filter(*s, *a, n, *p, f))
|
.filter(|(s, a, n, p, f)| filter(*s, *a, n, *p, f))
|
||||||
.for_each(|(.., f)| list.push(make_metadata(dict, namespace.into(), f).into()));
|
.for_each(|(.., f)| list.push(make_metadata(dict, namespace.into(), f).into()));
|
||||||
for (ns, m) in module.iter_sub_modules() {
|
for (name, m) in module.iter_sub_modules() {
|
||||||
let ns = format!(
|
use std::fmt::Write;
|
||||||
"{namespace}{}{ns}",
|
|
||||||
|
let mut ns = crate::SmartString::new_const();
|
||||||
|
write!(
|
||||||
|
&mut ns,
|
||||||
|
"{namespace}{}{name}",
|
||||||
crate::tokenizer::Token::DoubleColon.literal_syntax()
|
crate::tokenizer::Token::DoubleColon.literal_syntax()
|
||||||
);
|
);
|
||||||
scan_module(dict, list, &ns, &**m, filter);
|
scan_module(dict, list, &ns, &**m, filter);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, FnPtr, INT};
|
use crate::{def_package, FnPtr, SmartString, INT};
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::fmt::{Binary, LowerHex, Octal};
|
use std::fmt::{Binary, LowerHex, Octal, Write};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
@ -69,7 +69,9 @@ mod print_debug_functions {
|
|||||||
/// Convert the value of the `item` into a string in debug format.
|
/// Convert the value of the `item` into a string in debug format.
|
||||||
#[rhai_fn(name = "to_debug", pure)]
|
#[rhai_fn(name = "to_debug", pure)]
|
||||||
pub fn to_debug_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
|
pub fn to_debug_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
|
||||||
ctx.engine().map_type_name(&format!("{item:?}")).into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{item:?}").unwrap();
|
||||||
|
ctx.engine().map_type_name(&buf).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the empty string.
|
/// Return the empty string.
|
||||||
@ -86,7 +88,9 @@ mod print_debug_functions {
|
|||||||
/// Convert the string into debug format.
|
/// Convert the string into debug format.
|
||||||
#[rhai_fn(name = "debug", name = "to_debug", pure)]
|
#[rhai_fn(name = "debug", name = "to_debug", pure)]
|
||||||
pub fn debug_string(string: &mut ImmutableString) -> ImmutableString {
|
pub fn debug_string(string: &mut ImmutableString) -> ImmutableString {
|
||||||
format!("{string:?}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{string:?}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the character into a string.
|
/// Return the character into a string.
|
||||||
@ -97,7 +101,9 @@ mod print_debug_functions {
|
|||||||
/// Convert the string into debug format.
|
/// Convert the string into debug format.
|
||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_char(character: char) -> ImmutableString {
|
pub fn debug_char(character: char) -> ImmutableString {
|
||||||
format!("{character:?}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
buf.push(character);
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the function pointer into a string in debug format.
|
/// Convert the function pointer into a string in debug format.
|
||||||
@ -114,7 +120,9 @@ mod print_debug_functions {
|
|||||||
/// Convert the boolean value into a string in debug format.
|
/// Convert the boolean value into a string in debug format.
|
||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_bool(value: bool) -> ImmutableString {
|
pub fn debug_bool(value: bool) -> ImmutableString {
|
||||||
format!("{value:?}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{value:?}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the empty string.
|
/// Return the empty string.
|
||||||
@ -147,14 +155,18 @@ mod print_debug_functions {
|
|||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_f64(number: f64) -> ImmutableString {
|
pub fn debug_f64(number: f64) -> ImmutableString {
|
||||||
let number = crate::types::FloatWrapper::new(number);
|
let number = crate::types::FloatWrapper::new(number);
|
||||||
format!("{number:?}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{number:?}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
/// Convert the value of `number` into a string.
|
/// Convert the value of `number` into a string.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_f32(number: f32) -> ImmutableString {
|
pub fn debug_f32(number: f32) -> ImmutableString {
|
||||||
let number = crate::types::FloatWrapper::new(number);
|
let number = crate::types::FloatWrapper::new(number);
|
||||||
format!("{number:?}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{number:?}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the array into a string.
|
/// Convert the array into a string.
|
||||||
@ -217,13 +229,19 @@ mod print_debug_functions {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
mod number_formatting {
|
mod number_formatting {
|
||||||
fn to_hex<T: LowerHex>(value: T) -> ImmutableString {
|
fn to_hex<T: LowerHex>(value: T) -> ImmutableString {
|
||||||
format!("{value:x}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{value:x}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
fn to_octal<T: Octal>(value: T) -> ImmutableString {
|
fn to_octal<T: Octal>(value: T) -> ImmutableString {
|
||||||
format!("{value:o}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{value:o}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
fn to_binary<T: Binary>(value: T) -> ImmutableString {
|
fn to_binary<T: Binary>(value: T) -> ImmutableString {
|
||||||
format!("{value:b}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
write!(&mut buf, "{value:b}").unwrap();
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the `value` into a string in hex format.
|
/// Convert the `value` into a string in hex format.
|
||||||
|
@ -33,7 +33,9 @@ mod string_functions {
|
|||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
string.clone()
|
string.clone()
|
||||||
} else {
|
} else {
|
||||||
format!("{string}{s}").into()
|
let mut buf = SmartString::from(string.as_str());
|
||||||
|
buf.push_str(&s);
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+=", name = "append")]
|
#[rhai_fn(name = "+=", name = "append")]
|
||||||
@ -41,7 +43,9 @@ mod string_functions {
|
|||||||
let s = print_with_func(FUNC_TO_STRING, &ctx, &mut item);
|
let s = print_with_func(FUNC_TO_STRING, &ctx, &mut item);
|
||||||
|
|
||||||
if !s.is_empty() {
|
if !s.is_empty() {
|
||||||
*string = format!("{string}{s}").into();
|
let mut buf = SmartString::from(string.as_str());
|
||||||
|
buf.push_str(&s);
|
||||||
|
*string = buf.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+", pure)]
|
#[rhai_fn(name = "+", pure)]
|
||||||
@ -74,7 +78,10 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn add_prepend_char(character: char, string: &str) -> ImmutableString {
|
pub fn add_prepend_char(character: char, string: &str) -> ImmutableString {
|
||||||
format!("{character}{string}").into()
|
let mut buf = SmartString::new_const();
|
||||||
|
buf.push(character);
|
||||||
|
buf.push_str(string);
|
||||||
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
|
131
src/parser.rs
131
src/parser.rs
@ -333,8 +333,12 @@ impl ParseSettings {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn make_anonymous_fn(hash: u64) -> String {
|
pub fn make_anonymous_fn(hash: u64) -> Identifier {
|
||||||
format!("{}{:016x}", crate::engine::FN_ANONYMOUS, hash)
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
let mut buf = Identifier::new_const();
|
||||||
|
write!(&mut buf, "{}{:016x}", crate::engine::FN_ANONYMOUS, hash).unwrap();
|
||||||
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this function an anonymous function?
|
/// Is this function an anonymous function?
|
||||||
@ -387,7 +391,7 @@ impl Expr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Err(
|
Err(
|
||||||
PERR::MismatchedType("a boolean expression".to_string(), type_name.to_string())
|
PERR::MismatchedType("a boolean expression".into(), type_name.into())
|
||||||
.into_err(self.start_position()),
|
.into_err(self.start_position()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -405,7 +409,7 @@ impl Expr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Err(
|
Err(
|
||||||
PERR::MismatchedType("an iterable value".to_string(), type_name.to_string())
|
PERR::MismatchedType("an iterable value".into(), type_name.into())
|
||||||
.into_err(self.start_position()),
|
.into_err(self.start_position()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -426,8 +430,8 @@ fn ensure_not_statement_expr(
|
|||||||
fn ensure_not_assignment(input: &mut TokenStream) -> ParseResult<()> {
|
fn ensure_not_assignment(input: &mut TokenStream) -> ParseResult<()> {
|
||||||
match input.peek().expect(NEVER_ENDS) {
|
match input.peek().expect(NEVER_ENDS) {
|
||||||
(Token::Equals, pos) => Err(LexError::ImproperSymbol(
|
(Token::Equals, pos) => Err(LexError::ImproperSymbol(
|
||||||
"=".to_string(),
|
"=".into(),
|
||||||
"Possibly a typo of '=='?".to_string(),
|
"Possibly a typo of '=='?".into(),
|
||||||
)
|
)
|
||||||
.into_err(*pos)),
|
.into_err(*pos)),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
@ -438,15 +442,15 @@ fn ensure_not_assignment(input: &mut TokenStream) -> ParseResult<()> {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if the next token is not the expected one.
|
/// Panics if the next token is not the expected one, or either tokens is not a literal symbol.
|
||||||
fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position {
|
fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position {
|
||||||
let (t, pos) = input.next().expect(NEVER_ENDS);
|
let (t, pos) = input.next().expect(NEVER_ENDS);
|
||||||
|
|
||||||
if t != expected_token {
|
if t != expected_token {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"{} expected but gets {} at {}",
|
"{} expected but gets {} at {}",
|
||||||
expected_token.syntax(),
|
expected_token.literal_syntax(),
|
||||||
t.syntax(),
|
t.literal_syntax(),
|
||||||
pos
|
pos
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -588,7 +592,7 @@ impl Engine {
|
|||||||
&& !self.global_sub_modules.contains_key(root)
|
&& !self.global_sub_modules.contains_key(root)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
PERR::ModuleUndefined(root.to_string()).into_err(namespace.position())
|
PERR::ModuleUndefined(root.into()).into_err(namespace.position())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,8 +659,9 @@ impl Engine {
|
|||||||
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
||||||
&& !self.global_sub_modules.contains_key(root)
|
&& !self.global_sub_modules.contains_key(root)
|
||||||
{
|
{
|
||||||
return Err(PERR::ModuleUndefined(root.to_string())
|
return Err(
|
||||||
.into_err(namespace.position()));
|
PERR::ModuleUndefined(root.into()).into_err(namespace.position())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace.set_index(index);
|
namespace.set_index(index);
|
||||||
@ -901,7 +906,7 @@ impl Engine {
|
|||||||
|
|
||||||
if self.max_array_size() > 0 && array.len() >= self.max_array_size() {
|
if self.max_array_size() > 0 && array.len() >= self.max_array_size() {
|
||||||
return Err(PERR::LiteralTooLarge(
|
return Err(PERR::LiteralTooLarge(
|
||||||
"Size of array literal".to_string(),
|
"Size of array literal".into(),
|
||||||
self.max_array_size(),
|
self.max_array_size(),
|
||||||
)
|
)
|
||||||
.into_err(input.peek().expect(NEVER_ENDS).1));
|
.into_err(input.peek().expect(NEVER_ENDS).1));
|
||||||
@ -1037,7 +1042,7 @@ impl Engine {
|
|||||||
|
|
||||||
if self.max_map_size() > 0 && map.len() >= self.max_map_size() {
|
if self.max_map_size() > 0 && map.len() >= self.max_map_size() {
|
||||||
return Err(PERR::LiteralTooLarge(
|
return Err(PERR::LiteralTooLarge(
|
||||||
"Number of properties in object map literal".to_string(),
|
"Number of properties in object map literal".into(),
|
||||||
self.max_map_size(),
|
self.max_map_size(),
|
||||||
)
|
)
|
||||||
.into_err(input.peek().expect(NEVER_ENDS).1));
|
.into_err(input.peek().expect(NEVER_ENDS).1));
|
||||||
@ -1185,7 +1190,7 @@ impl Engine {
|
|||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::DoubleArrow.into(),
|
Token::DoubleArrow.into(),
|
||||||
"in this switch case".to_string(),
|
"in this switch case".into(),
|
||||||
)
|
)
|
||||||
.into_err(pos))
|
.into_err(pos))
|
||||||
}
|
}
|
||||||
@ -1213,7 +1218,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
for expr in case_expr_list {
|
for expr in case_expr_list {
|
||||||
let value = expr.get_literal_value().ok_or_else(|| {
|
let value = expr.get_literal_value().ok_or_else(|| {
|
||||||
PERR::ExprExpected("a literal".to_string()).into_err(expr.start_position())
|
PERR::ExprExpected("a literal".into()).into_err(expr.start_position())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut range_value: Option<RangeCase> = None;
|
let mut range_value: Option<RangeCase> = None;
|
||||||
@ -1315,9 +1320,7 @@ impl Engine {
|
|||||||
|
|
||||||
let root_expr = match token {
|
let root_expr = match token {
|
||||||
_ if !(state.expr_filter)(token) => {
|
_ if !(state.expr_filter)(token) => {
|
||||||
return Err(
|
return Err(LexError::UnexpectedInput(token.to_string()).into_err(settings.pos))
|
||||||
LexError::UnexpectedInput(token.syntax().to_string()).into_err(settings.pos)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)),
|
Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)),
|
||||||
@ -1674,11 +1677,7 @@ impl Engine {
|
|||||||
token => unreachable!("Token::LexError expected but gets {:?}", token),
|
token => unreachable!("Token::LexError expected but gets {:?}", token),
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => {
|
_ => return Err(LexError::UnexpectedInput(token.to_string()).into_err(settings.pos)),
|
||||||
return Err(
|
|
||||||
LexError::UnexpectedInput(token.syntax().to_string()).into_err(settings.pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !(state.expr_filter)(&input.peek().expect(NEVER_ENDS).0) {
|
if !(state.expr_filter)(&input.peek().expect(NEVER_ENDS).0) {
|
||||||
@ -1716,12 +1715,11 @@ impl Engine {
|
|||||||
(Expr::Variable(x, ..), Token::Bang) if !x.1.is_empty() => {
|
(Expr::Variable(x, ..), Token::Bang) if !x.1.is_empty() => {
|
||||||
return match input.peek().expect(NEVER_ENDS) {
|
return match input.peek().expect(NEVER_ENDS) {
|
||||||
(Token::LeftParen | Token::Unit, ..) => {
|
(Token::LeftParen | Token::Unit, ..) => {
|
||||||
Err(LexError::UnexpectedInput(Token::Bang.syntax().to_string())
|
Err(LexError::UnexpectedInput(Token::Bang.into()).into_err(tail_pos))
|
||||||
.into_err(tail_pos))
|
|
||||||
}
|
}
|
||||||
_ => Err(LexError::ImproperSymbol(
|
_ => Err(LexError::ImproperSymbol(
|
||||||
"!".to_string(),
|
"!".into(),
|
||||||
"'!' cannot be used to call module functions".to_string(),
|
"'!' cannot be used to call module functions".into(),
|
||||||
)
|
)
|
||||||
.into_err(tail_pos)),
|
.into_err(tail_pos)),
|
||||||
};
|
};
|
||||||
@ -1732,7 +1730,7 @@ impl Engine {
|
|||||||
(Token::LeftParen | Token::Unit, ..) => (),
|
(Token::LeftParen | Token::Unit, ..) => (),
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::LeftParen.syntax().into(),
|
Token::LeftParen.into(),
|
||||||
"to start arguments list of function call".into(),
|
"to start arguments list of function call".into(),
|
||||||
)
|
)
|
||||||
.into_err(*pos))
|
.into_err(*pos))
|
||||||
@ -1821,11 +1819,9 @@ impl Engine {
|
|||||||
Self::make_dot_expr(state, expr, rhs, ASTFlags::NONE, op_flags, tail_pos)?
|
Self::make_dot_expr(state, expr, rhs, ASTFlags::NONE, op_flags, tail_pos)?
|
||||||
}
|
}
|
||||||
// Unknown postfix operator
|
// Unknown postfix operator
|
||||||
(expr, token) => unreachable!(
|
(expr, token) => {
|
||||||
"unknown postfix operator '{}' for {:?}",
|
unreachable!("unknown postfix operator '{}' for {:?}", token, expr)
|
||||||
token.syntax(),
|
}
|
||||||
expr
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1863,7 +1859,7 @@ impl Engine {
|
|||||||
&& !self.global_sub_modules.contains_key(root)
|
&& !self.global_sub_modules.contains_key(root)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
PERR::ModuleUndefined(root.to_string()).into_err(namespace.position())
|
PERR::ModuleUndefined(root.into()).into_err(namespace.position())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1890,7 +1886,7 @@ impl Engine {
|
|||||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||||
|
|
||||||
if !(state.expr_filter)(token) {
|
if !(state.expr_filter)(token) {
|
||||||
return Err(LexError::UnexpectedInput(token.syntax().to_string()).into_err(*token_pos));
|
return Err(LexError::UnexpectedInput(token.to_string()).into_err(*token_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut settings = settings;
|
let mut settings = settings;
|
||||||
@ -2092,8 +2088,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// ??? && ??? = rhs, ??? || ??? = rhs, xxx ?? xxx = rhs
|
// ??? && ??? = rhs, ??? || ??? = rhs, xxx ?? xxx = rhs
|
||||||
Expr::And(..) | Expr::Or(..) | Expr::Coalesce(..) => Err(LexError::ImproperSymbol(
|
Expr::And(..) | Expr::Or(..) | Expr::Coalesce(..) => Err(LexError::ImproperSymbol(
|
||||||
"=".to_string(),
|
"=".into(),
|
||||||
"Possibly a typo of '=='?".to_string(),
|
"Possibly a typo of '=='?".into(),
|
||||||
)
|
)
|
||||||
.into_err(op_pos)),
|
.into_err(op_pos)),
|
||||||
// expr = rhs
|
// expr = rhs
|
||||||
@ -2362,7 +2358,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||||
|
|
||||||
let op = op_token.syntax();
|
let op = op_token.to_string();
|
||||||
let hash = calc_fn_hash(None, &op, 2);
|
let hash = calc_fn_hash(None, &op, 2);
|
||||||
let is_valid_script_function = is_valid_function_name(&op);
|
let is_valid_script_function = is_valid_function_name(&op);
|
||||||
let operator_token = if is_valid_script_function {
|
let operator_token = if is_valid_script_function {
|
||||||
@ -2379,7 +2375,7 @@ impl Engine {
|
|||||||
let mut op_base = FnCallExpr {
|
let mut op_base = FnCallExpr {
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
namespace: Default::default(),
|
namespace: Default::default(),
|
||||||
name: state.get_interned_string(op.as_ref()),
|
name: state.get_interned_string(&op),
|
||||||
hashes: FnCallHashes::from_native(hash),
|
hashes: FnCallHashes::from_native(hash),
|
||||||
args,
|
args,
|
||||||
op_token: operator_token,
|
op_token: operator_token,
|
||||||
@ -2492,7 +2488,7 @@ impl Engine {
|
|||||||
settings.pos = *fwd_pos;
|
settings.pos = *fwd_pos;
|
||||||
let settings = settings.level_up();
|
let settings = settings.level_up();
|
||||||
|
|
||||||
required_token = match parse_func(&segments, &*fwd_token.syntax(), &mut user_state) {
|
required_token = match parse_func(&segments, &fwd_token.to_string(), &mut user_state) {
|
||||||
Ok(Some(seg))
|
Ok(Some(seg))
|
||||||
if seg.starts_with(CUSTOM_SYNTAX_MARKER_SYNTAX_VARIANT)
|
if seg.starts_with(CUSTOM_SYNTAX_MARKER_SYNTAX_VARIANT)
|
||||||
&& seg.len() > CUSTOM_SYNTAX_MARKER_SYNTAX_VARIANT.len() =>
|
&& seg.len() > CUSTOM_SYNTAX_MARKER_SYNTAX_VARIANT.len() =>
|
||||||
@ -2551,8 +2547,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::MissingSymbol("Expecting 'true' or 'false'".to_string())
|
PERR::MissingSymbol("Expecting 'true' or 'false'".into()).into_err(pos)
|
||||||
.into_err(pos),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2564,8 +2559,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::MissingSymbol("Expecting an integer number".to_string())
|
PERR::MissingSymbol("Expecting an integer number".into()).into_err(pos)
|
||||||
.into_err(pos),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2577,10 +2571,10 @@ impl Engine {
|
|||||||
tokens.push(state.get_interned_string(CUSTOM_SYNTAX_MARKER_FLOAT));
|
tokens.push(state.get_interned_string(CUSTOM_SYNTAX_MARKER_FLOAT));
|
||||||
}
|
}
|
||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(PERR::MissingSymbol(
|
return Err(
|
||||||
"Expecting a floating-point number".to_string(),
|
PERR::MissingSymbol("Expecting a floating-point number".into())
|
||||||
|
.into_err(pos),
|
||||||
)
|
)
|
||||||
.into_err(pos))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CUSTOM_SYNTAX_MARKER_STRING => match input.next().expect(NEVER_ENDS) {
|
CUSTOM_SYNTAX_MARKER_STRING => match input.next().expect(NEVER_ENDS) {
|
||||||
@ -2591,20 +2585,26 @@ impl Engine {
|
|||||||
tokens.push(state.get_interned_string(CUSTOM_SYNTAX_MARKER_STRING));
|
tokens.push(state.get_interned_string(CUSTOM_SYNTAX_MARKER_STRING));
|
||||||
}
|
}
|
||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(
|
return Err(PERR::MissingSymbol("Expecting a string".into()).into_err(pos))
|
||||||
PERR::MissingSymbol("Expecting a string".to_string()).into_err(pos)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
s => match input.next().expect(NEVER_ENDS) {
|
s => match input.next().expect(NEVER_ENDS) {
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(t, ..) if &*t.syntax() == s => {
|
(Token::Identifier(t), ..)
|
||||||
|
| (Token::Reserved(t), ..)
|
||||||
|
| (Token::Custom(t), ..)
|
||||||
|
if *t == s =>
|
||||||
|
{
|
||||||
|
segments.push(required_token.clone());
|
||||||
|
tokens.push(required_token.clone().into());
|
||||||
|
}
|
||||||
|
(t, ..) if t.is_literal() && t.literal_syntax() == s => {
|
||||||
segments.push(required_token.clone());
|
segments.push(required_token.clone());
|
||||||
tokens.push(required_token.clone().into());
|
tokens.push(required_token.clone().into());
|
||||||
}
|
}
|
||||||
(.., pos) => {
|
(.., pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
s.to_string(),
|
s.into(),
|
||||||
format!("for '{}' expression", segments[0]),
|
format!("for '{}' expression", segments[0]),
|
||||||
)
|
)
|
||||||
.into_err(pos))
|
.into_err(pos))
|
||||||
@ -2805,9 +2805,7 @@ impl Engine {
|
|||||||
let (counter_name, counter_pos) = parse_var_name(input)?;
|
let (counter_name, counter_pos) = parse_var_name(input)?;
|
||||||
|
|
||||||
if counter_name == name {
|
if counter_name == name {
|
||||||
return Err(
|
return Err(PERR::DuplicatedVariable(counter_name.into()).into_err(counter_pos));
|
||||||
PERR::DuplicatedVariable(counter_name.to_string()).into_err(counter_pos)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (has_close_paren, pos) = match_token(input, Token::RightParen);
|
let (has_close_paren, pos) = match_token(input, Token::RightParen);
|
||||||
@ -2893,7 +2891,7 @@ impl Engine {
|
|||||||
let (name, pos) = parse_var_name(input)?;
|
let (name, pos) = parse_var_name(input)?;
|
||||||
|
|
||||||
if !self.allow_shadowing() && state.stack.iter().any(|(v, ..)| v == name) {
|
if !self.allow_shadowing() && state.stack.iter().any(|(v, ..)| v == name) {
|
||||||
return Err(PERR::VariableExists(name.to_string()).into_err(pos));
|
return Err(PERR::VariableExists(name.into()).into_err(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref filter) = self.def_var_filter {
|
if let Some(ref filter) = self.def_var_filter {
|
||||||
@ -2914,10 +2912,10 @@ impl Engine {
|
|||||||
|
|
||||||
match filter(false, info, context) {
|
match filter(false, info, context) {
|
||||||
Ok(true) => (),
|
Ok(true) => (),
|
||||||
Ok(false) => return Err(PERR::ForbiddenVariable(name.to_string()).into_err(pos)),
|
Ok(false) => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
||||||
Err(err) => match *err {
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorParsing(e, pos) => return Err(e.into_err(pos)),
|
EvalAltResult::ErrorParsing(e, pos) => return Err(e.into_err(pos)),
|
||||||
_ => return Err(PERR::ForbiddenVariable(name.to_string()).into_err(pos)),
|
_ => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3361,7 +3359,7 @@ impl Engine {
|
|||||||
|
|
||||||
(.., pos) => Err(PERR::MissingToken(
|
(.., pos) => Err(PERR::MissingToken(
|
||||||
Token::Fn.into(),
|
Token::Fn.into(),
|
||||||
format!("following '{}'", Token::Private.syntax()),
|
format!("following '{}'", Token::Private),
|
||||||
)
|
)
|
||||||
.into_err(pos)),
|
.into_err(pos)),
|
||||||
}
|
}
|
||||||
@ -3564,7 +3562,7 @@ impl Engine {
|
|||||||
eat_token(input, Token::Unit);
|
eat_token(input, Token::Unit);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(.., pos) => return Err(PERR::FnMissingParams(name.to_string()).into_err(*pos)),
|
(.., pos) => return Err(PERR::FnMissingParams(name.into()).into_err(*pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut params = StaticVec::<(ImmutableString, _)>::new_const();
|
let mut params = StaticVec::<(ImmutableString, _)>::new_const();
|
||||||
@ -3577,8 +3575,9 @@ impl Engine {
|
|||||||
(Token::RightParen, ..) => break,
|
(Token::RightParen, ..) => break,
|
||||||
(Token::Identifier(s), pos) => {
|
(Token::Identifier(s), pos) => {
|
||||||
if params.iter().any(|(p, _)| p.as_str() == &*s) {
|
if params.iter().any(|(p, _)| p.as_str() == &*s) {
|
||||||
return Err(PERR::FnDuplicatedParam(name.to_string(), s.to_string())
|
return Err(
|
||||||
.into_err(pos));
|
PERR::FnDuplicatedParam(name.into(), s.to_string()).into_err(pos)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(*s);
|
let s = state.get_interned_string(*s);
|
||||||
state.stack.push(s.clone(), ());
|
state.stack.push(s.clone(), ());
|
||||||
@ -3611,7 +3610,7 @@ impl Engine {
|
|||||||
settings.is_breakable = false;
|
settings.is_breakable = false;
|
||||||
self.parse_block(input, state, lib, settings.level_up())?
|
self.parse_block(input, state, lib, settings.level_up())?
|
||||||
}
|
}
|
||||||
(.., pos) => return Err(PERR::FnMissingBody(name.to_string()).into_err(*pos)),
|
(.., pos) => return Err(PERR::FnMissingBody(name.into()).into_err(*pos)),
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
@ -3851,9 +3850,7 @@ impl Engine {
|
|||||||
match input.peek().expect(NEVER_ENDS) {
|
match input.peek().expect(NEVER_ENDS) {
|
||||||
(Token::EOF, ..) => (),
|
(Token::EOF, ..) => (),
|
||||||
// Return error if the expression doesn't end
|
// Return error if the expression doesn't end
|
||||||
(token, pos) => {
|
(token, pos) => return Err(LexError::UnexpectedInput(token.to_string()).into_err(*pos)),
|
||||||
return Err(LexError::UnexpectedInput(token.syntax().to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut statements = StmtBlockContainer::new_const();
|
let mut statements = StmtBlockContainer::new_const();
|
||||||
|
@ -9,7 +9,6 @@ use crate::{Engine, Identifier, LexError, SmartString, StaticVec, INT, UNSIGNED_
|
|||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
char, fmt,
|
char, fmt,
|
||||||
iter::{FusedIterator, Peekable},
|
iter::{FusedIterator, Peekable},
|
||||||
@ -591,12 +590,62 @@ pub enum Token {
|
|||||||
impl fmt::Display for Token {
|
impl fmt::Display for Token {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str(&self.syntax())
|
use Token::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
IntegerConstant(i) => write!(f, "{i}"),
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
FloatConstant(v) => write!(f, "{v}"),
|
||||||
|
#[cfg(feature = "decimal")]
|
||||||
|
DecimalConstant(d) => write!(f, "{d}"),
|
||||||
|
StringConstant(s) => write!(f, r#""{s}""#),
|
||||||
|
InterpolatedString(..) => f.write_str("string"),
|
||||||
|
CharConstant(c) => write!(f, "{c}"),
|
||||||
|
Identifier(s) => f.write_str(s),
|
||||||
|
Reserved(s) => f.write_str(s),
|
||||||
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
|
Custom(s) => f.write_str(s),
|
||||||
|
LexError(err) => write!(f, "{err}"),
|
||||||
|
Comment(s) => f.write_str(s),
|
||||||
|
|
||||||
|
EOF => f.write_str("{EOF}"),
|
||||||
|
|
||||||
|
token => f.write_str(token.literal_syntax()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
|
/// Is the token a literal symbol?
|
||||||
|
#[must_use]
|
||||||
|
pub const fn is_literal(&self) -> bool {
|
||||||
|
use Token::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
IntegerConstant(..) => false,
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
FloatConstant(..) => false,
|
||||||
|
#[cfg(feature = "decimal")]
|
||||||
|
DecimalConstant(..) => false,
|
||||||
|
StringConstant(..)
|
||||||
|
| InterpolatedString(..)
|
||||||
|
| CharConstant(..)
|
||||||
|
| Identifier(..)
|
||||||
|
| Reserved(..) => false,
|
||||||
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
|
Custom(..) => false,
|
||||||
|
LexError(..) | Comment(..) => false,
|
||||||
|
|
||||||
|
EOF => false,
|
||||||
|
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Get the literal syntax of the token.
|
/// Get the literal syntax of the token.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the token is not a literal symbol.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn literal_syntax(&self) -> &'static str {
|
pub const fn literal_syntax(&self) -> &'static str {
|
||||||
use Token::*;
|
use Token::*;
|
||||||
@ -690,34 +739,7 @@ impl Token {
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
As => "as",
|
As => "as",
|
||||||
|
|
||||||
_ => "ERROR: NOT A KEYWORD",
|
_ => panic!("token is not a literal symbol"),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the syntax of the token.
|
|
||||||
#[must_use]
|
|
||||||
pub fn syntax(&self) -> Cow<'static, str> {
|
|
||||||
use Token::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
IntegerConstant(i) => i.to_string().into(),
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
FloatConstant(f) => f.to_string().into(),
|
|
||||||
#[cfg(feature = "decimal")]
|
|
||||||
DecimalConstant(d) => d.to_string().into(),
|
|
||||||
StringConstant(s) => format!("\"{s}\"").into(),
|
|
||||||
InterpolatedString(..) => "string".into(),
|
|
||||||
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(),
|
|
||||||
|
|
||||||
EOF => "{EOF}".into(),
|
|
||||||
|
|
||||||
token => token.literal_syntax().into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1127,7 +1149,7 @@ impl Token {
|
|||||||
impl From<Token> for String {
|
impl From<Token> for String {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(token: Token) -> Self {
|
fn from(token: Token) -> Self {
|
||||||
token.syntax().into()
|
token.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2399,7 +2421,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
Some((Token::Reserved(s), pos)) => (match
|
Some((Token::Reserved(s), pos)) => (match
|
||||||
(s.as_str(),
|
(s.as_str(),
|
||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
(!self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s)),
|
self.engine.custom_keywords.contains_key(&*s),
|
||||||
#[cfg(feature = "no_custom_syntax")]
|
#[cfg(feature = "no_custom_syntax")]
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
@ -2436,7 +2458,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
#[cfg(feature = "no_custom_syntax")]
|
#[cfg(feature = "no_custom_syntax")]
|
||||||
(.., true) => unreachable!("no custom operators"),
|
(.., true) => unreachable!("no custom operators"),
|
||||||
// Reserved keyword that is not custom and disabled.
|
// Reserved keyword that is not custom and disabled.
|
||||||
(token, false) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token) => {
|
(token, false) if self.engine.disabled_symbols.contains(token) => {
|
||||||
let msg = format!("reserved {} '{token}' is disabled", if is_valid_identifier(token) { "keyword"} else {"symbol"});
|
let msg = format!("reserved {} '{token}' is disabled", if is_valid_identifier(token) { "keyword"} else {"symbol"});
|
||||||
Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into())
|
Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into())
|
||||||
},
|
},
|
||||||
@ -2445,13 +2467,13 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
}, pos),
|
}, pos),
|
||||||
// Custom keyword
|
// Custom keyword
|
||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
#[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) => {
|
Some((Token::Identifier(s), pos)) if self.engine.custom_keywords.contains_key(&*s) => {
|
||||||
(Token::Custom(s), pos)
|
(Token::Custom(s), pos)
|
||||||
}
|
}
|
||||||
// Custom keyword/symbol - must be disabled
|
// Custom keyword/symbol - must be disabled
|
||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
#[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()) => {
|
Some((token, pos)) if token.is_literal() && self.engine.custom_keywords.contains_key(token.literal_syntax()) => {
|
||||||
if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) {
|
if self.engine.disabled_symbols.contains(token.literal_syntax()) {
|
||||||
// Disabled standard keyword/symbol
|
// Disabled standard keyword/symbol
|
||||||
(Token::Custom(Box::new(token.literal_syntax().into())), pos)
|
(Token::Custom(Box::new(token.literal_syntax().into())), pos)
|
||||||
} else {
|
} else {
|
||||||
@ -2460,7 +2482,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disabled symbol
|
// Disabled symbol
|
||||||
Some((token, pos)) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) => {
|
Some((token, pos)) if token.is_literal() && self.engine.disabled_symbols.contains(token.literal_syntax()) => {
|
||||||
(Token::Reserved(Box::new(token.literal_syntax().into())), pos)
|
(Token::Reserved(Box::new(token.literal_syntax().into())), pos)
|
||||||
}
|
}
|
||||||
// Normal symbol
|
// Normal symbol
|
||||||
|
Loading…
Reference in New Issue
Block a user