Add look-ahead to custom syntax parser.

This commit is contained in:
Stephen Chung 2020-12-15 19:23:30 +08:00
parent 17310ef576
commit f8c14ba1c4
4 changed files with 16 additions and 12 deletions

View File

@ -23,6 +23,7 @@ Breaking changes
* `Engine::on_progress` now takes `u64` instead of `&u64`. * `Engine::on_progress` now takes `u64` instead of `&u64`.
* The closure for `Engine::on_debug` now takes an additional `Position` parameter. * The closure for `Engine::on_debug` now takes an additional `Position` parameter.
* `AST::iter_functions` now returns `ScriptFnMetadata`. * `AST::iter_functions` now returns `ScriptFnMetadata`.
* The parser function passed to `Engine::register_custom_syntax_raw` now takes an additional parameter containing the _look-ahead_ symbol.
New features New features
------------ ------------
@ -34,6 +35,7 @@ Enhancements
* Capturing a constant variable in a closure is now supported, with no cloning. * Capturing a constant variable in a closure is now supported, with no cloning.
* Provides position info for `debug` statements. * Provides position info for `debug` statements.
* A _look-ahead_ symbol is provided to custom syntax parsers, which can be used to parse variable-length symbol streams.
Version 0.19.7 Version 0.19.7

View File

@ -1831,11 +1831,13 @@ fn parse_custom_syntax(
tokens.push(key.into()); tokens.push(key.into());
loop { loop {
settings.pos = input.peek().unwrap().1; let (fwd_token, fwd_pos) = input.peek().unwrap();
settings.pos = *fwd_pos;
let settings = settings.level_up(); let settings = settings.level_up();
let required_token = let required_token = if let Some(seg) = parse_func(&segments, fwd_token.syntax().as_ref())
if let Some(seg) = parse_func(&segments).map_err(|err| err.0.into_err(settings.pos))? { .map_err(|err| err.0.into_err(settings.pos))?
{
seg seg
} else { } else {
break; break;

View File

@ -26,11 +26,11 @@ pub type FnCustomSyntaxEval =
/// A general expression parsing trait object. /// A general expression parsing trait object.
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
pub type FnCustomSyntaxParse = pub type FnCustomSyntaxParse =
dyn Fn(&[ImmutableString]) -> Result<Option<ImmutableString>, ParseError>; dyn Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError>;
/// A general expression parsing trait object. /// A general expression parsing trait object.
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
pub type FnCustomSyntaxParse = pub type FnCustomSyntaxParse =
dyn Fn(&[ImmutableString]) -> Result<Option<ImmutableString>, ParseError> + Send + Sync; dyn Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError> + Send + Sync;
/// An expression sub-tree in an [`AST`][crate::AST]. /// An expression sub-tree in an [`AST`][crate::AST].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -185,7 +185,7 @@ impl Engine {
self.register_custom_syntax_raw( self.register_custom_syntax_raw(
key, key,
// Construct the parsing function // Construct the parsing function
move |stream| { move |stream, _| {
if stream.len() >= segments.len() { if stream.len() >= segments.len() {
Ok(None) Ok(None)
} else { } else {
@ -213,7 +213,7 @@ impl Engine {
pub fn register_custom_syntax_raw( pub fn register_custom_syntax_raw(
&mut self, &mut self,
key: impl Into<ImmutableString>, key: impl Into<ImmutableString>,
parse: impl Fn(&[ImmutableString]) -> Result<Option<ImmutableString>, ParseError> parse: impl Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError>
+ SendSync + SendSync
+ 'static, + 'static,
new_vars: isize, new_vars: isize,

View File

@ -93,7 +93,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
engine.register_custom_syntax_raw( engine.register_custom_syntax_raw(
"hello", "hello",
|stream| match stream.len() { |stream, _| match stream.len() {
0 => unreachable!(), 0 => unreachable!(),
1 => Ok(Some("$ident$".into())), 1 => Ok(Some("$ident$".into())),
2 => match stream[1].as_str() { 2 => match stream[1].as_str() {