Refine docs and add custom syntax.
This commit is contained in:
@@ -11,13 +11,15 @@ use crate::parser::{Expr, FnAccess, ImmutableString, ReturnType, ScriptFnDef, St
|
||||
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||
use crate::result::EvalAltResult;
|
||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||
use crate::syntax::CustomSyntax;
|
||||
use crate::token::Position;
|
||||
use crate::utils::StaticVec;
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
use crate::parser::FLOAT;
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
use crate::syntax::CustomSyntax;
|
||||
|
||||
use crate::stdlib::{
|
||||
any::{type_name, TypeId},
|
||||
borrow::Cow,
|
||||
@@ -85,9 +87,12 @@ pub const FN_GET: &str = "get$";
|
||||
pub const FN_SET: &str = "set$";
|
||||
pub const FN_IDX_GET: &str = "index$get$";
|
||||
pub const FN_IDX_SET: &str = "index$set$";
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
pub const MARKER_EXPR: &str = "$expr$";
|
||||
pub const MARKER_STMT: &str = "$stmt$";
|
||||
#[cfg(feature = "internals")]
|
||||
pub const MARKER_BLOCK: &str = "$block$";
|
||||
#[cfg(feature = "internals")]
|
||||
pub const MARKER_IDENT: &str = "$ident$";
|
||||
|
||||
/// A type specifying the method of chaining.
|
||||
@@ -279,6 +284,7 @@ pub struct Engine {
|
||||
/// A hashset containing custom keywords and precedence to recognize.
|
||||
pub(crate) custom_keywords: Option<HashMap<String, u8>>,
|
||||
/// Custom syntax.
|
||||
#[cfg(feature = "internals")]
|
||||
pub(crate) custom_syntax: Option<HashMap<String, CustomSyntax>>,
|
||||
|
||||
/// Callback closure for implementing the `print` command.
|
||||
@@ -329,6 +335,8 @@ impl Default for Engine {
|
||||
type_names: None,
|
||||
disabled_symbols: None,
|
||||
custom_keywords: None,
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
custom_syntax: None,
|
||||
|
||||
// default print/debug implementations
|
||||
@@ -562,6 +570,8 @@ impl Engine {
|
||||
type_names: None,
|
||||
disabled_symbols: None,
|
||||
custom_keywords: None,
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
custom_syntax: None,
|
||||
|
||||
print: Box::new(|_| {}),
|
||||
@@ -1667,14 +1677,14 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate an expression inside an AST.
|
||||
/// Evaluate an expression tree.
|
||||
///
|
||||
/// ## WARNING - Low Level API
|
||||
///
|
||||
/// This function is very low level. It evaluates an expression from an AST.
|
||||
#[cfg(feature = "internals")]
|
||||
#[deprecated(note = "this method is volatile and may change")]
|
||||
pub fn eval_expr_from_ast(
|
||||
pub fn eval_expression_tree(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
mods: &mut Imports,
|
||||
@@ -2118,6 +2128,7 @@ impl Engine {
|
||||
Expr::False(_) => Ok(false.into()),
|
||||
Expr::Unit(_) => Ok(().into()),
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
Expr::Custom(x) => {
|
||||
let func = (x.0).1.as_ref();
|
||||
let exprs = (x.0).0.as_ref();
|
||||
|
@@ -1,3 +1,4 @@
|
||||
//! Module containing interfaces with native-Rust functions.
|
||||
use crate::any::Dynamic;
|
||||
use crate::engine::Engine;
|
||||
use crate::module::Module;
|
||||
|
@@ -91,6 +91,7 @@ mod scope;
|
||||
mod serde;
|
||||
mod settings;
|
||||
mod stdlib;
|
||||
#[cfg(feature = "internals")]
|
||||
mod syntax;
|
||||
mod token;
|
||||
mod r#unsafe;
|
||||
|
@@ -2,10 +2,13 @@ use crate::any::Dynamic;
|
||||
use crate::calc_fn_hash;
|
||||
use crate::engine::{Engine, Imports, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
||||
use crate::module::Module;
|
||||
use crate::parser::{map_dynamic_to_expr, CustomExpr, Expr, ReturnType, ScriptFnDef, Stmt, AST};
|
||||
use crate::parser::{map_dynamic_to_expr, Expr, ReturnType, ScriptFnDef, Stmt, AST};
|
||||
use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope};
|
||||
use crate::utils::StaticVec;
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
use crate::parser::CustomExpr;
|
||||
|
||||
use crate::stdlib::{
|
||||
boxed::Box,
|
||||
iter::empty,
|
||||
@@ -599,6 +602,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
||||
}
|
||||
|
||||
// Custom syntax
|
||||
#[cfg(feature = "internals")]
|
||||
Expr::Custom(x) => Expr::Custom(Box::new((
|
||||
CustomExpr(
|
||||
(x.0).0.into_iter().map(|expr| optimize_expr(expr, state)).collect(),
|
||||
|
@@ -2,19 +2,23 @@
|
||||
|
||||
use crate::any::{Dynamic, Union};
|
||||
use crate::calc_fn_hash;
|
||||
use crate::engine::{
|
||||
make_getter, make_setter, Engine, KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT,
|
||||
MARKER_STMT,
|
||||
};
|
||||
use crate::engine::{make_getter, make_setter, Engine, KEYWORD_THIS};
|
||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||
use crate::fn_native::Shared;
|
||||
use crate::module::{Module, ModuleRef};
|
||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||
use crate::syntax::FnCustomSyntaxEval;
|
||||
use crate::token::{Position, Token, TokenStream};
|
||||
use crate::utils::{StaticVec, StraightHasherBuilder};
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
use crate::engine::{MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
use crate::fn_native::Shared;
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
use crate::syntax::FnCustomSyntaxEval;
|
||||
|
||||
use crate::stdlib::{
|
||||
borrow::Cow,
|
||||
boxed::Box,
|
||||
@@ -574,8 +578,10 @@ impl Stmt {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg(feature = "internals")]
|
||||
pub struct CustomExpr(pub StaticVec<Expr>, pub Shared<FnCustomSyntaxEval>);
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
impl fmt::Debug for CustomExpr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
@@ -647,6 +653,7 @@ pub enum Expr {
|
||||
/// ()
|
||||
Unit(Position),
|
||||
/// Custom syntax
|
||||
#[cfg(feature = "internals")]
|
||||
Custom(Box<(CustomExpr, Position)>),
|
||||
}
|
||||
|
||||
@@ -743,6 +750,7 @@ impl Expr {
|
||||
|
||||
Self::Dot(x) | Self::Index(x) => x.0.position(),
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
Self::Custom(x) => x.1,
|
||||
}
|
||||
}
|
||||
@@ -776,6 +784,8 @@ impl Expr {
|
||||
Self::Assignment(x) => x.3 = new_pos,
|
||||
Self::Dot(x) => x.2 = new_pos,
|
||||
Self::Index(x) => x.2 = new_pos,
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
Self::Custom(x) => x.1 = new_pos,
|
||||
}
|
||||
|
||||
@@ -881,6 +891,7 @@ impl Expr {
|
||||
_ => false,
|
||||
},
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
Self::Custom(_) => false,
|
||||
}
|
||||
}
|
||||
@@ -897,6 +908,14 @@ impl Expr {
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
pub fn get_variable_name(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Variable(x) => Some((x.0).0.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume a particular token, checking that it is the expected one.
|
||||
@@ -2046,6 +2065,7 @@ fn parse_expr(
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// Check if it is a custom syntax.
|
||||
#[cfg(feature = "internals")]
|
||||
if let Some(ref custom) = state.engine.custom_syntax {
|
||||
let (token, pos) = input.peek().unwrap();
|
||||
let token_pos = *pos;
|
||||
@@ -2085,12 +2105,6 @@ fn parse_expr(
|
||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||
},
|
||||
MARKER_EXPR => exprs.push(parse_expr(input, state, lib, settings)?),
|
||||
MARKER_STMT => {
|
||||
let stmt = parse_stmt(input, state, lib, settings)?
|
||||
.unwrap_or_else(|| Stmt::Noop(settings.pos));
|
||||
let pos = stmt.position();
|
||||
exprs.push(Expr::Stmt(Box::new((stmt, pos))))
|
||||
}
|
||||
MARKER_BLOCK => {
|
||||
let stmt = parse_block(input, state, lib, settings)?;
|
||||
let pos = stmt.position();
|
||||
|
@@ -1,5 +1,8 @@
|
||||
//! Module containing implementation for custom syntax.
|
||||
#![cfg(feature = "internals")]
|
||||
|
||||
use crate::any::Dynamic;
|
||||
use crate::engine::{Engine, Imports, State, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT, MARKER_STMT};
|
||||
use crate::engine::{Engine, Imports, State, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||
use crate::error::LexError;
|
||||
use crate::fn_native::{SendSync, Shared};
|
||||
use crate::module::Module;
|
||||
@@ -57,7 +60,7 @@ impl fmt::Debug for CustomSyntax {
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn add_custom_syntax<S: AsRef<str> + ToString>(
|
||||
pub fn register_custom_syntax<S: AsRef<str> + ToString>(
|
||||
&mut self,
|
||||
value: &[S],
|
||||
scope_delta: isize,
|
||||
@@ -83,12 +86,28 @@ impl Engine {
|
||||
for s in value {
|
||||
let seg = match s.as_ref() {
|
||||
// Markers not in first position
|
||||
MARKER_EXPR | MARKER_STMT | MARKER_BLOCK | MARKER_IDENT if !segments.is_empty() => {
|
||||
s.to_string()
|
||||
}
|
||||
MARKER_EXPR | MARKER_BLOCK | MARKER_IDENT if !segments.is_empty() => s.to_string(),
|
||||
// Standard symbols not in first position
|
||||
s if !segments.is_empty() && Token::lookup_from_syntax(s).is_some() => s.into(),
|
||||
// Custom keyword
|
||||
s if !segments.is_empty() && Token::lookup_from_syntax(s).is_some() => {
|
||||
if self
|
||||
.disabled_symbols
|
||||
.as_ref()
|
||||
.map(|d| d.contains(s))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
// 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
|
||||
s if is_valid_identifier(s.chars()) => {
|
||||
if self.custom_keywords.is_none() {
|
||||
self.custom_keywords = Some(Default::default());
|
||||
|
Reference in New Issue
Block a user