Fix custom syntax bug.

This commit is contained in:
Stephen Chung 2023-04-25 23:14:08 +08:00
parent 6be29cae54
commit 4ec16d14e0
3 changed files with 67 additions and 9 deletions

View File

@ -14,6 +14,7 @@ Bug fixes
* Expressions such as `(v[0].func()).prop` now parse correctly. * Expressions such as `(v[0].func()).prop` now parse correctly.
* Shadowed variable exports are now handled correctly. * Shadowed variable exports are now handled correctly.
* Shadowed constant definitions are now optimized correctly when propagated (e.g. `const X = 1; const X = 1 + 1 + 1; X` now evaluates to 3 instead of 0). * Shadowed constant definitions are now optimized correctly when propagated (e.g. `const X = 1; const X = 1 + 1 + 1; X` now evaluates to 3 instead of 0).
* Identifiers and comma's in the middle of custom syntax now register correctly.
New features New features
------------ ------------

View File

@ -232,11 +232,9 @@ impl Engine {
} }
let token = Token::lookup_symbol_from_syntax(s).or_else(|| { let token = Token::lookup_symbol_from_syntax(s).or_else(|| {
if is_reserved_keyword_or_symbol(s).0 { is_reserved_keyword_or_symbol(s)
Some(Token::Reserved(Box::new(s.into()))) .0
} else { .then(|| Token::Reserved(Box::new(s.into())))
None
}
}); });
let seg = match s { let seg = match s {
@ -256,6 +254,9 @@ impl Engine {
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(), CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(),
// Identifier not in first position
_ if !segments.is_empty() && is_valid_identifier(s) => s.into(),
// Keyword/symbol not in first position // Keyword/symbol not in first position
_ if !segments.is_empty() && token.is_some() => { _ if !segments.is_empty() && token.is_some() => {
// Make it a custom keyword/symbol if it is disabled or reserved // Make it a custom keyword/symbol if it is disabled or reserved
@ -277,10 +278,7 @@ impl Engine {
{ {
return Err(LexError::ImproperSymbol( return Err(LexError::ImproperSymbol(
s.to_string(), s.to_string(),
format!( format!("Improper symbol for custom syntax at position #0: '{s}'"),
"Improper symbol for custom syntax at position #{}: '{s}'",
segments.len() + 1,
),
) )
.into_err(Position::NONE)); .into_err(Position::NONE));
} }

View File

@ -251,6 +251,65 @@ fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_custom_syntax_scope() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_custom_syntax(
[
"with", "offset", "(", "$expr$", ",", "$expr$", ")", "$block$",
],
true,
|context, inputs| {
let x = context
.eval_expression_tree(&inputs[0])?
.as_int()
.map_err(|typ| {
Box::new(EvalAltResult::ErrorMismatchDataType(
"integer".to_string(),
typ.to_string(),
inputs[0].position(),
))
})?;
let y = context
.eval_expression_tree(&inputs[1])?
.as_int()
.map_err(|typ| {
Box::new(EvalAltResult::ErrorMismatchDataType(
"integer".to_string(),
typ.to_string(),
inputs[1].position(),
))
})?;
let orig_len = context.scope().len();
context.scope_mut().push_constant("x", x);
context.scope_mut().push_constant("y", y);
let result = context.eval_expression_tree(&inputs[2]);
context.scope_mut().rewind(orig_len);
result
},
)?;
assert_eq!(
engine.eval::<INT>(
"
let y = 1;
let x = 0;
with offset(44, 2) { x - y }
"
)?,
42
);
Ok(())
}
#[test] #[test]
fn test_custom_syntax_matrix() -> Result<(), Box<EvalAltResult>> { fn test_custom_syntax_matrix() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();