Formulas: count the leftmost operand of a chain at the same depth

The left end of a flat operator chain is not nesting, so (((...1)))+1 is
accepted whenever (((...1))) is, in Spanish entry and display.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Harrison Booth
2026-10-19 18:54:30 -05:00
co-authored by Claude Sonnet 5.5
parent 2aeb21d4d3
commit b3e0a7e8d3
2 changed files with 19 additions and 1 deletions
+1 -1
View File
@@ -194,7 +194,7 @@ fn normalize(expr: &mut Expr, known_name: &impl Fn(&str) -> bool, bindings: &mut
normalize(right, known_name, bindings, depth + 1, display)?;
node = left;
}
normalize(node, known_name, bindings, depth + 1, display)?;
normalize(node, known_name, bindings, depth, display)?;
}
Expr::Array(rows) if display => {
for row in rows {
+18
View File
@@ -435,3 +435,21 @@ fn longest_flat_chains_clone_compare_walk_and_adjust_without_deep_recursion() {
.expect("spawn");
handle.join().expect("long chains must not overflow the stack");
}
#[test]
fn spanish_input_counts_left_operand_of_a_chain_at_the_same_depth() {
// The leftmost operand of a flat chain is not nested, so `(((…1)))+1` is accepted whenever
// `(((…1)))` is, in both the pre-check and `normalize`.
let wrap = |n: usize| {
let mut e = Expr::Number(1.0);
for _ in 0..n {
e = Expr::Paren(Box::new(e));
}
e
};
let es = |e: &Expr| crate::print_input(e, FormulaLocale::Es, |_| false);
let deepest = (0..400).take_while(|&n| es(&wrap(n)).is_ok()).last().expect("depth 0 is accepted");
assert!(deepest > 1 && deepest < 400);
let chain = Expr::Binary(BinOp::Add, Box::new(wrap(deepest)), Box::new(Expr::Number(1.0)));
assert!(es(&chain).is_ok());
}