fix(spreadsheet): 함수 인자 수를 입력 때 막음 — =SUM() 이 0 이 되던 흠
- 파서가 함수 표(B) 최소 · 최대 인자 수로 검사 → 「SUM 인수가 너무 적음(1 개부터)」 식 오류(편집기가 이 실패로 Enter 를 막는 이음은 sub7) - B 표 min 0 인 SUM · MIN · MAX · COUNT · COUNTA · PRODUCT 는 엑셀대로 1 로 덧댐(sub5 가 표를 고치면 지움) - 풀이 때 인자 수 검사는 파서로 옮겨 뺌(엔진 31,787 → 31,603 B) - 시험: 엔진 오류 묶음에 인자 수 사례 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TULoa94ZFL26KU6ZqVpjkF
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
|
||||
import { parseDecimal, ZERO } from "@ui/sheet/ui_template_sheet_frac";
|
||||
import { colIndex, colName, quoteSheet, rowIndex } from "./spreadsheet_address";
|
||||
import { getFunction } from "./spreadsheet_functions";
|
||||
import { MAX_COLS, MAX_ROWS } from "./spreadsheet_types";
|
||||
import type { ErrorCode, FormulaNode, ParseResult, RefCell, Token } from "./spreadsheet_types";
|
||||
|
||||
@@ -151,6 +152,15 @@ class Fail {
|
||||
}
|
||||
|
||||
const COMPARE = ["=", "<>", "<", "<=", ">", ">="];
|
||||
// ponytail: B 함수 표 min 이 엑셀보다 낮은 것만 덧댐 — sub5 가 표를 고치면 지움
|
||||
const EXCEL_MIN: Record<string, number> = {
|
||||
SUM: 1,
|
||||
MIN: 1,
|
||||
MAX: 1,
|
||||
COUNT: 1,
|
||||
COUNTA: 1,
|
||||
PRODUCT: 1,
|
||||
};
|
||||
|
||||
/** 앞 `=` 뺀 식 글 → 나무. 앞에 `=` 가 붙어 와도 됨. 함수 이름은 대문자로. */
|
||||
export function parseFormula(formula: string): ParseResult {
|
||||
@@ -199,9 +209,19 @@ export function parseFormula(formula: string): ParseResult {
|
||||
const name = t.text.toUpperCase().replace(/^_XLFN\./, "");
|
||||
p++; // `(`
|
||||
const args: FormulaNode[] = [];
|
||||
// 인자 수는 엑셀처럼 입력 때 막음(편집기가 이 실패로 Enter 를 막음) · 모르는 함수는 풀 때 #NAME?
|
||||
const done = (): FormulaNode => {
|
||||
const fn = getFunction(name);
|
||||
const lo = Math.max(fn?.min ?? 0, EXCEL_MIN[name] ?? 0);
|
||||
if (fn && args.length < lo)
|
||||
throw new Fail(`${name} 인수가 너무 적음(${lo} 개부터)`, t.start);
|
||||
if (fn?.max !== undefined && args.length > fn.max)
|
||||
throw new Fail(`${name} 인수가 너무 많음(${fn.max} 개까지)`, t.start);
|
||||
return { type: "call", name, args };
|
||||
};
|
||||
if (peek()?.text === ")") {
|
||||
p++;
|
||||
return { type: "call", name, args };
|
||||
return done();
|
||||
}
|
||||
for (;;) {
|
||||
const k = peek();
|
||||
@@ -211,7 +231,7 @@ export function parseFormula(formula: string): ParseResult {
|
||||
else args.push(compare());
|
||||
const s = toks[p++];
|
||||
if (s?.kind === "comma") continue;
|
||||
if (s?.text === ")") return { type: "call", name, args };
|
||||
if (s?.text === ")") return done();
|
||||
throw new Fail("함수 괄호가 안 닫힘", s ? s.start : text.length);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user