Skip to content

feat(formula): one AST for both spreadsheet formula syntaxes - #884

Open
andiwand wants to merge 1 commit into
mainfrom
feat/formula-parser
Open

feat(formula): one AST for both spreadsheet formula syntaxes#884
andiwand wants to merge 1 commit into
mainfrom
feat/formula-parser

Conversation

@andiwand

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Step 3.1 of docs/design/spreadsheet-editing.md — the read side of formulas. First of four; the dependency graph, the view and the .ods cached value follow on top of this.

What it does

src/odr/internal/formula parses what a table:formula and an <f> state into one AST. The two syntaxes share their expression grammar — the same operators at the same precedence — and differ over three things, so one recursive descent takes a Syntax and branches where they part:

OpenFormula OOXML
reference [$'My Sheet'.$A$1:.B2] 'My Sheet'!$A$1:B2
argument separator ; ,
array row separator | ;

Read: cell references, ranges, whole columns (A:A), the $ of each axis, sheet-qualified and external references, named expressions, functions, arrays, errors, and the operators. A named expression and a reference over several sheets (Sheet1:Sheet3!A1) stay the spelling the file states — nothing resolves one.

Nothing evaluates anything: that is step 4.

Two decisions worth a look

  • A formula that does not parse answers nothing. A caller reads no reference out of one it cannot read, which keeps the dependency graph honest rather than half-built.
  • A spelling no position can hold is a name. A0 (rows are 1-based) and ABCDEFGHI1 (past what an index holds) are names, not refused parses — which is what a sheet calls them too, and a name carries no dependency.

Test

41 cases in test/src/internal/formula/formula_parser_test.cpp, inline strings only. They pin the precedence a sheet has (-2^2 is 4, -3% is -0.03), the LOG10( ambiguity against the reference LOG10, and each dialect's own spellings.

`internal/formula` parses what a `table:formula` and an `<f>` state into one
tree. The two syntaxes share their expression grammar, so one recursive
descent takes a `Syntax` and branches where they part: the reference
(`[Sheet1.A1:.B2]` against `Sheet1!A1:B2`), the argument separator and the
row separator of an array.

References, ranges, sheet-qualified references and named expressions are
read; nothing resolves a name or evaluates anything. A formula that does not
parse answers nothing, so a caller reads no reference out of one it cannot
read. A spelling past the grid is a name rather than a position, which is
also what `A0` and `ABCDEFGHI1` are.

Step 3.1 of `docs/design/spreadsheet-editing.md`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVmjmddv2Ui17Nptc1ggue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant