Change parser output to String.
This commit is contained in:
parent
54d68c1061
commit
4add90b215
@ -116,16 +116,19 @@ The function signature of an implementation is:
|
||||
|
||||
where:
|
||||
|
||||
* `context: &mut EvalContext` - mutable reference to the current evaluation _context_, exposing the following:
|
||||
* `context.scope: &mut Scope` - mutable reference to the current [`Scope`]; variables can be added to/removed from it.
|
||||
* `context.engine(): &Engine` - reference to the current [`Engine`].
|
||||
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
|
||||
* `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any.
|
||||
* `context.call_level(): usize` - the current nesting level of function calls.
|
||||
| Parameter | Type | Description |
|
||||
| ----------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------- |
|
||||
| `context` | `&mut EvalContext` | mutable reference to the current evaluation _context_ |
|
||||
| - `context.scope` | `&mut Scope` | mutable reference to the current [`Scope`]; variables can be added to/removed from it |
|
||||
| - `context.engine()` | `&Engine` | reference to the current [`Engine`] |
|
||||
| - `context.iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
||||
| - `context.this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any |
|
||||
| - `context.call_level()` | `usize` | the current nesting level of function calls |
|
||||
| `inputs` | `&[Expression]` | a list of input expression trees |
|
||||
|
||||
* `inputs: &[Expression]` - a list of input expression trees.
|
||||
### Return Value
|
||||
|
||||
* Return value - result of evaluating the custom syntax expression.
|
||||
Return value is the result of evaluating the custom syntax expression.
|
||||
|
||||
### Access Arguments
|
||||
|
||||
@ -283,12 +286,12 @@ engine.register_custom_syntax_raw(
|
||||
"perform",
|
||||
|stream| match stream.len() {
|
||||
// perform ...
|
||||
1 => Ok(Some("$ident$".into())),
|
||||
1 => Ok(Some("$ident$".to_string())),
|
||||
// perform command ...
|
||||
2 => match stream[1].as_str() {
|
||||
"action" => Ok(Some("$expr$".into())),
|
||||
"hello" => Ok(Some("world".into())),
|
||||
"update" | "check" | "add" | "remove" => Ok(Some("$ident$".into())),
|
||||
"action" => Ok(Some("$expr$".to_string())),
|
||||
"hello" => Ok(Some("world".to_string())),
|
||||
"update" | "check" | "add" | "remove" => Ok(Some("$ident$".to_string())),
|
||||
"cleanup" => Ok(None),
|
||||
cmd => Err(ParseError(Box::new(ParseErrorType::BadInput(
|
||||
format!("Improper command: {}", cmd))),
|
||||
@ -320,21 +323,20 @@ engine.register_custom_syntax_raw(
|
||||
|
||||
The custom syntax parser has the following signature:
|
||||
|
||||
> `Fn(stream: &[String]) -> Result<Option<ImmutableString>, ParseError>`
|
||||
> `Fn(stream: &[String]) -> Result<Option<String>, ParseError>`
|
||||
|
||||
where:
|
||||
|
||||
* `stream: &[String]` - a slice of symbols that have been parsed so far, perhaps containing the following:
|
||||
* `$expr$` - an expression
|
||||
* `$block$` - a statement block
|
||||
| Parameter | Type | Description |
|
||||
| --------- | :---------: | -------------------------------------------------------------------------------------------------- |
|
||||
| `stream` | `&[String]` | a slice of symbols that have been parsed so far, possibly containing `"$expr$"` and/or `"$block$"` |
|
||||
|
||||
### Return Value
|
||||
|
||||
The return value is `Result<Option<ImmutableString>, ParseError>` where:
|
||||
The return value is `Result<Option<String>, ParseError>` where:
|
||||
|
||||
* `Ok(None)` - parsing complete and there are no more symbols to match.
|
||||
|
||||
* `Ok(Some(symbol))` - next symbol to match.
|
||||
|
||||
* `Err(ParseError)` - error is reflected back to the [`Engine`].
|
||||
Normally this is `ParseErrorType::BadInput` to indicate that there is a syntax error, but it can be any error.
|
||||
| Value | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Ok(None)` | parsing complete and there are no more symbols to match |
|
||||
| `Ok(Some(symbol))` | next symbol to match, which can also be `"$expr$"`, `"$ident$"` or `"$block$"` |
|
||||
| `Err(ParseError)` | error that is reflected back to the [`Engine`].<br/>Normally this is `ParseError(ParseErrorType::BadInput(message), Position::none())` to indicate that there is a syntax error, but it can be any `ParseError`. |
|
||||
|
@ -67,27 +67,23 @@ The function signature passed to `Engine::on_var` takes the following form:
|
||||
|
||||
where:
|
||||
|
||||
* `name: &str` - variable name.
|
||||
|
||||
* `index: usize` - an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.
|
||||
Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.
|
||||
|
||||
If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed.
|
||||
|
||||
* `context: &EvalContext` - reference to the current evaluation _context_, which exposes the following fields:
|
||||
* `context.scope: &Scope` - reference to the current [`Scope`] containing all variables up to the current evaluation position.
|
||||
* `context.engine(): &Engine` - reference to the current [`Engine`].
|
||||
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
|
||||
* `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any.
|
||||
* `context.call_level(): usize` - the current nesting level of function calls.
|
||||
| Parameter | Type | Description |
|
||||
| ----------------------------- | :-----------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `name` | `&str` | variable name |
|
||||
| `index` | `usize` | an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.<br/>Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.<br/>If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed. |
|
||||
| `context` | `&EvalContext` | reference to the current evaluation _context_ |
|
||||
| - `context.scope` | `&Scope` | reference to the current [`Scope`] containing all variables up to the current evaluation position |
|
||||
| - `context.engine()` | `&Engine` | reference to the current [`Engine`] |
|
||||
| - `context.iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
||||
| - `context.this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any |
|
||||
| - `context.call_level()` | `usize` | the current nesting level of function calls |
|
||||
|
||||
### Return Value
|
||||
|
||||
The return value is `Result<Option<Dynamic>, Box<EvalAltResult>>` where:
|
||||
|
||||
* `Ok(None)` - normal variable resolution process should continue, meaning to continue searching through the [`Scope`].
|
||||
|
||||
* `Ok(Some(Dynamic))` - wrapped [`Dynamic`] is taken as the value of the variable, which is treated as a constant.
|
||||
|
||||
* `Err(Box<EvalAltResult>)` - error is reflected back to the [`Engine`].
|
||||
Normally this is `EvalAltResult::ErrorVariableNotFound` to indicate that the variable does not exist, but it can be any error.
|
||||
| Value | Description |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Ok(None)` | normal variable resolution process should continue, i.e. continue searching through the [`Scope`] |
|
||||
| `Ok(Some(Dynamic))` | value of the variable, treated as a constant |
|
||||
| `Err(Box<EvalAltResult>)` | error that is reflected back to the [`Engine`].<br/>Normally this is `EvalAltResult::ErrorVariableNotFound(var_name, Position::none())` to indicate that the variable does not exist, but it can be any `EvalAltResult`. |
|
||||
|
@ -65,18 +65,17 @@ The function signature passed to `Engine::register_raw_fn` takes the following f
|
||||
|
||||
where:
|
||||
|
||||
* `T: Clone` - return type of the function.
|
||||
| Parameter | Type | Description |
|
||||
| ----------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `T` | `impl Clone` | return type of the function |
|
||||
| `context` | `NativeCallContext` | the current _native call context_ |
|
||||
| - `context.engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. |
|
||||
| - `context.iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
||||
| `args` | `&mut [&mut Dynamic]` | a slice containing `&mut` references to [`Dynamic`] values.<br/>The slice is guaranteed to contain enough arguments _of the correct types_. |
|
||||
|
||||
* `context: NativeCallContext` - the current _native call context_, which exposes the following:
|
||||
### Return value
|
||||
|
||||
* `context.engine(): &Engine` - the current [`Engine`], with all configurations and settings.
|
||||
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer].
|
||||
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
|
||||
|
||||
* `args: &mut [&mut Dynamic]` - a slice containing `&mut` references to [`Dynamic`] values.
|
||||
The slice is guaranteed to contain enough arguments _of the correct types_.
|
||||
|
||||
* Return value - result of the function call.
|
||||
The return value is the result of the function call.
|
||||
|
||||
Remember, in Rhai, all arguments _except_ the _first_ one are always passed by _value_ (i.e. cloned).
|
||||
Therefore, it is unnecessary to ever mutate any argument except the first one, as all mutations
|
||||
@ -118,16 +117,16 @@ let mut engine = Engine::new();
|
||||
engine.register_raw_fn(
|
||||
"bar",
|
||||
&[
|
||||
std::any::TypeId::of::<i64>(), // parameter types
|
||||
std::any::TypeId::of::<i64>(), // parameter types
|
||||
std::any::TypeId::of::<FnPtr>(),
|
||||
std::any::TypeId::of::<i64>(),
|
||||
],
|
||||
|context, args| {
|
||||
// 'args' is guaranteed to contain enough arguments of the correct types
|
||||
|
||||
let fp = std::mem::take(args[1]).cast::<FnPtr>(); // 2nd argument - function pointer
|
||||
let value = args[2].clone(); // 3rd argument - function argument
|
||||
let this_ptr = args.get_mut(0).unwrap(); // 1st argument - this pointer
|
||||
let fp = std::mem::take(args[1]).cast::<FnPtr>(); // 2nd argument - function pointer
|
||||
let value = args[2].clone(); // 3rd argument - function argument
|
||||
let this_ptr = args.get_mut(0).unwrap(); // 1st argument - this pointer
|
||||
|
||||
// Use 'FnPtr::call_dynamic' to call the function pointer.
|
||||
// Beware, private script-defined functions will not be found.
|
||||
@ -135,13 +134,14 @@ engine.register_raw_fn(
|
||||
},
|
||||
);
|
||||
|
||||
let result = engine.eval::<i64>(r#"
|
||||
let result = engine.eval::<i64>(
|
||||
r#"
|
||||
fn foo(x) { this += x; } // script-defined function 'foo'
|
||||
|
||||
let x = 41; // object
|
||||
x.bar(Fn("foo"), 1); // pass 'foo' as function pointer
|
||||
x
|
||||
"#)?;
|
||||
"#)?;
|
||||
```
|
||||
|
||||
|
||||
@ -158,7 +158,8 @@ Shared values are implemented as `Rc<RefCell<Dynamic>>` (`Arc<RwLock<Dynamic>>`
|
||||
|
||||
If the value is _not_ a shared value, or if running under [`no_closure`] where there is
|
||||
no [capturing][automatic currying], this API de-sugars to a simple `Dynamic::downcast_ref` and
|
||||
`Dynamic::downcast_mut`.
|
||||
`Dynamic::downcast_mut`. In other words, there is no locking and reference counting overhead
|
||||
for the vast majority of non-shared values.
|
||||
|
||||
If the value is a shared value, then it is first locked and the returned lock guard
|
||||
then allows access to the underlying value in the specified type.
|
||||
|
@ -27,11 +27,11 @@ pub type FnCustomSyntaxEval =
|
||||
|
||||
/// A general expression parsing trait object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
pub type FnCustomSyntaxParse = dyn Fn(&[String]) -> Result<Option<ImmutableString>, ParseError>;
|
||||
pub type FnCustomSyntaxParse = dyn Fn(&[String]) -> Result<Option<String>, ParseError>;
|
||||
/// A general expression parsing trait object.
|
||||
#[cfg(feature = "sync")]
|
||||
pub type FnCustomSyntaxParse =
|
||||
dyn Fn(&[String]) -> Result<Option<ImmutableString>, ParseError> + Send + Sync;
|
||||
dyn Fn(&[String]) -> Result<Option<String>, ParseError> + Send + Sync;
|
||||
|
||||
/// An expression sub-tree in an AST.
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
@ -107,7 +107,7 @@ impl Engine {
|
||||
) -> Result<&mut Self, ParseError> {
|
||||
let keywords = keywords.as_ref();
|
||||
|
||||
let mut segments: StaticVec<ImmutableString> = Default::default();
|
||||
let mut segments: StaticVec<_> = Default::default();
|
||||
|
||||
for s in keywords {
|
||||
let s = s.as_ref().trim();
|
||||
@ -161,7 +161,7 @@ impl Engine {
|
||||
}
|
||||
};
|
||||
|
||||
segments.push(seg.into());
|
||||
segments.push(seg);
|
||||
}
|
||||
|
||||
// If the syntax has no keywords, just ignore the registration
|
||||
@ -204,7 +204,7 @@ impl Engine {
|
||||
pub fn register_custom_syntax_raw(
|
||||
&mut self,
|
||||
key: impl Into<ImmutableString>,
|
||||
parse: impl Fn(&[String]) -> Result<Option<ImmutableString>, ParseError> + SendSync + 'static,
|
||||
parse: impl Fn(&[String]) -> Result<Option<String>, ParseError> + SendSync + 'static,
|
||||
new_vars: isize,
|
||||
func: impl Fn(&mut EvalContext, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>>
|
||||
+ SendSync
|
||||
|
Loading…
Reference in New Issue
Block a user