Fix bug in parsing index chains.

This commit is contained in:
Stephen Chung 2023-04-19 23:17:54 +08:00
parent 0699f47ff9
commit fb88b79178
3 changed files with 31 additions and 8 deletions

View File

@ -11,6 +11,7 @@ Buf fixes
* `is_shared` is a reserved keyword and is now handled properly (e.g. it cannot be the target of a function pointer).
* Re-optimizing an AST via `optimize_ast` with constants now works correctly for closures. Previously the hidden `Share` nodes are not removed and causes variable-not-found errors during runtime if the constants are not available in the scope.
* Expressions such as `(v[0].func()).prop` now parse correctly.
New features
------------

View File

@ -1728,6 +1728,9 @@ impl Engine {
) -> ParseResult<Expr> {
let mut settings = settings;
// Break just in case `lhs` is `Expr::Dot` or `Expr::Index`
let mut parent_options = ASTFlags::BREAK;
// Tail processing all possible postfix operators
loop {
let (tail_token, ..) = input.peek().expect(NEVER_ENDS);
@ -1842,13 +1845,16 @@ impl Engine {
let rhs =
self.parse_primary(input, state, lib, settings.level_up()?, options)?;
Self::make_dot_expr(state, expr, rhs, ASTFlags::empty(), op_flags, tail_pos)?
Self::make_dot_expr(state, expr, rhs, parent_options, op_flags, tail_pos)?
}
// Unknown postfix operator
(expr, token) => {
unreachable!("unknown postfix operator '{}' for {:?}", token, expr)
}
}
};
// The chain is now extended
parent_options = ASTFlags::empty();
}
// Cache the hash key for namespace-qualified variables

View File

@ -203,6 +203,22 @@ fn test_arrays() -> Result<(), Box<EvalAltResult>> {
Ok(())
}
#[cfg(not(feature = "no_float"))]
#[cfg(not(feature = "no_object"))]
#[test]
fn test_array_chaining() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert!(engine.eval::<bool>(
"
let v = [ PI() ];
( v[0].cos() ).sin() == v[0].cos().sin()
"
)?);
Ok(())
}
#[test]
fn test_array_index_types() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
@ -508,9 +524,9 @@ fn test_arrays_map_reduce() -> Result<(), Box<EvalAltResult>> {
engine.eval::<()>(
"
let x = [1, 2, 3, 2, 1];
x.find(|v| v > 4)
",
let x = [1, 2, 3, 2, 1];
x.find(|v| v > 4)
",
)?;
assert_eq!(
@ -525,9 +541,9 @@ fn test_arrays_map_reduce() -> Result<(), Box<EvalAltResult>> {
engine.eval::<()>(
"
let x = [#{alice: 1}, #{bob: 2}, #{clara: 3}];
x.find_map(|v| v.dave)
",
let x = [#{alice: 1}, #{bob: 2}, #{clara: 3}];
x.find_map(|v| v.dave)
",
)?;
Ok(())