@particle-academy/fancy-sheets 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +38 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +38 -25
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -214,6 +214,7 @@ function lexFormula(input) {
|
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
// src/engine/formula/parser.ts
|
|
217
|
+
var MAX_DEPTH = 64;
|
|
217
218
|
function parseFormula(tokens) {
|
|
218
219
|
let pos = 0;
|
|
219
220
|
function peek() {
|
|
@@ -229,63 +230,75 @@ function parseFormula(tokens) {
|
|
|
229
230
|
}
|
|
230
231
|
return t;
|
|
231
232
|
}
|
|
232
|
-
function
|
|
233
|
-
|
|
233
|
+
function checkDepth(depth) {
|
|
234
|
+
if (depth > MAX_DEPTH) {
|
|
235
|
+
throw new Error(`Formula nested too deep (max ${MAX_DEPTH} levels)`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function parseExpression(depth = 0) {
|
|
239
|
+
checkDepth(depth);
|
|
240
|
+
return parseComparison(depth + 1);
|
|
234
241
|
}
|
|
235
|
-
function parseComparison() {
|
|
236
|
-
let left = parseConcatenation();
|
|
242
|
+
function parseComparison(depth) {
|
|
243
|
+
let left = parseConcatenation(depth + 1);
|
|
237
244
|
while (peek() && peek().type === "operator" && ["=", "<>", "<", ">", "<=", ">="].includes(peek().value)) {
|
|
238
245
|
const op = advance().value;
|
|
239
|
-
const right = parseConcatenation();
|
|
246
|
+
const right = parseConcatenation(depth + 1);
|
|
240
247
|
left = { type: "binaryOp", operator: op, left, right };
|
|
241
248
|
}
|
|
242
249
|
return left;
|
|
243
250
|
}
|
|
244
|
-
function parseConcatenation() {
|
|
245
|
-
|
|
251
|
+
function parseConcatenation(depth) {
|
|
252
|
+
checkDepth(depth);
|
|
253
|
+
let left = parseAddition(depth + 1);
|
|
246
254
|
while (peek() && peek().type === "operator" && peek().value === "&") {
|
|
247
255
|
advance();
|
|
248
|
-
const right = parseAddition();
|
|
256
|
+
const right = parseAddition(depth + 1);
|
|
249
257
|
left = { type: "binaryOp", operator: "&", left, right };
|
|
250
258
|
}
|
|
251
259
|
return left;
|
|
252
260
|
}
|
|
253
|
-
function parseAddition() {
|
|
254
|
-
|
|
261
|
+
function parseAddition(depth) {
|
|
262
|
+
checkDepth(depth);
|
|
263
|
+
let left = parseMultiplication(depth + 1);
|
|
255
264
|
while (peek() && peek().type === "operator" && (peek().value === "+" || peek().value === "-")) {
|
|
256
265
|
const op = advance().value;
|
|
257
|
-
const right = parseMultiplication();
|
|
266
|
+
const right = parseMultiplication(depth + 1);
|
|
258
267
|
left = { type: "binaryOp", operator: op, left, right };
|
|
259
268
|
}
|
|
260
269
|
return left;
|
|
261
270
|
}
|
|
262
|
-
function parseMultiplication() {
|
|
263
|
-
|
|
271
|
+
function parseMultiplication(depth) {
|
|
272
|
+
checkDepth(depth);
|
|
273
|
+
let left = parseExponentiation(depth + 1);
|
|
264
274
|
while (peek() && peek().type === "operator" && (peek().value === "*" || peek().value === "/")) {
|
|
265
275
|
const op = advance().value;
|
|
266
|
-
const right = parseExponentiation();
|
|
276
|
+
const right = parseExponentiation(depth + 1);
|
|
267
277
|
left = { type: "binaryOp", operator: op, left, right };
|
|
268
278
|
}
|
|
269
279
|
return left;
|
|
270
280
|
}
|
|
271
|
-
function parseExponentiation() {
|
|
272
|
-
|
|
281
|
+
function parseExponentiation(depth) {
|
|
282
|
+
checkDepth(depth);
|
|
283
|
+
let left = parseUnary(depth + 1);
|
|
273
284
|
while (peek() && peek().type === "operator" && peek().value === "^") {
|
|
274
285
|
advance();
|
|
275
|
-
const right = parseUnary();
|
|
286
|
+
const right = parseUnary(depth + 1);
|
|
276
287
|
left = { type: "binaryOp", operator: "^", left, right };
|
|
277
288
|
}
|
|
278
289
|
return left;
|
|
279
290
|
}
|
|
280
|
-
function parseUnary() {
|
|
291
|
+
function parseUnary(depth) {
|
|
292
|
+
checkDepth(depth);
|
|
281
293
|
if (peek() && peek().type === "operator" && (peek().value === "-" || peek().value === "+")) {
|
|
282
294
|
const op = advance().value;
|
|
283
|
-
const operand = parseUnary();
|
|
295
|
+
const operand = parseUnary(depth + 1);
|
|
284
296
|
return { type: "unaryOp", operator: op, operand };
|
|
285
297
|
}
|
|
286
|
-
return parseAtom();
|
|
298
|
+
return parseAtom(depth + 1);
|
|
287
299
|
}
|
|
288
|
-
function parseAtom() {
|
|
300
|
+
function parseAtom(depth) {
|
|
301
|
+
checkDepth(depth);
|
|
289
302
|
const t = peek();
|
|
290
303
|
if (!t) throw new Error("Unexpected end of formula");
|
|
291
304
|
if (t.type === "number") {
|
|
@@ -323,10 +336,10 @@ function parseFormula(tokens) {
|
|
|
323
336
|
expect("paren", "(");
|
|
324
337
|
const args = [];
|
|
325
338
|
if (peek() && !(peek().type === "paren" && peek().value === ")")) {
|
|
326
|
-
args.push(parseExpression());
|
|
339
|
+
args.push(parseExpression(depth + 1));
|
|
327
340
|
while (peek() && peek().type === "comma") {
|
|
328
341
|
advance();
|
|
329
|
-
args.push(parseExpression());
|
|
342
|
+
args.push(parseExpression(depth + 1));
|
|
330
343
|
}
|
|
331
344
|
}
|
|
332
345
|
expect("paren", ")");
|
|
@@ -338,13 +351,13 @@ function parseFormula(tokens) {
|
|
|
338
351
|
}
|
|
339
352
|
if (t.type === "paren" && t.value === "(") {
|
|
340
353
|
advance();
|
|
341
|
-
const expr = parseExpression();
|
|
354
|
+
const expr = parseExpression(depth + 1);
|
|
342
355
|
expect("paren", ")");
|
|
343
356
|
return expr;
|
|
344
357
|
}
|
|
345
358
|
throw new Error(`Unexpected token '${t.value}' at position ${t.position}`);
|
|
346
359
|
}
|
|
347
|
-
const ast = parseExpression();
|
|
360
|
+
const ast = parseExpression(0);
|
|
348
361
|
return ast;
|
|
349
362
|
}
|
|
350
363
|
|