@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 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 parseExpression() {
233
- return parseComparison();
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
- let left = parseAddition();
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
- let left = parseMultiplication();
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
- let left = parseExponentiation();
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
- let left = parseUnary();
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