Skip to content

fix: a quoted scope in an operand position does not parse - #65

Open
gthb wants to merge 5 commits into
borgar:masterfrom
gthb:fix-quoted-scope-operand-type
Open

fix: a quoted scope in an operand position does not parse#65
gthb wants to merge 5 commits into
borgar:masterfrom
gthb:fix-quoted-scope-operand-type

Conversation

@gthb

@gthb gthb commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

'Alpha':[Book.xlsx]Gamma!A1 and 'Alpha:Beta':Gamma!A1 fail to parse: "Unexpected context_quote token". Their first name is lexed as a quoted scope but has no ! after it, so it is an operand rather than a scope, and parse has no production for a scope in that position.

Cause

The lexer types a quoted name as a scope on the chance that a second sheet name follows. Where mergeRefTokens merges the run, the speculative type disappears into the merged reference. Where it declines to merge, the type is left behind on a token that is not a scope. Two forms reach that state: a workbook specifier in the second name, and a first name that already contains two names.

Fix

mergeRefTokens corrects such a token to ref_named, which is the type an unquoted first name already gets: Alpha:[Book.xlsx]Gamma!A1 lexes Alpha as a name today, and the quoted form now matches it.

A scope that does have its ! keeps the scope type, merged or not.

Four existing lexer expectations covered these forms and asserted the speculative type; they now assert ref_named. The mergeRefs: false expectations beside them are unchanged, since nothing corrects a type when no merging runs. A parse test asserts that both formulas reach an AST, with the quoted scope as the range operator's name operand.

Note

Excel reads both forms as the range operator over the quoted name, and stores them with the second name quoted, 'Alpha:Beta':'Gamma'!A1 and Alpha:'[1]Gamma'!A1. In the second it is the workbook bracket that rules out a sheet range, not the quote, which Excel drops. So the type this gives the operand is the reading Excel takes.

Left for later

An unquoted scope in the same position, 1 in 1:'dec'!B11, is left as context and still does not parse. A number is not a name, so it wants a different answer.

Under xlsx a scope that keeps its type still does not parse: 'Sheet1:Sheet2'!name and 'Sheet1:Sheet2'!tbl[col] raise the same error, since a scope containing a : does not merge with the name or table after it there. Unchanged here.

gthb added 5 commits September 3, 2026 15:07
`'Alpha':[Book.xlsx]Gamma!A1` and `'Alpha:Beta':Gamma!A1` fail to parse:
"Unexpected context_quote token". Their first name is a quoted scope with
no `!` after it, so it is not a scope but an operand, and `parse` has no
production for one there.

The lexer types it as a scope on the chance that a second sheet name
follows. Where nothing merges it, `mergeRefTokens` now corrects it to
`ref_named`, which is what Excel reads there and what the unquoted `a` of
`a:'b'!A1` already gets, so the two ways of writing the operation agree.

A scope that does have its `!` keeps the scope type whether or not it
merged, since a scope containing a `:` never merges with the name or
table after it, as in `'Sheet1:Sheet2'!name`.

Untouched: an unquoted scope in the same position, `1` in `1:'dec'!B11`,
which the lexer leaves as `context` and which still does not parse. A
number is not a name, so it wants a different answer.
The fix is a token type, and only the lexer specs covered it. These
assert the outcome that motivated it: both formulas reach an AST, with
the quoted scope as the name operand of the range operator.
The test asserted `'Alpha:Beta':Gamma!A1` as the name `Alpha:Beta`
joined to `Gamma!A1`, under a name that read as a claim about Excel.
Excel's reading of that form is unmeasured, and for the nearest measured
neighbour, a quoted first name followed by an unquoted second, Excel
reads the sheet range instead.

What the test is really for is that the formula reaches an AST at all,
where the quoted first name used to stop the parser. Renamed to say it
parses that way, with the scope of the claim in a comment.
The test name and its comment left the reading as fx's own. Excel takes
both formulas the same way and stores them with the second name quoted,
`'Alpha:Beta':'Gamma'!A1` and `Alpha:'[1]Gamma'!A1`.

Neither resolves: a defined name cannot contain a colon, and `Alpha` is
not a name in that workbook, so both are #NAME?. In the second form the
workbook bracket is what rules out a sheet range; the quote on the first
name is redundant and Excel drops it.
Two clauses went: the lexer's speculative typing, which the description
already gives as the cause, and a justification for the `!` exclusion
that was wrong. It said a scope containing a `:` never merges with the
name after it, which holds under `xlsx` only; in the default mode
`'Sheet1:Sheet2'!name` merges into one reference.

What is left is the rule the guard implements.
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