@cortex-js/compute-engine 0.12.4 → 0.12.6

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.
Files changed (89) hide show
  1. package/dist/compute-engine.esm.js +916 -782
  2. package/dist/compute-engine.js +916 -782
  3. package/dist/compute-engine.min.esm.js +916 -782
  4. package/dist/compute-engine.min.js +916 -782
  5. package/dist/math-json.esm.js +2 -2
  6. package/dist/math-json.js +2 -2
  7. package/dist/math-json.min.esm.js +2 -2
  8. package/dist/math-json.min.js +2 -2
  9. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  10. package/dist/types/common/signals.d.ts +1 -1
  11. package/dist/types/common/utils.d.ts +1 -1
  12. package/dist/types/compute-engine/assume.d.ts +1 -1
  13. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +1 -1
  14. package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
  15. package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
  16. package/dist/types/compute-engine/boxed-expression/boxed-domain.d.ts +1 -1
  17. package/dist/types/compute-engine/boxed-expression/boxed-function-definition.d.ts +1 -1
  18. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +2 -2
  19. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
  20. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
  21. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
  22. package/dist/types/compute-engine/boxed-expression/boxed-symbol-definition.d.ts +1 -1
  23. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
  24. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  25. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  26. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
  27. package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
  28. package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
  29. package/dist/types/compute-engine/compute-engine.d.ts +8 -6
  30. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  31. package/dist/types/compute-engine/domain-utils.d.ts +1 -1
  32. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  33. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  34. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  35. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  36. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-inequalities.d.ts +1 -1
  37. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  38. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  39. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  40. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  41. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  42. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +14 -9
  43. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +2 -2
  44. package/dist/types/compute-engine/latex-syntax/parse-identifier.d.ts +2 -2
  45. package/dist/types/compute-engine/latex-syntax/parse.d.ts +102 -75
  46. package/dist/types/compute-engine/latex-syntax/public.d.ts +138 -136
  47. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  48. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  49. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +4 -4
  50. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  51. package/dist/types/compute-engine/library/arithmetic-add.d.ts +1 -1
  52. package/dist/types/compute-engine/library/arithmetic-divide.d.ts +1 -1
  53. package/dist/types/compute-engine/library/arithmetic-multiply.d.ts +1 -1
  54. package/dist/types/compute-engine/library/arithmetic-power.d.ts +1 -1
  55. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  56. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  57. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  58. package/dist/types/compute-engine/library/core.d.ts +1 -1
  59. package/dist/types/compute-engine/library/domains.d.ts +2 -1
  60. package/dist/types/compute-engine/library/library.d.ts +1 -1
  61. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  62. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  63. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  64. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  65. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  66. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  67. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  68. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  69. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  70. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  71. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  72. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  73. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  74. package/dist/types/compute-engine/public.d.ts +102 -5
  75. package/dist/types/compute-engine/rules.d.ts +1 -1
  76. package/dist/types/compute-engine/simplify-rules.d.ts +1 -1
  77. package/dist/types/compute-engine/solve.d.ts +1 -1
  78. package/dist/types/compute-engine/symbolic/expand.d.ts +1 -1
  79. package/dist/types/compute-engine/symbolic/flatten.d.ts +1 -1
  80. package/dist/types/compute-engine/symbolic/negate.d.ts +1 -1
  81. package/dist/types/compute-engine/symbolic/polynomials.d.ts +1 -1
  82. package/dist/types/compute-engine/symbolic/product.d.ts +1 -1
  83. package/dist/types/compute-engine/symbolic/sum.d.ts +1 -1
  84. package/dist/types/compute-engine/symbolic/utils.d.ts +1 -1
  85. package/dist/types/compute-engine.d.ts +2 -2
  86. package/dist/types/math-json/math-json-format.d.ts +1 -1
  87. package/dist/types/math-json/utils.d.ts +2 -1
  88. package/dist/types/math-json.d.ts +2 -2
  89. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /** CortexJS Compute Engine 0.12.4 */
1
+ /** CortexJS Compute Engine 0.12.6 */
2
2
  (function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngine = {}));})(this, (function (exports) { 'use strict';
3
3
  var ComputeEngine = (() => {
4
4
  var __create = Object.create;
@@ -1040,21 +1040,25 @@ var ComputeEngine = (() => {
1040
1040
  __export(compute_engine_exports, {
1041
1041
  ComputeEngine: () => ComputeEngine,
1042
1042
  isEnvironmentEntry: () => isEnvironmentEntry,
1043
+ isExpressionEntry: () => isExpressionEntry,
1043
1044
  isFunctionEntry: () => isFunctionEntry,
1044
- isIdentifierEntry: () => isIdentifierEntry,
1045
1045
  isInfixEntry: () => isInfixEntry,
1046
1046
  isMatchfixEntry: () => isMatchfixEntry,
1047
1047
  isPostfixEntry: () => isPostfixEntry,
1048
1048
  isPrefixEntry: () => isPrefixEntry,
1049
+ isSymbolEntry: () => isSymbolEntry,
1049
1050
  version: () => version
1050
1051
  });
1051
1052
 
1052
1053
  // src/compute-engine/latex-syntax/public.ts
1053
- function isIdentifierEntry(entry) {
1054
- return !("kind" in entry) || entry.kind === "identifier";
1054
+ function isExpressionEntry(entry) {
1055
+ return !("kind" in entry) || entry.kind === "expression";
1056
+ }
1057
+ function isSymbolEntry(entry) {
1058
+ return "kind" in entry && entry.kind === "symbol";
1055
1059
  }
1056
1060
  function isFunctionEntry(entry) {
1057
- return !("kind" in entry) || entry.kind === "function";
1061
+ return "kind" in entry && entry.kind === "function";
1058
1062
  }
1059
1063
  function isMatchfixEntry(entry) {
1060
1064
  return "kind" in entry && entry.kind === "matchfix";
@@ -4119,9 +4123,9 @@ var ComputeEngine = (() => {
4119
4123
  return [op3, lhs, rhs];
4120
4124
  }
4121
4125
  function getSequence(expr) {
4122
- let h = head(expr);
4123
4126
  if (expr === null)
4124
4127
  return null;
4128
+ let h = head(expr);
4125
4129
  if (h === "Delimiter") {
4126
4130
  expr = op(expr, 1);
4127
4131
  if (expr === null)
@@ -4130,18 +4134,12 @@ var ComputeEngine = (() => {
4130
4134
  return [expr];
4131
4135
  }
4132
4136
  h = head(expr);
4133
- if (h === "Sequence")
4134
- return ops(expr) ?? [];
4135
- return null;
4137
+ if (h !== "Sequence")
4138
+ return null;
4139
+ return ops(expr) ?? [];
4136
4140
  }
4137
4141
  function isEmptySequence(expr) {
4138
- if (expr === null)
4139
- return false;
4140
- if (head(expr) !== "Sequence")
4141
- return false;
4142
- if (nops(expr) !== 0)
4143
- return false;
4144
- return true;
4142
+ return expr !== null && head(expr) === "Sequence" && nops(expr) === 0;
4145
4143
  }
4146
4144
  function missingIfEmpty(expr) {
4147
4145
  if (expr === null || isEmptySequence(expr))
@@ -4252,8 +4250,8 @@ var ComputeEngine = (() => {
4252
4250
  return [numerator, denominator];
4253
4251
  }
4254
4252
  function parseRoot(parser) {
4255
- const degree = parser.matchLatexOptionalGroup();
4256
- const base = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
4253
+ const degree = parser.parseOptionalGroup();
4254
+ const base = parser.parseGroup() ?? parser.parseToken();
4257
4255
  if (base === null || isEmptySequence(base)) {
4258
4256
  if (degree !== null)
4259
4257
  return ["Root", MISSING, missingIfEmpty(degree)];
@@ -4440,13 +4438,13 @@ var ComputeEngine = (() => {
4440
4438
  return isNegative ? "-" + result : result;
4441
4439
  }
4442
4440
  function parseFraction(parser) {
4443
- let numer = parser.matchLatexGroup();
4441
+ let numer = parser.parseGroup();
4444
4442
  let denom = null;
4445
4443
  if (numer === null) {
4446
- numer = parser.matchSingleAtomArgument();
4447
- denom = parser.matchSingleAtomArgument();
4444
+ numer = parser.parseToken();
4445
+ denom = parser.parseToken();
4448
4446
  } else {
4449
- denom = parser.matchLatexGroup();
4447
+ denom = parser.parseGroup();
4450
4448
  }
4451
4449
  numer = missingIfEmpty(numer);
4452
4450
  denom = missingIfEmpty(denom);
@@ -4454,7 +4452,7 @@ var ComputeEngine = (() => {
4454
4452
  const degree = op(numer, 3) ?? null;
4455
4453
  let fn = op(numer, 1);
4456
4454
  if (fn === null)
4457
- fn = missingIfEmpty(parser.matchExpression());
4455
+ fn = missingIfEmpty(parser.parseExpression());
4458
4456
  let vars = [];
4459
4457
  if (head(denom) === "Multiply") {
4460
4458
  for (const arg of ops(denom) ?? []) {
@@ -4583,7 +4581,7 @@ var ComputeEngine = (() => {
4583
4581
  {
4584
4582
  trigger: ["\\ang"],
4585
4583
  parse: (parser) => {
4586
- const arg = parser.matchLatexGroup();
4584
+ const arg = parser.parseGroup();
4587
4585
  return arg === null ? ["Degrees"] : ["Degrees", arg];
4588
4586
  }
4589
4587
  },
@@ -4600,7 +4598,7 @@ var ComputeEngine = (() => {
4600
4598
  trigger: ["\\tilde", "<{>", "\\infty", "<}>"],
4601
4599
  parse: "ComplexInfinity"
4602
4600
  },
4603
- { name: "Pi", trigger: ["\\pi"] },
4601
+ { name: "Pi", kind: "symbol", trigger: ["\\pi"] },
4604
4602
  { trigger: ["\u03C0"], parse: "Pi" },
4605
4603
  {
4606
4604
  name: "ExponentialE",
@@ -4608,6 +4606,15 @@ var ComputeEngine = (() => {
4608
4606
  parse: "ExponentialE",
4609
4607
  serialize: "\\exponentialE"
4610
4608
  },
4609
+ {
4610
+ kind: "function",
4611
+ trigger: "exp",
4612
+ parse: "Exp"
4613
+ },
4614
+ {
4615
+ trigger: "\\exp",
4616
+ parse: "Exp"
4617
+ },
4611
4618
  {
4612
4619
  name: "ImaginaryUnit",
4613
4620
  trigger: ["\\imaginaryI"]
@@ -4627,10 +4634,7 @@ var ComputeEngine = (() => {
4627
4634
  {
4628
4635
  trigger: "abs",
4629
4636
  kind: "function",
4630
- parse: (parser) => {
4631
- const arg = parser.matchArguments("enclosure");
4632
- return arg === null ? "Abs" : ["Abs", ...arg];
4633
- }
4637
+ parse: "Abs"
4634
4638
  },
4635
4639
  {
4636
4640
  name: "Add",
@@ -4638,10 +4642,10 @@ var ComputeEngine = (() => {
4638
4642
  kind: "infix",
4639
4643
  associativity: "both",
4640
4644
  precedence: 275,
4641
- parse: (parser, until, lhs) => {
4642
- if (275 < until.minPrec)
4645
+ parse: (parser, lhs, until) => {
4646
+ if (until && 275 < until.minPrec)
4643
4647
  return null;
4644
- const rhs = parser.matchExpression({ ...until, minPrec: 275 });
4648
+ const rhs = parser.parseExpression({ ...until, minPrec: 275 });
4645
4649
  if (rhs === null)
4646
4650
  return null;
4647
4651
  return applyAssociativeOperator("Add", lhs, rhs);
@@ -4653,9 +4657,9 @@ var ComputeEngine = (() => {
4653
4657
  trigger: ["+"],
4654
4658
  precedence: 275,
4655
4659
  parse: (parser, until) => {
4656
- if (275 < until.minPrec)
4660
+ if (until && 275 < until.minPrec)
4657
4661
  return null;
4658
- return parser.matchExpression({ ...until, minPrec: 400 });
4662
+ return parser.parseExpression({ ...until, minPrec: 400 });
4659
4663
  }
4660
4664
  },
4661
4665
  {
@@ -4664,13 +4668,16 @@ var ComputeEngine = (() => {
4664
4668
  openDelimiter: "\\lceil",
4665
4669
  closeDelimiter: "\\rceil"
4666
4670
  },
4671
+ {
4672
+ kind: "matchfix",
4673
+ openDelimiter: ["\u2308"],
4674
+ closeDelimiter: ["\u2309"],
4675
+ parse: (_, body) => ["Ceil", body]
4676
+ },
4667
4677
  {
4668
4678
  trigger: "ceil",
4669
4679
  kind: "function",
4670
- parse: (parser) => {
4671
- const arg = parser.matchArguments("enclosure");
4672
- return arg === null ? "Ceil" : ["Ceil", ...arg];
4673
- }
4680
+ parse: "Ceil"
4674
4681
  },
4675
4682
  {
4676
4683
  name: "Complex",
@@ -4731,11 +4738,12 @@ var ComputeEngine = (() => {
4731
4738
  },
4732
4739
  {
4733
4740
  name: "Exp",
4734
- serialize: (serializer, expr) => joinLatex([
4735
- "\\exponentialE^{",
4736
- serializer.serialize(missingIfEmpty(op(expr, 1))),
4737
- "}"
4738
- ])
4741
+ serialize: (serializer, expr) => {
4742
+ const op12 = op(expr, 1);
4743
+ if (symbol(op12) || machineValue(op12) !== null)
4744
+ return joinLatex(["\\exponentialE^{", serializer.serialize(op12)]);
4745
+ return joinLatex(["\\exp", serializer.wrap(missingIfEmpty(op12))]);
4746
+ }
4739
4747
  },
4740
4748
  {
4741
4749
  name: "Factorial",
@@ -4755,13 +4763,16 @@ var ComputeEngine = (() => {
4755
4763
  openDelimiter: "\\lfloor",
4756
4764
  closeDelimiter: "\\rfloor"
4757
4765
  },
4766
+ {
4767
+ kind: "matchfix",
4768
+ openDelimiter: ["\u230A"],
4769
+ closeDelimiter: ["\u230B"],
4770
+ parse: (_, body) => ["Floor", body]
4771
+ },
4758
4772
  {
4759
4773
  trigger: "floor",
4760
4774
  kind: "function",
4761
- parse: (parser) => {
4762
- const arg = parser.matchArguments("enclosure");
4763
- return arg === null ? "Floor" : ["Floor", ...arg];
4764
- }
4775
+ parse: "Floor"
4765
4776
  },
4766
4777
  {
4767
4778
  name: "Gcd",
@@ -4777,9 +4788,9 @@ var ComputeEngine = (() => {
4777
4788
  trigger: ["\\lg"],
4778
4789
  serialize: (serializer, expr) => "\\log_{10}" + serializer.wrapArguments(expr),
4779
4790
  parse: (parser) => {
4780
- const arg = parser.matchArguments("implicit");
4791
+ const arg = parser.parseArguments("implicit");
4781
4792
  if (arg === null)
4782
- return ["Lg"];
4793
+ return "Lg";
4783
4794
  return ["Log", ...arg, 10];
4784
4795
  }
4785
4796
  },
@@ -4787,9 +4798,9 @@ var ComputeEngine = (() => {
4787
4798
  name: "Lb",
4788
4799
  trigger: "\\lb",
4789
4800
  parse: (parser) => {
4790
- const arg = parser.matchArguments("implicit");
4801
+ const arg = parser.parseArguments("implicit");
4791
4802
  if (arg === null)
4792
- return ["Log"];
4803
+ return "Log";
4793
4804
  return ["Log", ...arg, 2];
4794
4805
  }
4795
4806
  },
@@ -4840,10 +4851,10 @@ var ComputeEngine = (() => {
4840
4851
  kind: "infix",
4841
4852
  associativity: "both",
4842
4853
  precedence: 390,
4843
- parse: (parser, terminator, lhs) => {
4844
- if (391 < terminator.minPrec)
4854
+ parse: (parser, lhs, terminator) => {
4855
+ if (terminator && 391 < terminator.minPrec)
4845
4856
  return null;
4846
- const rhs = parser.matchExpression({ ...terminator, minPrec: 392 });
4857
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4847
4858
  if (rhs === null)
4848
4859
  return ["Multiply", lhs, MISSING];
4849
4860
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4854,10 +4865,10 @@ var ComputeEngine = (() => {
4854
4865
  kind: "infix",
4855
4866
  associativity: "both",
4856
4867
  precedence: 390,
4857
- parse: (parser, terminator, lhs) => {
4858
- if (391 < terminator.minPrec)
4868
+ parse: (parser, lhs, terminator) => {
4869
+ if (terminator && 391 < terminator.minPrec)
4859
4870
  return null;
4860
- const rhs = parser.matchExpression({ ...terminator, minPrec: 392 });
4871
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4861
4872
  if (rhs === null)
4862
4873
  return ["Multiply", lhs, MISSING];
4863
4874
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4868,9 +4879,9 @@ var ComputeEngine = (() => {
4868
4879
  trigger: ["-"],
4869
4880
  kind: "prefix",
4870
4881
  parse: (parser, terminator) => {
4871
- if (276 < terminator.minPrec)
4882
+ if (terminator && 276 < terminator.minPrec)
4872
4883
  return null;
4873
- const rhs = parser.matchExpression({ ...terminator, minPrec: 400 });
4884
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4874
4885
  return ["Negate", missingIfEmpty(rhs)];
4875
4886
  },
4876
4887
  precedence: 275
@@ -4912,7 +4923,54 @@ var ComputeEngine = (() => {
4912
4923
  trigger: ["\\pm"],
4913
4924
  kind: "infix",
4914
4925
  associativity: "both",
4915
- precedence: 270
4926
+ precedence: 270,
4927
+ serialize: (serializer, expr) => {
4928
+ const op12 = op(expr, 1);
4929
+ if (op12 === null)
4930
+ return "\\pm";
4931
+ if (nops(expr) === 1)
4932
+ return joinLatex(["\\pm", serializer.serialize(op12)]);
4933
+ const op22 = op(expr, 2);
4934
+ return joinLatex([
4935
+ serializer.serialize(op12),
4936
+ "\\pm",
4937
+ serializer.serialize(op22)
4938
+ ]);
4939
+ }
4940
+ },
4941
+ {
4942
+ trigger: ["\\pm"],
4943
+ kind: "prefix",
4944
+ precedence: 270,
4945
+ parse: (parser, terminator) => {
4946
+ if (terminator && 270 < terminator.minPrec)
4947
+ return null;
4948
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4949
+ return ["PlusMinus", missingIfEmpty(rhs)];
4950
+ }
4951
+ },
4952
+ {
4953
+ trigger: ["\\plusmn"],
4954
+ kind: "infix",
4955
+ associativity: "both",
4956
+ precedence: 270,
4957
+ parse: (parser, lhs, terminator) => {
4958
+ if (270 < terminator.minPrec)
4959
+ return null;
4960
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4961
+ return ["PlusMinus", lhs, missingIfEmpty(rhs)];
4962
+ }
4963
+ },
4964
+ {
4965
+ trigger: ["\\plusmn"],
4966
+ kind: "prefix",
4967
+ precedence: 270,
4968
+ parse: (parser, terminator) => {
4969
+ if (terminator && 270 < terminator.minPrec)
4970
+ return null;
4971
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4972
+ return ["PlusMinus", missingIfEmpty(rhs)];
4973
+ }
4916
4974
  },
4917
4975
  {
4918
4976
  name: "Power",
@@ -4981,10 +5039,10 @@ var ComputeEngine = (() => {
4981
5039
  kind: "infix",
4982
5040
  associativity: "both",
4983
5041
  precedence: 275,
4984
- parse: (parser, terminator, lhs) => {
5042
+ parse: (parser, lhs, terminator) => {
4985
5043
  if (276 < terminator.minPrec)
4986
5044
  return null;
4987
- const rhs = parser.matchExpression({ ...terminator, minPrec: 277 });
5045
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 277 });
4988
5046
  return ["Subtract", lhs, missingIfEmpty(rhs)];
4989
5047
  }
4990
5048
  }
@@ -4996,9 +5054,9 @@ var ComputeEngine = (() => {
4996
5054
  let sub2 = null;
4997
5055
  while (!(sub2 && sup) && (parser.peek === "_" || parser.peek === "^")) {
4998
5056
  if (parser.match("_"))
4999
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
5057
+ sub2 = parser.parseGroup() ?? parser.parseToken();
5000
5058
  else if (parser.match("^"))
5001
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
5059
+ sup = parser.parseGroup() ?? parser.parseToken();
5002
5060
  parser.skipSpace();
5003
5061
  }
5004
5062
  if (sub2 === "Nothing" || isEmptySequence(sub2))
@@ -5016,7 +5074,7 @@ var ComputeEngine = (() => {
5016
5074
  const sym = symbol(index);
5017
5075
  if (sym)
5018
5076
  parser.computeEngine?.pushScope({ [sym]: { domain: "Integer" } });
5019
- const fn = parser.matchExpression({ minPrec: prec + 1 });
5077
+ const fn = parser.parseExpression({ minPrec: prec + 1 });
5020
5078
  if (sym)
5021
5079
  parser.computeEngine?.popScope();
5022
5080
  if (!fn)
@@ -5077,10 +5135,10 @@ var ComputeEngine = (() => {
5077
5135
  let sub2 = null;
5078
5136
  let base = null;
5079
5137
  if (parser.match("_")) {
5080
- sub2 = parser.matchStringArgument() ?? parser.next();
5138
+ sub2 = parser.parseStringGroup()?.trim() ?? parser.nextToken();
5081
5139
  base = Number.parseFloat(sub2 ?? "10");
5082
5140
  }
5083
- const arg = parser.matchArguments("implicit");
5141
+ const arg = parser.parseArguments("implicit");
5084
5142
  if (arg === null)
5085
5143
  return [command];
5086
5144
  if (base === 10)
@@ -5109,7 +5167,7 @@ var ComputeEngine = (() => {
5109
5167
  if (parser.atTerminator(terminator)) {
5110
5168
  result.push("Nothing");
5111
5169
  } else {
5112
- const rhs = parser.matchExpression({ ...terminator, minPrec: prec });
5170
+ const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
5113
5171
  result.push(rhs ?? "Nothing");
5114
5172
  done = rhs === null;
5115
5173
  }
@@ -5129,15 +5187,18 @@ var ComputeEngine = (() => {
5129
5187
  //
5130
5188
  {
5131
5189
  trigger: ["\\placeholder"],
5190
+ kind: "symbol",
5132
5191
  parse: (parser) => {
5133
- parser.skipSpaceTokens();
5192
+ while (parser.match("<space>")) {
5193
+ }
5134
5194
  if (parser.match("["))
5135
5195
  while (!parser.match("]") && !parser.atBoundary)
5136
- parser.next();
5137
- parser.skipSpaceTokens();
5196
+ parser.nextToken();
5197
+ while (parser.match("<space>")) {
5198
+ }
5138
5199
  if (parser.match("<{>"))
5139
5200
  while (!parser.match("<}>") && !parser.atBoundary)
5140
- parser.next();
5201
+ parser.nextToken();
5141
5202
  return "Nothing";
5142
5203
  }
5143
5204
  },
@@ -5146,7 +5207,6 @@ var ComputeEngine = (() => {
5146
5207
  //
5147
5208
  {
5148
5209
  name: "BaseForm",
5149
- kind: "function",
5150
5210
  serialize: (serializer, expr) => {
5151
5211
  const radix = machineValue(op(expr, 2)) ?? NaN;
5152
5212
  if (isFinite(radix) && radix >= 2 && radix <= 36) {
@@ -5193,9 +5253,9 @@ var ComputeEngine = (() => {
5193
5253
  let close = "";
5194
5254
  if (argCount > 1) {
5195
5255
  const op22 = stringValue(op(expr, 2)) ?? "";
5196
- open = op22[0] ?? "";
5197
- close = op22[1] ?? "";
5198
- sep = op22[2] ?? "";
5256
+ open = op22[0] ?? "(";
5257
+ close = op22[1] ?? ")";
5258
+ sep = op22[2] ?? ",";
5199
5259
  }
5200
5260
  const body = head(arg1) === "List" ? serializeSequence(sep)(serializer, arg1) : serializer.serialize(arg1);
5201
5261
  serializer.wrapString(body, style, stringValue(op(expr, 2)) ?? void 0);
@@ -5215,22 +5275,22 @@ var ComputeEngine = (() => {
5215
5275
  {
5216
5276
  trigger: ["\\mathtip"],
5217
5277
  parse: (parser) => {
5218
- const op12 = parser.matchLatexGroup();
5219
- const op22 = parser.matchLatexGroup();
5278
+ const op12 = parser.parseGroup();
5279
+ const op22 = parser.parseGroup();
5220
5280
  return op12;
5221
5281
  }
5222
5282
  },
5223
5283
  {
5224
5284
  trigger: ["\\texttip"],
5225
5285
  parse: (parser) => {
5226
- const op12 = parser.matchLatexGroup();
5227
- const op22 = parser.matchLatexGroup();
5286
+ const op12 = parser.parseGroup();
5287
+ const op22 = parser.parseGroup();
5228
5288
  return op12;
5229
5289
  }
5230
5290
  },
5231
5291
  {
5232
5292
  trigger: ["\\error"],
5233
- parse: (parser) => parser.matchLatexGroup()
5293
+ parse: (parser) => parser.parseGroup()
5234
5294
  },
5235
5295
  {
5236
5296
  name: "Error",
@@ -5292,12 +5352,12 @@ var ComputeEngine = (() => {
5292
5352
  kind: "matchfix",
5293
5353
  openDelimiter: "[",
5294
5354
  closeDelimiter: "]",
5295
- parse: (_parser, lhs) => {
5296
- if (lhs === null)
5355
+ parse: (_parser, body) => {
5356
+ if (body === null)
5297
5357
  return ["List"];
5298
- if (head(lhs) !== "Sequence" && head(lhs) !== "List")
5299
- return ["List", lhs];
5300
- return ["List", ...ops(lhs) ?? []];
5358
+ if (head(body) !== "Sequence" && head(body) !== "List")
5359
+ return ["List", body];
5360
+ return ["List", ...ops(body) ?? []];
5301
5361
  },
5302
5362
  serialize: (serializer, expr) => {
5303
5363
  return joinLatex([
@@ -5330,8 +5390,8 @@ var ComputeEngine = (() => {
5330
5390
  // when the comma operator is used, the lhs and rhs are flattened,
5331
5391
  // i.e. `1,2,3` -> `["Delimiter", ["List", 1, 2, 3], ","]`,
5332
5392
  // and `1, (2, 3)` -> `["Delimiter",
5333
- // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "(", ",", ")"]], ","],
5334
- parse: (parser, terminator, lhs) => {
5393
+ // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "()", ","]]],
5394
+ parse: (parser, lhs, terminator) => {
5335
5395
  const seq = parseSequence(parser, terminator, lhs, 20, ",");
5336
5396
  if (seq === null)
5337
5397
  return null;
@@ -5346,7 +5406,7 @@ var ComputeEngine = (() => {
5346
5406
  trigger: [";"],
5347
5407
  kind: "infix",
5348
5408
  precedence: 19,
5349
- parse: (parser, terminator, lhs) => {
5409
+ parse: (parser, lhs, terminator) => {
5350
5410
  const seq = parseSequence(parser, terminator, lhs, 19, ";");
5351
5411
  if (seq === null)
5352
5412
  return null;
@@ -5418,10 +5478,20 @@ var ComputeEngine = (() => {
5418
5478
  kind: "postfix",
5419
5479
  parse: (_parser, lhs) => ["Prime", missingIfEmpty(lhs), 2]
5420
5480
  },
5481
+ {
5482
+ trigger: ["^", "\\tripleprime"],
5483
+ kind: "postfix",
5484
+ parse: (_parser, lhs) => ["Prime", missingIfEmpty(lhs), 3]
5485
+ },
5421
5486
  {
5422
5487
  name: "InverseFunction",
5423
- // trigger: '^{-1}',
5424
- // kind: 'postfix',
5488
+ trigger: "^{-1}",
5489
+ kind: "postfix",
5490
+ parse: (parser, lhs) => {
5491
+ if (parser.computeEngine?.box(lhs)?.domain.isFunction)
5492
+ return ["InverseFunction", lhs];
5493
+ return null;
5494
+ },
5425
5495
  serialize: (serializer, expr) => serializer.serialize(op(expr, 1)) + "^{-1}"
5426
5496
  },
5427
5497
  {
@@ -5431,9 +5501,9 @@ var ComputeEngine = (() => {
5431
5501
  const base = serializer.serialize(op(expr, 1));
5432
5502
  if (degree === 1)
5433
5503
  return base + "^{\\prime}";
5434
- else if (degree === 2)
5504
+ if (degree === 2)
5435
5505
  return base + "^{\\doubleprime}";
5436
- else if (degree === 3)
5506
+ if (degree === 3)
5437
5507
  return base + "^{\\tripleprime}";
5438
5508
  return base + "^{(" + Number(degree).toString() + ")}";
5439
5509
  }
@@ -5443,7 +5513,7 @@ var ComputeEngine = (() => {
5443
5513
  trigger: "cases",
5444
5514
  kind: "environment",
5445
5515
  parse: (parser) => {
5446
- const tabular = parser.matchTabular("cases");
5516
+ const tabular = parser.parseTabular();
5447
5517
  if (!tabular)
5448
5518
  return ["Which"];
5449
5519
  const result = ["Which"];
@@ -5492,9 +5562,9 @@ var ComputeEngine = (() => {
5492
5562
  runs.push(parseTextRun(parser));
5493
5563
  } else if (parser.match("\\textbf") && parser.match("<{>")) {
5494
5564
  runs.push(parseTextRun(parser, { "font-weight": "bold" }));
5495
- } else if (parser.match("\\color") && parser.match("<{>")) {
5496
- const color = parser.matchColor();
5497
- if (color && parser.match("<}>")) {
5565
+ } else if (parser.match("\\color")) {
5566
+ const color = parser.parseStringGroup();
5567
+ if (color !== null) {
5498
5568
  if (runinStyle !== null && text) {
5499
5569
  runs.push(["Style", text, { dict: runinStyle }]);
5500
5570
  } else if (text) {
@@ -5507,7 +5577,7 @@ var ComputeEngine = (() => {
5507
5577
  text += " ";
5508
5578
  } else if (parser.match("<$>")) {
5509
5579
  const index = parser.index;
5510
- const expr = parser.matchExpression() ?? ["Sequence"];
5580
+ const expr = parser.parseExpression() ?? ["Sequence"];
5511
5581
  parser.skipSpace();
5512
5582
  if (parser.match("<$>")) {
5513
5583
  runs.push(expr);
@@ -5517,7 +5587,7 @@ var ComputeEngine = (() => {
5517
5587
  }
5518
5588
  } else if (parser.match("<$$>")) {
5519
5589
  const index = parser.index;
5520
- const expr = parser.matchExpression() ?? ["Sequence"];
5590
+ const expr = parser.parseExpression() ?? ["Sequence"];
5521
5591
  parser.skipSpace();
5522
5592
  if (parser.match("<$$>")) {
5523
5593
  runs.push(expr);
@@ -5526,7 +5596,7 @@ var ComputeEngine = (() => {
5526
5596
  parser.index = index;
5527
5597
  }
5528
5598
  } else
5529
- text += parser.matchChar() ?? parser.next();
5599
+ text += parser.matchChar() ?? parser.nextToken();
5530
5600
  }
5531
5601
  if (runinStyle !== null && text) {
5532
5602
  runs.push(["Style", `'${text}'`, { dict: runinStyle }]);
@@ -5595,7 +5665,7 @@ var ComputeEngine = (() => {
5595
5665
  // src/compute-engine/latex-syntax/dictionary/definitions-inequalities.ts
5596
5666
  var DEFINITIONS_INEQUALITIES = [
5597
5667
  {
5598
- trigger: ["!", "<"],
5668
+ trigger: ["\\not", "<"],
5599
5669
  kind: "infix",
5600
5670
  associativity: "right",
5601
5671
  precedence: 246,
@@ -5641,7 +5711,7 @@ var ComputeEngine = (() => {
5641
5711
  kind: "infix",
5642
5712
  associativity: "right",
5643
5713
  precedence: 241,
5644
- parse: "Equal"
5714
+ parse: "LessEqual"
5645
5715
  },
5646
5716
  {
5647
5717
  trigger: ["\\leqslant"],
@@ -5777,7 +5847,7 @@ var ComputeEngine = (() => {
5777
5847
  {
5778
5848
  name: "NotApprox",
5779
5849
  // Note: Mathematica TildeTilde
5780
- trigger: ["\\approx"],
5850
+ trigger: ["\\not", "\\approx"],
5781
5851
  kind: "infix",
5782
5852
  associativity: "right",
5783
5853
  precedence: 247
@@ -5793,7 +5863,7 @@ var ComputeEngine = (() => {
5793
5863
  {
5794
5864
  name: "NotApproxEqual",
5795
5865
  // Note: Mathematica NotTildeEqual
5796
- trigger: ["!", "\\approxeq"],
5866
+ trigger: ["\\not", "\\approxeq"],
5797
5867
  kind: "infix",
5798
5868
  // Note: no LaTeX symbol for char U+2249
5799
5869
  associativity: "right",
@@ -5881,7 +5951,7 @@ var ComputeEngine = (() => {
5881
5951
  precedence: 244
5882
5952
  },
5883
5953
  {
5884
- trigger: ["!", ">"],
5954
+ trigger: ["\\not", ">"],
5885
5955
  kind: "infix",
5886
5956
  associativity: "right",
5887
5957
  precedence: 244,
@@ -6044,7 +6114,7 @@ var ComputeEngine = (() => {
6044
6114
  // src/compute-engine/latex-syntax/dictionary/definitions-other.ts
6045
6115
  function parseSingleArg(cmd) {
6046
6116
  return (parser) => {
6047
- const arg = parser.matchLatexGroup();
6117
+ const arg = parser.parseGroup();
6048
6118
  return arg === null ? [cmd] : [cmd, arg];
6049
6119
  };
6050
6120
  }
@@ -6098,14 +6168,14 @@ var ComputeEngine = (() => {
6098
6168
  {
6099
6169
  name: "Transpose",
6100
6170
  trigger: ["^", "T"],
6101
- kind: "infix"
6171
+ kind: "postfix"
6102
6172
  // @todo: if lhs is a list/tensor
6103
6173
  },
6104
6174
  {
6105
6175
  // @todo: if lhs is a list/tensor
6106
6176
  name: "ConjugateTranspose",
6107
6177
  trigger: ["^", "H"],
6108
- kind: "infix"
6178
+ kind: "postfix"
6109
6179
  },
6110
6180
  {
6111
6181
  name: "StringJoin",
@@ -6135,9 +6205,9 @@ var ComputeEngine = (() => {
6135
6205
  while (!done) {
6136
6206
  parser.skipSpace();
6137
6207
  if (parser.match("_")) {
6138
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6208
+ sub2 = parser.parseGroup() ?? parser.parseToken();
6139
6209
  } else if (parser.match("^")) {
6140
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6210
+ sup = parser.parseGroup() ?? parser.parseToken();
6141
6211
  } else {
6142
6212
  done = true;
6143
6213
  }
@@ -6147,9 +6217,9 @@ var ComputeEngine = (() => {
6147
6217
  sub2 = ["List", ...seq];
6148
6218
  if (sub2 === null || sup === null)
6149
6219
  return null;
6150
- let rhs = parser.matchLatexGroup() ?? "Nothing";
6220
+ let rhs = parser.parseGroup() ?? "Nothing";
6151
6221
  if (rhs !== "Nothing" && !isEmptySequence(rhs)) {
6152
- const arg = parser.matchArguments("enclosure") ?? ["Nothing"];
6222
+ const arg = parser.parseArguments() ?? ["Nothing"];
6153
6223
  rhs = [rhs, ...arg];
6154
6224
  }
6155
6225
  return ["PartialDerivative", rhs, sub2, sup];
@@ -6426,7 +6496,7 @@ var ComputeEngine = (() => {
6426
6496
  // src/compute-engine/latex-syntax/dictionary/definitions-trigonometry.ts
6427
6497
  function parseTrig(op3) {
6428
6498
  return (parser, until) => {
6429
- let head2 = {
6499
+ const head2 = {
6430
6500
  "\\arcsin": "Arcsin",
6431
6501
  "\\arccos": "Arccos",
6432
6502
  "\\arctan": "Arctan",
@@ -6461,37 +6531,11 @@ var ComputeEngine = (() => {
6461
6531
  }[op3 ?? ""] ?? op3 ?? "";
6462
6532
  if (parser.atTerminator(until))
6463
6533
  return head2;
6464
- let isInverse = false;
6465
- let primeLevel = 0;
6466
- let sup = null;
6467
- parser.skipSpace();
6468
- const start = parser.index;
6469
- if (parser.match("^")) {
6470
- parser.skipSpace();
6471
- const superscriptIndex = parser.index;
6472
- if (parser.matchAll(["<{>", "-", "1", "<}>"]))
6473
- isInverse = true;
6474
- else {
6475
- parser.index = start;
6476
- parser.index = start;
6477
- primeLevel = parser.matchPrimeSuffix();
6478
- if (primeLevel === 0) {
6479
- parser.index = superscriptIndex;
6480
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6481
- }
6482
- }
6483
- }
6484
- primeLevel += parser.matchPrimeSuffix();
6485
- if (isInverse)
6486
- head2 = ["InverseFunction", head2];
6487
- if (primeLevel === 1)
6488
- head2 = ["Derivative", head2];
6489
- else if (primeLevel > 1)
6490
- head2 = ["Derivative", head2, primeLevel];
6491
- const args = parser.matchArguments("implicit", until);
6492
- if (args === null)
6493
- return sup ? [["Power", [head2], sup]] : head2;
6494
- return sup ? ["Power", [head2, ...args], sup] : [head2, ...args];
6534
+ const fn = parser.parsePostfixOperator(head2, until);
6535
+ if (fn !== null)
6536
+ return fn;
6537
+ const args = parser.parseArguments("implicit", until);
6538
+ return args === null ? head2 : [head2, ...args];
6495
6539
  };
6496
6540
  }
6497
6541
  var DEFINITIONS_TRIGONOMETRY = [
@@ -6520,7 +6564,6 @@ var ComputeEngine = (() => {
6520
6564
  parse: parseTrig("Arccot")
6521
6565
  },
6522
6566
  {
6523
- kind: "function",
6524
6567
  name: "Arcsec",
6525
6568
  trigger: "arcsec",
6526
6569
  parse: parseTrig("Arcsec")
@@ -6721,14 +6764,14 @@ var ComputeEngine = (() => {
6721
6764
  // Caution: cartesian product is not associative
6722
6765
  precedence: 390,
6723
6766
  // Same as Multiply?
6724
- parse: (parser, until, lhs) => {
6767
+ parse: (parser, lhs, until) => {
6725
6768
  if (390 < until.minPrec)
6726
6769
  return null;
6727
6770
  const ce = parser.computeEngine;
6728
6771
  if (!ce || !ce.box(lhs).domain.isCompatible("Set"))
6729
6772
  return null;
6730
6773
  const index = parser.index;
6731
- const rhs = parser.matchExpression({ ...until, minPrec: 390 });
6774
+ const rhs = parser.parseExpression({ ...until, minPrec: 390 });
6732
6775
  if (rhs === null || ce.box(lhs).domain.isCompatible("Set") !== true) {
6733
6776
  parser.index = index;
6734
6777
  return null;
@@ -6808,8 +6851,8 @@ var ComputeEngine = (() => {
6808
6851
  associativity: "right",
6809
6852
  precedence: 160,
6810
6853
  // As per MathML, lower precedence
6811
- parse: (parser, terminator, lhs) => {
6812
- const rhs = parser.matchExpression(terminator);
6854
+ parse: (parser, lhs, terminator) => {
6855
+ const rhs = parser.parseExpression(terminator);
6813
6856
  return rhs === null ? null : ["Element", rhs, lhs];
6814
6857
  }
6815
6858
  },
@@ -7014,9 +7057,10 @@ var ComputeEngine = (() => {
7014
7057
  let sub2 = null;
7015
7058
  while (!(sub2 !== null && sup !== null) && (parser.peek === "_" || parser.peek === "^")) {
7016
7059
  if (parser.match("_"))
7017
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
7018
- else if (parser.match("^"))
7019
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
7060
+ sub2 = parser.parseGroup() ?? parser.parseToken();
7061
+ else if (parser.match("^")) {
7062
+ sup = parser.parseGroup() ?? parser.parseToken();
7063
+ }
7020
7064
  parser.skipSpace();
7021
7065
  }
7022
7066
  if (sub2 === "Nothing" || isEmptySequence(sub2))
@@ -7092,7 +7136,7 @@ var ComputeEngine = (() => {
7092
7136
  function parseIntegralBody(parser, n = 1) {
7093
7137
  const start = parser.index;
7094
7138
  let found = false;
7095
- let fn = parser.matchExpression({
7139
+ let fn = parser.parseExpression({
7096
7140
  minPrec: 266,
7097
7141
  condition: () => {
7098
7142
  if (parser.matchAll(["\\mathrm", "<{>", "d", "<}>"]))
@@ -7102,7 +7146,7 @@ var ComputeEngine = (() => {
7102
7146
  });
7103
7147
  if (!found) {
7104
7148
  parser.index = start;
7105
- fn = parser.matchExpression({
7149
+ fn = parser.parseExpression({
7106
7150
  minPrec: 266,
7107
7151
  condition: () => {
7108
7152
  if (parser.match("d"))
@@ -7119,7 +7163,7 @@ var ComputeEngine = (() => {
7119
7163
  function parseIndexes(parser, n = 1) {
7120
7164
  parser.skipSpace();
7121
7165
  const result = [];
7122
- const index = symbol(parser.matchSymbol());
7166
+ const index = symbol(parser.parseSymbol());
7123
7167
  if (index === null)
7124
7168
  return [];
7125
7169
  result.push(index);
@@ -7238,30 +7282,36 @@ var ComputeEngine = (() => {
7238
7282
  }
7239
7283
  var DEFINITIONS_CALCULUS = [
7240
7284
  {
7285
+ kind: "expression",
7241
7286
  name: "Integrate",
7242
7287
  trigger: ["\\int"],
7243
7288
  parse: parseIntegral("Integrate"),
7244
7289
  serialize: serializeIntegral("\\int")
7245
7290
  },
7246
7291
  {
7292
+ kind: "expression",
7247
7293
  trigger: ["\\iint"],
7248
7294
  parse: parseIntegral("Integrate", 2)
7249
7295
  },
7250
7296
  {
7297
+ kind: "expression",
7251
7298
  trigger: ["\\iiint"],
7252
7299
  parse: parseIntegral("Integrate", 3)
7253
7300
  },
7254
7301
  {
7302
+ kind: "expression",
7255
7303
  name: "CircularIntegrate",
7256
7304
  trigger: ["\\oint"],
7257
7305
  parse: parseIntegral("CircularIntegrate"),
7258
7306
  serialize: serializeIntegral("\\oint")
7259
7307
  },
7260
7308
  {
7309
+ kind: "expression",
7261
7310
  trigger: ["\\oiint"],
7262
7311
  parse: parseIntegral("CircularIntegrate", 2)
7263
7312
  },
7264
7313
  {
7314
+ kind: "expression",
7265
7315
  trigger: ["\\oiiint"],
7266
7316
  parse: parseIntegral("CircularIntegrate", 3)
7267
7317
  }
@@ -7367,6 +7417,7 @@ var ComputeEngine = (() => {
7367
7417
  var DEFINITIONS_SYMBOLS = [
7368
7418
  ...SYMBOLS.map(([symbol2, latex, _codepoint]) => {
7369
7419
  return {
7420
+ kind: "symbol",
7370
7421
  name: symbol2,
7371
7422
  trigger: [latex],
7372
7423
  parse: symbol2
@@ -7374,6 +7425,7 @@ var ComputeEngine = (() => {
7374
7425
  }),
7375
7426
  ...SYMBOLS.map(([symbol2, _latex, codepoint]) => {
7376
7427
  return {
7428
+ kind: "symbol",
7377
7429
  trigger: [String.fromCodePoint(codepoint)],
7378
7430
  parse: symbol2
7379
7431
  };
@@ -7402,98 +7454,99 @@ var ComputeEngine = (() => {
7402
7454
  return trigger.length;
7403
7455
  return 1;
7404
7456
  }
7457
+ function addEntry(result, entry, onError) {
7458
+ const [trigger, indexedEntry] = makeIndexedEntry(entry, onError);
7459
+ if (indexedEntry === null)
7460
+ return;
7461
+ const kind = "kind" in entry ? entry.kind : "expression";
7462
+ if (trigger && trigger.length === 2 && /[_^]/.test(trigger[0]) && trigger[1] !== "<{>" && kind !== "function" && entry.name) {
7463
+ let parse = entry.parse;
7464
+ if (parse === void 0) {
7465
+ if (kind === "symbol")
7466
+ parse = entry.name;
7467
+ if (kind === "postfix" || kind === "prefix")
7468
+ parse = (_parser, expr) => [entry.name, expr];
7469
+ }
7470
+ addEntry(
7471
+ result,
7472
+ {
7473
+ ...entry,
7474
+ kind,
7475
+ parse,
7476
+ name: void 0,
7477
+ trigger: [trigger[0], "<{>", trigger[1], "<}>"]
7478
+ },
7479
+ onError
7480
+ );
7481
+ }
7482
+ if (indexedEntry.name !== void 0) {
7483
+ if (result.name.has(indexedEntry.name)) {
7484
+ onError({
7485
+ severity: "warning",
7486
+ message: [
7487
+ "invalid-dictionary-entry",
7488
+ indexedEntry.name,
7489
+ "Duplicate definition. The name must be unique, but a trigger can be used by multiple definitions."
7490
+ ]
7491
+ });
7492
+ }
7493
+ result.name.set(indexedEntry.name, indexedEntry);
7494
+ }
7495
+ if (indexedEntry.kind === "matchfix") {
7496
+ result.matchfix.push(indexedEntry);
7497
+ } else if (indexedEntry.kind === "environment") {
7498
+ const triggerString = tokensToString(entry.trigger ?? "");
7499
+ if (result.environment.has(triggerString)) {
7500
+ onError({
7501
+ severity: "warning",
7502
+ message: [
7503
+ "invalid-dictionary-entry",
7504
+ triggerString,
7505
+ "Duplicate environment definition"
7506
+ ]
7507
+ });
7508
+ }
7509
+ result.environment.set(triggerString, indexedEntry);
7510
+ } else if (trigger) {
7511
+ console.assert(entry.trigger);
7512
+ const triggerString = tokensToString(entry.trigger ?? "");
7513
+ const n = triggerLength(trigger);
7514
+ result.lookahead = Math.max(result.lookahead, n);
7515
+ if (indexedEntry.kind === "function") {
7516
+ if (!result.function.has(triggerString))
7517
+ result.function.set(triggerString, [indexedEntry]);
7518
+ else
7519
+ result.function.set(triggerString, [
7520
+ ...result.function.get(triggerString),
7521
+ indexedEntry
7522
+ ]);
7523
+ } else {
7524
+ const kind2 = indexedEntry.kind;
7525
+ if (result[kind2][n] === void 0)
7526
+ result[kind2][n] = /* @__PURE__ */ new Map();
7527
+ const list = result[kind2][n];
7528
+ if (list.has(triggerString))
7529
+ list.get(triggerString).push(indexedEntry);
7530
+ else
7531
+ list.set(triggerString, [indexedEntry]);
7532
+ }
7533
+ }
7534
+ }
7405
7535
  function indexLatexDictionary(dic, onError) {
7406
7536
  const result = {
7407
7537
  lookahead: 1,
7408
7538
  name: /* @__PURE__ */ new Map(),
7539
+ expression: /* @__PURE__ */ new Map(),
7409
7540
  function: /* @__PURE__ */ new Map(),
7410
- identifier: [],
7541
+ symbol: [],
7411
7542
  infix: [],
7412
7543
  prefix: [],
7413
7544
  postfix: [],
7414
7545
  environment: /* @__PURE__ */ new Map(),
7415
7546
  matchfix: []
7416
7547
  };
7417
- for (const entry of dic) {
7418
- const [trigger, indexedEntry] = makeIndexedEntry(entry, onError);
7419
- if (indexedEntry === null)
7420
- continue;
7421
- if (indexedEntry.name !== void 0) {
7422
- if (result.name.has(indexedEntry.name)) {
7423
- onError({
7424
- severity: "warning",
7425
- message: [
7426
- "invalid-dictionary-entry",
7427
- indexedEntry.name,
7428
- "Duplicate definition"
7429
- ]
7430
- });
7431
- }
7432
- result.name.set(indexedEntry.name, indexedEntry);
7433
- }
7434
- if (indexedEntry.kind === "matchfix") {
7435
- result.matchfix.push(indexedEntry);
7436
- } else if (indexedEntry.kind === "environment") {
7437
- const triggerString = tokensToString(entry.trigger ?? "");
7438
- if (result.environment.has(triggerString)) {
7439
- onError({
7440
- severity: "warning",
7441
- message: [
7442
- "invalid-dictionary-entry",
7443
- triggerString,
7444
- "Duplicate environment definition"
7445
- ]
7446
- });
7447
- }
7448
- result.environment.set(triggerString, indexedEntry);
7449
- } else if (trigger) {
7450
- console.assert(entry.trigger);
7451
- const triggerString = tokensToString(entry.trigger ?? "");
7452
- const n = triggerLength(trigger);
7453
- result.lookahead = Math.max(result.lookahead, n);
7454
- if (indexedEntry.kind === "function") {
7455
- if (!result.function.has(triggerString))
7456
- result.function.set(triggerString, [indexedEntry]);
7457
- else
7458
- result.function.set(triggerString, [
7459
- ...result.function.get(triggerString),
7460
- indexedEntry
7461
- ]);
7462
- } else if (indexedEntry.kind === "identifier") {
7463
- if (result.identifier[n] === void 0)
7464
- result.identifier[n] = /* @__PURE__ */ new Map();
7465
- const list = result.identifier[n];
7466
- if (list.has(triggerString))
7467
- list.get(triggerString).push(indexedEntry);
7468
- else
7469
- list.set(triggerString, [indexedEntry]);
7470
- } else if (indexedEntry.kind === "prefix") {
7471
- if (result.prefix[n] === void 0)
7472
- result.prefix[n] = /* @__PURE__ */ new Map();
7473
- const list = result.prefix[n];
7474
- if (list.has(triggerString))
7475
- list.get(triggerString).push(indexedEntry);
7476
- else
7477
- list.set(triggerString, [indexedEntry]);
7478
- } else if (indexedEntry.kind === "infix") {
7479
- if (result.infix[n] === void 0)
7480
- result.infix[n] = /* @__PURE__ */ new Map();
7481
- const list = result.infix[n];
7482
- if (list.has(triggerString))
7483
- list.get(triggerString).push(indexedEntry);
7484
- else
7485
- list.set(triggerString, [indexedEntry]);
7486
- } else if (indexedEntry.kind === "postfix") {
7487
- if (result.postfix[n] === void 0)
7488
- result.postfix[n] = /* @__PURE__ */ new Map();
7489
- const list = result.postfix[n];
7490
- if (list.has(triggerString))
7491
- list.get(triggerString).push(indexedEntry);
7492
- else
7493
- list.set(triggerString, [indexedEntry]);
7494
- }
7495
- }
7496
- }
7548
+ for (const entry of dic)
7549
+ addEntry(result, entry, onError);
7497
7550
  return result;
7498
7551
  }
7499
7552
  function makeIndexedEntry(entry, onError) {
@@ -7501,7 +7554,7 @@ var ComputeEngine = (() => {
7501
7554
  return [null, null];
7502
7555
  const result = {
7503
7556
  name: entry.name,
7504
- kind: "kind" in entry ? entry.kind : "identifier"
7557
+ kind: "kind" in entry ? entry.kind : "expression"
7505
7558
  };
7506
7559
  if (result.kind === "matchfix" && isMatchfixEntry(entry)) {
7507
7560
  result.openDelimiter = entry.openDelimiter;
@@ -7534,29 +7587,57 @@ var ComputeEngine = (() => {
7534
7587
  const triggerString = trigger ? tokensToString(trigger) : "";
7535
7588
  if (result.kind === "function" && isFunctionEntry(entry)) {
7536
7589
  result.serialize = entry.serialize;
7537
- if (triggerString && !entry.serialize)
7538
- result.serialize = (serializer, expr) => `\\mathrm{${triggerString}}${serializer.wrapArguments(expr)}`;
7539
- result.parse = entry.parse;
7540
- if (!result.parse && entry.name)
7541
- result.parse = (parser) => {
7542
- const arg = parser.matchArguments("enclosure");
7543
- return arg === null ? entry.name : [entry.name, ...arg];
7544
- };
7590
+ if (triggerString && !entry.serialize) {
7591
+ if (triggerString.startsWith("\\")) {
7592
+ result.serialize = (serializer, expr) => `${triggerString}${serializer.wrapArguments(expr)}`;
7593
+ } else
7594
+ result.serialize = (serializer, expr) => `\\mathrm{${triggerString}}${serializer.wrapArguments(expr)}`;
7595
+ }
7596
+ if (typeof entry.parse === "function")
7597
+ result.parse = entry.parse;
7598
+ else if (typeof entry.parse === "string")
7599
+ result.parse = () => entry.parse;
7600
+ else if (entry.name)
7601
+ result.parse = () => entry.name;
7545
7602
  return [triggerString, result];
7546
7603
  }
7547
- if (typeof entry.trigger === "string") {
7548
- console.assert(
7549
- entry.parse || trigger.length > 1,
7550
- `Trigger shortcut should produce more than one token. Otherwise, not worth using the shortcut. (${triggerString})`
7551
- );
7604
+ if (result.kind === "expression" && isExpressionEntry(entry)) {
7605
+ result.serialize = entry.serialize ?? triggerString;
7606
+ if (typeof result.serialize === "string") {
7607
+ const serializeExpr = result.serialize;
7608
+ result.serialize = (serializer, expr) => {
7609
+ if (!head(expr))
7610
+ return serializer.serialize(serializeExpr);
7611
+ return `${serializer.serialize(
7612
+ serializeExpr
7613
+ )}${serializer.wrapArguments(expr)}`;
7614
+ };
7615
+ }
7616
+ {
7617
+ if (typeof entry.parse === "function") {
7618
+ result.parse = entry.parse;
7619
+ } else {
7620
+ const parseResult = entry.parse ?? entry.name;
7621
+ result.parse = () => parseResult;
7622
+ }
7623
+ }
7624
+ return [triggerString, result];
7552
7625
  }
7553
- if (result.kind === "identifier" && isIdentifierEntry(entry)) {
7626
+ console.assert(
7627
+ typeof entry.trigger !== "string" || entry.parse || trigger.length > 1 || "kind" in entry && entry.kind === "function",
7628
+ `Trigger shortcuts should produce more than one token. Otherwise, not worth using them. (${triggerString})`
7629
+ );
7630
+ if (result.kind === "symbol" && isSymbolEntry(entry)) {
7554
7631
  result.precedence = entry.precedence ?? 1e4;
7555
7632
  }
7556
7633
  if ((result.kind === "infix" || result.kind === "prefix" || result.kind === "postfix") && (isInfixEntry(entry) || isPrefixEntry(entry) || isPostfixEntry(entry))) {
7557
- if (trigger && (trigger[0] === "^" || trigger[0] === "_"))
7634
+ if (trigger && (trigger[0] === "^" || trigger[0] === "_")) {
7558
7635
  result.precedence = 720;
7559
- else
7636
+ console.assert(
7637
+ entry.precedence === void 0,
7638
+ "'precedence' not allowed with ^ and _ triggers"
7639
+ );
7640
+ } else
7560
7641
  result.precedence = entry.precedence ?? 1e4;
7561
7642
  }
7562
7643
  if (result.kind === "infix" && isInfixEntry(entry)) {
@@ -7569,7 +7650,7 @@ var ComputeEngine = (() => {
7569
7650
  } else if (trigger && (trigger[0] === "^" || trigger[0] === "_")) {
7570
7651
  console.assert(!entry.parse);
7571
7652
  const name = entry.parse ?? entry.name;
7572
- result.parse = (_scanner, _terminator, arg) => [
7653
+ result.parse = (_scanner, arg, _terminator) => [
7573
7654
  name,
7574
7655
  missingIfEmpty(op(arg, 1)),
7575
7656
  missingIfEmpty(op(arg, 2))
@@ -7578,11 +7659,11 @@ var ComputeEngine = (() => {
7578
7659
  const head2 = entry.parse ?? entry.name;
7579
7660
  const prec = result.precedence;
7580
7661
  const associativity = result.associativity;
7581
- result.parse = (scanner, terminator, lhs) => {
7662
+ result.parse = (scanner, lhs, terminator) => {
7582
7663
  if (prec < terminator.minPrec)
7583
7664
  return null;
7584
7665
  const rhs = missingIfEmpty(
7585
- scanner.matchExpression({
7666
+ scanner.parseExpression({
7586
7667
  ...terminator,
7587
7668
  minPrec: prec
7588
7669
  })
@@ -7594,7 +7675,7 @@ var ComputeEngine = (() => {
7594
7675
  if (typeof entry.parse === "function") {
7595
7676
  result.parse = entry.parse;
7596
7677
  } else if (entry.parse !== void 0) {
7597
- console.assert(result.kind === "identifier");
7678
+ console.assert(result.kind === "symbol" || result.kind === "expression");
7598
7679
  result.parse = () => entry.parse;
7599
7680
  } else if (entry.parse === void 0 && entry.name !== void 0) {
7600
7681
  if (result.kind === "postfix") {
@@ -7604,9 +7685,9 @@ var ComputeEngine = (() => {
7604
7685
  console.assert(entry.name);
7605
7686
  const head2 = entry.name;
7606
7687
  result.parse = (parser, terminator) => {
7607
- if (prec < terminator.minPrec)
7688
+ if (terminator && prec < terminator.minPrec)
7608
7689
  return null;
7609
- const rhs = parser.matchExpression({ ...terminator, minPrec: prec });
7690
+ const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
7610
7691
  return rhs === null ? null : [head2, rhs];
7611
7692
  };
7612
7693
  }
@@ -7621,7 +7702,7 @@ var ComputeEngine = (() => {
7621
7702
  result.serialize = triggerString + "#1";
7622
7703
  } else if (result.kind === "infix") {
7623
7704
  result.serialize = "#1" + triggerString + "#2";
7624
- } else if (result.kind === "identifier") {
7705
+ } else if (result.kind === "symbol") {
7625
7706
  result.serialize = triggerString;
7626
7707
  } else {
7627
7708
  result.serialize = "";
@@ -7751,6 +7832,7 @@ var ComputeEngine = (() => {
7751
7832
  physics: [
7752
7833
  {
7753
7834
  name: "mu0",
7835
+ kind: "symbol",
7754
7836
  trigger: "\\mu_0"
7755
7837
  }
7756
7838
  ],
@@ -7800,6 +7882,7 @@ var ComputeEngine = (() => {
7800
7882
  special = {
7801
7883
  "+": "plus",
7802
7884
  "-": "minus",
7885
+ "\\plusmn": "pm",
7803
7886
  "\\pm": "pm",
7804
7887
  "\\ast": "ast",
7805
7888
  "\\dag": "dag",
@@ -7815,22 +7898,22 @@ var ComputeEngine = (() => {
7815
7898
  }[token];
7816
7899
  }
7817
7900
  if (special) {
7818
- parser.next();
7901
+ parser.nextToken();
7819
7902
  return special;
7820
7903
  }
7821
7904
  const i = SYMBOLS.findIndex((x) => x[1] === token);
7822
7905
  if (i >= 0) {
7823
- parser.next();
7906
+ parser.nextToken();
7824
7907
  return SYMBOLS[i][0];
7825
7908
  }
7826
- return parser.matchChar() ?? parser.next();
7909
+ return parser.matchChar() ?? parser.nextToken();
7827
7910
  }
7828
7911
  function matchIdentifierBody(parser) {
7829
7912
  let id = matchPrefixedIdentifier(parser);
7830
7913
  const start = parser.index;
7831
7914
  const prefix = IDENTIFIER_MODIFIER[parser.peek] ?? null;
7832
7915
  if (prefix) {
7833
- parser.next();
7916
+ parser.nextToken();
7834
7917
  if (!parser.match("<{>")) {
7835
7918
  parser.index = start;
7836
7919
  return null;
@@ -7856,7 +7939,7 @@ var ComputeEngine = (() => {
7856
7939
  id += next;
7857
7940
  }
7858
7941
  while (!parser.atEnd && /\d/.test(parser.peek))
7859
- id += parser.next();
7942
+ id += parser.nextToken();
7860
7943
  }
7861
7944
  while (!parser.atEnd) {
7862
7945
  if (parser.match("\\degree"))
@@ -7905,7 +7988,7 @@ var ComputeEngine = (() => {
7905
7988
  const prefix = IDENTIFIER_PREFIX[parser.peek] ?? null;
7906
7989
  if (prefix === null)
7907
7990
  return null;
7908
- parser.next();
7991
+ parser.nextToken();
7909
7992
  if (parser.match("<{>")) {
7910
7993
  let body = "";
7911
7994
  const digit = {
@@ -7922,7 +8005,7 @@ var ComputeEngine = (() => {
7922
8005
  }[parser.peek] ?? "";
7923
8006
  if (digit) {
7924
8007
  body = digit;
7925
- parser.next();
8008
+ parser.nextToken();
7926
8009
  }
7927
8010
  body += matchIdentifierBody(parser);
7928
8011
  if (body === null || !parser.match("<}>")) {
@@ -7936,7 +8019,7 @@ var ComputeEngine = (() => {
7936
8019
  parser.index = start;
7937
8020
  return null;
7938
8021
  }
7939
- function matchInvalidIdentifier(parser) {
8022
+ function parseInvalidIdentifier(parser) {
7940
8023
  const start = parser.index;
7941
8024
  const id = matchPrefixedIdentifier(parser);
7942
8025
  if (id === null || isValidIdentifier(id)) {
@@ -7950,13 +8033,13 @@ var ComputeEngine = (() => {
7950
8033
  }
7951
8034
  function matchIdentifier(parser) {
7952
8035
  if (/^[a-zA-Z]$/.test(parser.peek) || /^\p{XIDS}$/u.test(parser.peek))
7953
- return parser.next();
8036
+ return parser.nextToken();
7954
8037
  const start = parser.index;
7955
8038
  let id = matchPrefixedIdentifier(parser);
7956
8039
  if (!id) {
7957
8040
  id = "";
7958
8041
  while (!parser.atEnd && ONLY_EMOJIS.test(id + parser.peek))
7959
- id += parser.next();
8042
+ id += parser.nextToken();
7960
8043
  }
7961
8044
  if (id) {
7962
8045
  id = id.normalize();
@@ -8003,10 +8086,6 @@ var ComputeEngine = (() => {
8003
8086
  "\\lmoustache": ["\\lmoustache"],
8004
8087
  "\\rmoustache": ["\\rmoustache"]
8005
8088
  };
8006
- var MIDDLE_DELIMITER = {
8007
- ":": [":", "\\colon"],
8008
- "|": ["|", "\\|", "\\mid", "\\mvert"]
8009
- };
8010
8089
  var OPEN_DELIMITER_PREFIX = {
8011
8090
  "\\left": "\\right",
8012
8091
  "\\bigl": "\\bigr",
@@ -8018,17 +8097,6 @@ var ComputeEngine = (() => {
8018
8097
  "\\bigg": "\\bigg",
8019
8098
  "\\Bigg": "\\Bigg"
8020
8099
  };
8021
- var MIDDLE_DELIMITER_PREFIX = [
8022
- "\\middle",
8023
- "\\bigm",
8024
- "\\Bigm",
8025
- "\\biggm",
8026
- "\\Biggm",
8027
- "\\big",
8028
- "\\Big",
8029
- "\\bigg",
8030
- "\\Bigg"
8031
- ];
8032
8100
  var CLOSE_DELIMITER = {
8033
8101
  "(": ")",
8034
8102
  "[": "]",
@@ -8183,7 +8251,7 @@ var ComputeEngine = (() => {
8183
8251
  this._lastPeek = peek;
8184
8252
  return peek;
8185
8253
  }
8186
- next() {
8254
+ nextToken() {
8187
8255
  return this._tokens[this.index++];
8188
8256
  }
8189
8257
  /**
@@ -8236,15 +8304,14 @@ var ComputeEngine = (() => {
8236
8304
  latexAhead(n) {
8237
8305
  return this.latex(this.index, this.index + n);
8238
8306
  }
8239
- latexBefore() {
8240
- return this.latex(0, this.index);
8241
- }
8242
- latexAfter() {
8243
- return this.latex(this.index);
8244
- }
8307
+ // latexBefore(): string {
8308
+ // return this.latex(0, this.index);
8309
+ // }
8310
+ // latexAfter(): string {
8311
+ // return this.latex(this.index);
8312
+ // }
8245
8313
  /**
8246
- * Return at most `this._dictionary.lookahead` strings made from the tokens
8247
- * ahead.
8314
+ * Return at most `this._dictionary.lookahead` LaTeX tokens.
8248
8315
  *
8249
8316
  * The index in the returned array correspond to the number of tokens.
8250
8317
  * Note that since a token can be longer than one char ('\\pi', but also
@@ -8252,6 +8319,10 @@ var ComputeEngine = (() => {
8252
8319
  * does not match that index. However, knowing the index is important
8253
8320
  * to know by how many tokens to advance.
8254
8321
  *
8322
+ * For example:
8323
+ *
8324
+ * `[empty, '\\sqrt', '\\sqrt{', '\\sqrt{2', '\\sqrt{2}']`
8325
+ *
8255
8326
  */
8256
8327
  lookAhead() {
8257
8328
  let n = Math.min(
@@ -8270,12 +8341,12 @@ var ComputeEngine = (() => {
8270
8341
  if (kind === "function") {
8271
8342
  const start = this.index;
8272
8343
  if (this.match("\\operatorname") || this.match("\\mathrm") || this.match("\\mathit")) {
8273
- const fn = this.matchStringArgument();
8344
+ const fn = this.parseStringGroup()?.trim();
8274
8345
  const n = this.index - start;
8275
8346
  this.index = start;
8276
- if (fn !== null && this._dictionary.function.has(fn))
8277
- return this._dictionary.function.get(fn).map((x) => [x, n]);
8278
- return null;
8347
+ if (!fn || !this._dictionary.function.has(fn))
8348
+ return null;
8349
+ return this._dictionary.function.get(fn).map((x) => [x, n]);
8279
8350
  }
8280
8351
  return null;
8281
8352
  } else if (kind === "operator") {
@@ -8308,19 +8379,19 @@ var ComputeEngine = (() => {
8308
8379
  * instead.
8309
8380
  */
8310
8381
  skipSpace() {
8311
- if (!this.options.skipSpace)
8312
- return false;
8313
8382
  if (!this.atEnd && this.peek === "<{>") {
8314
8383
  const index = this.index;
8315
- this.next();
8384
+ this.nextToken();
8316
8385
  while (this.match("<space>")) {
8317
8386
  }
8318
- if (this.next() === "<}>") {
8387
+ if (this.nextToken() === "<}>") {
8319
8388
  this.skipSpace();
8320
8389
  return true;
8321
8390
  }
8322
8391
  this.index = index;
8323
8392
  }
8393
+ if (!this.options.skipSpace)
8394
+ return false;
8324
8395
  let result = false;
8325
8396
  while (this.match("<space>"))
8326
8397
  result = true;
@@ -8343,11 +8414,36 @@ var ComputeEngine = (() => {
8343
8414
  "\\quad",
8344
8415
  "\\qquad"
8345
8416
  ].includes(this.peek)) {
8346
- this.next();
8417
+ this.nextToken();
8347
8418
  this.skipVisualSpace();
8348
8419
  }
8349
8420
  this.skipSpace();
8350
8421
  }
8422
+ match(token) {
8423
+ if (this._tokens[this.index] === token) {
8424
+ this.index++;
8425
+ return true;
8426
+ }
8427
+ return false;
8428
+ }
8429
+ matchAll(tokens) {
8430
+ console.assert(Array.isArray(tokens));
8431
+ if (tokens.length === 0)
8432
+ return false;
8433
+ let matched = true;
8434
+ let i = 0;
8435
+ do {
8436
+ matched = this._tokens[this.index + i] === tokens[i++];
8437
+ } while (matched && i < tokens.length);
8438
+ if (matched)
8439
+ this.index += i;
8440
+ return matched;
8441
+ }
8442
+ matchAny(tokens) {
8443
+ if (tokens.includes(this._tokens[this.index]))
8444
+ return this._tokens[this.index++];
8445
+ return "";
8446
+ }
8351
8447
  matchChar() {
8352
8448
  const index = this.index;
8353
8449
  let caretCount = 0;
@@ -8394,7 +8490,7 @@ var ComputeEngine = (() => {
8394
8490
  } else if (this.match("\\unicode")) {
8395
8491
  this.skipSpaceTokens();
8396
8492
  if (this.peek === "<{>") {
8397
- this.next();
8493
+ this.nextToken();
8398
8494
  const codepoint = this.matchLatexNumber();
8399
8495
  if (this.match("<}>") && codepoint !== null && codepoint >= 0 && codepoint <= 1114111) {
8400
8496
  return String.fromCodePoint(codepoint);
@@ -8409,62 +8505,171 @@ var ComputeEngine = (() => {
8409
8505
  this.index = index;
8410
8506
  return null;
8411
8507
  }
8412
- matchColor(_background = false) {
8413
- let s = "";
8414
- while (!this.atEnd && this.peek !== "}")
8415
- s += this.next();
8416
- return s;
8417
- }
8418
- matchLatexDimension() {
8419
- return null;
8420
- }
8421
- match(token) {
8422
- if (this._tokens[this.index] === token) {
8423
- this.index++;
8424
- return true;
8508
+ parseGroup() {
8509
+ const start = this.index;
8510
+ this.skipSpaceTokens();
8511
+ if (this.match("<{>")) {
8512
+ this.addBoundary(["<}>"]);
8513
+ const expr = this.parseExpression();
8514
+ this.skipSpace();
8515
+ if (this.matchBoundary())
8516
+ return expr ?? ["Sequence"];
8517
+ const from = this.index;
8518
+ while (!this.matchBoundary() && !this.atEnd)
8519
+ this.nextToken();
8520
+ const err = this.error("syntax-error", from);
8521
+ return expr ? ["Sequence", expr, err] : err;
8425
8522
  }
8426
- return false;
8523
+ this.index = start;
8524
+ return null;
8427
8525
  }
8428
- matchAll(tokens) {
8429
- if (typeof tokens === "string")
8430
- tokens = [tokens];
8431
- if (tokens.length === 0)
8432
- return false;
8433
- let matched = true;
8434
- let i = 0;
8435
- do {
8436
- matched = this._tokens[this.index + i] === tokens[i++];
8437
- } while (matched && i < tokens.length);
8438
- if (matched)
8439
- this.index += i;
8440
- return matched;
8526
+ // Some LaTeX commands (but not all) can accept an argument without braces,
8527
+ // for example `^` , `\sqrt` or `\frac`.
8528
+ // This argument will usually be a single token, but can be a sequence of
8529
+ // tokens (e.g. `\sqrt\frac12` or `\sqrt\mathrm{speed}`).
8530
+ parseToken() {
8531
+ const excluding = [
8532
+ ...'!"#$%&(),/;:?@[]\\`|~'.split(""),
8533
+ "\\left",
8534
+ "\\bigl"
8535
+ ];
8536
+ if (excluding.includes(this.peek))
8537
+ return null;
8538
+ if (/^[0-9]$/.test(this.peek))
8539
+ return parseInt(this.nextToken());
8540
+ const result = this.parseGenericExpression() ?? this.parseSymbol();
8541
+ if (!result)
8542
+ return null;
8543
+ return result;
8441
8544
  }
8442
- matchAny(tokens) {
8443
- if (tokens.includes(this._tokens[this.index]))
8444
- return this._tokens[this.index++];
8445
- return "";
8545
+ parseOptionalGroup() {
8546
+ const index = this.index;
8547
+ this.skipSpaceTokens();
8548
+ if (this.match("[")) {
8549
+ this.addBoundary(["]"]);
8550
+ const expr = this.parseExpression();
8551
+ this.skipSpace();
8552
+ if (this.matchBoundary())
8553
+ return expr;
8554
+ return this.boundaryError("expected-closing-delimiter");
8555
+ }
8556
+ this.index = index;
8557
+ return null;
8446
8558
  }
8447
- matchSequence(tokens) {
8559
+ /**
8560
+ * Parse an expression in a tabular format, where rows are separated by `\\`
8561
+ * and columns by `&`.
8562
+ *
8563
+ * Return rows of sparse columns: empty rows are indicated with `Nothing`,
8564
+ * and empty cells are also indicated with `Nothing`.
8565
+ */
8566
+ parseTabular() {
8448
8567
  const result = [];
8449
- while (tokens.includes(this._tokens[this.index]))
8450
- result.push(this._tokens[this.index++]);
8568
+ let row = [];
8569
+ let expr = null;
8570
+ while (!this.atBoundary) {
8571
+ this.skipSpace();
8572
+ if (this.match("&")) {
8573
+ row.push(expr ?? "Nothing");
8574
+ expr = null;
8575
+ } else if (this.match("\\\\") || this.match("\\cr")) {
8576
+ this.skipSpace();
8577
+ this.parseOptionalGroup();
8578
+ if (expr !== null)
8579
+ row.push(expr);
8580
+ result.push(row);
8581
+ row = [];
8582
+ expr = null;
8583
+ } else {
8584
+ const cell = [];
8585
+ let peek = this.peek;
8586
+ while (peek !== "&" && peek !== "\\\\" && peek !== "\\cr" && !this.atBoundary) {
8587
+ expr = this.parseExpression({
8588
+ condition: (p) => {
8589
+ const peek2 = p.peek;
8590
+ return peek2 === "&" || peek2 === "\\\\" || peek2 === "\\cr";
8591
+ }
8592
+ });
8593
+ if (expr)
8594
+ cell.push(expr);
8595
+ else {
8596
+ cell.push(["Error", ["'unexpected-token'", peek]]);
8597
+ this.nextToken();
8598
+ }
8599
+ this.skipSpace();
8600
+ peek = this.peek;
8601
+ }
8602
+ if (cell.length > 1)
8603
+ expr = ["Sequence", ...cell];
8604
+ else
8605
+ expr = cell[0] ?? "Nothing";
8606
+ }
8607
+ }
8608
+ if (expr !== null)
8609
+ row.push(expr);
8610
+ if (row.length > 0)
8611
+ result.push(row);
8451
8612
  return result;
8452
8613
  }
8453
- matchOptionalSign() {
8614
+ /** Parse a group as a a string, for example for `\operatorname` or `\begin` */
8615
+ parseStringGroup() {
8616
+ const start = this.index;
8617
+ while (this.match("<space>")) {
8618
+ }
8619
+ if (this.match("<{>")) {
8620
+ this.addBoundary(["<}>"]);
8621
+ const arg = this.parseStringGroupContent();
8622
+ if (this.matchBoundary())
8623
+ return arg;
8624
+ this.removeBoundary();
8625
+ }
8626
+ this.index = start;
8627
+ return null;
8628
+ }
8629
+ /** Parse an environment: `\begin{env}...\end{end}`
8630
+ */
8631
+ parseEnvironment() {
8632
+ const index = this.index;
8633
+ if (!this.match("\\begin"))
8634
+ return null;
8635
+ const name = this.parseStringGroup()?.trim();
8636
+ if (!name)
8637
+ return this.error("expected-environment-name", index);
8638
+ this.addBoundary(["\\end", "<{>", ...name.split(""), "<}>"]);
8639
+ const def = this._dictionary.environment.get(name);
8640
+ if (!def) {
8641
+ this.parseTabular();
8642
+ this.skipSpace();
8643
+ if (!this.matchBoundary())
8644
+ return this.boundaryError("unbalanced-environment");
8645
+ return this.error(["unknown-environment", { str: name }], index);
8646
+ }
8647
+ const expr = def.parse(this, [], []);
8648
+ this.skipSpace();
8649
+ if (!this.matchBoundary())
8650
+ return this.boundaryError("unbalanced-environment");
8651
+ if (expr !== null)
8652
+ return this.decorate(expr, index);
8653
+ this.index = index;
8654
+ return null;
8655
+ }
8656
+ /** If the next token matches a `+` or `-` sign, return it and advance the index.
8657
+ * Otherwise return `''` and do not advance */
8658
+ parseOptionalSign() {
8454
8659
  let isNegative = !!this.matchAny(["-", "\u2212"]);
8455
8660
  while (this.matchAny(["+", "\uFE62"]) || this.skipSpace())
8456
8661
  if (this.matchAny(["-", "\u2212"]))
8457
8662
  isNegative = !isNegative;
8458
8663
  return isNegative ? "-" : "+";
8459
8664
  }
8460
- matchDecimalDigits(options) {
8665
+ parseDecimalDigits(options) {
8461
8666
  options ?? (options = {});
8462
8667
  options.withGrouping ?? (options.withGrouping = false);
8463
8668
  const result = [];
8464
8669
  let done = false;
8465
8670
  while (!done) {
8466
8671
  while (/^[0-9]$/.test(this.peek)) {
8467
- result.push(this.next());
8672
+ result.push(this.nextToken());
8468
8673
  this.skipVisualSpace();
8469
8674
  }
8470
8675
  done = true;
@@ -8482,21 +8687,21 @@ var ComputeEngine = (() => {
8482
8687
  }
8483
8688
  return result.join("");
8484
8689
  }
8485
- matchSignedInteger(options) {
8690
+ parseSignedInteger(options) {
8486
8691
  options ?? (options = {});
8487
8692
  options.withGrouping ?? (options.withGrouping = false);
8488
8693
  const start = this.index;
8489
- const sign2 = this.matchOptionalSign();
8490
- const result = this.matchDecimalDigits(options);
8694
+ const sign2 = this.parseOptionalSign();
8695
+ const result = this.parseDecimalDigits(options);
8491
8696
  if (result)
8492
8697
  return sign2 === "-" ? "-" + result : result;
8493
8698
  this.index = start;
8494
8699
  return "";
8495
8700
  }
8496
- matchExponent() {
8701
+ parseExponent() {
8497
8702
  const start = this.index;
8498
8703
  if (this.matchAny(["e", "E"])) {
8499
- const exponent = this.matchSignedInteger({ withGrouping: false });
8704
+ const exponent = this.parseSignedInteger({ withGrouping: false });
8500
8705
  if (exponent)
8501
8706
  return "e" + exponent;
8502
8707
  }
@@ -8505,10 +8710,10 @@ var ComputeEngine = (() => {
8505
8710
  this.skipSpaceTokens();
8506
8711
  if (this.match("1") && this.match("0") && this.match("^")) {
8507
8712
  if (/^[0-9]$/.test(this.peek))
8508
- return "e" + this.next();
8713
+ return "e" + this.nextToken();
8509
8714
  if (this.match("<{>")) {
8510
8715
  this.skipSpaceTokens();
8511
- const exponent = this.matchSignedInteger();
8716
+ const exponent = this.parseSignedInteger();
8512
8717
  this.skipSpaceTokens();
8513
8718
  if (this.match("<}>") && exponent)
8514
8719
  return "e" + exponent;
@@ -8524,7 +8729,7 @@ var ComputeEngine = (() => {
8524
8729
  this.skipSpaceTokens();
8525
8730
  if (this.matchAll(this._beginExponentMarkerTokens)) {
8526
8731
  this.skipSpaceTokens();
8527
- const exponent = this.matchSignedInteger();
8732
+ const exponent = this.parseSignedInteger();
8528
8733
  this.skipSpaceTokens();
8529
8734
  if (this.matchAll(this._endExponentMarkerTokens) && exponent)
8530
8735
  return "e" + exponent;
@@ -8533,11 +8738,11 @@ var ComputeEngine = (() => {
8533
8738
  this.index = start;
8534
8739
  return "";
8535
8740
  }
8536
- matchRepeatingDecimal() {
8741
+ parseRepeatingDecimal() {
8537
8742
  const start = this.index;
8538
8743
  let repeatingDecimals2 = "";
8539
8744
  if (this.match("(")) {
8540
- repeatingDecimals2 = this.matchDecimalDigits();
8745
+ repeatingDecimals2 = this.parseDecimalDigits();
8541
8746
  if (repeatingDecimals2 && this.match(")"))
8542
8747
  return "(" + repeatingDecimals2 + ")";
8543
8748
  this.index = start;
@@ -8545,7 +8750,7 @@ var ComputeEngine = (() => {
8545
8750
  }
8546
8751
  this.index = start;
8547
8752
  if (this.matchAll([`\\left`, "("])) {
8548
- repeatingDecimals2 = this.matchDecimalDigits();
8753
+ repeatingDecimals2 = this.parseDecimalDigits();
8549
8754
  if (repeatingDecimals2 && this.matchAll([`\\right`, ")"]))
8550
8755
  return "(" + repeatingDecimals2 + ")";
8551
8756
  this.index = start;
@@ -8553,7 +8758,7 @@ var ComputeEngine = (() => {
8553
8758
  }
8554
8759
  this.index = start;
8555
8760
  if (this.matchAll([`\\overline`, "<{>"])) {
8556
- repeatingDecimals2 = this.matchDecimalDigits();
8761
+ repeatingDecimals2 = this.parseDecimalDigits();
8557
8762
  if (repeatingDecimals2 && this.match("<}>"))
8558
8763
  return "(" + repeatingDecimals2 + ")";
8559
8764
  this.index = start;
@@ -8561,7 +8766,7 @@ var ComputeEngine = (() => {
8561
8766
  }
8562
8767
  this.index = start;
8563
8768
  if (this.matchAll(this._beginRepeatingDigitsTokens)) {
8564
- repeatingDecimals2 = this.matchDecimalDigits();
8769
+ repeatingDecimals2 = this.parseDecimalDigits();
8565
8770
  if (repeatingDecimals2 && this.matchAll(this._endRepeatingDigitsTokens))
8566
8771
  return "(" + repeatingDecimals2 + ")";
8567
8772
  this.index = start;
@@ -8570,9 +8775,13 @@ var ComputeEngine = (() => {
8570
8775
  this.index = start;
8571
8776
  return "";
8572
8777
  }
8573
- matchNumber() {
8778
+ /**
8779
+ * Parse a number, with an optional sign, exponent, decimal marker,
8780
+ * repeating decimals, etc...
8781
+ */
8782
+ parseNumber() {
8574
8783
  if (!this.options.parseNumbers)
8575
- return "";
8784
+ return null;
8576
8785
  const start = this.index;
8577
8786
  this.skipVisualSpace();
8578
8787
  this.match("+");
@@ -8582,32 +8791,32 @@ var ComputeEngine = (() => {
8582
8791
  const peek = this.peek;
8583
8792
  if (peek !== "\\overline" && peek !== this._beginRepeatingDigitsTokens[0] && !/[0-9\(]/.test(peek)) {
8584
8793
  this.index = start;
8585
- return "";
8794
+ return null;
8586
8795
  }
8587
8796
  dotPrefix = true;
8588
8797
  } else {
8589
- result = this.matchDecimalDigits({ withGrouping: true });
8798
+ result = this.parseDecimalDigits({ withGrouping: true });
8590
8799
  if (!result) {
8591
8800
  this.index = start;
8592
- return "";
8801
+ return null;
8593
8802
  }
8594
8803
  }
8595
8804
  let hasDecimal = true;
8596
8805
  if (!dotPrefix && (this.match(".") || this.matchAll(this._decimalMarkerTokens)))
8597
- result += "." + this.matchDecimalDigits({ withGrouping: true });
8806
+ result += "." + this.parseDecimalDigits({ withGrouping: true });
8598
8807
  else if (dotPrefix)
8599
- result = "0." + this.matchDecimalDigits({ withGrouping: true });
8808
+ result = "0." + this.parseDecimalDigits({ withGrouping: true });
8600
8809
  else
8601
8810
  hasDecimal = false;
8602
8811
  if (hasDecimal) {
8603
- const repeat = this.matchRepeatingDecimal();
8812
+ const repeat = this.parseRepeatingDecimal();
8604
8813
  if (repeat)
8605
8814
  result += repeat;
8606
8815
  else if (this.match("\\ldots") || this.matchAll(this._truncationMarkerTokens)) {
8607
8816
  }
8608
8817
  }
8609
8818
  this.skipVisualSpace();
8610
- return result + this.matchExponent();
8819
+ return result + this.parseExponent();
8611
8820
  }
8612
8821
  /**
8613
8822
  * A Latex number can be a decimal, hex or octal number.
@@ -8626,7 +8835,7 @@ var ComputeEngine = (() => {
8626
8835
  while (token === "<space>" || token === "+" || token === "-") {
8627
8836
  if (token === "-")
8628
8837
  negative = !negative;
8629
- this.next();
8838
+ this.nextToken();
8630
8839
  token = this.peek;
8631
8840
  }
8632
8841
  let radix = 10;
@@ -8657,7 +8866,7 @@ var ComputeEngine = (() => {
8657
8866
  ];
8658
8867
  isInteger = true;
8659
8868
  } else if (this.match("`")) {
8660
- token = this.next();
8869
+ token = this.nextToken();
8661
8870
  if (token) {
8662
8871
  if (token.startsWith("\\") && token.length === 2) {
8663
8872
  return (negative ? -1 : 1) * (token.codePointAt(1) ?? 0);
@@ -8668,12 +8877,12 @@ var ComputeEngine = (() => {
8668
8877
  }
8669
8878
  let value = "";
8670
8879
  while (digits.includes(this.peek)) {
8671
- value += this.next();
8880
+ value += this.nextToken();
8672
8881
  }
8673
8882
  if (!isInteger && this.match(".")) {
8674
8883
  value += ".";
8675
8884
  while (digits.includes(this.peek)) {
8676
- value += this.next();
8885
+ value += this.nextToken();
8677
8886
  }
8678
8887
  }
8679
8888
  const result = isInteger ? Number.parseInt(value, radix) : Number.parseFloat(value);
@@ -8681,7 +8890,7 @@ var ComputeEngine = (() => {
8681
8890
  return null;
8682
8891
  return negative ? -result : result;
8683
8892
  }
8684
- matchPrefixOperator(until) {
8893
+ parsePrefixOperator(until) {
8685
8894
  if (!until)
8686
8895
  until = { minPrec: 0 };
8687
8896
  if (!until.minPrec)
@@ -8699,7 +8908,7 @@ var ComputeEngine = (() => {
8699
8908
  this.index = start;
8700
8909
  return null;
8701
8910
  }
8702
- matchInfixOperator(lhs, until) {
8911
+ parseInfixOperator(lhs, until) {
8703
8912
  until ?? (until = { minPrec: 0 });
8704
8913
  if (until.minPrec === void 0)
8705
8914
  until = { ...until, minPrec: 0 };
@@ -8710,7 +8919,7 @@ var ComputeEngine = (() => {
8710
8919
  for (const [def, n] of defs) {
8711
8920
  if (def.precedence >= until.minPrec) {
8712
8921
  this.index = start + n;
8713
- const rhs = def.parse(this, until, lhs);
8922
+ const rhs = def.parse(this, lhs, until);
8714
8923
  if (rhs)
8715
8924
  return rhs;
8716
8925
  }
@@ -8719,99 +8928,74 @@ var ComputeEngine = (() => {
8719
8928
  return null;
8720
8929
  }
8721
8930
  /**
8722
- * - 'enclosure' : will look for an argument inside an enclosure (open/close fence)
8931
+ * This returns an array of arguments (as in a function application),
8932
+ * or null if there is no match.
8933
+ *
8934
+ * - 'enclosure' : will look for an argument inside an enclosure
8935
+ * (open/close fence)
8723
8936
  * - 'implicit': either an expression inside a pair of `()`, or just a product
8724
8937
  * (i.e. we interpret `\cos 2x + 1` as `\cos(2x) + 1`)
8938
+ *
8725
8939
  */
8726
- matchArguments(kind, until) {
8727
- if (!kind)
8728
- return null;
8940
+ parseArguments(kind = "enclosure", until) {
8729
8941
  if (this.atTerminator(until))
8730
8942
  return null;
8731
- const savedIndex = this.index;
8732
- const group = this.matchEnclosure();
8733
- if (kind === "enclosure" && head(group) === "Delimiter") {
8734
- if (op(group, 1) === "Sequence")
8735
- return ops(op(group, 1)) ?? [];
8736
- return [op(group, 1) ?? ["Sequence"]];
8737
- }
8738
- if (kind === "implicit") {
8739
- if (head(group) === "Delimiter") {
8740
- if (head(op(group, 1)) === "Sequence")
8741
- return getSequence(group) ?? [];
8742
- return [op(group, 1) ?? ["Sequence"]];
8743
- }
8744
- if (group !== null)
8745
- return [group];
8746
- const primary = this.matchExpression({ ...until, minPrec: 390 });
8747
- if (primary !== null)
8748
- return [primary];
8749
- return null;
8750
- }
8751
- this.index = savedIndex;
8752
- return null;
8753
- }
8754
- /**
8755
- * A function can be followed by the following suffixes:
8756
- * - a `\prime`, `\doubleprime`, `'`, `(n)` to indicate a derivative
8757
- * - a subscript to indicate an argument
8758
- * - an argument, optionally inside an enclosure
8759
- */
8760
- matchFunctionSuffix(id) {
8761
- let fn = id;
8762
- do {
8763
- const pf = this.matchPostfix(fn);
8764
- if (pf === null)
8765
- break;
8766
- fn = pf;
8767
- } while (true);
8768
- const seq = this.matchArguments("enclosure");
8769
- return seq ? [fn, ...seq] : id;
8770
- }
8771
- /** A prime suffix is a sequence of `'`, `\prime` or `\doubleprime`
8772
- * after a function or in a superscript.
8773
- */
8774
- matchPrimeSuffix() {
8775
- this.skipSpace();
8776
- const start = this.index;
8777
- let count = 0;
8778
- if (this.match("^")) {
8779
- if (this.match("<{>")) {
8780
- if (this.match("(")) {
8781
- const n = this.matchNumber();
8782
- if (n && this.match(")"))
8783
- return parseInt(n);
8784
- this.index = start;
8785
- return 0;
8786
- }
8787
- do {
8788
- const c = countPrimeLevel(this);
8789
- if (c === 0)
8790
- break;
8791
- count += c;
8792
- } while (true);
8793
- if (count !== 0 && this.match("<}>"))
8794
- return count;
8795
- this.index = start;
8796
- return 0;
8797
- }
8798
- count = countPrimeLevel(this);
8799
- if (count !== 0)
8800
- return count;
8801
- this.index = start;
8802
- return 0;
8943
+ const savedIndex = this.index;
8944
+ const group = this.parseEnclosure();
8945
+ if (kind === "enclosure") {
8946
+ if (group === null)
8947
+ return null;
8948
+ return getSequence(group) ?? [];
8803
8949
  }
8804
- do {
8805
- const c = countPrimeLevel(this);
8806
- if (c === 0)
8807
- break;
8808
- count += c;
8809
- } while (true);
8810
- if (count !== 0)
8811
- return count;
8812
- this.index = start;
8813
- return 0;
8950
+ if (kind === "implicit") {
8951
+ if (head(group) === "Delimiter")
8952
+ return getSequence(group) ?? [];
8953
+ if (group !== null)
8954
+ return [group];
8955
+ const primary = this.parseExpression({ ...until, minPrec: 390 });
8956
+ return primary === null ? null : [primary];
8957
+ }
8958
+ this.index = savedIndex;
8959
+ return null;
8814
8960
  }
8961
+ /** A prime suffix is a sequence of `'`, `\prime` or `\doubleprime`
8962
+ * after a function or in a superscript.
8963
+ */
8964
+ // matchPrimeSuffix(): number {
8965
+ // this.skipSpace();
8966
+ // const start = this.index;
8967
+ // let count = 0;
8968
+ // if (this.match('^')) {
8969
+ // if (this.match('<{>')) {
8970
+ // if (this.match('(')) {
8971
+ // const n = this.parseNumber();
8972
+ // if (n && this.match(')')) return parseInt(n);
8973
+ // this.index = start;
8974
+ // return 0;
8975
+ // }
8976
+ // do {
8977
+ // const c = countPrimeLevel(this);
8978
+ // if (c === 0) break;
8979
+ // count += c;
8980
+ // } while (true);
8981
+ // if (count !== 0 && this.match('<}>')) return count;
8982
+ // this.index = start;
8983
+ // return 0;
8984
+ // }
8985
+ // count = countPrimeLevel(this);
8986
+ // if (count !== 0) return count;
8987
+ // this.index = start;
8988
+ // return 0;
8989
+ // }
8990
+ // do {
8991
+ // const c = countPrimeLevel(this);
8992
+ // if (c === 0) break;
8993
+ // count += c;
8994
+ // } while (true);
8995
+ // if (count !== 0) return count;
8996
+ // this.index = start;
8997
+ // return 0;
8998
+ // }
8815
8999
  /** If matches the normalized open delimiter, return the
8816
9000
  * expected closing delimiter.
8817
9001
  *
@@ -8824,7 +9008,7 @@ var ComputeEngine = (() => {
8824
9008
  const index = this.index;
8825
9009
  const closePrefix = OPEN_DELIMITER_PREFIX[this.peek];
8826
9010
  if (closePrefix)
8827
- this.next();
9011
+ this.nextToken();
8828
9012
  const alternatives = DELIMITER_SHORTHAND[openDelim] ?? [openDelim];
8829
9013
  const result = closePrefix ? [closePrefix] : [];
8830
9014
  if (alternatives.includes("||") && this.matchAll(["|", "|"])) {
@@ -8841,28 +9025,30 @@ var ComputeEngine = (() => {
8841
9025
  } else {
8842
9026
  result.push(closeDelim);
8843
9027
  }
8844
- this.next();
9028
+ this.nextToken();
8845
9029
  return result;
8846
9030
  }
8847
- matchMiddleDelimiter(delimiter) {
8848
- const delimiters = MIDDLE_DELIMITER[delimiter] ?? [delimiter];
8849
- if (MIDDLE_DELIMITER_PREFIX.includes(this.peek)) {
8850
- const index = this.index;
8851
- this.next();
8852
- if (delimiters.includes(this.peek)) {
8853
- this.next();
8854
- return true;
8855
- }
8856
- this.index = index;
8857
- return false;
8858
- } else if (delimiters.include(this.peek)) {
8859
- this.next();
8860
- return true;
8861
- }
8862
- return false;
8863
- }
9031
+ // matchMiddleDelimiter(delimiter: '|' | ':' | LatexToken): boolean {
9032
+ // const delimiters = MIDDLE_DELIMITER[delimiter] ?? [delimiter];
9033
+ // if (MIDDLE_DELIMITER_PREFIX.includes(this.peek)) {
9034
+ // const index = this.index;
9035
+ // this.nextToken();
9036
+ // if (delimiters.includes(this.peek)) {
9037
+ // this.nextToken();
9038
+ // return true;
9039
+ // }
9040
+ // this.index = index;
9041
+ // return false;
9042
+ // } else if (delimiters.include(this.peek)) {
9043
+ // this.nextToken();
9044
+ // return true;
9045
+ // }
9046
+ // return false;
9047
+ // }
8864
9048
  /** For error handling, when there is potentially a mismatched delimiter.
8865
9049
  * Return a LaTeX fragment of the expected closing delimiter
9050
+ *
9051
+ * @internal
8866
9052
  */
8867
9053
  matchEnclosureOpen() {
8868
9054
  const defs = this._dictionary.matchfix;
@@ -8886,6 +9072,9 @@ var ComputeEngine = (() => {
8886
9072
  this.index = start;
8887
9073
  return null;
8888
9074
  }
9075
+ /**
9076
+ * Used for error handling
9077
+ * @internal */
8889
9078
  matchEnclosureClose() {
8890
9079
  const defs = this._dictionary.matchfix;
8891
9080
  if (defs.length === 0)
@@ -8904,7 +9093,7 @@ var ComputeEngine = (() => {
8904
9093
  (x) => OPEN_DELIMITER_PREFIX[x] === peek
8905
9094
  );
8906
9095
  if (prefix)
8907
- this.next();
9096
+ this.nextToken();
8908
9097
  let openDelimiter = [];
8909
9098
  peek = this.peek;
8910
9099
  const matchingDelim = Object.keys(CLOSE_DELIMITER).find(
@@ -8915,7 +9104,7 @@ var ComputeEngine = (() => {
8915
9104
  if (prefix)
8916
9105
  openDelimiter = [prefix, ...openDelimiter];
8917
9106
  if (openDelimiter.length > 0) {
8918
- this.next();
9107
+ this.nextToken();
8919
9108
  return tokensToString(openDelimiter);
8920
9109
  }
8921
9110
  }
@@ -8927,7 +9116,7 @@ var ComputeEngine = (() => {
8927
9116
  * optionally followed multiple times by a separator and another expression,
8928
9117
  * and finally a closing matching operator.
8929
9118
  */
8930
- matchEnclosure() {
9119
+ parseEnclosure() {
8931
9120
  const defs = this._dictionary.matchfix;
8932
9121
  if (defs.length === 0)
8933
9122
  return null;
@@ -8938,7 +9127,7 @@ var ComputeEngine = (() => {
8938
9127
  if (!this.matchAll(def.openDelimiter))
8939
9128
  continue;
8940
9129
  this.addBoundary(def.closeDelimiter);
8941
- const body2 = this.matchExpression();
9130
+ const body2 = this.parseExpression();
8942
9131
  this.skipSpace();
8943
9132
  if (!this.matchBoundary()) {
8944
9133
  this.removeBoundary();
@@ -8963,12 +9152,12 @@ var ComputeEngine = (() => {
8963
9152
  }
8964
9153
  this.addBoundary(closeDelimiter);
8965
9154
  const bodyStart = this.index;
8966
- let body = this.matchExpression();
9155
+ let body = this.parseExpression();
8967
9156
  this.skipSpace();
8968
9157
  if (!this.matchBoundary()) {
8969
9158
  this.removeBoundary();
8970
9159
  this.index = bodyStart;
8971
- body = this.matchExpression();
9160
+ body = this.parseExpression();
8972
9161
  if (!this.matchAll(closeDelimiter)) {
8973
9162
  if (!this.atEnd)
8974
9163
  continue;
@@ -8983,52 +9172,74 @@ var ComputeEngine = (() => {
8983
9172
  this.index = start;
8984
9173
  return null;
8985
9174
  }
8986
- matchIdentifier() {
8987
- return matchIdentifier(this);
8988
- }
8989
9175
  /**
8990
- * A function is an identifier followed by arguments
8991
- * - a single letter identifier with explicit arguments `f(x)`
8992
- * - a multiletter identifier with explicit arguments `\mathrm{floor}(x)`
8993
- * - an identifier: `\mathrm{floor}`
8994
- * - a command with implicit arguments: `\cos x` (via a custom parser)
8995
- *
9176
+ * A generic expression is used for dictionary entries that take do
9177
+ * some complex (non-standard) parsing. This includes trig functions (to
9178
+ * parse implicit arguments), and integrals (to parse the integrand and
9179
+ * limits and the "dx" terminator).
8996
9180
  */
8997
- matchFunction(until) {
9181
+ parseGenericExpression(until) {
8998
9182
  if (this.atTerminator(until))
8999
9183
  return null;
9000
9184
  const start = this.index;
9001
- const fnDefs = this.peekDefinitions("function");
9002
- if (fnDefs) {
9003
- for (const [def, tokenCount] of fnDefs) {
9004
- this.index = start + tokenCount;
9005
- if (typeof def.parse === "function") {
9006
- const result = def.parse(this, until);
9007
- if (result)
9008
- return result;
9009
- } else {
9010
- return this.matchFunctionSuffix(def.name);
9011
- }
9185
+ let expr = null;
9186
+ const fnDefs = this.peekDefinitions("expression") ?? [];
9187
+ for (const [def, tokenCount] of fnDefs) {
9188
+ this.index = start + tokenCount;
9189
+ if (typeof def.parse === "function") {
9190
+ expr = def.parse(this, until);
9191
+ if (expr !== null)
9192
+ return expr;
9193
+ } else {
9194
+ return def.name;
9012
9195
  }
9013
9196
  }
9014
9197
  this.index = start;
9015
- const fn = this.matchIdentifier();
9016
- if (fn === null)
9198
+ return null;
9199
+ }
9200
+ /**
9201
+ * A function is an identifier followed by postfix operators
9202
+ * (`\prime`...) and some arguments.
9203
+ */
9204
+ parseFunction(until) {
9205
+ if (this.atTerminator(until))
9017
9206
  return null;
9018
- if (this.options.parseUnknownIdentifier?.(fn, this) !== "function") {
9207
+ const start = this.index;
9208
+ let fn = null;
9209
+ const fnDefs = this.peekDefinitions("function") ?? [];
9210
+ for (const [def, tokenCount] of fnDefs) {
9211
+ this.index = start + tokenCount;
9212
+ if (typeof def.parse === "function") {
9213
+ fn = def.parse(this, until);
9214
+ if (fn !== null)
9215
+ break;
9216
+ } else {
9217
+ fn = def.name;
9218
+ break;
9219
+ }
9220
+ }
9221
+ if (fn === null) {
9019
9222
  this.index = start;
9020
- return null;
9223
+ fn = matchIdentifier(this);
9224
+ if (!this.isFunctionHead(fn)) {
9225
+ this.index = start;
9226
+ return null;
9227
+ }
9021
9228
  }
9022
- return this.matchFunctionSuffix(fn);
9229
+ do {
9230
+ const pf = this.parsePostfixOperator(fn);
9231
+ if (pf === null)
9232
+ break;
9233
+ fn = pf;
9234
+ } while (true);
9235
+ const seq = this.isFunctionHead(fn) ? this.parseArguments() : null;
9236
+ return seq ? [fn, ...seq] : fn;
9023
9237
  }
9024
- /**
9025
- * A symbol is an identifier or a custom definition
9026
- */
9027
- matchSymbol(until) {
9238
+ parseSymbol(until) {
9028
9239
  if (this.atTerminator(until))
9029
9240
  return null;
9030
9241
  const start = this.index;
9031
- const defs = this.peekDefinitions("identifier");
9242
+ const defs = this.peekDefinitions("symbol");
9032
9243
  if (defs) {
9033
9244
  for (const [def, tokenCount] of defs) {
9034
9245
  this.index = start + tokenCount;
@@ -9041,7 +9252,7 @@ var ComputeEngine = (() => {
9041
9252
  }
9042
9253
  }
9043
9254
  this.index = start;
9044
- const id = this.matchIdentifier();
9255
+ const id = matchIdentifier(this);
9045
9256
  if (id === null)
9046
9257
  return null;
9047
9258
  if (this.options.parseUnknownIdentifier?.(id, this) === "symbol")
@@ -9049,57 +9260,19 @@ var ComputeEngine = (() => {
9049
9260
  this.index = start;
9050
9261
  return null;
9051
9262
  }
9052
- matchLatexOptionalGroup() {
9053
- const index = this.index;
9054
- this.skipSpaceTokens();
9055
- if (this.match("[")) {
9056
- this.addBoundary(["]"]);
9057
- const expr = this.matchExpression();
9058
- this.skipSpace();
9059
- if (this.matchBoundary())
9060
- return expr;
9061
- return this.boundaryError("expected-closing-delimiter");
9062
- }
9063
- this.index = index;
9064
- return null;
9065
- }
9066
- // Some LaTeX commands (but not all) can accept an argument without braces,
9067
- // for example `^` , `\sqrt` or `\frac`.
9068
- matchSingleAtomArgument() {
9069
- const excluding = [...'!"#$%&(),/;:?@[]`|~'.split(""), "\\left", "\\bigl"];
9070
- if (excluding.includes(this.peek))
9071
- return null;
9072
- if (/^[0-9]$/.test(this.peek))
9073
- return parseInt(this.next());
9074
- if (/^[^\\#]$/.test(this.peek) && isValidIdentifier(this.peek))
9075
- return this.next();
9076
- const sym = this.matchSymbol();
9077
- if (sym)
9078
- return sym;
9079
- return null;
9080
- }
9081
- matchLatexGroup() {
9082
- const start = this.index;
9083
- this.skipSpaceTokens();
9084
- if (this.match("<{>")) {
9085
- this.addBoundary(["<}>"]);
9086
- const expr = this.matchExpression();
9087
- this.skipSpace();
9088
- if (this.matchBoundary())
9089
- return expr ?? ["Sequence"];
9090
- const from = this.index;
9091
- while (!this.matchBoundary() && !this.atEnd)
9092
- this.next();
9093
- const err = this.error("syntax-error", from);
9094
- return expr ? ["Sequence", expr, err] : err;
9095
- }
9096
- this.index = start;
9097
- return null;
9098
- }
9099
- matchSupsub(lhs) {
9263
+ /**
9264
+ * Parse a sequence superfix/subfix operator, e.g. `^{*}`
9265
+ *
9266
+ * Superfix and subfix need special handling:
9267
+ *
9268
+ * - they act mostly like an infix operator, but they are commutative, i.e.
9269
+ * `x_a^b` should be parsed identically to `x^b_a`.
9270
+ *
9271
+ * - furthermore, in LaTeX `x^a^b` parses the same as `x^a{}^b`.
9272
+ *
9273
+ */
9274
+ parseSupsub(lhs) {
9100
9275
  console.assert(lhs !== null);
9101
- if (lhs === null)
9102
- return null;
9103
9276
  const index = this.index;
9104
9277
  this.skipSpace();
9105
9278
  const superscripts = [];
@@ -9111,7 +9284,7 @@ var ComputeEngine = (() => {
9111
9284
  if (this.match("_") || this.match("^"))
9112
9285
  subscripts.push(this.error("syntax-error", subIndex));
9113
9286
  else {
9114
- const sub2 = this.matchLatexGroup() ?? this.matchSingleAtomArgument() ?? this.matchStringArgument();
9287
+ const sub2 = this.parseGroup() ?? this.parseToken() ?? this.parseStringGroup();
9115
9288
  if (sub2 === null)
9116
9289
  return this.error("missing", index);
9117
9290
  subscripts.push(sub2);
@@ -9121,7 +9294,7 @@ var ComputeEngine = (() => {
9121
9294
  if (this.match("_") || this.match("^"))
9122
9295
  superscripts.push(this.error("syntax-error", subIndex));
9123
9296
  else {
9124
- const sup = this.matchLatexGroup() ?? this.matchSingleAtomArgument();
9297
+ const sup = this.parseGroup() ?? this.parseToken();
9125
9298
  if (sup === null)
9126
9299
  return this.error("missing", index);
9127
9300
  superscripts.push(sup);
@@ -9145,7 +9318,7 @@ var ComputeEngine = (() => {
9145
9318
  ];
9146
9319
  for (const def of defs) {
9147
9320
  if (typeof def.parse === "function")
9148
- result = def.parse(this, { minPrec: 0 }, arg);
9321
+ result = def.parse(this, arg, { minPrec: 0 });
9149
9322
  else
9150
9323
  result = arg;
9151
9324
  if (result)
@@ -9163,7 +9336,7 @@ var ComputeEngine = (() => {
9163
9336
  ];
9164
9337
  for (const def of defs) {
9165
9338
  if (typeof def.parse === "function")
9166
- result = def.parse(this, { minPrec: 0 }, arg);
9339
+ result = def.parse(this, arg, { minPrec: 0 });
9167
9340
  else
9168
9341
  result = arg;
9169
9342
  if (result)
@@ -9175,7 +9348,7 @@ var ComputeEngine = (() => {
9175
9348
  this.index = index;
9176
9349
  return result;
9177
9350
  }
9178
- matchPostfix(lhs) {
9351
+ parsePostfixOperator(lhs, until) {
9179
9352
  console.assert(lhs !== null);
9180
9353
  if (lhs === null)
9181
9354
  return null;
@@ -9185,7 +9358,7 @@ var ComputeEngine = (() => {
9185
9358
  const start = this.index;
9186
9359
  for (const [def, n] of defs) {
9187
9360
  this.index = start + n;
9188
- const result = def.parse(this, lhs);
9361
+ const result = def.parse(this, lhs, until);
9189
9362
  if (result !== null)
9190
9363
  return result;
9191
9364
  }
@@ -9197,119 +9370,32 @@ var ComputeEngine = (() => {
9197
9370
  * Not suitable for general purpose text, e.g. argument of a `\text{}
9198
9371
  * command. See `matchChar()` instead.
9199
9372
  */
9200
- matchString() {
9373
+ parseStringGroupContent() {
9374
+ const start = this.index;
9201
9375
  let result = "";
9202
- while (!this.atBoundary) {
9203
- const token = this.peek;
9376
+ let level = 0;
9377
+ while (!this.atBoundary || level > 0) {
9378
+ const token = this.nextToken();
9204
9379
  if (token === "<$>" || token === "<$$>") {
9380
+ this.index = start;
9205
9381
  return "";
9382
+ }
9383
+ if (token === "<{>") {
9384
+ level += 1;
9385
+ result += "\\{";
9386
+ } else if (token === "<}>") {
9387
+ level -= 1;
9388
+ result += "\\}";
9206
9389
  } else if (token === "<space>") {
9207
- this.next();
9208
9390
  result += " ";
9209
9391
  } else if (token[0] === "\\") {
9210
- result += this.next();
9211
- } else {
9212
- result += this.next();
9213
- }
9214
- }
9215
- return result;
9216
- }
9217
- /** Match a string as an argument (in a `{}` pair) */
9218
- matchStringArgument() {
9219
- const start = this.index;
9220
- this.skipSpaceTokens();
9221
- if (this.match("<{>")) {
9222
- this.addBoundary(["<}>"]);
9223
- while (this.match("<space>")) {
9224
- }
9225
- const arg = this.matchString();
9226
- if (this.matchBoundary())
9227
- return arg.trimEnd();
9228
- this.removeBoundary();
9229
- }
9230
- this.index = start;
9231
- return null;
9232
- }
9233
- /**
9234
- * Match an expression in a tabular format, where rows are separated by `\\`
9235
- * and columns by `&`.
9236
- *
9237
- * Return rows of sparse columns: empty rows are indicated with `Nothing`,
9238
- * and empty cells are also indicated with `Nothing`.
9239
- */
9240
- matchTabular() {
9241
- const result = [];
9242
- let row = [];
9243
- let expr = null;
9244
- while (!this.atBoundary) {
9245
- this.skipSpace();
9246
- if (this.match("&")) {
9247
- row.push(expr ?? "Nothing");
9248
- expr = null;
9249
- } else if (this.match("\\\\") || this.match("\\cr")) {
9250
- this.skipSpace();
9251
- this.matchLatexOptionalGroup();
9252
- if (expr !== null)
9253
- row.push(expr);
9254
- result.push(row);
9255
- row = [];
9256
- expr = null;
9392
+ result += token;
9257
9393
  } else {
9258
- const cell = [];
9259
- let peek = this.peek;
9260
- while (peek !== "&" && peek !== "\\\\" && peek !== "\\cr" && !this.atBoundary) {
9261
- expr = this.matchExpression({
9262
- condition: (p) => {
9263
- const peek2 = p.peek;
9264
- return peek2 === "&" || peek2 === "\\\\" || peek2 === "\\cr";
9265
- }
9266
- });
9267
- if (expr)
9268
- cell.push(expr);
9269
- else {
9270
- cell.push(["Error", ["'unexpected-token'", peek]]);
9271
- this.next();
9272
- }
9273
- this.skipSpace();
9274
- peek = this.peek;
9275
- }
9276
- if (cell.length > 1)
9277
- expr = ["Sequence", ...cell];
9278
- else
9279
- expr = cell[0] ?? "Nothing";
9394
+ result += token;
9280
9395
  }
9281
9396
  }
9282
- if (expr !== null)
9283
- row.push(expr);
9284
- if (row.length > 0)
9285
- result.push(row);
9286
9397
  return result;
9287
9398
  }
9288
- matchEnvironment() {
9289
- const index = this.index;
9290
- if (!this.match("\\begin"))
9291
- return null;
9292
- const name = this.matchStringArgument();
9293
- if (name === null)
9294
- return this.error("expected-environment-name", index);
9295
- this.addBoundary(["\\end", "<{>", ...name.split(""), "<}>"]);
9296
- const def = this._dictionary.environment.get(name);
9297
- if (!def) {
9298
- this.matchTabular();
9299
- this.skipSpace();
9300
- if (!this.matchBoundary())
9301
- return this.boundaryError("unbalanced-environment");
9302
- return this.error(["unknown-environment", { str: name }], index);
9303
- }
9304
- const expr = def.parse(this, [], []);
9305
- this.skipSpace();
9306
- if (!this.matchBoundary())
9307
- return this.boundaryError("unbalanced-environment");
9308
- if (expr !== null)
9309
- return this.decorate(expr, index);
9310
- this.index = index;
9311
- return null;
9312
- }
9313
9399
  /**
9314
9400
  * Apply an invisible operator between two expressions.
9315
9401
  *
@@ -9332,12 +9418,18 @@ var ComputeEngine = (() => {
9332
9418
  * => lhs is a number, rhs is a number, but not a literal
9333
9419
  */
9334
9420
  applyInvisibleOperator(until, lhs) {
9335
- if (lhs === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until) || this.options.applyInvisibleOperator === null)
9421
+ if (lhs === null || this.options.applyInvisibleOperator === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until))
9336
9422
  return null;
9423
+ if (this.isFunctionHead(lhs)) {
9424
+ const args = this.parseArguments("enclosure", until);
9425
+ if (args === null)
9426
+ return null;
9427
+ return [lhs, ...args];
9428
+ }
9337
9429
  if (this.peekDefinitions("operator") !== null)
9338
9430
  return null;
9339
9431
  const start = this.index;
9340
- const rhs = this.matchExpression({ ...until, minPrec: 390 });
9432
+ const rhs = this.parseExpression({ ...until, minPrec: 390 });
9341
9433
  if (rhs === null || symbol(rhs) === "Nothing" || isEmptySequence(rhs)) {
9342
9434
  this.index = start;
9343
9435
  return null;
@@ -9346,13 +9438,9 @@ var ComputeEngine = (() => {
9346
9438
  return applyAssociativeOperator("Sequence", lhs, rhs);
9347
9439
  if (typeof this.options.applyInvisibleOperator === "function")
9348
9440
  return this.options.applyInvisibleOperator(this, lhs, rhs);
9349
- const lhsSymbol = symbol(lhs);
9350
- if (lhsSymbol) {
9351
- const isFunction = this.options.parseUnknownIdentifier(lhsSymbol, this) === "function";
9352
- if (isFunction) {
9353
- const seq = getSequence(rhs);
9354
- return seq ? [lhs, ...seq] : lhsSymbol;
9355
- }
9441
+ if (this.isFunctionHead(lhs)) {
9442
+ const seq = getSequence(rhs);
9443
+ return seq ? [lhs, ...seq] : lhs;
9356
9444
  }
9357
9445
  const lhsNumber = machineValue(lhs);
9358
9446
  if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
@@ -9365,7 +9453,7 @@ var ComputeEngine = (() => {
9365
9453
  }
9366
9454
  if (head(rhs) === "Delimiter") {
9367
9455
  if (head(op(rhs, 1)) === "Sequence")
9368
- return [lhsSymbol ?? lhs, ...ops(op(rhs, 1)) ?? []];
9456
+ return [lhs, ...ops(op(rhs, 1)) ?? []];
9369
9457
  if (!op(rhs, 1) || symbol(op(rhs, 1)) === "Nothing")
9370
9458
  return applyAssociativeOperator(
9371
9459
  "Sequence",
@@ -9377,7 +9465,13 @@ var ComputeEngine = (() => {
9377
9465
  return applyAssociativeOperator("Sequence", lhs, rhs);
9378
9466
  return applyAssociativeOperator("Multiply", lhs, rhs);
9379
9467
  }
9380
- matchUnexpectedLatexCommand() {
9468
+ /**
9469
+ * This is an error handling method. We've encountered a LaTeX command
9470
+ * but were not able to match it to any entry in the LaTeX dictionary,
9471
+ * or ran into it in an unexpected context (postfix operator lacking an
9472
+ * argument, for example)
9473
+ */
9474
+ parseUnexpectedLatexCommand() {
9381
9475
  const start = this.index;
9382
9476
  let opDefs = this.peekDefinitions("operator");
9383
9477
  if (opDefs) {
@@ -9406,7 +9500,7 @@ var ComputeEngine = (() => {
9406
9500
  if (def.name)
9407
9501
  return [
9408
9502
  def.name,
9409
- this.matchExpression() ?? this.error("missing", start)
9503
+ this.parseExpression() ?? this.error("missing", start)
9410
9504
  ];
9411
9505
  return this.error("unexpected-operator", start);
9412
9506
  }
@@ -9415,11 +9509,9 @@ var ComputeEngine = (() => {
9415
9509
  const [def, n] = opDefs[0];
9416
9510
  this.index += n;
9417
9511
  if (typeof def.parse === "function") {
9418
- const result = def.parse(
9419
- this,
9420
- { minPrec: 0 },
9421
- this.error("missing", start)
9422
- );
9512
+ const result = def.parse(this, this.error("missing", start), {
9513
+ minPrec: 0
9514
+ });
9423
9515
  if (result)
9424
9516
  return result;
9425
9517
  }
@@ -9427,7 +9519,7 @@ var ComputeEngine = (() => {
9427
9519
  return [
9428
9520
  def.name,
9429
9521
  this.error("missing", start),
9430
- this.matchExpression() ?? this.error("missing", start)
9522
+ this.parseExpression() ?? this.error("missing", start)
9431
9523
  ];
9432
9524
  return this.error("unexpected-operator", start);
9433
9525
  }
@@ -9435,10 +9527,10 @@ var ComputeEngine = (() => {
9435
9527
  const command = this.peek;
9436
9528
  if (!command || command[0] !== "\\")
9437
9529
  return null;
9438
- this.next();
9530
+ this.nextToken();
9439
9531
  this.skipSpaceTokens();
9440
9532
  if (command === "\\end") {
9441
- const name = this.matchStringArgument();
9533
+ const name = this.parseStringGroup();
9442
9534
  if (name === null)
9443
9535
  return this.error("expected-environment-name", start);
9444
9536
  return this.error(["unbalanced-environment", { str: name }], start);
@@ -9450,7 +9542,7 @@ var ComputeEngine = (() => {
9450
9542
  level += 1;
9451
9543
  if (this.peek === "]")
9452
9544
  level -= 1;
9453
- this.next();
9545
+ this.nextToken();
9454
9546
  }
9455
9547
  this.match("]");
9456
9548
  }
@@ -9476,7 +9568,7 @@ var ComputeEngine = (() => {
9476
9568
  level += 1;
9477
9569
  if (this.peek === "<}>")
9478
9570
  level -= 1;
9479
- this.next();
9571
+ this.nextToken();
9480
9572
  }
9481
9573
  this.match("<}>");
9482
9574
  }
@@ -9484,15 +9576,20 @@ var ComputeEngine = (() => {
9484
9576
  }
9485
9577
  /**
9486
9578
  * <primary> :=
9487
- * (<number> | <symbol> | <environment> | <matchfix-expr>) <subsup>* <postfix-operator>*
9579
+ * (<number> | <symbol> | <environment> | <matchfix-expr>)
9580
+ * <subsup>* <postfix-operator>*
9488
9581
  *
9489
- * <symbol> ::= (<symbol-id> | (<latex-command><latex-arguments>)) <arguments>
9582
+ * <symbol> ::=
9583
+ * (<symbol-id> | (<latex-command><latex-arguments>)) <arguments>
9490
9584
  *
9491
9585
  * <matchfix-expr> :=
9492
- * <matchfix-op-open> <expression> [<matchfix-op-separator> <expression>] <matchfix-op-close>
9586
+ * <matchfix-op-open>
9587
+ * <expression>
9588
+ * (<matchfix-op-separator> <expression>)*
9589
+ * <matchfix-op-close>
9493
9590
  *
9494
9591
  */
9495
- matchPrimary(until) {
9592
+ parsePrimary(until) {
9496
9593
  if (this.atBoundary)
9497
9594
  return null;
9498
9595
  if (this.atTerminator(until))
@@ -9502,7 +9599,7 @@ var ComputeEngine = (() => {
9502
9599
  if (this.match("<}>"))
9503
9600
  return this.error("unexpected-closing-delimiter", start);
9504
9601
  if (this.match("<{>")) {
9505
- result = this.matchExpression({ condition: (p) => p.peek === "<}>" });
9602
+ result = this.parseExpression({ condition: (p) => p.peek === "<}>" });
9506
9603
  if (result === null)
9507
9604
  return this.error("expected-expression", start);
9508
9605
  if (!this.match("<}>")) {
@@ -9513,25 +9610,25 @@ var ComputeEngine = (() => {
9513
9610
  }
9514
9611
  }
9515
9612
  if (result === null) {
9516
- const num = this.matchNumber();
9517
- if (num)
9613
+ const num = this.parseNumber();
9614
+ if (num !== null)
9518
9615
  result = { num };
9519
9616
  }
9520
- result ?? (result = this.matchEnclosure());
9521
- result ?? (result = this.matchEnvironment());
9617
+ result ?? (result = this.parseEnclosure());
9618
+ result ?? (result = this.parseEnvironment());
9522
9619
  if (result === null && this.matchAll(this._positiveInfinityTokens))
9523
9620
  result = { num: "+Infinity" };
9524
9621
  if (result === null && this.matchAll(this._negativeInfinityTokens))
9525
9622
  result = { num: "-Infinity" };
9526
9623
  if (result === null && this.matchAll(this._notANumberTokens))
9527
9624
  result = { num: "NaN" };
9528
- result ?? (result = this.matchFunction(until) ?? this.matchSymbol(until) ?? matchInvalidIdentifier(this));
9625
+ result ?? (result = this.parseGenericExpression(until) ?? this.parseFunction(until) ?? this.parseSymbol(until) ?? parseInvalidIdentifier(this));
9529
9626
  if (result !== null) {
9530
9627
  result = this.decorate(result, start);
9531
9628
  let postfix = null;
9532
9629
  let index = this.index;
9533
9630
  do {
9534
- postfix = this.matchPostfix(result);
9631
+ postfix = this.parsePostfixOperator(result, until);
9535
9632
  result = postfix ?? result;
9536
9633
  if (this.index === index && postfix !== null) {
9537
9634
  console.assert(this.index !== index, "No token consumed");
@@ -9540,9 +9637,8 @@ var ComputeEngine = (() => {
9540
9637
  index = this.index;
9541
9638
  } while (postfix !== null);
9542
9639
  }
9543
- result ?? (result = this.matchUnexpectedLatexCommand());
9544
9640
  if (result !== null)
9545
- result = this.matchSupsub(result);
9641
+ result = this.parseSupsub(result);
9546
9642
  return this.decorate(result, start);
9547
9643
  }
9548
9644
  /**
@@ -9553,9 +9649,10 @@ var ComputeEngine = (() => {
9553
9649
  * | <prefix-op> <primary>
9554
9650
  * | <primary> <infix-op> <expression>
9555
9651
  *
9556
- * Stop when an operator of precedence less than `until.minPrec` is encountered
9652
+ * Stop when an operator of precedence less than `until.minPrec`
9653
+ * is encountered
9557
9654
  */
9558
- matchExpression(until) {
9655
+ parseExpression(until) {
9559
9656
  const start = this.index;
9560
9657
  this.skipSpace();
9561
9658
  if (this.atBoundary) {
@@ -9565,9 +9662,9 @@ var ComputeEngine = (() => {
9565
9662
  until ?? (until = { minPrec: 0 });
9566
9663
  if (until.minPrec === void 0)
9567
9664
  until.minPrec = 0;
9568
- let lhs = this.matchPrefixOperator({ ...until, minPrec: 0 });
9665
+ let lhs = this.parsePrefixOperator({ ...until, minPrec: 0 });
9569
9666
  if (lhs === null) {
9570
- lhs = this.matchPrimary(until);
9667
+ lhs = this.parsePrimary(until);
9571
9668
  if (head(lhs) === "Sequence" && nops(lhs) === 0)
9572
9669
  lhs = null;
9573
9670
  }
@@ -9575,7 +9672,7 @@ var ComputeEngine = (() => {
9575
9672
  let done = false;
9576
9673
  while (!done && !this.atTerminator(until)) {
9577
9674
  this.skipSpace();
9578
- let result = this.matchInfixOperator(lhs, until);
9675
+ let result = this.parseInfixOperator(lhs, until);
9579
9676
  if (result === null) {
9580
9677
  result = this.applyInvisibleOperator(until, lhs);
9581
9678
  }
@@ -9586,6 +9683,7 @@ var ComputeEngine = (() => {
9586
9683
  }
9587
9684
  }
9588
9685
  }
9686
+ lhs ?? (lhs = this.parseUnexpectedLatexCommand());
9589
9687
  return this.decorate(lhs, start);
9590
9688
  }
9591
9689
  /**
@@ -9620,18 +9718,19 @@ var ComputeEngine = (() => {
9620
9718
  const latex = this.latex(fromToken, this.index);
9621
9719
  return latex ? ["Error", msg, ["Latex", { str: latex }]] : ["Error", msg];
9622
9720
  }
9721
+ isFunctionHead(expr) {
9722
+ if (expr === null)
9723
+ return false;
9724
+ const s = symbol(expr);
9725
+ if (!s)
9726
+ return this.computeEngine.box(expr).domain.isFunction;
9727
+ if (this.computeEngine && this.computeEngine.lookupFunction(s) !== void 0)
9728
+ return true;
9729
+ if (this.options.parseUnknownIdentifier?.(s, this) === "function")
9730
+ return true;
9731
+ return false;
9732
+ }
9623
9733
  };
9624
- function countPrimeLevel(parser) {
9625
- if (parser.match("\\tripleprime"))
9626
- return 3;
9627
- if (parser.match("\\doubleprime"))
9628
- return 2;
9629
- if (parser.match("\\prime"))
9630
- return 1;
9631
- if (parser.match("'"))
9632
- return 1;
9633
- return 0;
9634
- }
9635
9734
 
9636
9735
  // src/compute-engine/latex-syntax/serialize-number.ts
9637
9736
  function formatFractionalPart(m, options) {
@@ -9975,7 +10074,7 @@ var ComputeEngine = (() => {
9975
10074
  const name = head(expr);
9976
10075
  if (typeof name === "string" && name !== "Delimiter" && name !== "Subscript") {
9977
10076
  const def = this.dictionary.name.get(name);
9978
- if (def && (def.kind === "identifier" || def.kind === "prefix" || def.kind === "infix" || def.kind === "postfix") && def.precedence < prec)
10077
+ if (def && (def.kind === "symbol" || def.kind === "prefix" || def.kind === "infix" || def.kind === "postfix") && def.precedence < prec)
9979
10078
  return this.wrapString(
9980
10079
  this.serialize(expr),
9981
10080
  this.options.applyFunctionStyle(expr, this.level)
@@ -10055,8 +10154,11 @@ var ComputeEngine = (() => {
10055
10154
  if (typeof h === "string" && h.length > 0 && h[0] === "\\") {
10056
10155
  return joinLatex([h, ...args.map((x) => `{${this.serialize(x)}}`)]);
10057
10156
  }
10058
- if (typeof h === "string")
10157
+ if (typeof h === "string") {
10158
+ if (h.length === 1)
10159
+ return serializeIdentifier(h) + this.wrapArguments(expr);
10059
10160
  return serializeIdentifier(h, "upright") + this.wrapArguments(expr);
10161
+ }
10060
10162
  const style = this.options.applyFunctionStyle(expr, this.level);
10061
10163
  return "\\mathrm{Apply}" + this.wrapString(
10062
10164
  this.serialize(h) + ", " + this.serialize(["List", ...args]),
@@ -10083,10 +10185,12 @@ var ComputeEngine = (() => {
10083
10185
  const symbolName = symbol(expr);
10084
10186
  if (symbolName !== null) {
10085
10187
  const def = this.dictionary.name.get(symbolName);
10086
- if (def?.kind === "identifier")
10188
+ if (def?.kind === "symbol")
10087
10189
  return this.serializeSymbol(expr, def);
10088
10190
  if (def?.kind === "function")
10089
10191
  return this.serializeFunction(expr, def);
10192
+ if (typeof def?.serialize === "function")
10193
+ return def.serialize(this, expr);
10090
10194
  }
10091
10195
  const dict = dictionary(expr);
10092
10196
  if (dict !== null)
@@ -10099,7 +10203,7 @@ var ComputeEngine = (() => {
10099
10203
  return def.serialize(this, expr);
10100
10204
  if (def.kind === "infix" || def.kind === "postfix" || def.kind === "prefix")
10101
10205
  return serializeOperator(this, expr, def);
10102
- if (def.kind === "identifier")
10206
+ if (def.kind === "symbol")
10103
10207
  return this.serializeSymbol(expr, def);
10104
10208
  if (def.kind === "function")
10105
10209
  return this.serializeFunction(expr, def);
@@ -10363,7 +10467,7 @@ var ComputeEngine = (() => {
10363
10467
  ...DEFAULT_SERIALIZE_LATEX_OPTIONS,
10364
10468
  ...opts
10365
10469
  };
10366
- this.dictionary = indexLatexDictionary(
10470
+ this._dictionary = indexLatexDictionary(
10367
10471
  options.dictionary ?? _LatexSyntax.getDictionary(),
10368
10472
  (sig) => this.onError([sig])
10369
10473
  );
@@ -10384,16 +10488,16 @@ var ComputeEngine = (() => {
10384
10488
  }
10385
10489
  if (!DEFAULT_LATEX_DICTIONARY[category])
10386
10490
  return [];
10387
- return [...DEFAULT_LATEX_DICTIONARY[category]];
10491
+ return Object.freeze([...DEFAULT_LATEX_DICTIONARY[category]]);
10388
10492
  }
10389
10493
  parse(latex) {
10390
10494
  const parser = new _Parser(
10391
10495
  tokenize(latex, []),
10392
10496
  this.options,
10393
- this.dictionary,
10497
+ this._dictionary,
10394
10498
  this.computeEngine
10395
10499
  );
10396
- let expr = parser.matchExpression();
10500
+ let expr = parser.parseExpression();
10397
10501
  if (!parser.atEnd) {
10398
10502
  const opDefs = parser.peekDefinitions("infix");
10399
10503
  if (opDefs) {
@@ -10402,8 +10506,8 @@ var ComputeEngine = (() => {
10402
10506
  parser.index += n;
10403
10507
  const result = def.parse(
10404
10508
  parser,
10405
- { minPrec: 0 },
10406
- expr ?? parser.error("missing", start)
10509
+ expr ?? parser.error("missing", start),
10510
+ { minPrec: 0 }
10407
10511
  );
10408
10512
  if (result)
10409
10513
  return result;
@@ -10417,7 +10521,7 @@ var ComputeEngine = (() => {
10417
10521
  parser.index = start;
10418
10522
  }
10419
10523
  const index = parser.index;
10420
- const id = parser.matchIdentifier();
10524
+ const id = matchIdentifier(parser);
10421
10525
  if (id) {
10422
10526
  const idError = parser.error(["unexpected-identifier", id], index);
10423
10527
  return expr ? ["Sequence", expr, idError] : idError;
@@ -10439,9 +10543,9 @@ var ComputeEngine = (() => {
10439
10543
  return expr ? ["Sequence", expr, enclosureError] : enclosureError;
10440
10544
  }
10441
10545
  const rest = parser.index;
10442
- const token = parser.next();
10546
+ const token = parser.nextToken();
10443
10547
  while (!parser.atEnd)
10444
- parser.next();
10548
+ parser.nextToken();
10445
10549
  if (!token)
10446
10550
  return parser.error("syntax-error", rest);
10447
10551
  const error = parser.error(
@@ -10474,7 +10578,7 @@ var ComputeEngine = (() => {
10474
10578
  return this._serializer;
10475
10579
  this._serializer = new Serializer(
10476
10580
  this.options,
10477
- this.dictionary,
10581
+ this._dictionary,
10478
10582
  this.onError
10479
10583
  );
10480
10584
  return this._serializer;
@@ -13048,6 +13152,14 @@ var ComputeEngine = (() => {
13048
13152
  gDomainLiterals[dom] = new Set(result);
13049
13153
  return result;
13050
13154
  }
13155
+ function domainSetsLibrary() {
13156
+ const table = {};
13157
+ for (const dom of Object.keys(DOMAIN_LITERAL)) {
13158
+ if (dom !== "Domain" && dom !== "Nothing" && dom !== "String" && dom !== "Symbol" && dom !== "List" && dom !== "Tuple" && dom !== "Sequence")
13159
+ table[dom] = { domain: "Set" };
13160
+ }
13161
+ return table;
13162
+ }
13051
13163
 
13052
13164
  // src/compute-engine/boxed-expression/abstract-boxed-expression.ts
13053
13165
  var import_complex6 = __toESM(require_complex());
@@ -15392,7 +15504,7 @@ var ComputeEngine = (() => {
15392
15504
  const ce = expr.engine;
15393
15505
  if (expr.op1.head === "Negate") {
15394
15506
  const sign2 = exp2 % 2 === 0 ? 1 : -1;
15395
- const result2 = expandMultinomial(ce.box(["Power", expr.op1.op1, expr.op2]));
15507
+ const result2 = expandMultinomial(ce.pow(expr.op1.op1, expr.op2));
15396
15508
  if (result2 === null)
15397
15509
  return null;
15398
15510
  if (sign2 > 0)
@@ -15617,15 +15729,14 @@ var ComputeEngine = (() => {
15617
15729
  const sols = findUnivariateRoots(proposition, lhs2);
15618
15730
  if (sols.length === 0) {
15619
15731
  ce.assumptions.set(
15620
- ce.box([
15621
- "Equal",
15732
+ ce.fn("Equal", [
15622
15733
  ce.add([proposition.op1.canonical, ce.neg(proposition.op2.canonical)]).simplify(),
15623
15734
  0
15624
15735
  ]),
15625
15736
  true
15626
15737
  );
15627
15738
  }
15628
- const val = sols.length === 1 ? sols[0] : ce.box(["List", ...sols]);
15739
+ const val = sols.length === 1 ? sols[0] : ce.fn("List", sols);
15629
15740
  const def = ce.lookupSymbol(lhs2);
15630
15741
  if (!def) {
15631
15742
  ce.defineSymbol(lhs2, { value: val });
@@ -16607,7 +16718,6 @@ var ComputeEngine = (() => {
16607
16718
  return result;
16608
16719
  }
16609
16720
  solve(vars) {
16610
- console.log("solve this:", this.toString());
16611
16721
  if (vars.length !== 1)
16612
16722
  return null;
16613
16723
  const roots = findUnivariateRoots(this.simplify(), vars[0]);
@@ -16686,6 +16796,8 @@ var ComputeEngine = (() => {
16686
16796
  xs.push(y);
16687
16797
  }
16688
16798
  }
16799
+ if (!xs.every((x) => x.isValid))
16800
+ return new BoxedFunction(ce, head2, xs, { metadata, canonical: false });
16689
16801
  const sig = def.signature;
16690
16802
  if (sig.canonical) {
16691
16803
  try {
@@ -16716,21 +16828,22 @@ var ComputeEngine = (() => {
16716
16828
  return new BoxedFunction(ce, head2, xs, { metadata, def, canonical: true });
16717
16829
  }
16718
16830
  function apply(fn, args) {
16831
+ const ce = fn.engine;
16719
16832
  if (fn.head !== "Lambda")
16720
- return fn.engine._fn(fn.evaluate(), args);
16833
+ return ce._fn(fn.evaluate(), args);
16721
16834
  const subs2 = {
16722
- "__": fn.engine.tuple(args),
16723
- "_#": fn.engine.number(args.length)
16835
+ "__": ce.tuple(args),
16836
+ "_#": ce.number(args.length)
16724
16837
  };
16725
16838
  let n = 1;
16726
16839
  for (const op3 of args)
16727
16840
  subs2[`_${n++}`] = op3;
16728
16841
  subs2["_"] = subs2["_1"];
16729
- const savedContext = this.context;
16730
- this.context = fn.scope ?? null;
16731
- const result = fn.subs(subs2).evaluate();
16732
- this.context = savedContext;
16733
- return result;
16842
+ const savedContext = ce.context;
16843
+ ce.context = fn.scope ?? null;
16844
+ const result = fn.subs(subs2);
16845
+ ce.context = savedContext;
16846
+ return result.op1.evaluate();
16734
16847
  }
16735
16848
  function holdMap(xs, skip, associativeHead, f) {
16736
16849
  if (xs.length === 0)
@@ -18845,7 +18958,7 @@ var ComputeEngine = (() => {
18845
18958
  return ce._NEGATIVE_INFINITY;
18846
18959
  if (ops2.length === 1)
18847
18960
  return ops2[0];
18848
- return ce.box(["Max", ...ops2]);
18961
+ return ce.fn("Max", ops2);
18849
18962
  },
18850
18963
  evaluate: (ce, ops2) => {
18851
18964
  if (ops2.length === 0)
@@ -18874,7 +18987,7 @@ var ComputeEngine = (() => {
18874
18987
  return ce._NEGATIVE_INFINITY;
18875
18988
  if (ops2.length === 1)
18876
18989
  return ops2[0];
18877
- return ce.box(["Min", ...ops2]);
18990
+ return ce.fn("Min", ops2);
18878
18991
  },
18879
18992
  evaluate: (ce, ops2) => {
18880
18993
  if (ops2.length === 0)
@@ -19241,14 +19354,13 @@ var ComputeEngine = (() => {
19241
19354
  },
19242
19355
  Half: {
19243
19356
  constant: true,
19244
- holdUntil: "never",
19357
+ holdUntil: "evaluate",
19245
19358
  value: ["Rational", 1, 2]
19246
19359
  },
19247
19360
  ImaginaryUnit: {
19248
19361
  domain: "ImaginaryNumber",
19249
19362
  constant: true,
19250
19363
  holdUntil: "evaluate",
19251
- // @todo maybe?
19252
19364
  wikidata: "Q193796",
19253
19365
  flags: { imaginary: true },
19254
19366
  value: ["Complex", 0, 1]
@@ -20076,8 +20188,7 @@ var ComputeEngine = (() => {
20076
20188
  signature: {
20077
20189
  domain: ["Function", ["Maybe", ["Sequence", "Anything"]], "String"],
20078
20190
  evaluate: (ce, ops2) => {
20079
- return ce.box([
20080
- "Latex",
20191
+ return ce.fn("Latex", [
20081
20192
  ce.string(tokensToString(ops2.map((x) => x.string ?? x.latex)))
20082
20193
  ]);
20083
20194
  }
@@ -20100,7 +20211,7 @@ var ComputeEngine = (() => {
20100
20211
  hold: "all",
20101
20212
  signature: {
20102
20213
  domain: ["Function", ["Maybe", ["Sequence", "Anything"]], "String"],
20103
- evaluate: (ce, ops2) => ce.box(["Latex", ce.string(joinLatex(ops2.map((x) => x.latex)))])
20214
+ evaluate: (ce, ops2) => ce.fn("Latex", [ce.string(joinLatex(ops2.map((x) => x.latex)))])
20104
20215
  }
20105
20216
  },
20106
20217
  SplitAsLatexTokens: {
@@ -20937,13 +21048,13 @@ var ComputeEngine = (() => {
20937
21048
  "Number"
20938
21049
  ]);
20939
21050
  if (ops2.length !== 1)
20940
- return ce.box(["Degrees", ops2]);
21051
+ return ce.fn("Degrees", ops2, { canonical: false });
20941
21052
  const arg = ops2[0];
20942
21053
  if (arg.numericValue === null || !arg.isValid)
20943
- return ce.box(["Degrees", arg]);
21054
+ return ce.fn("Degrees", ops2, { canonical: false });
20944
21055
  return ce.div(ce.mul([arg, ce.symbol("Pi")]), ce.number(180));
20945
21056
  },
20946
- evaluate: (ce, ops2) => ce.mul([ops2[0], ce.box(["Divide", "Pi", 180])])
21057
+ evaluate: (ce, ops2) => ce.mul([ops2[0], ce.div(ce.symbol("Pi"), ce.number(180))])
20947
21058
  }
20948
21059
  },
20949
21060
  Hypot: {
@@ -21311,8 +21422,8 @@ var ComputeEngine = (() => {
21311
21422
  [
21312
21423
  [1, 8],
21313
21424
  {
21314
- Sin: "$\\frac\\sqrt{2-\\sqrt2}{2}$",
21315
- Cos: "$\\frac {\\sqrt {2+{\\sqrt {2}}}}{2}$",
21425
+ Sin: "$\\frac{\\sqrt{2-\\sqrt2}}{2}$",
21426
+ Cos: "$\\frac{\\sqrt {2+{\\sqrt {2}}}}{2}$",
21316
21427
  Tan: "$\\sqrt{2} - 1$",
21317
21428
  Cot: "$\\sqrt{2} + 1$",
21318
21429
  Sec: "$\\sqrt{ 4 - 2\\sqrt{2}}$",
@@ -21463,6 +21574,8 @@ var ComputeEngine = (() => {
21463
21574
  ]
21464
21575
  };
21465
21576
  function constructibleValues(ce, head2, x) {
21577
+ if (!x)
21578
+ return void 0;
21466
21579
  const specialValues = ce.cache(
21467
21580
  "constructible-trigonometric-values",
21468
21581
  () => {
@@ -21539,6 +21652,8 @@ var ComputeEngine = (() => {
21539
21652
  return newHead ? ce.symbol(newHead) : void 0;
21540
21653
  }
21541
21654
  function evalTrig(ce, mode, head2, op3) {
21655
+ if (!op3)
21656
+ return void 0;
21542
21657
  if (mode === "evaluate") {
21543
21658
  const result = constructibleValues(ce, head2, op3)?.evaluate();
21544
21659
  if (result)
@@ -21736,7 +21851,7 @@ var ComputeEngine = (() => {
21736
21851
  this._flags = def.flags ? normalizeFlags(def.flags) : void 0;
21737
21852
  this._domain = def.domain ? ce.domain(def.domain) : void 0;
21738
21853
  this.constant = def.constant ?? false;
21739
- this.holdUntil = def.holdUntil ?? "simplify";
21854
+ this.holdUntil = def.holdUntil ?? "evaluate";
21740
21855
  if (this.constant) {
21741
21856
  this._defValue = def.value;
21742
21857
  this._value = null;
@@ -22411,7 +22526,19 @@ var ComputeEngine = (() => {
22411
22526
  return !!def && typeof def === "object" && ("domain" in def || "value" in def || "constant" in def);
22412
22527
  }
22413
22528
  function isFunctionDefinition(def) {
22414
- return !!def && typeof def === "object" && ("complexity" in def || "numeric" in def || "signature" in def);
22529
+ if (def === void 0 || def === null)
22530
+ return false;
22531
+ if (typeof def !== "object")
22532
+ return false;
22533
+ if ("complexity" in def || "numeric" in def || "signature" in def)
22534
+ return true;
22535
+ if (!("domain" in def))
22536
+ return false;
22537
+ if (def.domain === void 0)
22538
+ return false;
22539
+ if (typeof def.domain === "string")
22540
+ return def.domain === "Function";
22541
+ return def.domain.isFunction;
22415
22542
  }
22416
22543
 
22417
22544
  // src/compute-engine/library/library.ts
@@ -22491,7 +22618,7 @@ var ComputeEngine = (() => {
22491
22618
  // @todo // volume, speed, area
22492
22619
  "domains": [],
22493
22620
  "core": CORE_LIBRARY,
22494
- "collections": [SETS_LIBRARY, COLLECTIONS_LIBRARY],
22621
+ "collections": [SETS_LIBRARY, COLLECTIONS_LIBRARY, domainSetsLibrary()],
22495
22622
  // 'domains': getDomainsDictionary(),
22496
22623
  "linear-algebra": [],
22497
22624
  //@todo // 'linear-algebra': [
@@ -23392,17 +23519,20 @@ ${JSON.stringify(entry)}`
23392
23519
  }
23393
23520
  simplify(options) {
23394
23521
  const def = this.symbolDefinition;
23395
- if ((def?.holdUntil === "never" || def?.holdUntil === "simplify") && def.value)
23522
+ if (def?.holdUntil === "simplify" && def.value)
23396
23523
  return def.value.simplify(options);
23397
23524
  return options?.rules ? this.replace(options.rules) ?? this : this;
23398
23525
  }
23399
23526
  evaluate(options) {
23400
23527
  const def = this.symbolDefinition;
23401
- if (def?.holdUntil !== "N")
23402
- return def?.value?.evaluate(options) ?? this;
23528
+ if (def && (def.holdUntil === "simplify" || def.holdUntil === "evaluate"))
23529
+ return def.value?.evaluate(options) ?? this;
23403
23530
  return this;
23404
23531
  }
23405
23532
  N(options) {
23533
+ const def = this.symbolDefinition;
23534
+ if (def && def.holdUntil === "never")
23535
+ return this;
23406
23536
  return this.symbolDefinition?.value?.N(options) ?? this;
23407
23537
  }
23408
23538
  replace(rules, options) {
@@ -23788,16 +23918,6 @@ ${JSON.stringify(entry)}`
23788
23918
  this._tolerance = NUMERIC_TOLERANCE;
23789
23919
  this._bignumTolerance = this.bignum(this._tolerance);
23790
23920
  }
23791
- /** @internal */
23792
- bignum(a) {
23793
- if (typeof a === "bigint")
23794
- return new this._bignum(a.toString());
23795
- return new this._bignum(a);
23796
- }
23797
- /** @internal */
23798
- complex(a, b) {
23799
- return new import_complex19.Complex(a, b);
23800
- }
23801
23921
  chop(n) {
23802
23922
  if (typeof n === "number" && Math.abs(n) <= this._tolerance)
23803
23923
  return 0;
@@ -23807,6 +23927,20 @@ ${JSON.stringify(entry)}`
23807
23927
  return 0;
23808
23928
  return n;
23809
23929
  }
23930
+ bignum(a) {
23931
+ if (typeof a === "bigint")
23932
+ return new this._bignum(a.toString());
23933
+ return new this._bignum(a);
23934
+ }
23935
+ complex(a, b) {
23936
+ return new import_complex19.Complex(a, b);
23937
+ }
23938
+ isBignum(a) {
23939
+ return a instanceof Decimal;
23940
+ }
23941
+ isComplex(a) {
23942
+ return a instanceof import_complex19.Complex;
23943
+ }
23810
23944
  get latexSyntax() {
23811
23945
  if (!this._latexSyntax)
23812
23946
  this._latexSyntax = new LatexSyntax({
@@ -23815,7 +23949,7 @@ ${JSON.stringify(entry)}`
23815
23949
  precision: this.precision,
23816
23950
  avoidExponentsInRange: [-6, this.precision],
23817
23951
  onError: (err) => {
23818
- throw new Error(err[0].message.toString());
23952
+ throw new Error(JSON.stringify(err[0].message));
23819
23953
  }
23820
23954
  });
23821
23955
  return this._latexSyntax;
@@ -24079,8 +24213,8 @@ ${JSON.stringify(entry)}`
24079
24213
  const bxs = xs;
24080
24214
  return bxs.every((x) => x.isCanonical) ? bxs : bxs.map((x) => x.canonical);
24081
24215
  }
24082
- fn(head2, ops2, metadata) {
24083
- return boxFunction(this, head2, ops2, { metadata, canonical: true });
24216
+ fn(head2, ops2, options) {
24217
+ return boxFunction(this, head2, ops2, options ?? { canonical: true });
24084
24218
  }
24085
24219
  /** @internal */
24086
24220
  _fn(head2, ops2, metadata) {
@@ -24494,10 +24628,10 @@ ${JSON.stringify(entry)}`
24494
24628
  };
24495
24629
 
24496
24630
  // src/compute-engine.ts
24497
- var version = "0.12.4";
24631
+ var version = "0.12.6";
24498
24632
  globalThis[Symbol.for("io.cortexjs.compute-engine")] = {
24499
24633
  ComputeEngine: ComputeEngine.prototype.constructor,
24500
- version: "0.12.4"
24634
+ version: "0.12.6"
24501
24635
  };
24502
24636
  return __toCommonJS(compute_engine_exports);
24503
24637
  })();