Allow self-terminating custom syntax.
This commit is contained in:
parent
3127f9a8af
commit
e0125a1033
@ -8,6 +8,7 @@ Enhancements
|
||||
------------
|
||||
|
||||
* `$symbol$` is supported in custom syntax to match any symbol.
|
||||
* Custom syntax with `$block$`, `}` or `;` as the last symbol are now self-terminating (i.e. no need to attach a terminating `;`).
|
||||
* `Dynamic::as_string` and `Dynamic::as_immutable_string` are deprecated and replaced by `into_string` and `into_immutable_string` respectively.
|
||||
* Added a number of constants to `Dynamic`.
|
||||
* Added a number of constants and `fromXXX` constant methods to `Dynamic`.
|
||||
|
17
src/ast.rs
17
src/ast.rs
@ -1263,10 +1263,12 @@ impl Stmt {
|
||||
// A No-op requires a semicolon in order to know it is an empty statement!
|
||||
Self::Noop(_) => false,
|
||||
|
||||
Self::Expr(Expr::Custom(x, _)) if x.is_self_terminated() => true,
|
||||
|
||||
Self::Var(_, _, _, _)
|
||||
| Self::Assignment(_, _)
|
||||
| Self::FnCall(_, _)
|
||||
| Self::Expr(_)
|
||||
| Self::FnCall(_, _)
|
||||
| Self::Do(_, _, _, _)
|
||||
| Self::Continue(_)
|
||||
| Self::Break(_)
|
||||
@ -1509,6 +1511,19 @@ pub struct CustomExpr {
|
||||
pub scope_may_be_changed: bool,
|
||||
/// List of tokens actually parsed.
|
||||
pub tokens: StaticVec<Identifier>,
|
||||
/// Is this custom syntax self-terminated?
|
||||
pub self_terminated: bool,
|
||||
}
|
||||
|
||||
impl CustomExpr {
|
||||
/// Is this custom syntax self-terminated (i.e. no need for a semicolon terminator)?
|
||||
///
|
||||
/// A self-terminated custom syntax always ends in `$block$`, `}` or `;`
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
pub const fn is_self_terminated(&self) -> bool {
|
||||
self.self_terminated
|
||||
}
|
||||
}
|
||||
|
||||
/// _(internals)_ A binary expression.
|
||||
|
19
src/parse.rs
19
src/parse.rs
@ -2004,16 +2004,17 @@ fn parse_custom_syntax(
|
||||
}
|
||||
|
||||
let parse_func = syntax.parse.as_ref();
|
||||
let mut required_token: ImmutableString = key.into();
|
||||
|
||||
segments.push(key.into());
|
||||
tokens.push(key.into());
|
||||
tokens.push(required_token.clone().into());
|
||||
segments.push(required_token.clone());
|
||||
|
||||
loop {
|
||||
let (fwd_token, fwd_pos) = input.peek().expect(NEVER_ENDS);
|
||||
settings.pos = *fwd_pos;
|
||||
let settings = settings.level_up();
|
||||
|
||||
let required_token = match parse_func(&segments, fwd_token.syntax().as_ref()) {
|
||||
required_token = match parse_func(&segments, fwd_token.syntax().as_ref()) {
|
||||
Ok(Some(seg)) => seg,
|
||||
Ok(None) => break,
|
||||
Err(err) => return Err(err.0.into_err(settings.pos)),
|
||||
@ -2120,11 +2121,23 @@ fn parse_custom_syntax(
|
||||
keywords.shrink_to_fit();
|
||||
tokens.shrink_to_fit();
|
||||
|
||||
const KEYWORD_SEMICOLON: &str = Token::SemiColon.literal_syntax();
|
||||
const KEYWORD_CLOSE_BRACE: &str = Token::RightBrace.literal_syntax();
|
||||
|
||||
let self_terminated = match required_token.as_str() {
|
||||
// It is self-terminating if the last symbol is a block
|
||||
CUSTOM_SYNTAX_MARKER_BLOCK => true,
|
||||
// If the last symbol is `;` or `}`, it is self-terminating
|
||||
KEYWORD_SEMICOLON | KEYWORD_CLOSE_BRACE => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Ok(Expr::Custom(
|
||||
CustomExpr {
|
||||
keywords,
|
||||
tokens,
|
||||
scope_may_be_changed: syntax.scope_may_be_changed,
|
||||
self_terminated,
|
||||
}
|
||||
.into(),
|
||||
pos,
|
||||
|
@ -136,6 +136,16 @@ fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
|
||||
))
|
||||
);
|
||||
|
||||
// Check self-termination
|
||||
engine
|
||||
.register_custom_syntax(&["test1", "$block$"], true, |_, _| Ok(Dynamic::UNIT))?
|
||||
.register_custom_syntax(&["test2", "}"], true, |_, _| Ok(Dynamic::UNIT))?
|
||||
.register_custom_syntax(&["test3", ";"], true, |_, _| Ok(Dynamic::UNIT))?;
|
||||
|
||||
assert_eq!(engine.eval::<INT>("test1 { x = y + z; } 42")?, 42);
|
||||
assert_eq!(engine.eval::<INT>("test2 } 42")?, 42);
|
||||
assert_eq!(engine.eval::<INT>("test3; 42")?, 42);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user