diff --git a/crates/formula/src/parser.rs b/crates/formula/src/parser.rs index 4fd3b7b..355a964 100644 --- a/crates/formula/src/parser.rs +++ b/crates/formula/src/parser.rs @@ -50,8 +50,9 @@ fn significant_spaces(toks: Vec) -> Vec { let mut out: Vec = Vec::with_capacity(toks.len()); for (i, t) in toks.iter().enumerate() { if t.tok == Tok::Space { - let prev_end = out.last().is_some_and(|p| matches!(p.tok, Tok::Word(_) | Tok::RParen | Tok::Struct(_))); - let next_start = toks.get(i + 1).is_some_and(|n| matches!(n.tok, Tok::Word(_) | Tok::Sheet(..) | Tok::LParen | Tok::Func(_))); + let prev_end = out.last().is_some_and(|p| matches!(p.tok, Tok::Word(_) | Tok::RParen | Tok::Struct(_) | Tok::Error(_))); + let next_start = + toks.get(i + 1).is_some_and(|n| matches!(n.tok, Tok::Word(_) | Tok::Sheet(..) | Tok::LParen | Tok::Func(_) | Tok::Error(_))); if prev_end && next_start { out.push(t.clone()); } diff --git a/crates/formula/src/tests.rs b/crates/formula/src/tests.rs index d3dd4c2..2de0daa 100644 --- a/crates/formula/src/tests.rs +++ b/crates/formula/src/tests.rs @@ -5,6 +5,22 @@ fn rt(src: &str) -> String { print(&parse(src).unwrap_or_else(|e| panic!("{src}: {e}"))) } +#[test] +fn intersection_with_deleted_operand_reparses() { + // Deleting the columns of an intersection operand prints `A1:B2 #REF!`; that text must parse back. + assert_eq!(rt("A1:B2 #REF!"), "A1:B2 #REF!"); + assert_eq!(rt("#REF! A1:B2"), "#REF! A1:B2"); + assert_eq!(parse("A1:B2 #REF!"), parse("A1:B2 (#REF!)").map(|e| strip_paren(&e))); +} + +fn strip_paren(e: &Expr) -> Expr { + match e { + Expr::Binary(op, a, b) => Expr::Binary(*op, Box::new(strip_paren(a)), Box::new(strip_paren(b))), + Expr::Paren(x) => strip_paren(x), + other => other.clone(), + } +} + #[test] fn roundtrips() { for f in [