rhai/src/syntax.rs

147 lines
4.6 KiB
Rust
Raw Normal View History

2020-07-10 16:01:47 +02:00
//! Module containing implementation for custom syntax.
#![cfg(feature = "internals")]
2020-07-09 13:54:28 +02:00
use crate::any::Dynamic;
2020-07-11 09:09:17 +02:00
use crate::engine::{Engine, Expression, Imports, State, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
2020-07-09 13:54:28 +02:00
use crate::error::LexError;
use crate::fn_native::{SendSync, Shared};
use crate::module::Module;
use crate::result::EvalAltResult;
use crate::scope::Scope;
use crate::token::{is_valid_identifier, Token};
use crate::utils::StaticVec;
use crate::stdlib::{
fmt,
rc::Rc,
string::{String, ToString},
sync::Arc,
};
/// A general function trail object.
#[cfg(not(feature = "sync"))]
pub type FnCustomSyntaxEval = dyn Fn(
&Engine,
2020-07-22 07:08:51 +02:00
&mut EvalContext,
2020-07-09 13:54:28 +02:00
&mut Scope,
2020-07-11 09:09:17 +02:00
&[Expression],
2020-07-09 13:54:28 +02:00
) -> Result<Dynamic, Box<EvalAltResult>>;
/// A general function trail object.
#[cfg(feature = "sync")]
2020-07-22 07:08:51 +02:00
pub type FnCustomSyntaxEval = dyn Fn(&Engine, &mut EvalContext, &mut Scope, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>>
2020-07-09 13:54:28 +02:00
+ Send
+ Sync;
#[derive(Clone)]
pub struct CustomSyntax {
pub segments: StaticVec<String>,
pub func: Shared<FnCustomSyntaxEval>,
pub scope_delta: isize,
}
impl fmt::Debug for CustomSyntax {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.segments, f)
}
}
2020-07-22 07:08:51 +02:00
pub struct EvalContext<'a, 'b: 'a, 's, 'm, 't, 'd: 't> {
pub(crate) mods: &'a mut Imports<'b>,
pub(crate) state: &'s mut State,
pub(crate) lib: &'m Module,
pub(crate) this_ptr: &'t mut Option<&'d mut Dynamic>,
pub(crate) level: usize,
}
2020-07-09 13:54:28 +02:00
impl Engine {
2020-07-10 16:01:47 +02:00
pub fn register_custom_syntax<S: AsRef<str> + ToString>(
2020-07-09 13:54:28 +02:00
&mut self,
value: &[S],
scope_delta: isize,
func: impl Fn(
&Engine,
2020-07-22 07:08:51 +02:00
&mut EvalContext,
2020-07-09 13:54:28 +02:00
&mut Scope,
2020-07-11 09:09:17 +02:00
&[Expression],
2020-07-09 13:54:28 +02:00
) -> Result<Dynamic, Box<EvalAltResult>>
+ SendSync
+ 'static,
2020-07-13 13:38:50 +02:00
) -> Result<&mut Self, Box<LexError>> {
2020-07-09 13:54:28 +02:00
if value.is_empty() {
return Err(Box::new(LexError::ImproperSymbol("".to_string())));
}
let mut segments: StaticVec<_> = Default::default();
for s in value {
let seg = match s.as_ref() {
// Markers not in first position
2020-07-10 16:01:47 +02:00
MARKER_EXPR | MARKER_BLOCK | MARKER_IDENT if !segments.is_empty() => s.to_string(),
2020-07-09 13:54:28 +02:00
// Standard symbols not in first position
2020-07-10 16:01:47 +02:00
s if !segments.is_empty() && Token::lookup_from_syntax(s).is_some() => {
// Make it a custom keyword/operator if it is a disabled standard keyword/operator
// or a reserved keyword/operator.
2020-07-10 16:01:47 +02:00
if self
.disabled_symbols
.as_ref()
.map(|d| d.contains(s))
.unwrap_or(false)
|| Token::lookup_from_syntax(s)
.map(|token| token.is_reserved())
.unwrap_or(false)
2020-07-10 16:01:47 +02:00
{
// If symbol is disabled, make it a custom keyword
if self.custom_keywords.is_none() {
self.custom_keywords = Some(Default::default());
}
if !self.custom_keywords.as_ref().unwrap().contains_key(s) {
self.custom_keywords.as_mut().unwrap().insert(s.into(), 0);
}
}
s.into()
}
// Identifier
2020-07-09 13:54:28 +02:00
s if is_valid_identifier(s.chars()) => {
if self.custom_keywords.is_none() {
self.custom_keywords = Some(Default::default());
}
if !self.custom_keywords.as_ref().unwrap().contains_key(s) {
self.custom_keywords.as_mut().unwrap().insert(s.into(), 0);
}
s.into()
}
// Anything else is an error
_ => return Err(Box::new(LexError::ImproperSymbol(s.to_string()))),
};
segments.push(seg);
}
let key = segments.remove(0);
let syntax = CustomSyntax {
segments,
#[cfg(not(feature = "sync"))]
func: Rc::new(func),
#[cfg(feature = "sync")]
func: Arc::new(func),
scope_delta,
};
if self.custom_syntax.is_none() {
self.custom_syntax = Some(Default::default());
}
self.custom_syntax
.as_mut()
.unwrap()
.insert(key, syntax.into());
2020-07-12 05:46:53 +02:00
Ok(self)
2020-07-09 13:54:28 +02:00
}
}