@particle-academy/fancy-sheets 0.7.1 → 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 +1 -1
package/dist/index.js
CHANGED
|
@@ -208,6 +208,7 @@ function lexFormula(input) {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// src/engine/formula/parser.ts
|
|
211
|
+
var MAX_DEPTH = 64;
|
|
211
212
|
function parseFormula(tokens) {
|
|
212
213
|
let pos = 0;
|
|
213
214
|
function peek() {
|
|
@@ -223,63 +224,75 @@ function parseFormula(tokens) {
|
|
|
223
224
|
}
|
|
224
225
|
return t;
|
|
225
226
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
227
|
+
function checkDepth(depth) {
|
|
228
|
+
if (depth > MAX_DEPTH) {
|
|
229
|
+
throw new Error(`Formula nested too deep (max ${MAX_DEPTH} levels)`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function parseExpression(depth = 0) {
|
|
233
|
+
checkDepth(depth);
|
|
234
|
+
return parseComparison(depth + 1);
|
|
228
235
|
}
|
|
229
|
-
function parseComparison() {
|
|
230
|
-
let left = parseConcatenation();
|
|
236
|
+
function parseComparison(depth) {
|
|
237
|
+
let left = parseConcatenation(depth + 1);
|
|
231
238
|
while (peek() && peek().type === "operator" && ["=", "<>", "<", ">", "<=", ">="].includes(peek().value)) {
|
|
232
239
|
const op = advance().value;
|
|
233
|
-
const right = parseConcatenation();
|
|
240
|
+
const right = parseConcatenation(depth + 1);
|
|
234
241
|
left = { type: "binaryOp", operator: op, left, right };
|
|
235
242
|
}
|
|
236
243
|
return left;
|
|
237
244
|
}
|
|
238
|
-
function parseConcatenation() {
|
|
239
|
-
|
|
245
|
+
function parseConcatenation(depth) {
|
|
246
|
+
checkDepth(depth);
|
|
247
|
+
let left = parseAddition(depth + 1);
|
|
240
248
|
while (peek() && peek().type === "operator" && peek().value === "&") {
|
|
241
249
|
advance();
|
|
242
|
-
const right = parseAddition();
|
|
250
|
+
const right = parseAddition(depth + 1);
|
|
243
251
|
left = { type: "binaryOp", operator: "&", left, right };
|
|
244
252
|
}
|
|
245
253
|
return left;
|
|
246
254
|
}
|
|
247
|
-
function parseAddition() {
|
|
248
|
-
|
|
255
|
+
function parseAddition(depth) {
|
|
256
|
+
checkDepth(depth);
|
|
257
|
+
let left = parseMultiplication(depth + 1);
|
|
249
258
|
while (peek() && peek().type === "operator" && (peek().value === "+" || peek().value === "-")) {
|
|
250
259
|
const op = advance().value;
|
|
251
|
-
const right = parseMultiplication();
|
|
260
|
+
const right = parseMultiplication(depth + 1);
|
|
252
261
|
left = { type: "binaryOp", operator: op, left, right };
|
|
253
262
|
}
|
|
254
263
|
return left;
|
|
255
264
|
}
|
|
256
|
-
function parseMultiplication() {
|
|
257
|
-
|
|
265
|
+
function parseMultiplication(depth) {
|
|
266
|
+
checkDepth(depth);
|
|
267
|
+
let left = parseExponentiation(depth + 1);
|
|
258
268
|
while (peek() && peek().type === "operator" && (peek().value === "*" || peek().value === "/")) {
|
|
259
269
|
const op = advance().value;
|
|
260
|
-
const right = parseExponentiation();
|
|
270
|
+
const right = parseExponentiation(depth + 1);
|
|
261
271
|
left = { type: "binaryOp", operator: op, left, right };
|
|
262
272
|
}
|
|
263
273
|
return left;
|
|
264
274
|
}
|
|
265
|
-
function parseExponentiation() {
|
|
266
|
-
|
|
275
|
+
function parseExponentiation(depth) {
|
|
276
|
+
checkDepth(depth);
|
|
277
|
+
let left = parseUnary(depth + 1);
|
|
267
278
|
while (peek() && peek().type === "operator" && peek().value === "^") {
|
|
268
279
|
advance();
|
|
269
|
-
const right = parseUnary();
|
|
280
|
+
const right = parseUnary(depth + 1);
|
|
270
281
|
left = { type: "binaryOp", operator: "^", left, right };
|
|
271
282
|
}
|
|
272
283
|
return left;
|
|
273
284
|
}
|
|
274
|
-
function parseUnary() {
|
|
285
|
+
function parseUnary(depth) {
|
|
286
|
+
checkDepth(depth);
|
|
275
287
|
if (peek() && peek().type === "operator" && (peek().value === "-" || peek().value === "+")) {
|
|
276
288
|
const op = advance().value;
|
|
277
|
-
const operand = parseUnary();
|
|
289
|
+
const operand = parseUnary(depth + 1);
|
|
278
290
|
return { type: "unaryOp", operator: op, operand };
|
|
279
291
|
}
|
|
280
|
-
return parseAtom();
|
|
292
|
+
return parseAtom(depth + 1);
|
|
281
293
|
}
|
|
282
|
-
function parseAtom() {
|
|
294
|
+
function parseAtom(depth) {
|
|
295
|
+
checkDepth(depth);
|
|
283
296
|
const t = peek();
|
|
284
297
|
if (!t) throw new Error("Unexpected end of formula");
|
|
285
298
|
if (t.type === "number") {
|
|
@@ -317,10 +330,10 @@ function parseFormula(tokens) {
|
|
|
317
330
|
expect("paren", "(");
|
|
318
331
|
const args = [];
|
|
319
332
|
if (peek() && !(peek().type === "paren" && peek().value === ")")) {
|
|
320
|
-
args.push(parseExpression());
|
|
333
|
+
args.push(parseExpression(depth + 1));
|
|
321
334
|
while (peek() && peek().type === "comma") {
|
|
322
335
|
advance();
|
|
323
|
-
args.push(parseExpression());
|
|
336
|
+
args.push(parseExpression(depth + 1));
|
|
324
337
|
}
|
|
325
338
|
}
|
|
326
339
|
expect("paren", ")");
|
|
@@ -332,13 +345,13 @@ function parseFormula(tokens) {
|
|
|
332
345
|
}
|
|
333
346
|
if (t.type === "paren" && t.value === "(") {
|
|
334
347
|
advance();
|
|
335
|
-
const expr = parseExpression();
|
|
348
|
+
const expr = parseExpression(depth + 1);
|
|
336
349
|
expect("paren", ")");
|
|
337
350
|
return expr;
|
|
338
351
|
}
|
|
339
352
|
throw new Error(`Unexpected token '${t.value}' at position ${t.position}`);
|
|
340
353
|
}
|
|
341
|
-
const ast = parseExpression();
|
|
354
|
+
const ast = parseExpression(0);
|
|
342
355
|
return ast;
|
|
343
356
|
}
|
|
344
357
|
|