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