Fix custom syntax with method calls.
This commit is contained in:
parent
224aa0ea68
commit
10fa6844c4
@ -7,7 +7,7 @@ Version 1.3.1
|
|||||||
Bug fixes
|
Bug fixes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* Custom syntax now works properly inside binary expressions.
|
* Custom syntax now works properly inside binary expressions and with method calls.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
@ -2421,7 +2421,8 @@ impl Expr {
|
|||||||
| Self::Dot(_, _, _)
|
| Self::Dot(_, _, _)
|
||||||
| Self::Index(_, _, _)
|
| Self::Index(_, _, _)
|
||||||
| Self::Array(_, _)
|
| Self::Array(_, _)
|
||||||
| Self::Map(_, _) => match token {
|
| Self::Map(_, _)
|
||||||
|
| Self::Custom(_, _) => match token {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Token::LeftBracket => true,
|
Token::LeftBracket => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -2443,8 +2444,6 @@ impl Expr {
|
|||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::Custom(_, _) => false,
|
|
||||||
|
|
||||||
Self::Stack(_, _) => false,
|
Self::Stack(_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1135,7 +1135,7 @@ fn parse_primary(
|
|||||||
let mut settings = settings;
|
let mut settings = settings;
|
||||||
settings.pos = *token_pos;
|
settings.pos = *token_pos;
|
||||||
|
|
||||||
let mut root_expr = match token {
|
let root_expr = match token {
|
||||||
Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)),
|
Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)),
|
||||||
|
|
||||||
Token::IntegerConstant(_)
|
Token::IntegerConstant(_)
|
||||||
@ -1294,6 +1294,20 @@ fn parse_primary(
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Token::MapStart => parse_map_literal(input, state, lib, settings.level_up())?,
|
Token::MapStart => parse_map_literal(input, state, lib, settings.level_up())?,
|
||||||
|
|
||||||
|
// Custom syntax.
|
||||||
|
Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key)
|
||||||
|
if state.engine.custom_syntax.contains_key(&**key) =>
|
||||||
|
{
|
||||||
|
let (key, syntax) = state
|
||||||
|
.engine
|
||||||
|
.custom_syntax
|
||||||
|
.get_key_value(&**key)
|
||||||
|
.expect("exists");
|
||||||
|
let (_, pos) = input.next().expect(NEVER_ENDS);
|
||||||
|
let settings2 = settings.level_up();
|
||||||
|
parse_custom_syntax(input, state, lib, settings2, key, syntax, pos)?
|
||||||
|
}
|
||||||
|
|
||||||
// Identifier
|
// Identifier
|
||||||
Token::Identifier(_) => {
|
Token::Identifier(_) => {
|
||||||
let s = match input.next().expect(NEVER_ENDS) {
|
let s = match input.next().expect(NEVER_ENDS) {
|
||||||
@ -1398,18 +1412,31 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
parse_postfix(input, state, lib, root_expr, settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tail processing of all possible postfix operators of a primary expression.
|
||||||
|
fn parse_postfix(
|
||||||
|
input: &mut TokenStream,
|
||||||
|
state: &mut ParseState,
|
||||||
|
lib: &mut FunctionsLib,
|
||||||
|
mut lhs: Expr,
|
||||||
|
settings: ParseSettings,
|
||||||
|
) -> Result<Expr, ParseError> {
|
||||||
|
let mut settings = settings;
|
||||||
|
|
||||||
// Tail processing all possible postfix operators
|
// Tail processing all possible postfix operators
|
||||||
loop {
|
loop {
|
||||||
let (tail_token, _) = input.peek().expect(NEVER_ENDS);
|
let (tail_token, _) = input.peek().expect(NEVER_ENDS);
|
||||||
|
|
||||||
if !root_expr.is_valid_postfix(tail_token) {
|
if !lhs.is_valid_postfix(tail_token) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tail_token, tail_pos) = input.next().expect(NEVER_ENDS);
|
let (tail_token, tail_pos) = input.next().expect(NEVER_ENDS);
|
||||||
settings.pos = tail_pos;
|
settings.pos = tail_pos;
|
||||||
|
|
||||||
root_expr = match (root_expr, tail_token) {
|
lhs = match (lhs, tail_token) {
|
||||||
// Qualified function call with !
|
// Qualified function call with !
|
||||||
(Expr::Variable(_, _, x), Token::Bang) if x.1.is_some() => {
|
(Expr::Variable(_, _, x), Token::Bang) if x.1.is_some() => {
|
||||||
return if !match_token(input, Token::LeftParen).0 {
|
return if !match_token(input, Token::LeftParen).0 {
|
||||||
@ -1503,7 +1530,7 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the hash key for namespace-qualified variables
|
// Cache the hash key for namespace-qualified variables
|
||||||
let namespaced_variable = match root_expr {
|
let namespaced_variable = match lhs {
|
||||||
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
|
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
|
||||||
Expr::Index(ref mut x, _, _) | Expr::Dot(ref mut x, _, _) => match x.lhs {
|
Expr::Index(ref mut x, _, _) | Expr::Dot(ref mut x, _, _) => match x.lhs {
|
||||||
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
|
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
|
||||||
@ -1536,7 +1563,7 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure identifiers are valid
|
// Make sure identifiers are valid
|
||||||
Ok(root_expr)
|
Ok(lhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a potential unary operator.
|
/// Parse a potential unary operator.
|
||||||
@ -1550,26 +1577,9 @@ fn parse_unary(
|
|||||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||||
|
|
||||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||||
let token_pos = *token_pos;
|
|
||||||
|
|
||||||
let mut settings = settings;
|
let mut settings = settings;
|
||||||
settings.pos = token_pos;
|
settings.pos = *token_pos;
|
||||||
|
|
||||||
// Check if it is a custom syntax.
|
|
||||||
if !state.engine.custom_syntax.is_empty() {
|
|
||||||
match token {
|
|
||||||
Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key) => {
|
|
||||||
if let Some((key, syntax)) = state.engine.custom_syntax.get_key_value(key.as_ref())
|
|
||||||
{
|
|
||||||
input.next().expect(NEVER_ENDS);
|
|
||||||
return parse_custom_syntax(
|
|
||||||
input, state, lib, settings, key, syntax, token_pos,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
// -expr
|
// -expr
|
||||||
|
@ -268,6 +268,7 @@ fn test_custom_syntax_raw2() -> Result<(), Box<EvalAltResult>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(engine.eval::<INT>("let x = 41; x + #1")?, 42);
|
assert_eq!(engine.eval::<INT>("let x = 41; x + #1")?, 42);
|
||||||
|
assert_eq!(engine.eval::<INT>("#-42.abs()")?, 42);
|
||||||
assert_eq!(engine.eval::<INT>("#42/2")?, 21);
|
assert_eq!(engine.eval::<INT>("#42/2")?, 21);
|
||||||
assert_eq!(engine.eval::<INT>("#-1")?, -1);
|
assert_eq!(engine.eval::<INT>("#-1")?, -1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user