AND/OR/NOT, Fehler-Literale und Zeilen/Spalten einfügen/löschen
- AND(...)/OR(...)/NOT(...) als gewöhnliche Funktionen (kein Kurzschluss- Sonderfall wie IF/XLOOKUP nötig, werten wie in echtem Excel alle Argumente eager aus). Dabei die bisher dreifach duplizierte Wahrheits-Prüfung zu functions.ts#isTruthy() zusammengezogen, jetzt von FUNCTIONS.IF, evalIf() und dem Block-IF-Statement gemeinsam genutzt. Schließt "kein AND/OR für zusammengesetzte Bedingungen" aus den Bekannten Grenzen, auch nutzbar in "Mit Schleife"-IF-Bedingungen. - Neue Grammatik-Ergänzung: ErrorLiteralNode. Jeder der sieben Fehlercodes (#REF, #DIV/0!, #NAME?, #ERR, #CIRC, #VALUE!, #N/A) lässt sich jetzt direkt in eine Formel tippen (=IF(A1=0;#N/A;A1)) und wertet unbedingt zu genau diesem Fehler aus. - Zeilen/Spalten einfügen/löschen mitten im Gitter (Rechtsklick auf einen Zeilen-/Spaltenkopf), nicht nur am Rand wie bisher: Zellinhalte, Formate und Zeilenhöhen/Spaltenbreiten verschieben sich innerhalb der Tabelle, und jede Formel im gesamten Dokument, die die Tabelle referenziert (auch über Tabelle!Zelle/Blatt!Tabelle::Zelle-Qualifier aus anderen Tabellen), wird automatisch mitgezogen. Ein Bereich, der die Stelle überspannt, wächst/schrumpft entsprechend; eine Referenz, die exakt die gelöschte Zeile/Spalte trifft, wird zu einem echten #REF-Literal im Formeltext (nutzt die neue ErrorLiteralNode-Grammatik). $-Sperren bleiben dabei bewusst wirkungslos (anders als beim Kopieren), unveränderte Referenzen bleiben byte-identisch. Token-Level-Splice wie shiftFormula (Kopieren/ Ausschneiden), keine AST-Neuserialisierung. 406 Tests, vue-tsc/eslint/build sauber, Playwright-live-verifiziert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,7 @@ power = primary [ "^" unary ] ; (* rechts-assoziativ; bindet
|
||||
-2^2 = -(2^2) = -4 *)
|
||||
primary = NUMBER
|
||||
| STRING
|
||||
| ERRORLIT
|
||||
| "(" expression ")"
|
||||
| funcall
|
||||
| reference
|
||||
@@ -85,6 +86,9 @@ STRING = /" ... "/ (Backslash-Escapes) ;
|
||||
IDENT = /[A-Za-z_][A-Za-z0-9_]*/ ;
|
||||
QUOTED = /' ( [^'] | '' )* '/ (* Tabellenname mit Leer-/Sonderzeichen *)
|
||||
CELL = /\$?[A-Za-z]{1,3}\$?[0-9]{1,7}/ ;
|
||||
ERRORLIT = "#REF" | "#DIV/0!" | "#NAME?" | "#ERR" | "#CIRC" |
|
||||
"#VALUE!" | "#N/A" ; (* longest-match in the lexer -- see
|
||||
lexer.ts's ERROR_CODES_BY_LENGTH *)
|
||||
```
|
||||
|
||||
Präzedenz, schwach → stark: Vergleich (`= <> > < >= <=`) < `&` < `+ -` < `* /` < unäres `+ -` < `^`.
|
||||
@@ -417,6 +421,16 @@ dagegen erlaubt), `blockAlwaysReturns` sowie die Zyklus-Prüfung.
|
||||
Konvention wie bei `kind: 'block'`s `IF`-Abhängigkeiten (s. u.). Ein
|
||||
benutzerdefiniertes „IF" ist nicht anlegbar (Namenskollision mit dem
|
||||
eingebauten `FUNCTIONS.IF`-Eintrag).
|
||||
- **`AND`/`OR`/`NOT` brauchen dagegen keine Sonderbehandlung** — anders als
|
||||
`IF`/`XLOOKUP` sind es ganz normale `functions.ts`-Einträge, ohne
|
||||
`evaluator.ts`-Kurzschluss: `AND`/`OR` werten (wie in echtem Excel) **alle**
|
||||
Argumente eager aus, ein Fehler in irgendeinem Argument propagiert also
|
||||
immer, egal ob das logische Ergebnis schon feststeht (`=AND(1=2; 1/0)` →
|
||||
`#DIV/0!`, nicht `0`). `functions.ts#isTruthy()` ist die eine
|
||||
Wahrheits-Konvention, die überall im Motor geteilt wird, wo eine Bedingung
|
||||
gebraucht wird – `evalIf()` und `execStatement`s `ifstmt`-Fall importieren
|
||||
sie jetzt aus `functions.ts`, statt sie (wie vor diesem Feature) je einmal
|
||||
inline zu duplizieren.
|
||||
|
||||
## Datum & Zeit
|
||||
|
||||
@@ -558,3 +572,13 @@ rufen `rebuild()` für einen vollständigen – trotzdem billigen – Durchlauf.
|
||||
|
||||
Es gibt **keinen** Absturz und **keinen** Hang: Lexer/Parser werfen intern,
|
||||
`Workbook` fängt alles ab und schreibt einen Fehlerwert in die Zelle.
|
||||
|
||||
Jeder dieser sieben Codes ist außerdem als **`ErrorLiteralNode`** direkt in
|
||||
eine Formel tippbar (`=#REF`, `=IF(A1=0;#N/A;A1)`, …) – der Lexer erkennt
|
||||
ihn als eigenes `ERRORLIT`-Token (längster Treffer zuerst, s. o. EBNF),
|
||||
`evalScalar`s `case 'errorliteral':` gibt unbedingt `new FormulaError(code)`
|
||||
zurück. `store/document.ts`s Zeilen-/Spalten-Löschen ist der eine Ort, der
|
||||
selbst *Formeltext* mit `#REF`-Literalen erzeugt (für eine dadurch
|
||||
kollabierte Referenz) – ansonsten ist es reine Nutzer-Eingabe, wie eine
|
||||
Zahl- oder Text-Konstante. Kein `!` am Ende (`#REF`, nicht Excels `#REF!`)
|
||||
– derselbe Code, den diese Engine selbst überall sonst produziert.
|
||||
|
||||
Reference in New Issue
Block a user