@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
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1029,11 +1029,14 @@ var require_complex = __commonJS({
1029
1029
  });
1030
1030
 
1031
1031
  // src/compute-engine/latex-syntax/public.ts
1032
- function isIdentifierEntry(entry) {
1033
- return !("kind" in entry) || entry.kind === "identifier";
1032
+ function isExpressionEntry(entry) {
1033
+ return !("kind" in entry) || entry.kind === "expression";
1034
+ }
1035
+ function isSymbolEntry(entry) {
1036
+ return "kind" in entry && entry.kind === "symbol";
1034
1037
  }
1035
1038
  function isFunctionEntry(entry) {
1036
- return !("kind" in entry) || entry.kind === "function";
1039
+ return "kind" in entry && entry.kind === "function";
1037
1040
  }
1038
1041
  function isMatchfixEntry(entry) {
1039
1042
  return "kind" in entry && entry.kind === "matchfix";
@@ -4098,9 +4101,9 @@ function applyAssociativeOperator(op3, lhs, rhs, associativity = "both") {
4098
4101
  return [op3, lhs, rhs];
4099
4102
  }
4100
4103
  function getSequence(expr) {
4101
- let h = head(expr);
4102
4104
  if (expr === null)
4103
4105
  return null;
4106
+ let h = head(expr);
4104
4107
  if (h === "Delimiter") {
4105
4108
  expr = op(expr, 1);
4106
4109
  if (expr === null)
@@ -4109,18 +4112,12 @@ function getSequence(expr) {
4109
4112
  return [expr];
4110
4113
  }
4111
4114
  h = head(expr);
4112
- if (h === "Sequence")
4113
- return ops(expr) ?? [];
4114
- return null;
4115
+ if (h !== "Sequence")
4116
+ return null;
4117
+ return ops(expr) ?? [];
4115
4118
  }
4116
4119
  function isEmptySequence(expr) {
4117
- if (expr === null)
4118
- return false;
4119
- if (head(expr) !== "Sequence")
4120
- return false;
4121
- if (nops(expr) !== 0)
4122
- return false;
4123
- return true;
4120
+ return expr !== null && head(expr) === "Sequence" && nops(expr) === 0;
4124
4121
  }
4125
4122
  function missingIfEmpty(expr) {
4126
4123
  if (expr === null || isEmptySequence(expr))
@@ -4231,8 +4228,8 @@ function numeratorDenominator(expr) {
4231
4228
  return [numerator, denominator];
4232
4229
  }
4233
4230
  function parseRoot(parser) {
4234
- const degree = parser.matchLatexOptionalGroup();
4235
- const base = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
4231
+ const degree = parser.parseOptionalGroup();
4232
+ const base = parser.parseGroup() ?? parser.parseToken();
4236
4233
  if (base === null || isEmptySequence(base)) {
4237
4234
  if (degree !== null)
4238
4235
  return ["Root", MISSING, missingIfEmpty(degree)];
@@ -4419,13 +4416,13 @@ function serializeMultiply(serializer, expr) {
4419
4416
  return isNegative ? "-" + result : result;
4420
4417
  }
4421
4418
  function parseFraction(parser) {
4422
- let numer = parser.matchLatexGroup();
4419
+ let numer = parser.parseGroup();
4423
4420
  let denom = null;
4424
4421
  if (numer === null) {
4425
- numer = parser.matchSingleAtomArgument();
4426
- denom = parser.matchSingleAtomArgument();
4422
+ numer = parser.parseToken();
4423
+ denom = parser.parseToken();
4427
4424
  } else {
4428
- denom = parser.matchLatexGroup();
4425
+ denom = parser.parseGroup();
4429
4426
  }
4430
4427
  numer = missingIfEmpty(numer);
4431
4428
  denom = missingIfEmpty(denom);
@@ -4433,7 +4430,7 @@ function parseFraction(parser) {
4433
4430
  const degree = op(numer, 3) ?? null;
4434
4431
  let fn = op(numer, 1);
4435
4432
  if (fn === null)
4436
- fn = missingIfEmpty(parser.matchExpression());
4433
+ fn = missingIfEmpty(parser.parseExpression());
4437
4434
  let vars = [];
4438
4435
  if (head(denom) === "Multiply") {
4439
4436
  for (const arg of ops(denom) ?? []) {
@@ -4562,7 +4559,7 @@ var DEFINITIONS_ARITHMETIC = [
4562
4559
  {
4563
4560
  trigger: ["\\ang"],
4564
4561
  parse: (parser) => {
4565
- const arg = parser.matchLatexGroup();
4562
+ const arg = parser.parseGroup();
4566
4563
  return arg === null ? ["Degrees"] : ["Degrees", arg];
4567
4564
  }
4568
4565
  },
@@ -4579,7 +4576,7 @@ var DEFINITIONS_ARITHMETIC = [
4579
4576
  trigger: ["\\tilde", "<{>", "\\infty", "<}>"],
4580
4577
  parse: "ComplexInfinity"
4581
4578
  },
4582
- { name: "Pi", trigger: ["\\pi"] },
4579
+ { name: "Pi", kind: "symbol", trigger: ["\\pi"] },
4583
4580
  { trigger: ["\u03C0"], parse: "Pi" },
4584
4581
  {
4585
4582
  name: "ExponentialE",
@@ -4587,6 +4584,15 @@ var DEFINITIONS_ARITHMETIC = [
4587
4584
  parse: "ExponentialE",
4588
4585
  serialize: "\\exponentialE"
4589
4586
  },
4587
+ {
4588
+ kind: "function",
4589
+ trigger: "exp",
4590
+ parse: "Exp"
4591
+ },
4592
+ {
4593
+ trigger: "\\exp",
4594
+ parse: "Exp"
4595
+ },
4590
4596
  {
4591
4597
  name: "ImaginaryUnit",
4592
4598
  trigger: ["\\imaginaryI"]
@@ -4606,10 +4612,7 @@ var DEFINITIONS_ARITHMETIC = [
4606
4612
  {
4607
4613
  trigger: "abs",
4608
4614
  kind: "function",
4609
- parse: (parser) => {
4610
- const arg = parser.matchArguments("enclosure");
4611
- return arg === null ? "Abs" : ["Abs", ...arg];
4612
- }
4615
+ parse: "Abs"
4613
4616
  },
4614
4617
  {
4615
4618
  name: "Add",
@@ -4617,10 +4620,10 @@ var DEFINITIONS_ARITHMETIC = [
4617
4620
  kind: "infix",
4618
4621
  associativity: "both",
4619
4622
  precedence: 275,
4620
- parse: (parser, until, lhs) => {
4621
- if (275 < until.minPrec)
4623
+ parse: (parser, lhs, until) => {
4624
+ if (until && 275 < until.minPrec)
4622
4625
  return null;
4623
- const rhs = parser.matchExpression({ ...until, minPrec: 275 });
4626
+ const rhs = parser.parseExpression({ ...until, minPrec: 275 });
4624
4627
  if (rhs === null)
4625
4628
  return null;
4626
4629
  return applyAssociativeOperator("Add", lhs, rhs);
@@ -4632,9 +4635,9 @@ var DEFINITIONS_ARITHMETIC = [
4632
4635
  trigger: ["+"],
4633
4636
  precedence: 275,
4634
4637
  parse: (parser, until) => {
4635
- if (275 < until.minPrec)
4638
+ if (until && 275 < until.minPrec)
4636
4639
  return null;
4637
- return parser.matchExpression({ ...until, minPrec: 400 });
4640
+ return parser.parseExpression({ ...until, minPrec: 400 });
4638
4641
  }
4639
4642
  },
4640
4643
  {
@@ -4643,13 +4646,16 @@ var DEFINITIONS_ARITHMETIC = [
4643
4646
  openDelimiter: "\\lceil",
4644
4647
  closeDelimiter: "\\rceil"
4645
4648
  },
4649
+ {
4650
+ kind: "matchfix",
4651
+ openDelimiter: ["\u2308"],
4652
+ closeDelimiter: ["\u2309"],
4653
+ parse: (_, body) => ["Ceil", body]
4654
+ },
4646
4655
  {
4647
4656
  trigger: "ceil",
4648
4657
  kind: "function",
4649
- parse: (parser) => {
4650
- const arg = parser.matchArguments("enclosure");
4651
- return arg === null ? "Ceil" : ["Ceil", ...arg];
4652
- }
4658
+ parse: "Ceil"
4653
4659
  },
4654
4660
  {
4655
4661
  name: "Complex",
@@ -4710,11 +4716,12 @@ var DEFINITIONS_ARITHMETIC = [
4710
4716
  },
4711
4717
  {
4712
4718
  name: "Exp",
4713
- serialize: (serializer, expr) => joinLatex([
4714
- "\\exponentialE^{",
4715
- serializer.serialize(missingIfEmpty(op(expr, 1))),
4716
- "}"
4717
- ])
4719
+ serialize: (serializer, expr) => {
4720
+ const op12 = op(expr, 1);
4721
+ if (symbol(op12) || machineValue(op12) !== null)
4722
+ return joinLatex(["\\exponentialE^{", serializer.serialize(op12)]);
4723
+ return joinLatex(["\\exp", serializer.wrap(missingIfEmpty(op12))]);
4724
+ }
4718
4725
  },
4719
4726
  {
4720
4727
  name: "Factorial",
@@ -4734,13 +4741,16 @@ var DEFINITIONS_ARITHMETIC = [
4734
4741
  openDelimiter: "\\lfloor",
4735
4742
  closeDelimiter: "\\rfloor"
4736
4743
  },
4744
+ {
4745
+ kind: "matchfix",
4746
+ openDelimiter: ["\u230A"],
4747
+ closeDelimiter: ["\u230B"],
4748
+ parse: (_, body) => ["Floor", body]
4749
+ },
4737
4750
  {
4738
4751
  trigger: "floor",
4739
4752
  kind: "function",
4740
- parse: (parser) => {
4741
- const arg = parser.matchArguments("enclosure");
4742
- return arg === null ? "Floor" : ["Floor", ...arg];
4743
- }
4753
+ parse: "Floor"
4744
4754
  },
4745
4755
  {
4746
4756
  name: "Gcd",
@@ -4756,9 +4766,9 @@ var DEFINITIONS_ARITHMETIC = [
4756
4766
  trigger: ["\\lg"],
4757
4767
  serialize: (serializer, expr) => "\\log_{10}" + serializer.wrapArguments(expr),
4758
4768
  parse: (parser) => {
4759
- const arg = parser.matchArguments("implicit");
4769
+ const arg = parser.parseArguments("implicit");
4760
4770
  if (arg === null)
4761
- return ["Lg"];
4771
+ return "Lg";
4762
4772
  return ["Log", ...arg, 10];
4763
4773
  }
4764
4774
  },
@@ -4766,9 +4776,9 @@ var DEFINITIONS_ARITHMETIC = [
4766
4776
  name: "Lb",
4767
4777
  trigger: "\\lb",
4768
4778
  parse: (parser) => {
4769
- const arg = parser.matchArguments("implicit");
4779
+ const arg = parser.parseArguments("implicit");
4770
4780
  if (arg === null)
4771
- return ["Log"];
4781
+ return "Log";
4772
4782
  return ["Log", ...arg, 2];
4773
4783
  }
4774
4784
  },
@@ -4819,10 +4829,10 @@ var DEFINITIONS_ARITHMETIC = [
4819
4829
  kind: "infix",
4820
4830
  associativity: "both",
4821
4831
  precedence: 390,
4822
- parse: (parser, terminator, lhs) => {
4823
- if (391 < terminator.minPrec)
4832
+ parse: (parser, lhs, terminator) => {
4833
+ if (terminator && 391 < terminator.minPrec)
4824
4834
  return null;
4825
- const rhs = parser.matchExpression({ ...terminator, minPrec: 392 });
4835
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4826
4836
  if (rhs === null)
4827
4837
  return ["Multiply", lhs, MISSING];
4828
4838
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4833,10 +4843,10 @@ var DEFINITIONS_ARITHMETIC = [
4833
4843
  kind: "infix",
4834
4844
  associativity: "both",
4835
4845
  precedence: 390,
4836
- parse: (parser, terminator, lhs) => {
4837
- if (391 < terminator.minPrec)
4846
+ parse: (parser, lhs, terminator) => {
4847
+ if (terminator && 391 < terminator.minPrec)
4838
4848
  return null;
4839
- const rhs = parser.matchExpression({ ...terminator, minPrec: 392 });
4849
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4840
4850
  if (rhs === null)
4841
4851
  return ["Multiply", lhs, MISSING];
4842
4852
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4847,9 +4857,9 @@ var DEFINITIONS_ARITHMETIC = [
4847
4857
  trigger: ["-"],
4848
4858
  kind: "prefix",
4849
4859
  parse: (parser, terminator) => {
4850
- if (276 < terminator.minPrec)
4860
+ if (terminator && 276 < terminator.minPrec)
4851
4861
  return null;
4852
- const rhs = parser.matchExpression({ ...terminator, minPrec: 400 });
4862
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4853
4863
  return ["Negate", missingIfEmpty(rhs)];
4854
4864
  },
4855
4865
  precedence: 275
@@ -4891,7 +4901,54 @@ var DEFINITIONS_ARITHMETIC = [
4891
4901
  trigger: ["\\pm"],
4892
4902
  kind: "infix",
4893
4903
  associativity: "both",
4894
- precedence: 270
4904
+ precedence: 270,
4905
+ serialize: (serializer, expr) => {
4906
+ const op12 = op(expr, 1);
4907
+ if (op12 === null)
4908
+ return "\\pm";
4909
+ if (nops(expr) === 1)
4910
+ return joinLatex(["\\pm", serializer.serialize(op12)]);
4911
+ const op22 = op(expr, 2);
4912
+ return joinLatex([
4913
+ serializer.serialize(op12),
4914
+ "\\pm",
4915
+ serializer.serialize(op22)
4916
+ ]);
4917
+ }
4918
+ },
4919
+ {
4920
+ trigger: ["\\pm"],
4921
+ kind: "prefix",
4922
+ precedence: 270,
4923
+ parse: (parser, terminator) => {
4924
+ if (terminator && 270 < terminator.minPrec)
4925
+ return null;
4926
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4927
+ return ["PlusMinus", missingIfEmpty(rhs)];
4928
+ }
4929
+ },
4930
+ {
4931
+ trigger: ["\\plusmn"],
4932
+ kind: "infix",
4933
+ associativity: "both",
4934
+ precedence: 270,
4935
+ parse: (parser, lhs, terminator) => {
4936
+ if (270 < terminator.minPrec)
4937
+ return null;
4938
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4939
+ return ["PlusMinus", lhs, missingIfEmpty(rhs)];
4940
+ }
4941
+ },
4942
+ {
4943
+ trigger: ["\\plusmn"],
4944
+ kind: "prefix",
4945
+ precedence: 270,
4946
+ parse: (parser, terminator) => {
4947
+ if (terminator && 270 < terminator.minPrec)
4948
+ return null;
4949
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
4950
+ return ["PlusMinus", missingIfEmpty(rhs)];
4951
+ }
4895
4952
  },
4896
4953
  {
4897
4954
  name: "Power",
@@ -4960,10 +5017,10 @@ var DEFINITIONS_ARITHMETIC = [
4960
5017
  kind: "infix",
4961
5018
  associativity: "both",
4962
5019
  precedence: 275,
4963
- parse: (parser, terminator, lhs) => {
5020
+ parse: (parser, lhs, terminator) => {
4964
5021
  if (276 < terminator.minPrec)
4965
5022
  return null;
4966
- const rhs = parser.matchExpression({ ...terminator, minPrec: 277 });
5023
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 277 });
4967
5024
  return ["Subtract", lhs, missingIfEmpty(rhs)];
4968
5025
  }
4969
5026
  }
@@ -4975,9 +5032,9 @@ function parseBigOp(name, prec) {
4975
5032
  let sub2 = null;
4976
5033
  while (!(sub2 && sup) && (parser.peek === "_" || parser.peek === "^")) {
4977
5034
  if (parser.match("_"))
4978
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
5035
+ sub2 = parser.parseGroup() ?? parser.parseToken();
4979
5036
  else if (parser.match("^"))
4980
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
5037
+ sup = parser.parseGroup() ?? parser.parseToken();
4981
5038
  parser.skipSpace();
4982
5039
  }
4983
5040
  if (sub2 === "Nothing" || isEmptySequence(sub2))
@@ -4995,7 +5052,7 @@ function parseBigOp(name, prec) {
4995
5052
  const sym = symbol(index);
4996
5053
  if (sym)
4997
5054
  parser.computeEngine?.pushScope({ [sym]: { domain: "Integer" } });
4998
- const fn = parser.matchExpression({ minPrec: prec + 1 });
5055
+ const fn = parser.parseExpression({ minPrec: prec + 1 });
4999
5056
  if (sym)
5000
5057
  parser.computeEngine?.popScope();
5001
5058
  if (!fn)
@@ -5056,10 +5113,10 @@ function parseLog(command, parser) {
5056
5113
  let sub2 = null;
5057
5114
  let base = null;
5058
5115
  if (parser.match("_")) {
5059
- sub2 = parser.matchStringArgument() ?? parser.next();
5116
+ sub2 = parser.parseStringGroup()?.trim() ?? parser.nextToken();
5060
5117
  base = Number.parseFloat(sub2 ?? "10");
5061
5118
  }
5062
- const arg = parser.matchArguments("implicit");
5119
+ const arg = parser.parseArguments("implicit");
5063
5120
  if (arg === null)
5064
5121
  return [command];
5065
5122
  if (base === 10)
@@ -5088,7 +5145,7 @@ function parseSequence(parser, terminator, lhs, prec, sep) {
5088
5145
  if (parser.atTerminator(terminator)) {
5089
5146
  result.push("Nothing");
5090
5147
  } else {
5091
- const rhs = parser.matchExpression({ ...terminator, minPrec: prec });
5148
+ const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
5092
5149
  result.push(rhs ?? "Nothing");
5093
5150
  done = rhs === null;
5094
5151
  }
@@ -5108,15 +5165,18 @@ var DEFINITIONS_CORE = [
5108
5165
  //
5109
5166
  {
5110
5167
  trigger: ["\\placeholder"],
5168
+ kind: "symbol",
5111
5169
  parse: (parser) => {
5112
- parser.skipSpaceTokens();
5170
+ while (parser.match("<space>")) {
5171
+ }
5113
5172
  if (parser.match("["))
5114
5173
  while (!parser.match("]") && !parser.atBoundary)
5115
- parser.next();
5116
- parser.skipSpaceTokens();
5174
+ parser.nextToken();
5175
+ while (parser.match("<space>")) {
5176
+ }
5117
5177
  if (parser.match("<{>"))
5118
5178
  while (!parser.match("<}>") && !parser.atBoundary)
5119
- parser.next();
5179
+ parser.nextToken();
5120
5180
  return "Nothing";
5121
5181
  }
5122
5182
  },
@@ -5125,7 +5185,6 @@ var DEFINITIONS_CORE = [
5125
5185
  //
5126
5186
  {
5127
5187
  name: "BaseForm",
5128
- kind: "function",
5129
5188
  serialize: (serializer, expr) => {
5130
5189
  const radix = machineValue(op(expr, 2)) ?? NaN;
5131
5190
  if (isFinite(radix) && radix >= 2 && radix <= 36) {
@@ -5172,9 +5231,9 @@ var DEFINITIONS_CORE = [
5172
5231
  let close = "";
5173
5232
  if (argCount > 1) {
5174
5233
  const op22 = stringValue(op(expr, 2)) ?? "";
5175
- open = op22[0] ?? "";
5176
- close = op22[1] ?? "";
5177
- sep = op22[2] ?? "";
5234
+ open = op22[0] ?? "(";
5235
+ close = op22[1] ?? ")";
5236
+ sep = op22[2] ?? ",";
5178
5237
  }
5179
5238
  const body = head(arg1) === "List" ? serializeSequence(sep)(serializer, arg1) : serializer.serialize(arg1);
5180
5239
  serializer.wrapString(body, style, stringValue(op(expr, 2)) ?? void 0);
@@ -5194,22 +5253,22 @@ var DEFINITIONS_CORE = [
5194
5253
  {
5195
5254
  trigger: ["\\mathtip"],
5196
5255
  parse: (parser) => {
5197
- const op12 = parser.matchLatexGroup();
5198
- const op22 = parser.matchLatexGroup();
5256
+ const op12 = parser.parseGroup();
5257
+ const op22 = parser.parseGroup();
5199
5258
  return op12;
5200
5259
  }
5201
5260
  },
5202
5261
  {
5203
5262
  trigger: ["\\texttip"],
5204
5263
  parse: (parser) => {
5205
- const op12 = parser.matchLatexGroup();
5206
- const op22 = parser.matchLatexGroup();
5264
+ const op12 = parser.parseGroup();
5265
+ const op22 = parser.parseGroup();
5207
5266
  return op12;
5208
5267
  }
5209
5268
  },
5210
5269
  {
5211
5270
  trigger: ["\\error"],
5212
- parse: (parser) => parser.matchLatexGroup()
5271
+ parse: (parser) => parser.parseGroup()
5213
5272
  },
5214
5273
  {
5215
5274
  name: "Error",
@@ -5271,12 +5330,12 @@ var DEFINITIONS_CORE = [
5271
5330
  kind: "matchfix",
5272
5331
  openDelimiter: "[",
5273
5332
  closeDelimiter: "]",
5274
- parse: (_parser, lhs) => {
5275
- if (lhs === null)
5333
+ parse: (_parser, body) => {
5334
+ if (body === null)
5276
5335
  return ["List"];
5277
- if (head(lhs) !== "Sequence" && head(lhs) !== "List")
5278
- return ["List", lhs];
5279
- return ["List", ...ops(lhs) ?? []];
5336
+ if (head(body) !== "Sequence" && head(body) !== "List")
5337
+ return ["List", body];
5338
+ return ["List", ...ops(body) ?? []];
5280
5339
  },
5281
5340
  serialize: (serializer, expr) => {
5282
5341
  return joinLatex([
@@ -5309,8 +5368,8 @@ var DEFINITIONS_CORE = [
5309
5368
  // when the comma operator is used, the lhs and rhs are flattened,
5310
5369
  // i.e. `1,2,3` -> `["Delimiter", ["List", 1, 2, 3], ","]`,
5311
5370
  // and `1, (2, 3)` -> `["Delimiter",
5312
- // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "(", ",", ")"]], ","],
5313
- parse: (parser, terminator, lhs) => {
5371
+ // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "()", ","]]],
5372
+ parse: (parser, lhs, terminator) => {
5314
5373
  const seq = parseSequence(parser, terminator, lhs, 20, ",");
5315
5374
  if (seq === null)
5316
5375
  return null;
@@ -5325,7 +5384,7 @@ var DEFINITIONS_CORE = [
5325
5384
  trigger: [";"],
5326
5385
  kind: "infix",
5327
5386
  precedence: 19,
5328
- parse: (parser, terminator, lhs) => {
5387
+ parse: (parser, lhs, terminator) => {
5329
5388
  const seq = parseSequence(parser, terminator, lhs, 19, ";");
5330
5389
  if (seq === null)
5331
5390
  return null;
@@ -5397,10 +5456,20 @@ var DEFINITIONS_CORE = [
5397
5456
  kind: "postfix",
5398
5457
  parse: (_parser, lhs) => ["Prime", missingIfEmpty(lhs), 2]
5399
5458
  },
5459
+ {
5460
+ trigger: ["^", "\\tripleprime"],
5461
+ kind: "postfix",
5462
+ parse: (_parser, lhs) => ["Prime", missingIfEmpty(lhs), 3]
5463
+ },
5400
5464
  {
5401
5465
  name: "InverseFunction",
5402
- // trigger: '^{-1}',
5403
- // kind: 'postfix',
5466
+ trigger: "^{-1}",
5467
+ kind: "postfix",
5468
+ parse: (parser, lhs) => {
5469
+ if (parser.computeEngine?.box(lhs)?.domain.isFunction)
5470
+ return ["InverseFunction", lhs];
5471
+ return null;
5472
+ },
5404
5473
  serialize: (serializer, expr) => serializer.serialize(op(expr, 1)) + "^{-1}"
5405
5474
  },
5406
5475
  {
@@ -5410,9 +5479,9 @@ var DEFINITIONS_CORE = [
5410
5479
  const base = serializer.serialize(op(expr, 1));
5411
5480
  if (degree === 1)
5412
5481
  return base + "^{\\prime}";
5413
- else if (degree === 2)
5482
+ if (degree === 2)
5414
5483
  return base + "^{\\doubleprime}";
5415
- else if (degree === 3)
5484
+ if (degree === 3)
5416
5485
  return base + "^{\\tripleprime}";
5417
5486
  return base + "^{(" + Number(degree).toString() + ")}";
5418
5487
  }
@@ -5422,7 +5491,7 @@ var DEFINITIONS_CORE = [
5422
5491
  trigger: "cases",
5423
5492
  kind: "environment",
5424
5493
  parse: (parser) => {
5425
- const tabular = parser.matchTabular("cases");
5494
+ const tabular = parser.parseTabular();
5426
5495
  if (!tabular)
5427
5496
  return ["Which"];
5428
5497
  const result = ["Which"];
@@ -5471,9 +5540,9 @@ function parseTextRun(parser, style) {
5471
5540
  runs.push(parseTextRun(parser));
5472
5541
  } else if (parser.match("\\textbf") && parser.match("<{>")) {
5473
5542
  runs.push(parseTextRun(parser, { "font-weight": "bold" }));
5474
- } else if (parser.match("\\color") && parser.match("<{>")) {
5475
- const color = parser.matchColor();
5476
- if (color && parser.match("<}>")) {
5543
+ } else if (parser.match("\\color")) {
5544
+ const color = parser.parseStringGroup();
5545
+ if (color !== null) {
5477
5546
  if (runinStyle !== null && text) {
5478
5547
  runs.push(["Style", text, { dict: runinStyle }]);
5479
5548
  } else if (text) {
@@ -5486,7 +5555,7 @@ function parseTextRun(parser, style) {
5486
5555
  text += " ";
5487
5556
  } else if (parser.match("<$>")) {
5488
5557
  const index = parser.index;
5489
- const expr = parser.matchExpression() ?? ["Sequence"];
5558
+ const expr = parser.parseExpression() ?? ["Sequence"];
5490
5559
  parser.skipSpace();
5491
5560
  if (parser.match("<$>")) {
5492
5561
  runs.push(expr);
@@ -5496,7 +5565,7 @@ function parseTextRun(parser, style) {
5496
5565
  }
5497
5566
  } else if (parser.match("<$$>")) {
5498
5567
  const index = parser.index;
5499
- const expr = parser.matchExpression() ?? ["Sequence"];
5568
+ const expr = parser.parseExpression() ?? ["Sequence"];
5500
5569
  parser.skipSpace();
5501
5570
  if (parser.match("<$$>")) {
5502
5571
  runs.push(expr);
@@ -5505,7 +5574,7 @@ function parseTextRun(parser, style) {
5505
5574
  parser.index = index;
5506
5575
  }
5507
5576
  } else
5508
- text += parser.matchChar() ?? parser.next();
5577
+ text += parser.matchChar() ?? parser.nextToken();
5509
5578
  }
5510
5579
  if (runinStyle !== null && text) {
5511
5580
  runs.push(["Style", `'${text}'`, { dict: runinStyle }]);
@@ -5574,7 +5643,7 @@ function errorContextAsLatex(serializer, error) {
5574
5643
  // src/compute-engine/latex-syntax/dictionary/definitions-inequalities.ts
5575
5644
  var DEFINITIONS_INEQUALITIES = [
5576
5645
  {
5577
- trigger: ["!", "<"],
5646
+ trigger: ["\\not", "<"],
5578
5647
  kind: "infix",
5579
5648
  associativity: "right",
5580
5649
  precedence: 246,
@@ -5620,7 +5689,7 @@ var DEFINITIONS_INEQUALITIES = [
5620
5689
  kind: "infix",
5621
5690
  associativity: "right",
5622
5691
  precedence: 241,
5623
- parse: "Equal"
5692
+ parse: "LessEqual"
5624
5693
  },
5625
5694
  {
5626
5695
  trigger: ["\\leqslant"],
@@ -5756,7 +5825,7 @@ var DEFINITIONS_INEQUALITIES = [
5756
5825
  {
5757
5826
  name: "NotApprox",
5758
5827
  // Note: Mathematica TildeTilde
5759
- trigger: ["\\approx"],
5828
+ trigger: ["\\not", "\\approx"],
5760
5829
  kind: "infix",
5761
5830
  associativity: "right",
5762
5831
  precedence: 247
@@ -5772,7 +5841,7 @@ var DEFINITIONS_INEQUALITIES = [
5772
5841
  {
5773
5842
  name: "NotApproxEqual",
5774
5843
  // Note: Mathematica NotTildeEqual
5775
- trigger: ["!", "\\approxeq"],
5844
+ trigger: ["\\not", "\\approxeq"],
5776
5845
  kind: "infix",
5777
5846
  // Note: no LaTeX symbol for char U+2249
5778
5847
  associativity: "right",
@@ -5860,7 +5929,7 @@ var DEFINITIONS_INEQUALITIES = [
5860
5929
  precedence: 244
5861
5930
  },
5862
5931
  {
5863
- trigger: ["!", ">"],
5932
+ trigger: ["\\not", ">"],
5864
5933
  kind: "infix",
5865
5934
  associativity: "right",
5866
5935
  precedence: 244,
@@ -6023,7 +6092,7 @@ var DEFINITIONS_LOGIC = [
6023
6092
  // src/compute-engine/latex-syntax/dictionary/definitions-other.ts
6024
6093
  function parseSingleArg(cmd) {
6025
6094
  return (parser) => {
6026
- const arg = parser.matchLatexGroup();
6095
+ const arg = parser.parseGroup();
6027
6096
  return arg === null ? [cmd] : [cmd, arg];
6028
6097
  };
6029
6098
  }
@@ -6077,14 +6146,14 @@ var DEFINITIONS_OTHERS = [
6077
6146
  {
6078
6147
  name: "Transpose",
6079
6148
  trigger: ["^", "T"],
6080
- kind: "infix"
6149
+ kind: "postfix"
6081
6150
  // @todo: if lhs is a list/tensor
6082
6151
  },
6083
6152
  {
6084
6153
  // @todo: if lhs is a list/tensor
6085
6154
  name: "ConjugateTranspose",
6086
6155
  trigger: ["^", "H"],
6087
- kind: "infix"
6156
+ kind: "postfix"
6088
6157
  },
6089
6158
  {
6090
6159
  name: "StringJoin",
@@ -6114,9 +6183,9 @@ var DEFINITIONS_OTHERS = [
6114
6183
  while (!done) {
6115
6184
  parser.skipSpace();
6116
6185
  if (parser.match("_")) {
6117
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6186
+ sub2 = parser.parseGroup() ?? parser.parseToken();
6118
6187
  } else if (parser.match("^")) {
6119
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6188
+ sup = parser.parseGroup() ?? parser.parseToken();
6120
6189
  } else {
6121
6190
  done = true;
6122
6191
  }
@@ -6126,9 +6195,9 @@ var DEFINITIONS_OTHERS = [
6126
6195
  sub2 = ["List", ...seq];
6127
6196
  if (sub2 === null || sup === null)
6128
6197
  return null;
6129
- let rhs = parser.matchLatexGroup() ?? "Nothing";
6198
+ let rhs = parser.parseGroup() ?? "Nothing";
6130
6199
  if (rhs !== "Nothing" && !isEmptySequence(rhs)) {
6131
- const arg = parser.matchArguments("enclosure") ?? ["Nothing"];
6200
+ const arg = parser.parseArguments() ?? ["Nothing"];
6132
6201
  rhs = [rhs, ...arg];
6133
6202
  }
6134
6203
  return ["PartialDerivative", rhs, sub2, sup];
@@ -6405,7 +6474,7 @@ var DEFINITIONS_OTHERS = [
6405
6474
  // src/compute-engine/latex-syntax/dictionary/definitions-trigonometry.ts
6406
6475
  function parseTrig(op3) {
6407
6476
  return (parser, until) => {
6408
- let head2 = {
6477
+ const head2 = {
6409
6478
  "\\arcsin": "Arcsin",
6410
6479
  "\\arccos": "Arccos",
6411
6480
  "\\arctan": "Arctan",
@@ -6440,37 +6509,11 @@ function parseTrig(op3) {
6440
6509
  }[op3 ?? ""] ?? op3 ?? "";
6441
6510
  if (parser.atTerminator(until))
6442
6511
  return head2;
6443
- let isInverse = false;
6444
- let primeLevel = 0;
6445
- let sup = null;
6446
- parser.skipSpace();
6447
- const start = parser.index;
6448
- if (parser.match("^")) {
6449
- parser.skipSpace();
6450
- const superscriptIndex = parser.index;
6451
- if (parser.matchAll(["<{>", "-", "1", "<}>"]))
6452
- isInverse = true;
6453
- else {
6454
- parser.index = start;
6455
- parser.index = start;
6456
- primeLevel = parser.matchPrimeSuffix();
6457
- if (primeLevel === 0) {
6458
- parser.index = superscriptIndex;
6459
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6460
- }
6461
- }
6462
- }
6463
- primeLevel += parser.matchPrimeSuffix();
6464
- if (isInverse)
6465
- head2 = ["InverseFunction", head2];
6466
- if (primeLevel === 1)
6467
- head2 = ["Derivative", head2];
6468
- else if (primeLevel > 1)
6469
- head2 = ["Derivative", head2, primeLevel];
6470
- const args = parser.matchArguments("implicit", until);
6471
- if (args === null)
6472
- return sup ? [["Power", [head2], sup]] : head2;
6473
- return sup ? ["Power", [head2, ...args], sup] : [head2, ...args];
6512
+ const fn = parser.parsePostfixOperator(head2, until);
6513
+ if (fn !== null)
6514
+ return fn;
6515
+ const args = parser.parseArguments("implicit", until);
6516
+ return args === null ? head2 : [head2, ...args];
6474
6517
  };
6475
6518
  }
6476
6519
  var DEFINITIONS_TRIGONOMETRY = [
@@ -6499,7 +6542,6 @@ var DEFINITIONS_TRIGONOMETRY = [
6499
6542
  parse: parseTrig("Arccot")
6500
6543
  },
6501
6544
  {
6502
- kind: "function",
6503
6545
  name: "Arcsec",
6504
6546
  trigger: "arcsec",
6505
6547
  parse: parseTrig("Arcsec")
@@ -6700,14 +6742,14 @@ var DEFINITIONS_SETS = [
6700
6742
  // Caution: cartesian product is not associative
6701
6743
  precedence: 390,
6702
6744
  // Same as Multiply?
6703
- parse: (parser, until, lhs) => {
6745
+ parse: (parser, lhs, until) => {
6704
6746
  if (390 < until.minPrec)
6705
6747
  return null;
6706
6748
  const ce = parser.computeEngine;
6707
6749
  if (!ce || !ce.box(lhs).domain.isCompatible("Set"))
6708
6750
  return null;
6709
6751
  const index = parser.index;
6710
- const rhs = parser.matchExpression({ ...until, minPrec: 390 });
6752
+ const rhs = parser.parseExpression({ ...until, minPrec: 390 });
6711
6753
  if (rhs === null || ce.box(lhs).domain.isCompatible("Set") !== true) {
6712
6754
  parser.index = index;
6713
6755
  return null;
@@ -6787,8 +6829,8 @@ var DEFINITIONS_SETS = [
6787
6829
  associativity: "right",
6788
6830
  precedence: 160,
6789
6831
  // As per MathML, lower precedence
6790
- parse: (parser, terminator, lhs) => {
6791
- const rhs = parser.matchExpression(terminator);
6832
+ parse: (parser, lhs, terminator) => {
6833
+ const rhs = parser.parseExpression(terminator);
6792
6834
  return rhs === null ? null : ["Element", rhs, lhs];
6793
6835
  }
6794
6836
  },
@@ -6993,9 +7035,10 @@ function parseIntegral(command, n = 1) {
6993
7035
  let sub2 = null;
6994
7036
  while (!(sub2 !== null && sup !== null) && (parser.peek === "_" || parser.peek === "^")) {
6995
7037
  if (parser.match("_"))
6996
- sub2 = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
6997
- else if (parser.match("^"))
6998
- sup = parser.matchLatexGroup() ?? parser.matchSingleAtomArgument();
7038
+ sub2 = parser.parseGroup() ?? parser.parseToken();
7039
+ else if (parser.match("^")) {
7040
+ sup = parser.parseGroup() ?? parser.parseToken();
7041
+ }
6999
7042
  parser.skipSpace();
7000
7043
  }
7001
7044
  if (sub2 === "Nothing" || isEmptySequence(sub2))
@@ -7071,7 +7114,7 @@ function makeRange(range) {
7071
7114
  function parseIntegralBody(parser, n = 1) {
7072
7115
  const start = parser.index;
7073
7116
  let found = false;
7074
- let fn = parser.matchExpression({
7117
+ let fn = parser.parseExpression({
7075
7118
  minPrec: 266,
7076
7119
  condition: () => {
7077
7120
  if (parser.matchAll(["\\mathrm", "<{>", "d", "<}>"]))
@@ -7081,7 +7124,7 @@ function parseIntegralBody(parser, n = 1) {
7081
7124
  });
7082
7125
  if (!found) {
7083
7126
  parser.index = start;
7084
- fn = parser.matchExpression({
7127
+ fn = parser.parseExpression({
7085
7128
  minPrec: 266,
7086
7129
  condition: () => {
7087
7130
  if (parser.match("d"))
@@ -7098,7 +7141,7 @@ function parseIntegralBody(parser, n = 1) {
7098
7141
  function parseIndexes(parser, n = 1) {
7099
7142
  parser.skipSpace();
7100
7143
  const result = [];
7101
- const index = symbol(parser.matchSymbol());
7144
+ const index = symbol(parser.parseSymbol());
7102
7145
  if (index === null)
7103
7146
  return [];
7104
7147
  result.push(index);
@@ -7217,30 +7260,36 @@ function serializeIntegral(command) {
7217
7260
  }
7218
7261
  var DEFINITIONS_CALCULUS = [
7219
7262
  {
7263
+ kind: "expression",
7220
7264
  name: "Integrate",
7221
7265
  trigger: ["\\int"],
7222
7266
  parse: parseIntegral("Integrate"),
7223
7267
  serialize: serializeIntegral("\\int")
7224
7268
  },
7225
7269
  {
7270
+ kind: "expression",
7226
7271
  trigger: ["\\iint"],
7227
7272
  parse: parseIntegral("Integrate", 2)
7228
7273
  },
7229
7274
  {
7275
+ kind: "expression",
7230
7276
  trigger: ["\\iiint"],
7231
7277
  parse: parseIntegral("Integrate", 3)
7232
7278
  },
7233
7279
  {
7280
+ kind: "expression",
7234
7281
  name: "CircularIntegrate",
7235
7282
  trigger: ["\\oint"],
7236
7283
  parse: parseIntegral("CircularIntegrate"),
7237
7284
  serialize: serializeIntegral("\\oint")
7238
7285
  },
7239
7286
  {
7287
+ kind: "expression",
7240
7288
  trigger: ["\\oiint"],
7241
7289
  parse: parseIntegral("CircularIntegrate", 2)
7242
7290
  },
7243
7291
  {
7292
+ kind: "expression",
7244
7293
  trigger: ["\\oiiint"],
7245
7294
  parse: parseIntegral("CircularIntegrate", 3)
7246
7295
  }
@@ -7346,6 +7395,7 @@ var SYMBOLS = [
7346
7395
  var DEFINITIONS_SYMBOLS = [
7347
7396
  ...SYMBOLS.map(([symbol2, latex, _codepoint]) => {
7348
7397
  return {
7398
+ kind: "symbol",
7349
7399
  name: symbol2,
7350
7400
  trigger: [latex],
7351
7401
  parse: symbol2
@@ -7353,6 +7403,7 @@ var DEFINITIONS_SYMBOLS = [
7353
7403
  }),
7354
7404
  ...SYMBOLS.map(([symbol2, _latex, codepoint]) => {
7355
7405
  return {
7406
+ kind: "symbol",
7356
7407
  trigger: [String.fromCodePoint(codepoint)],
7357
7408
  parse: symbol2
7358
7409
  };
@@ -7381,98 +7432,99 @@ function triggerLength(trigger) {
7381
7432
  return trigger.length;
7382
7433
  return 1;
7383
7434
  }
7435
+ function addEntry(result, entry, onError) {
7436
+ const [trigger, indexedEntry] = makeIndexedEntry(entry, onError);
7437
+ if (indexedEntry === null)
7438
+ return;
7439
+ const kind = "kind" in entry ? entry.kind : "expression";
7440
+ if (trigger && trigger.length === 2 && /[_^]/.test(trigger[0]) && trigger[1] !== "<{>" && kind !== "function" && entry.name) {
7441
+ let parse = entry.parse;
7442
+ if (parse === void 0) {
7443
+ if (kind === "symbol")
7444
+ parse = entry.name;
7445
+ if (kind === "postfix" || kind === "prefix")
7446
+ parse = (_parser, expr) => [entry.name, expr];
7447
+ }
7448
+ addEntry(
7449
+ result,
7450
+ {
7451
+ ...entry,
7452
+ kind,
7453
+ parse,
7454
+ name: void 0,
7455
+ trigger: [trigger[0], "<{>", trigger[1], "<}>"]
7456
+ },
7457
+ onError
7458
+ );
7459
+ }
7460
+ if (indexedEntry.name !== void 0) {
7461
+ if (result.name.has(indexedEntry.name)) {
7462
+ onError({
7463
+ severity: "warning",
7464
+ message: [
7465
+ "invalid-dictionary-entry",
7466
+ indexedEntry.name,
7467
+ "Duplicate definition. The name must be unique, but a trigger can be used by multiple definitions."
7468
+ ]
7469
+ });
7470
+ }
7471
+ result.name.set(indexedEntry.name, indexedEntry);
7472
+ }
7473
+ if (indexedEntry.kind === "matchfix") {
7474
+ result.matchfix.push(indexedEntry);
7475
+ } else if (indexedEntry.kind === "environment") {
7476
+ const triggerString = tokensToString(entry.trigger ?? "");
7477
+ if (result.environment.has(triggerString)) {
7478
+ onError({
7479
+ severity: "warning",
7480
+ message: [
7481
+ "invalid-dictionary-entry",
7482
+ triggerString,
7483
+ "Duplicate environment definition"
7484
+ ]
7485
+ });
7486
+ }
7487
+ result.environment.set(triggerString, indexedEntry);
7488
+ } else if (trigger) {
7489
+ console.assert(entry.trigger);
7490
+ const triggerString = tokensToString(entry.trigger ?? "");
7491
+ const n = triggerLength(trigger);
7492
+ result.lookahead = Math.max(result.lookahead, n);
7493
+ if (indexedEntry.kind === "function") {
7494
+ if (!result.function.has(triggerString))
7495
+ result.function.set(triggerString, [indexedEntry]);
7496
+ else
7497
+ result.function.set(triggerString, [
7498
+ ...result.function.get(triggerString),
7499
+ indexedEntry
7500
+ ]);
7501
+ } else {
7502
+ const kind2 = indexedEntry.kind;
7503
+ if (result[kind2][n] === void 0)
7504
+ result[kind2][n] = /* @__PURE__ */ new Map();
7505
+ const list = result[kind2][n];
7506
+ if (list.has(triggerString))
7507
+ list.get(triggerString).push(indexedEntry);
7508
+ else
7509
+ list.set(triggerString, [indexedEntry]);
7510
+ }
7511
+ }
7512
+ }
7384
7513
  function indexLatexDictionary(dic, onError) {
7385
7514
  const result = {
7386
7515
  lookahead: 1,
7387
7516
  name: /* @__PURE__ */ new Map(),
7517
+ expression: /* @__PURE__ */ new Map(),
7388
7518
  function: /* @__PURE__ */ new Map(),
7389
- identifier: [],
7519
+ symbol: [],
7390
7520
  infix: [],
7391
7521
  prefix: [],
7392
7522
  postfix: [],
7393
7523
  environment: /* @__PURE__ */ new Map(),
7394
7524
  matchfix: []
7395
7525
  };
7396
- for (const entry of dic) {
7397
- const [trigger, indexedEntry] = makeIndexedEntry(entry, onError);
7398
- if (indexedEntry === null)
7399
- continue;
7400
- if (indexedEntry.name !== void 0) {
7401
- if (result.name.has(indexedEntry.name)) {
7402
- onError({
7403
- severity: "warning",
7404
- message: [
7405
- "invalid-dictionary-entry",
7406
- indexedEntry.name,
7407
- "Duplicate definition"
7408
- ]
7409
- });
7410
- }
7411
- result.name.set(indexedEntry.name, indexedEntry);
7412
- }
7413
- if (indexedEntry.kind === "matchfix") {
7414
- result.matchfix.push(indexedEntry);
7415
- } else if (indexedEntry.kind === "environment") {
7416
- const triggerString = tokensToString(entry.trigger ?? "");
7417
- if (result.environment.has(triggerString)) {
7418
- onError({
7419
- severity: "warning",
7420
- message: [
7421
- "invalid-dictionary-entry",
7422
- triggerString,
7423
- "Duplicate environment definition"
7424
- ]
7425
- });
7426
- }
7427
- result.environment.set(triggerString, indexedEntry);
7428
- } else if (trigger) {
7429
- console.assert(entry.trigger);
7430
- const triggerString = tokensToString(entry.trigger ?? "");
7431
- const n = triggerLength(trigger);
7432
- result.lookahead = Math.max(result.lookahead, n);
7433
- if (indexedEntry.kind === "function") {
7434
- if (!result.function.has(triggerString))
7435
- result.function.set(triggerString, [indexedEntry]);
7436
- else
7437
- result.function.set(triggerString, [
7438
- ...result.function.get(triggerString),
7439
- indexedEntry
7440
- ]);
7441
- } else if (indexedEntry.kind === "identifier") {
7442
- if (result.identifier[n] === void 0)
7443
- result.identifier[n] = /* @__PURE__ */ new Map();
7444
- const list = result.identifier[n];
7445
- if (list.has(triggerString))
7446
- list.get(triggerString).push(indexedEntry);
7447
- else
7448
- list.set(triggerString, [indexedEntry]);
7449
- } else if (indexedEntry.kind === "prefix") {
7450
- if (result.prefix[n] === void 0)
7451
- result.prefix[n] = /* @__PURE__ */ new Map();
7452
- const list = result.prefix[n];
7453
- if (list.has(triggerString))
7454
- list.get(triggerString).push(indexedEntry);
7455
- else
7456
- list.set(triggerString, [indexedEntry]);
7457
- } else if (indexedEntry.kind === "infix") {
7458
- if (result.infix[n] === void 0)
7459
- result.infix[n] = /* @__PURE__ */ new Map();
7460
- const list = result.infix[n];
7461
- if (list.has(triggerString))
7462
- list.get(triggerString).push(indexedEntry);
7463
- else
7464
- list.set(triggerString, [indexedEntry]);
7465
- } else if (indexedEntry.kind === "postfix") {
7466
- if (result.postfix[n] === void 0)
7467
- result.postfix[n] = /* @__PURE__ */ new Map();
7468
- const list = result.postfix[n];
7469
- if (list.has(triggerString))
7470
- list.get(triggerString).push(indexedEntry);
7471
- else
7472
- list.set(triggerString, [indexedEntry]);
7473
- }
7474
- }
7475
- }
7526
+ for (const entry of dic)
7527
+ addEntry(result, entry, onError);
7476
7528
  return result;
7477
7529
  }
7478
7530
  function makeIndexedEntry(entry, onError) {
@@ -7480,7 +7532,7 @@ function makeIndexedEntry(entry, onError) {
7480
7532
  return [null, null];
7481
7533
  const result = {
7482
7534
  name: entry.name,
7483
- kind: "kind" in entry ? entry.kind : "identifier"
7535
+ kind: "kind" in entry ? entry.kind : "expression"
7484
7536
  };
7485
7537
  if (result.kind === "matchfix" && isMatchfixEntry(entry)) {
7486
7538
  result.openDelimiter = entry.openDelimiter;
@@ -7513,29 +7565,57 @@ function makeIndexedEntry(entry, onError) {
7513
7565
  const triggerString = trigger ? tokensToString(trigger) : "";
7514
7566
  if (result.kind === "function" && isFunctionEntry(entry)) {
7515
7567
  result.serialize = entry.serialize;
7516
- if (triggerString && !entry.serialize)
7517
- result.serialize = (serializer, expr) => `\\mathrm{${triggerString}}${serializer.wrapArguments(expr)}`;
7518
- result.parse = entry.parse;
7519
- if (!result.parse && entry.name)
7520
- result.parse = (parser) => {
7521
- const arg = parser.matchArguments("enclosure");
7522
- return arg === null ? entry.name : [entry.name, ...arg];
7523
- };
7568
+ if (triggerString && !entry.serialize) {
7569
+ if (triggerString.startsWith("\\")) {
7570
+ result.serialize = (serializer, expr) => `${triggerString}${serializer.wrapArguments(expr)}`;
7571
+ } else
7572
+ result.serialize = (serializer, expr) => `\\mathrm{${triggerString}}${serializer.wrapArguments(expr)}`;
7573
+ }
7574
+ if (typeof entry.parse === "function")
7575
+ result.parse = entry.parse;
7576
+ else if (typeof entry.parse === "string")
7577
+ result.parse = () => entry.parse;
7578
+ else if (entry.name)
7579
+ result.parse = () => entry.name;
7524
7580
  return [triggerString, result];
7525
7581
  }
7526
- if (typeof entry.trigger === "string") {
7527
- console.assert(
7528
- entry.parse || trigger.length > 1,
7529
- `Trigger shortcut should produce more than one token. Otherwise, not worth using the shortcut. (${triggerString})`
7530
- );
7582
+ if (result.kind === "expression" && isExpressionEntry(entry)) {
7583
+ result.serialize = entry.serialize ?? triggerString;
7584
+ if (typeof result.serialize === "string") {
7585
+ const serializeExpr = result.serialize;
7586
+ result.serialize = (serializer, expr) => {
7587
+ if (!head(expr))
7588
+ return serializer.serialize(serializeExpr);
7589
+ return `${serializer.serialize(
7590
+ serializeExpr
7591
+ )}${serializer.wrapArguments(expr)}`;
7592
+ };
7593
+ }
7594
+ {
7595
+ if (typeof entry.parse === "function") {
7596
+ result.parse = entry.parse;
7597
+ } else {
7598
+ const parseResult = entry.parse ?? entry.name;
7599
+ result.parse = () => parseResult;
7600
+ }
7601
+ }
7602
+ return [triggerString, result];
7531
7603
  }
7532
- if (result.kind === "identifier" && isIdentifierEntry(entry)) {
7604
+ console.assert(
7605
+ typeof entry.trigger !== "string" || entry.parse || trigger.length > 1 || "kind" in entry && entry.kind === "function",
7606
+ `Trigger shortcuts should produce more than one token. Otherwise, not worth using them. (${triggerString})`
7607
+ );
7608
+ if (result.kind === "symbol" && isSymbolEntry(entry)) {
7533
7609
  result.precedence = entry.precedence ?? 1e4;
7534
7610
  }
7535
7611
  if ((result.kind === "infix" || result.kind === "prefix" || result.kind === "postfix") && (isInfixEntry(entry) || isPrefixEntry(entry) || isPostfixEntry(entry))) {
7536
- if (trigger && (trigger[0] === "^" || trigger[0] === "_"))
7612
+ if (trigger && (trigger[0] === "^" || trigger[0] === "_")) {
7537
7613
  result.precedence = 720;
7538
- else
7614
+ console.assert(
7615
+ entry.precedence === void 0,
7616
+ "'precedence' not allowed with ^ and _ triggers"
7617
+ );
7618
+ } else
7539
7619
  result.precedence = entry.precedence ?? 1e4;
7540
7620
  }
7541
7621
  if (result.kind === "infix" && isInfixEntry(entry)) {
@@ -7548,7 +7628,7 @@ function makeIndexedEntry(entry, onError) {
7548
7628
  } else if (trigger && (trigger[0] === "^" || trigger[0] === "_")) {
7549
7629
  console.assert(!entry.parse);
7550
7630
  const name = entry.parse ?? entry.name;
7551
- result.parse = (_scanner, _terminator, arg) => [
7631
+ result.parse = (_scanner, arg, _terminator) => [
7552
7632
  name,
7553
7633
  missingIfEmpty(op(arg, 1)),
7554
7634
  missingIfEmpty(op(arg, 2))
@@ -7557,11 +7637,11 @@ function makeIndexedEntry(entry, onError) {
7557
7637
  const head2 = entry.parse ?? entry.name;
7558
7638
  const prec = result.precedence;
7559
7639
  const associativity = result.associativity;
7560
- result.parse = (scanner, terminator, lhs) => {
7640
+ result.parse = (scanner, lhs, terminator) => {
7561
7641
  if (prec < terminator.minPrec)
7562
7642
  return null;
7563
7643
  const rhs = missingIfEmpty(
7564
- scanner.matchExpression({
7644
+ scanner.parseExpression({
7565
7645
  ...terminator,
7566
7646
  minPrec: prec
7567
7647
  })
@@ -7573,7 +7653,7 @@ function makeIndexedEntry(entry, onError) {
7573
7653
  if (typeof entry.parse === "function") {
7574
7654
  result.parse = entry.parse;
7575
7655
  } else if (entry.parse !== void 0) {
7576
- console.assert(result.kind === "identifier");
7656
+ console.assert(result.kind === "symbol" || result.kind === "expression");
7577
7657
  result.parse = () => entry.parse;
7578
7658
  } else if (entry.parse === void 0 && entry.name !== void 0) {
7579
7659
  if (result.kind === "postfix") {
@@ -7583,9 +7663,9 @@ function makeIndexedEntry(entry, onError) {
7583
7663
  console.assert(entry.name);
7584
7664
  const head2 = entry.name;
7585
7665
  result.parse = (parser, terminator) => {
7586
- if (prec < terminator.minPrec)
7666
+ if (terminator && prec < terminator.minPrec)
7587
7667
  return null;
7588
- const rhs = parser.matchExpression({ ...terminator, minPrec: prec });
7668
+ const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
7589
7669
  return rhs === null ? null : [head2, rhs];
7590
7670
  };
7591
7671
  }
@@ -7600,7 +7680,7 @@ function makeIndexedEntry(entry, onError) {
7600
7680
  result.serialize = triggerString + "#1";
7601
7681
  } else if (result.kind === "infix") {
7602
7682
  result.serialize = "#1" + triggerString + "#2";
7603
- } else if (result.kind === "identifier") {
7683
+ } else if (result.kind === "symbol") {
7604
7684
  result.serialize = triggerString;
7605
7685
  } else {
7606
7686
  result.serialize = "";
@@ -7730,6 +7810,7 @@ var DEFAULT_LATEX_DICTIONARY = {
7730
7810
  physics: [
7731
7811
  {
7732
7812
  name: "mu0",
7813
+ kind: "symbol",
7733
7814
  trigger: "\\mu_0"
7734
7815
  }
7735
7816
  ],
@@ -7779,6 +7860,7 @@ function matchIdentifierToken(parser, options) {
7779
7860
  special = {
7780
7861
  "+": "plus",
7781
7862
  "-": "minus",
7863
+ "\\plusmn": "pm",
7782
7864
  "\\pm": "pm",
7783
7865
  "\\ast": "ast",
7784
7866
  "\\dag": "dag",
@@ -7794,22 +7876,22 @@ function matchIdentifierToken(parser, options) {
7794
7876
  }[token];
7795
7877
  }
7796
7878
  if (special) {
7797
- parser.next();
7879
+ parser.nextToken();
7798
7880
  return special;
7799
7881
  }
7800
7882
  const i = SYMBOLS.findIndex((x) => x[1] === token);
7801
7883
  if (i >= 0) {
7802
- parser.next();
7884
+ parser.nextToken();
7803
7885
  return SYMBOLS[i][0];
7804
7886
  }
7805
- return parser.matchChar() ?? parser.next();
7887
+ return parser.matchChar() ?? parser.nextToken();
7806
7888
  }
7807
7889
  function matchIdentifierBody(parser) {
7808
7890
  let id = matchPrefixedIdentifier(parser);
7809
7891
  const start = parser.index;
7810
7892
  const prefix = IDENTIFIER_MODIFIER[parser.peek] ?? null;
7811
7893
  if (prefix) {
7812
- parser.next();
7894
+ parser.nextToken();
7813
7895
  if (!parser.match("<{>")) {
7814
7896
  parser.index = start;
7815
7897
  return null;
@@ -7835,7 +7917,7 @@ function matchIdentifierBody(parser) {
7835
7917
  id += next;
7836
7918
  }
7837
7919
  while (!parser.atEnd && /\d/.test(parser.peek))
7838
- id += parser.next();
7920
+ id += parser.nextToken();
7839
7921
  }
7840
7922
  while (!parser.atEnd) {
7841
7923
  if (parser.match("\\degree"))
@@ -7884,7 +7966,7 @@ function matchPrefixedIdentifier(parser) {
7884
7966
  const prefix = IDENTIFIER_PREFIX[parser.peek] ?? null;
7885
7967
  if (prefix === null)
7886
7968
  return null;
7887
- parser.next();
7969
+ parser.nextToken();
7888
7970
  if (parser.match("<{>")) {
7889
7971
  let body = "";
7890
7972
  const digit = {
@@ -7901,7 +7983,7 @@ function matchPrefixedIdentifier(parser) {
7901
7983
  }[parser.peek] ?? "";
7902
7984
  if (digit) {
7903
7985
  body = digit;
7904
- parser.next();
7986
+ parser.nextToken();
7905
7987
  }
7906
7988
  body += matchIdentifierBody(parser);
7907
7989
  if (body === null || !parser.match("<}>")) {
@@ -7915,7 +7997,7 @@ function matchPrefixedIdentifier(parser) {
7915
7997
  parser.index = start;
7916
7998
  return null;
7917
7999
  }
7918
- function matchInvalidIdentifier(parser) {
8000
+ function parseInvalidIdentifier(parser) {
7919
8001
  const start = parser.index;
7920
8002
  const id = matchPrefixedIdentifier(parser);
7921
8003
  if (id === null || isValidIdentifier(id)) {
@@ -7929,13 +8011,13 @@ function matchInvalidIdentifier(parser) {
7929
8011
  }
7930
8012
  function matchIdentifier(parser) {
7931
8013
  if (/^[a-zA-Z]$/.test(parser.peek) || /^\p{XIDS}$/u.test(parser.peek))
7932
- return parser.next();
8014
+ return parser.nextToken();
7933
8015
  const start = parser.index;
7934
8016
  let id = matchPrefixedIdentifier(parser);
7935
8017
  if (!id) {
7936
8018
  id = "";
7937
8019
  while (!parser.atEnd && ONLY_EMOJIS.test(id + parser.peek))
7938
- id += parser.next();
8020
+ id += parser.nextToken();
7939
8021
  }
7940
8022
  if (id) {
7941
8023
  id = id.normalize();
@@ -7982,10 +8064,6 @@ var DELIMITER_SHORTHAND = {
7982
8064
  "\\lmoustache": ["\\lmoustache"],
7983
8065
  "\\rmoustache": ["\\rmoustache"]
7984
8066
  };
7985
- var MIDDLE_DELIMITER = {
7986
- ":": [":", "\\colon"],
7987
- "|": ["|", "\\|", "\\mid", "\\mvert"]
7988
- };
7989
8067
  var OPEN_DELIMITER_PREFIX = {
7990
8068
  "\\left": "\\right",
7991
8069
  "\\bigl": "\\bigr",
@@ -7997,17 +8075,6 @@ var OPEN_DELIMITER_PREFIX = {
7997
8075
  "\\bigg": "\\bigg",
7998
8076
  "\\Bigg": "\\Bigg"
7999
8077
  };
8000
- var MIDDLE_DELIMITER_PREFIX = [
8001
- "\\middle",
8002
- "\\bigm",
8003
- "\\Bigm",
8004
- "\\biggm",
8005
- "\\Biggm",
8006
- "\\big",
8007
- "\\Big",
8008
- "\\bigg",
8009
- "\\Bigg"
8010
- ];
8011
8078
  var CLOSE_DELIMITER = {
8012
8079
  "(": ")",
8013
8080
  "[": "]",
@@ -8162,7 +8229,7 @@ var _Parser = class {
8162
8229
  this._lastPeek = peek;
8163
8230
  return peek;
8164
8231
  }
8165
- next() {
8232
+ nextToken() {
8166
8233
  return this._tokens[this.index++];
8167
8234
  }
8168
8235
  /**
@@ -8215,15 +8282,14 @@ var _Parser = class {
8215
8282
  latexAhead(n) {
8216
8283
  return this.latex(this.index, this.index + n);
8217
8284
  }
8218
- latexBefore() {
8219
- return this.latex(0, this.index);
8220
- }
8221
- latexAfter() {
8222
- return this.latex(this.index);
8223
- }
8285
+ // latexBefore(): string {
8286
+ // return this.latex(0, this.index);
8287
+ // }
8288
+ // latexAfter(): string {
8289
+ // return this.latex(this.index);
8290
+ // }
8224
8291
  /**
8225
- * Return at most `this._dictionary.lookahead` strings made from the tokens
8226
- * ahead.
8292
+ * Return at most `this._dictionary.lookahead` LaTeX tokens.
8227
8293
  *
8228
8294
  * The index in the returned array correspond to the number of tokens.
8229
8295
  * Note that since a token can be longer than one char ('\\pi', but also
@@ -8231,6 +8297,10 @@ var _Parser = class {
8231
8297
  * does not match that index. However, knowing the index is important
8232
8298
  * to know by how many tokens to advance.
8233
8299
  *
8300
+ * For example:
8301
+ *
8302
+ * `[empty, '\\sqrt', '\\sqrt{', '\\sqrt{2', '\\sqrt{2}']`
8303
+ *
8234
8304
  */
8235
8305
  lookAhead() {
8236
8306
  let n = Math.min(
@@ -8249,12 +8319,12 @@ var _Parser = class {
8249
8319
  if (kind === "function") {
8250
8320
  const start = this.index;
8251
8321
  if (this.match("\\operatorname") || this.match("\\mathrm") || this.match("\\mathit")) {
8252
- const fn = this.matchStringArgument();
8322
+ const fn = this.parseStringGroup()?.trim();
8253
8323
  const n = this.index - start;
8254
8324
  this.index = start;
8255
- if (fn !== null && this._dictionary.function.has(fn))
8256
- return this._dictionary.function.get(fn).map((x) => [x, n]);
8257
- return null;
8325
+ if (!fn || !this._dictionary.function.has(fn))
8326
+ return null;
8327
+ return this._dictionary.function.get(fn).map((x) => [x, n]);
8258
8328
  }
8259
8329
  return null;
8260
8330
  } else if (kind === "operator") {
@@ -8287,19 +8357,19 @@ var _Parser = class {
8287
8357
  * instead.
8288
8358
  */
8289
8359
  skipSpace() {
8290
- if (!this.options.skipSpace)
8291
- return false;
8292
8360
  if (!this.atEnd && this.peek === "<{>") {
8293
8361
  const index = this.index;
8294
- this.next();
8362
+ this.nextToken();
8295
8363
  while (this.match("<space>")) {
8296
8364
  }
8297
- if (this.next() === "<}>") {
8365
+ if (this.nextToken() === "<}>") {
8298
8366
  this.skipSpace();
8299
8367
  return true;
8300
8368
  }
8301
8369
  this.index = index;
8302
8370
  }
8371
+ if (!this.options.skipSpace)
8372
+ return false;
8303
8373
  let result = false;
8304
8374
  while (this.match("<space>"))
8305
8375
  result = true;
@@ -8322,11 +8392,36 @@ var _Parser = class {
8322
8392
  "\\quad",
8323
8393
  "\\qquad"
8324
8394
  ].includes(this.peek)) {
8325
- this.next();
8395
+ this.nextToken();
8326
8396
  this.skipVisualSpace();
8327
8397
  }
8328
8398
  this.skipSpace();
8329
8399
  }
8400
+ match(token) {
8401
+ if (this._tokens[this.index] === token) {
8402
+ this.index++;
8403
+ return true;
8404
+ }
8405
+ return false;
8406
+ }
8407
+ matchAll(tokens) {
8408
+ console.assert(Array.isArray(tokens));
8409
+ if (tokens.length === 0)
8410
+ return false;
8411
+ let matched = true;
8412
+ let i = 0;
8413
+ do {
8414
+ matched = this._tokens[this.index + i] === tokens[i++];
8415
+ } while (matched && i < tokens.length);
8416
+ if (matched)
8417
+ this.index += i;
8418
+ return matched;
8419
+ }
8420
+ matchAny(tokens) {
8421
+ if (tokens.includes(this._tokens[this.index]))
8422
+ return this._tokens[this.index++];
8423
+ return "";
8424
+ }
8330
8425
  matchChar() {
8331
8426
  const index = this.index;
8332
8427
  let caretCount = 0;
@@ -8373,7 +8468,7 @@ var _Parser = class {
8373
8468
  } else if (this.match("\\unicode")) {
8374
8469
  this.skipSpaceTokens();
8375
8470
  if (this.peek === "<{>") {
8376
- this.next();
8471
+ this.nextToken();
8377
8472
  const codepoint = this.matchLatexNumber();
8378
8473
  if (this.match("<}>") && codepoint !== null && codepoint >= 0 && codepoint <= 1114111) {
8379
8474
  return String.fromCodePoint(codepoint);
@@ -8388,62 +8483,171 @@ var _Parser = class {
8388
8483
  this.index = index;
8389
8484
  return null;
8390
8485
  }
8391
- matchColor(_background = false) {
8392
- let s = "";
8393
- while (!this.atEnd && this.peek !== "}")
8394
- s += this.next();
8395
- return s;
8396
- }
8397
- matchLatexDimension() {
8398
- return null;
8399
- }
8400
- match(token) {
8401
- if (this._tokens[this.index] === token) {
8402
- this.index++;
8403
- return true;
8486
+ parseGroup() {
8487
+ const start = this.index;
8488
+ this.skipSpaceTokens();
8489
+ if (this.match("<{>")) {
8490
+ this.addBoundary(["<}>"]);
8491
+ const expr = this.parseExpression();
8492
+ this.skipSpace();
8493
+ if (this.matchBoundary())
8494
+ return expr ?? ["Sequence"];
8495
+ const from = this.index;
8496
+ while (!this.matchBoundary() && !this.atEnd)
8497
+ this.nextToken();
8498
+ const err = this.error("syntax-error", from);
8499
+ return expr ? ["Sequence", expr, err] : err;
8404
8500
  }
8405
- return false;
8501
+ this.index = start;
8502
+ return null;
8406
8503
  }
8407
- matchAll(tokens) {
8408
- if (typeof tokens === "string")
8409
- tokens = [tokens];
8410
- if (tokens.length === 0)
8411
- return false;
8412
- let matched = true;
8413
- let i = 0;
8414
- do {
8415
- matched = this._tokens[this.index + i] === tokens[i++];
8416
- } while (matched && i < tokens.length);
8417
- if (matched)
8418
- this.index += i;
8419
- return matched;
8504
+ // Some LaTeX commands (but not all) can accept an argument without braces,
8505
+ // for example `^` , `\sqrt` or `\frac`.
8506
+ // This argument will usually be a single token, but can be a sequence of
8507
+ // tokens (e.g. `\sqrt\frac12` or `\sqrt\mathrm{speed}`).
8508
+ parseToken() {
8509
+ const excluding = [
8510
+ ...'!"#$%&(),/;:?@[]\\`|~'.split(""),
8511
+ "\\left",
8512
+ "\\bigl"
8513
+ ];
8514
+ if (excluding.includes(this.peek))
8515
+ return null;
8516
+ if (/^[0-9]$/.test(this.peek))
8517
+ return parseInt(this.nextToken());
8518
+ const result = this.parseGenericExpression() ?? this.parseSymbol();
8519
+ if (!result)
8520
+ return null;
8521
+ return result;
8420
8522
  }
8421
- matchAny(tokens) {
8422
- if (tokens.includes(this._tokens[this.index]))
8423
- return this._tokens[this.index++];
8424
- return "";
8523
+ parseOptionalGroup() {
8524
+ const index = this.index;
8525
+ this.skipSpaceTokens();
8526
+ if (this.match("[")) {
8527
+ this.addBoundary(["]"]);
8528
+ const expr = this.parseExpression();
8529
+ this.skipSpace();
8530
+ if (this.matchBoundary())
8531
+ return expr;
8532
+ return this.boundaryError("expected-closing-delimiter");
8533
+ }
8534
+ this.index = index;
8535
+ return null;
8425
8536
  }
8426
- matchSequence(tokens) {
8537
+ /**
8538
+ * Parse an expression in a tabular format, where rows are separated by `\\`
8539
+ * and columns by `&`.
8540
+ *
8541
+ * Return rows of sparse columns: empty rows are indicated with `Nothing`,
8542
+ * and empty cells are also indicated with `Nothing`.
8543
+ */
8544
+ parseTabular() {
8427
8545
  const result = [];
8428
- while (tokens.includes(this._tokens[this.index]))
8429
- result.push(this._tokens[this.index++]);
8546
+ let row = [];
8547
+ let expr = null;
8548
+ while (!this.atBoundary) {
8549
+ this.skipSpace();
8550
+ if (this.match("&")) {
8551
+ row.push(expr ?? "Nothing");
8552
+ expr = null;
8553
+ } else if (this.match("\\\\") || this.match("\\cr")) {
8554
+ this.skipSpace();
8555
+ this.parseOptionalGroup();
8556
+ if (expr !== null)
8557
+ row.push(expr);
8558
+ result.push(row);
8559
+ row = [];
8560
+ expr = null;
8561
+ } else {
8562
+ const cell = [];
8563
+ let peek = this.peek;
8564
+ while (peek !== "&" && peek !== "\\\\" && peek !== "\\cr" && !this.atBoundary) {
8565
+ expr = this.parseExpression({
8566
+ condition: (p) => {
8567
+ const peek2 = p.peek;
8568
+ return peek2 === "&" || peek2 === "\\\\" || peek2 === "\\cr";
8569
+ }
8570
+ });
8571
+ if (expr)
8572
+ cell.push(expr);
8573
+ else {
8574
+ cell.push(["Error", ["'unexpected-token'", peek]]);
8575
+ this.nextToken();
8576
+ }
8577
+ this.skipSpace();
8578
+ peek = this.peek;
8579
+ }
8580
+ if (cell.length > 1)
8581
+ expr = ["Sequence", ...cell];
8582
+ else
8583
+ expr = cell[0] ?? "Nothing";
8584
+ }
8585
+ }
8586
+ if (expr !== null)
8587
+ row.push(expr);
8588
+ if (row.length > 0)
8589
+ result.push(row);
8430
8590
  return result;
8431
8591
  }
8432
- matchOptionalSign() {
8592
+ /** Parse a group as a a string, for example for `\operatorname` or `\begin` */
8593
+ parseStringGroup() {
8594
+ const start = this.index;
8595
+ while (this.match("<space>")) {
8596
+ }
8597
+ if (this.match("<{>")) {
8598
+ this.addBoundary(["<}>"]);
8599
+ const arg = this.parseStringGroupContent();
8600
+ if (this.matchBoundary())
8601
+ return arg;
8602
+ this.removeBoundary();
8603
+ }
8604
+ this.index = start;
8605
+ return null;
8606
+ }
8607
+ /** Parse an environment: `\begin{env}...\end{end}`
8608
+ */
8609
+ parseEnvironment() {
8610
+ const index = this.index;
8611
+ if (!this.match("\\begin"))
8612
+ return null;
8613
+ const name = this.parseStringGroup()?.trim();
8614
+ if (!name)
8615
+ return this.error("expected-environment-name", index);
8616
+ this.addBoundary(["\\end", "<{>", ...name.split(""), "<}>"]);
8617
+ const def = this._dictionary.environment.get(name);
8618
+ if (!def) {
8619
+ this.parseTabular();
8620
+ this.skipSpace();
8621
+ if (!this.matchBoundary())
8622
+ return this.boundaryError("unbalanced-environment");
8623
+ return this.error(["unknown-environment", { str: name }], index);
8624
+ }
8625
+ const expr = def.parse(this, [], []);
8626
+ this.skipSpace();
8627
+ if (!this.matchBoundary())
8628
+ return this.boundaryError("unbalanced-environment");
8629
+ if (expr !== null)
8630
+ return this.decorate(expr, index);
8631
+ this.index = index;
8632
+ return null;
8633
+ }
8634
+ /** If the next token matches a `+` or `-` sign, return it and advance the index.
8635
+ * Otherwise return `''` and do not advance */
8636
+ parseOptionalSign() {
8433
8637
  let isNegative = !!this.matchAny(["-", "\u2212"]);
8434
8638
  while (this.matchAny(["+", "\uFE62"]) || this.skipSpace())
8435
8639
  if (this.matchAny(["-", "\u2212"]))
8436
8640
  isNegative = !isNegative;
8437
8641
  return isNegative ? "-" : "+";
8438
8642
  }
8439
- matchDecimalDigits(options) {
8643
+ parseDecimalDigits(options) {
8440
8644
  options ?? (options = {});
8441
8645
  options.withGrouping ?? (options.withGrouping = false);
8442
8646
  const result = [];
8443
8647
  let done = false;
8444
8648
  while (!done) {
8445
8649
  while (/^[0-9]$/.test(this.peek)) {
8446
- result.push(this.next());
8650
+ result.push(this.nextToken());
8447
8651
  this.skipVisualSpace();
8448
8652
  }
8449
8653
  done = true;
@@ -8461,21 +8665,21 @@ var _Parser = class {
8461
8665
  }
8462
8666
  return result.join("");
8463
8667
  }
8464
- matchSignedInteger(options) {
8668
+ parseSignedInteger(options) {
8465
8669
  options ?? (options = {});
8466
8670
  options.withGrouping ?? (options.withGrouping = false);
8467
8671
  const start = this.index;
8468
- const sign2 = this.matchOptionalSign();
8469
- const result = this.matchDecimalDigits(options);
8672
+ const sign2 = this.parseOptionalSign();
8673
+ const result = this.parseDecimalDigits(options);
8470
8674
  if (result)
8471
8675
  return sign2 === "-" ? "-" + result : result;
8472
8676
  this.index = start;
8473
8677
  return "";
8474
8678
  }
8475
- matchExponent() {
8679
+ parseExponent() {
8476
8680
  const start = this.index;
8477
8681
  if (this.matchAny(["e", "E"])) {
8478
- const exponent = this.matchSignedInteger({ withGrouping: false });
8682
+ const exponent = this.parseSignedInteger({ withGrouping: false });
8479
8683
  if (exponent)
8480
8684
  return "e" + exponent;
8481
8685
  }
@@ -8484,10 +8688,10 @@ var _Parser = class {
8484
8688
  this.skipSpaceTokens();
8485
8689
  if (this.match("1") && this.match("0") && this.match("^")) {
8486
8690
  if (/^[0-9]$/.test(this.peek))
8487
- return "e" + this.next();
8691
+ return "e" + this.nextToken();
8488
8692
  if (this.match("<{>")) {
8489
8693
  this.skipSpaceTokens();
8490
- const exponent = this.matchSignedInteger();
8694
+ const exponent = this.parseSignedInteger();
8491
8695
  this.skipSpaceTokens();
8492
8696
  if (this.match("<}>") && exponent)
8493
8697
  return "e" + exponent;
@@ -8503,7 +8707,7 @@ var _Parser = class {
8503
8707
  this.skipSpaceTokens();
8504
8708
  if (this.matchAll(this._beginExponentMarkerTokens)) {
8505
8709
  this.skipSpaceTokens();
8506
- const exponent = this.matchSignedInteger();
8710
+ const exponent = this.parseSignedInteger();
8507
8711
  this.skipSpaceTokens();
8508
8712
  if (this.matchAll(this._endExponentMarkerTokens) && exponent)
8509
8713
  return "e" + exponent;
@@ -8512,11 +8716,11 @@ var _Parser = class {
8512
8716
  this.index = start;
8513
8717
  return "";
8514
8718
  }
8515
- matchRepeatingDecimal() {
8719
+ parseRepeatingDecimal() {
8516
8720
  const start = this.index;
8517
8721
  let repeatingDecimals2 = "";
8518
8722
  if (this.match("(")) {
8519
- repeatingDecimals2 = this.matchDecimalDigits();
8723
+ repeatingDecimals2 = this.parseDecimalDigits();
8520
8724
  if (repeatingDecimals2 && this.match(")"))
8521
8725
  return "(" + repeatingDecimals2 + ")";
8522
8726
  this.index = start;
@@ -8524,7 +8728,7 @@ var _Parser = class {
8524
8728
  }
8525
8729
  this.index = start;
8526
8730
  if (this.matchAll([`\\left`, "("])) {
8527
- repeatingDecimals2 = this.matchDecimalDigits();
8731
+ repeatingDecimals2 = this.parseDecimalDigits();
8528
8732
  if (repeatingDecimals2 && this.matchAll([`\\right`, ")"]))
8529
8733
  return "(" + repeatingDecimals2 + ")";
8530
8734
  this.index = start;
@@ -8532,7 +8736,7 @@ var _Parser = class {
8532
8736
  }
8533
8737
  this.index = start;
8534
8738
  if (this.matchAll([`\\overline`, "<{>"])) {
8535
- repeatingDecimals2 = this.matchDecimalDigits();
8739
+ repeatingDecimals2 = this.parseDecimalDigits();
8536
8740
  if (repeatingDecimals2 && this.match("<}>"))
8537
8741
  return "(" + repeatingDecimals2 + ")";
8538
8742
  this.index = start;
@@ -8540,7 +8744,7 @@ var _Parser = class {
8540
8744
  }
8541
8745
  this.index = start;
8542
8746
  if (this.matchAll(this._beginRepeatingDigitsTokens)) {
8543
- repeatingDecimals2 = this.matchDecimalDigits();
8747
+ repeatingDecimals2 = this.parseDecimalDigits();
8544
8748
  if (repeatingDecimals2 && this.matchAll(this._endRepeatingDigitsTokens))
8545
8749
  return "(" + repeatingDecimals2 + ")";
8546
8750
  this.index = start;
@@ -8549,9 +8753,13 @@ var _Parser = class {
8549
8753
  this.index = start;
8550
8754
  return "";
8551
8755
  }
8552
- matchNumber() {
8756
+ /**
8757
+ * Parse a number, with an optional sign, exponent, decimal marker,
8758
+ * repeating decimals, etc...
8759
+ */
8760
+ parseNumber() {
8553
8761
  if (!this.options.parseNumbers)
8554
- return "";
8762
+ return null;
8555
8763
  const start = this.index;
8556
8764
  this.skipVisualSpace();
8557
8765
  this.match("+");
@@ -8561,32 +8769,32 @@ var _Parser = class {
8561
8769
  const peek = this.peek;
8562
8770
  if (peek !== "\\overline" && peek !== this._beginRepeatingDigitsTokens[0] && !/[0-9\(]/.test(peek)) {
8563
8771
  this.index = start;
8564
- return "";
8772
+ return null;
8565
8773
  }
8566
8774
  dotPrefix = true;
8567
8775
  } else {
8568
- result = this.matchDecimalDigits({ withGrouping: true });
8776
+ result = this.parseDecimalDigits({ withGrouping: true });
8569
8777
  if (!result) {
8570
8778
  this.index = start;
8571
- return "";
8779
+ return null;
8572
8780
  }
8573
8781
  }
8574
8782
  let hasDecimal = true;
8575
8783
  if (!dotPrefix && (this.match(".") || this.matchAll(this._decimalMarkerTokens)))
8576
- result += "." + this.matchDecimalDigits({ withGrouping: true });
8784
+ result += "." + this.parseDecimalDigits({ withGrouping: true });
8577
8785
  else if (dotPrefix)
8578
- result = "0." + this.matchDecimalDigits({ withGrouping: true });
8786
+ result = "0." + this.parseDecimalDigits({ withGrouping: true });
8579
8787
  else
8580
8788
  hasDecimal = false;
8581
8789
  if (hasDecimal) {
8582
- const repeat = this.matchRepeatingDecimal();
8790
+ const repeat = this.parseRepeatingDecimal();
8583
8791
  if (repeat)
8584
8792
  result += repeat;
8585
8793
  else if (this.match("\\ldots") || this.matchAll(this._truncationMarkerTokens)) {
8586
8794
  }
8587
8795
  }
8588
8796
  this.skipVisualSpace();
8589
- return result + this.matchExponent();
8797
+ return result + this.parseExponent();
8590
8798
  }
8591
8799
  /**
8592
8800
  * A Latex number can be a decimal, hex or octal number.
@@ -8605,7 +8813,7 @@ var _Parser = class {
8605
8813
  while (token === "<space>" || token === "+" || token === "-") {
8606
8814
  if (token === "-")
8607
8815
  negative = !negative;
8608
- this.next();
8816
+ this.nextToken();
8609
8817
  token = this.peek;
8610
8818
  }
8611
8819
  let radix = 10;
@@ -8636,7 +8844,7 @@ var _Parser = class {
8636
8844
  ];
8637
8845
  isInteger = true;
8638
8846
  } else if (this.match("`")) {
8639
- token = this.next();
8847
+ token = this.nextToken();
8640
8848
  if (token) {
8641
8849
  if (token.startsWith("\\") && token.length === 2) {
8642
8850
  return (negative ? -1 : 1) * (token.codePointAt(1) ?? 0);
@@ -8647,12 +8855,12 @@ var _Parser = class {
8647
8855
  }
8648
8856
  let value = "";
8649
8857
  while (digits.includes(this.peek)) {
8650
- value += this.next();
8858
+ value += this.nextToken();
8651
8859
  }
8652
8860
  if (!isInteger && this.match(".")) {
8653
8861
  value += ".";
8654
8862
  while (digits.includes(this.peek)) {
8655
- value += this.next();
8863
+ value += this.nextToken();
8656
8864
  }
8657
8865
  }
8658
8866
  const result = isInteger ? Number.parseInt(value, radix) : Number.parseFloat(value);
@@ -8660,7 +8868,7 @@ var _Parser = class {
8660
8868
  return null;
8661
8869
  return negative ? -result : result;
8662
8870
  }
8663
- matchPrefixOperator(until) {
8871
+ parsePrefixOperator(until) {
8664
8872
  if (!until)
8665
8873
  until = { minPrec: 0 };
8666
8874
  if (!until.minPrec)
@@ -8678,7 +8886,7 @@ var _Parser = class {
8678
8886
  this.index = start;
8679
8887
  return null;
8680
8888
  }
8681
- matchInfixOperator(lhs, until) {
8889
+ parseInfixOperator(lhs, until) {
8682
8890
  until ?? (until = { minPrec: 0 });
8683
8891
  if (until.minPrec === void 0)
8684
8892
  until = { ...until, minPrec: 0 };
@@ -8689,7 +8897,7 @@ var _Parser = class {
8689
8897
  for (const [def, n] of defs) {
8690
8898
  if (def.precedence >= until.minPrec) {
8691
8899
  this.index = start + n;
8692
- const rhs = def.parse(this, until, lhs);
8900
+ const rhs = def.parse(this, lhs, until);
8693
8901
  if (rhs)
8694
8902
  return rhs;
8695
8903
  }
@@ -8698,99 +8906,74 @@ var _Parser = class {
8698
8906
  return null;
8699
8907
  }
8700
8908
  /**
8701
- * - 'enclosure' : will look for an argument inside an enclosure (open/close fence)
8909
+ * This returns an array of arguments (as in a function application),
8910
+ * or null if there is no match.
8911
+ *
8912
+ * - 'enclosure' : will look for an argument inside an enclosure
8913
+ * (open/close fence)
8702
8914
  * - 'implicit': either an expression inside a pair of `()`, or just a product
8703
8915
  * (i.e. we interpret `\cos 2x + 1` as `\cos(2x) + 1`)
8916
+ *
8704
8917
  */
8705
- matchArguments(kind, until) {
8706
- if (!kind)
8707
- return null;
8918
+ parseArguments(kind = "enclosure", until) {
8708
8919
  if (this.atTerminator(until))
8709
8920
  return null;
8710
- const savedIndex = this.index;
8711
- const group = this.matchEnclosure();
8712
- if (kind === "enclosure" && head(group) === "Delimiter") {
8713
- if (op(group, 1) === "Sequence")
8714
- return ops(op(group, 1)) ?? [];
8715
- return [op(group, 1) ?? ["Sequence"]];
8716
- }
8717
- if (kind === "implicit") {
8718
- if (head(group) === "Delimiter") {
8719
- if (head(op(group, 1)) === "Sequence")
8720
- return getSequence(group) ?? [];
8721
- return [op(group, 1) ?? ["Sequence"]];
8722
- }
8723
- if (group !== null)
8724
- return [group];
8725
- const primary = this.matchExpression({ ...until, minPrec: 390 });
8726
- if (primary !== null)
8727
- return [primary];
8728
- return null;
8729
- }
8730
- this.index = savedIndex;
8731
- return null;
8732
- }
8733
- /**
8734
- * A function can be followed by the following suffixes:
8735
- * - a `\prime`, `\doubleprime`, `'`, `(n)` to indicate a derivative
8736
- * - a subscript to indicate an argument
8737
- * - an argument, optionally inside an enclosure
8738
- */
8739
- matchFunctionSuffix(id) {
8740
- let fn = id;
8741
- do {
8742
- const pf = this.matchPostfix(fn);
8743
- if (pf === null)
8744
- break;
8745
- fn = pf;
8746
- } while (true);
8747
- const seq = this.matchArguments("enclosure");
8748
- return seq ? [fn, ...seq] : id;
8749
- }
8750
- /** A prime suffix is a sequence of `'`, `\prime` or `\doubleprime`
8751
- * after a function or in a superscript.
8752
- */
8753
- matchPrimeSuffix() {
8754
- this.skipSpace();
8755
- const start = this.index;
8756
- let count = 0;
8757
- if (this.match("^")) {
8758
- if (this.match("<{>")) {
8759
- if (this.match("(")) {
8760
- const n = this.matchNumber();
8761
- if (n && this.match(")"))
8762
- return parseInt(n);
8763
- this.index = start;
8764
- return 0;
8765
- }
8766
- do {
8767
- const c = countPrimeLevel(this);
8768
- if (c === 0)
8769
- break;
8770
- count += c;
8771
- } while (true);
8772
- if (count !== 0 && this.match("<}>"))
8773
- return count;
8774
- this.index = start;
8775
- return 0;
8776
- }
8777
- count = countPrimeLevel(this);
8778
- if (count !== 0)
8779
- return count;
8780
- this.index = start;
8781
- return 0;
8921
+ const savedIndex = this.index;
8922
+ const group = this.parseEnclosure();
8923
+ if (kind === "enclosure") {
8924
+ if (group === null)
8925
+ return null;
8926
+ return getSequence(group) ?? [];
8782
8927
  }
8783
- do {
8784
- const c = countPrimeLevel(this);
8785
- if (c === 0)
8786
- break;
8787
- count += c;
8788
- } while (true);
8789
- if (count !== 0)
8790
- return count;
8791
- this.index = start;
8792
- return 0;
8928
+ if (kind === "implicit") {
8929
+ if (head(group) === "Delimiter")
8930
+ return getSequence(group) ?? [];
8931
+ if (group !== null)
8932
+ return [group];
8933
+ const primary = this.parseExpression({ ...until, minPrec: 390 });
8934
+ return primary === null ? null : [primary];
8935
+ }
8936
+ this.index = savedIndex;
8937
+ return null;
8793
8938
  }
8939
+ /** A prime suffix is a sequence of `'`, `\prime` or `\doubleprime`
8940
+ * after a function or in a superscript.
8941
+ */
8942
+ // matchPrimeSuffix(): number {
8943
+ // this.skipSpace();
8944
+ // const start = this.index;
8945
+ // let count = 0;
8946
+ // if (this.match('^')) {
8947
+ // if (this.match('<{>')) {
8948
+ // if (this.match('(')) {
8949
+ // const n = this.parseNumber();
8950
+ // if (n && this.match(')')) return parseInt(n);
8951
+ // this.index = start;
8952
+ // return 0;
8953
+ // }
8954
+ // do {
8955
+ // const c = countPrimeLevel(this);
8956
+ // if (c === 0) break;
8957
+ // count += c;
8958
+ // } while (true);
8959
+ // if (count !== 0 && this.match('<}>')) return count;
8960
+ // this.index = start;
8961
+ // return 0;
8962
+ // }
8963
+ // count = countPrimeLevel(this);
8964
+ // if (count !== 0) return count;
8965
+ // this.index = start;
8966
+ // return 0;
8967
+ // }
8968
+ // do {
8969
+ // const c = countPrimeLevel(this);
8970
+ // if (c === 0) break;
8971
+ // count += c;
8972
+ // } while (true);
8973
+ // if (count !== 0) return count;
8974
+ // this.index = start;
8975
+ // return 0;
8976
+ // }
8794
8977
  /** If matches the normalized open delimiter, return the
8795
8978
  * expected closing delimiter.
8796
8979
  *
@@ -8803,7 +8986,7 @@ var _Parser = class {
8803
8986
  const index = this.index;
8804
8987
  const closePrefix = OPEN_DELIMITER_PREFIX[this.peek];
8805
8988
  if (closePrefix)
8806
- this.next();
8989
+ this.nextToken();
8807
8990
  const alternatives = DELIMITER_SHORTHAND[openDelim] ?? [openDelim];
8808
8991
  const result = closePrefix ? [closePrefix] : [];
8809
8992
  if (alternatives.includes("||") && this.matchAll(["|", "|"])) {
@@ -8820,28 +9003,30 @@ var _Parser = class {
8820
9003
  } else {
8821
9004
  result.push(closeDelim);
8822
9005
  }
8823
- this.next();
9006
+ this.nextToken();
8824
9007
  return result;
8825
9008
  }
8826
- matchMiddleDelimiter(delimiter) {
8827
- const delimiters = MIDDLE_DELIMITER[delimiter] ?? [delimiter];
8828
- if (MIDDLE_DELIMITER_PREFIX.includes(this.peek)) {
8829
- const index = this.index;
8830
- this.next();
8831
- if (delimiters.includes(this.peek)) {
8832
- this.next();
8833
- return true;
8834
- }
8835
- this.index = index;
8836
- return false;
8837
- } else if (delimiters.include(this.peek)) {
8838
- this.next();
8839
- return true;
8840
- }
8841
- return false;
8842
- }
9009
+ // matchMiddleDelimiter(delimiter: '|' | ':' | LatexToken): boolean {
9010
+ // const delimiters = MIDDLE_DELIMITER[delimiter] ?? [delimiter];
9011
+ // if (MIDDLE_DELIMITER_PREFIX.includes(this.peek)) {
9012
+ // const index = this.index;
9013
+ // this.nextToken();
9014
+ // if (delimiters.includes(this.peek)) {
9015
+ // this.nextToken();
9016
+ // return true;
9017
+ // }
9018
+ // this.index = index;
9019
+ // return false;
9020
+ // } else if (delimiters.include(this.peek)) {
9021
+ // this.nextToken();
9022
+ // return true;
9023
+ // }
9024
+ // return false;
9025
+ // }
8843
9026
  /** For error handling, when there is potentially a mismatched delimiter.
8844
9027
  * Return a LaTeX fragment of the expected closing delimiter
9028
+ *
9029
+ * @internal
8845
9030
  */
8846
9031
  matchEnclosureOpen() {
8847
9032
  const defs = this._dictionary.matchfix;
@@ -8865,6 +9050,9 @@ var _Parser = class {
8865
9050
  this.index = start;
8866
9051
  return null;
8867
9052
  }
9053
+ /**
9054
+ * Used for error handling
9055
+ * @internal */
8868
9056
  matchEnclosureClose() {
8869
9057
  const defs = this._dictionary.matchfix;
8870
9058
  if (defs.length === 0)
@@ -8883,7 +9071,7 @@ var _Parser = class {
8883
9071
  (x) => OPEN_DELIMITER_PREFIX[x] === peek
8884
9072
  );
8885
9073
  if (prefix)
8886
- this.next();
9074
+ this.nextToken();
8887
9075
  let openDelimiter = [];
8888
9076
  peek = this.peek;
8889
9077
  const matchingDelim = Object.keys(CLOSE_DELIMITER).find(
@@ -8894,7 +9082,7 @@ var _Parser = class {
8894
9082
  if (prefix)
8895
9083
  openDelimiter = [prefix, ...openDelimiter];
8896
9084
  if (openDelimiter.length > 0) {
8897
- this.next();
9085
+ this.nextToken();
8898
9086
  return tokensToString(openDelimiter);
8899
9087
  }
8900
9088
  }
@@ -8906,7 +9094,7 @@ var _Parser = class {
8906
9094
  * optionally followed multiple times by a separator and another expression,
8907
9095
  * and finally a closing matching operator.
8908
9096
  */
8909
- matchEnclosure() {
9097
+ parseEnclosure() {
8910
9098
  const defs = this._dictionary.matchfix;
8911
9099
  if (defs.length === 0)
8912
9100
  return null;
@@ -8917,7 +9105,7 @@ var _Parser = class {
8917
9105
  if (!this.matchAll(def.openDelimiter))
8918
9106
  continue;
8919
9107
  this.addBoundary(def.closeDelimiter);
8920
- const body2 = this.matchExpression();
9108
+ const body2 = this.parseExpression();
8921
9109
  this.skipSpace();
8922
9110
  if (!this.matchBoundary()) {
8923
9111
  this.removeBoundary();
@@ -8942,12 +9130,12 @@ var _Parser = class {
8942
9130
  }
8943
9131
  this.addBoundary(closeDelimiter);
8944
9132
  const bodyStart = this.index;
8945
- let body = this.matchExpression();
9133
+ let body = this.parseExpression();
8946
9134
  this.skipSpace();
8947
9135
  if (!this.matchBoundary()) {
8948
9136
  this.removeBoundary();
8949
9137
  this.index = bodyStart;
8950
- body = this.matchExpression();
9138
+ body = this.parseExpression();
8951
9139
  if (!this.matchAll(closeDelimiter)) {
8952
9140
  if (!this.atEnd)
8953
9141
  continue;
@@ -8962,52 +9150,74 @@ var _Parser = class {
8962
9150
  this.index = start;
8963
9151
  return null;
8964
9152
  }
8965
- matchIdentifier() {
8966
- return matchIdentifier(this);
8967
- }
8968
9153
  /**
8969
- * A function is an identifier followed by arguments
8970
- * - a single letter identifier with explicit arguments `f(x)`
8971
- * - a multiletter identifier with explicit arguments `\mathrm{floor}(x)`
8972
- * - an identifier: `\mathrm{floor}`
8973
- * - a command with implicit arguments: `\cos x` (via a custom parser)
8974
- *
9154
+ * A generic expression is used for dictionary entries that take do
9155
+ * some complex (non-standard) parsing. This includes trig functions (to
9156
+ * parse implicit arguments), and integrals (to parse the integrand and
9157
+ * limits and the "dx" terminator).
8975
9158
  */
8976
- matchFunction(until) {
9159
+ parseGenericExpression(until) {
8977
9160
  if (this.atTerminator(until))
8978
9161
  return null;
8979
9162
  const start = this.index;
8980
- const fnDefs = this.peekDefinitions("function");
8981
- if (fnDefs) {
8982
- for (const [def, tokenCount] of fnDefs) {
8983
- this.index = start + tokenCount;
8984
- if (typeof def.parse === "function") {
8985
- const result = def.parse(this, until);
8986
- if (result)
8987
- return result;
8988
- } else {
8989
- return this.matchFunctionSuffix(def.name);
8990
- }
9163
+ let expr = null;
9164
+ const fnDefs = this.peekDefinitions("expression") ?? [];
9165
+ for (const [def, tokenCount] of fnDefs) {
9166
+ this.index = start + tokenCount;
9167
+ if (typeof def.parse === "function") {
9168
+ expr = def.parse(this, until);
9169
+ if (expr !== null)
9170
+ return expr;
9171
+ } else {
9172
+ return def.name;
8991
9173
  }
8992
9174
  }
8993
9175
  this.index = start;
8994
- const fn = this.matchIdentifier();
8995
- if (fn === null)
9176
+ return null;
9177
+ }
9178
+ /**
9179
+ * A function is an identifier followed by postfix operators
9180
+ * (`\prime`...) and some arguments.
9181
+ */
9182
+ parseFunction(until) {
9183
+ if (this.atTerminator(until))
8996
9184
  return null;
8997
- if (this.options.parseUnknownIdentifier?.(fn, this) !== "function") {
9185
+ const start = this.index;
9186
+ let fn = null;
9187
+ const fnDefs = this.peekDefinitions("function") ?? [];
9188
+ for (const [def, tokenCount] of fnDefs) {
9189
+ this.index = start + tokenCount;
9190
+ if (typeof def.parse === "function") {
9191
+ fn = def.parse(this, until);
9192
+ if (fn !== null)
9193
+ break;
9194
+ } else {
9195
+ fn = def.name;
9196
+ break;
9197
+ }
9198
+ }
9199
+ if (fn === null) {
8998
9200
  this.index = start;
8999
- return null;
9201
+ fn = matchIdentifier(this);
9202
+ if (!this.isFunctionHead(fn)) {
9203
+ this.index = start;
9204
+ return null;
9205
+ }
9000
9206
  }
9001
- return this.matchFunctionSuffix(fn);
9207
+ do {
9208
+ const pf = this.parsePostfixOperator(fn);
9209
+ if (pf === null)
9210
+ break;
9211
+ fn = pf;
9212
+ } while (true);
9213
+ const seq = this.isFunctionHead(fn) ? this.parseArguments() : null;
9214
+ return seq ? [fn, ...seq] : fn;
9002
9215
  }
9003
- /**
9004
- * A symbol is an identifier or a custom definition
9005
- */
9006
- matchSymbol(until) {
9216
+ parseSymbol(until) {
9007
9217
  if (this.atTerminator(until))
9008
9218
  return null;
9009
9219
  const start = this.index;
9010
- const defs = this.peekDefinitions("identifier");
9220
+ const defs = this.peekDefinitions("symbol");
9011
9221
  if (defs) {
9012
9222
  for (const [def, tokenCount] of defs) {
9013
9223
  this.index = start + tokenCount;
@@ -9020,7 +9230,7 @@ var _Parser = class {
9020
9230
  }
9021
9231
  }
9022
9232
  this.index = start;
9023
- const id = this.matchIdentifier();
9233
+ const id = matchIdentifier(this);
9024
9234
  if (id === null)
9025
9235
  return null;
9026
9236
  if (this.options.parseUnknownIdentifier?.(id, this) === "symbol")
@@ -9028,57 +9238,19 @@ var _Parser = class {
9028
9238
  this.index = start;
9029
9239
  return null;
9030
9240
  }
9031
- matchLatexOptionalGroup() {
9032
- const index = this.index;
9033
- this.skipSpaceTokens();
9034
- if (this.match("[")) {
9035
- this.addBoundary(["]"]);
9036
- const expr = this.matchExpression();
9037
- this.skipSpace();
9038
- if (this.matchBoundary())
9039
- return expr;
9040
- return this.boundaryError("expected-closing-delimiter");
9041
- }
9042
- this.index = index;
9043
- return null;
9044
- }
9045
- // Some LaTeX commands (but not all) can accept an argument without braces,
9046
- // for example `^` , `\sqrt` or `\frac`.
9047
- matchSingleAtomArgument() {
9048
- const excluding = [...'!"#$%&(),/;:?@[]`|~'.split(""), "\\left", "\\bigl"];
9049
- if (excluding.includes(this.peek))
9050
- return null;
9051
- if (/^[0-9]$/.test(this.peek))
9052
- return parseInt(this.next());
9053
- if (/^[^\\#]$/.test(this.peek) && isValidIdentifier(this.peek))
9054
- return this.next();
9055
- const sym = this.matchSymbol();
9056
- if (sym)
9057
- return sym;
9058
- return null;
9059
- }
9060
- matchLatexGroup() {
9061
- const start = this.index;
9062
- this.skipSpaceTokens();
9063
- if (this.match("<{>")) {
9064
- this.addBoundary(["<}>"]);
9065
- const expr = this.matchExpression();
9066
- this.skipSpace();
9067
- if (this.matchBoundary())
9068
- return expr ?? ["Sequence"];
9069
- const from = this.index;
9070
- while (!this.matchBoundary() && !this.atEnd)
9071
- this.next();
9072
- const err = this.error("syntax-error", from);
9073
- return expr ? ["Sequence", expr, err] : err;
9074
- }
9075
- this.index = start;
9076
- return null;
9077
- }
9078
- matchSupsub(lhs) {
9241
+ /**
9242
+ * Parse a sequence superfix/subfix operator, e.g. `^{*}`
9243
+ *
9244
+ * Superfix and subfix need special handling:
9245
+ *
9246
+ * - they act mostly like an infix operator, but they are commutative, i.e.
9247
+ * `x_a^b` should be parsed identically to `x^b_a`.
9248
+ *
9249
+ * - furthermore, in LaTeX `x^a^b` parses the same as `x^a{}^b`.
9250
+ *
9251
+ */
9252
+ parseSupsub(lhs) {
9079
9253
  console.assert(lhs !== null);
9080
- if (lhs === null)
9081
- return null;
9082
9254
  const index = this.index;
9083
9255
  this.skipSpace();
9084
9256
  const superscripts = [];
@@ -9090,7 +9262,7 @@ var _Parser = class {
9090
9262
  if (this.match("_") || this.match("^"))
9091
9263
  subscripts.push(this.error("syntax-error", subIndex));
9092
9264
  else {
9093
- const sub2 = this.matchLatexGroup() ?? this.matchSingleAtomArgument() ?? this.matchStringArgument();
9265
+ const sub2 = this.parseGroup() ?? this.parseToken() ?? this.parseStringGroup();
9094
9266
  if (sub2 === null)
9095
9267
  return this.error("missing", index);
9096
9268
  subscripts.push(sub2);
@@ -9100,7 +9272,7 @@ var _Parser = class {
9100
9272
  if (this.match("_") || this.match("^"))
9101
9273
  superscripts.push(this.error("syntax-error", subIndex));
9102
9274
  else {
9103
- const sup = this.matchLatexGroup() ?? this.matchSingleAtomArgument();
9275
+ const sup = this.parseGroup() ?? this.parseToken();
9104
9276
  if (sup === null)
9105
9277
  return this.error("missing", index);
9106
9278
  superscripts.push(sup);
@@ -9124,7 +9296,7 @@ var _Parser = class {
9124
9296
  ];
9125
9297
  for (const def of defs) {
9126
9298
  if (typeof def.parse === "function")
9127
- result = def.parse(this, { minPrec: 0 }, arg);
9299
+ result = def.parse(this, arg, { minPrec: 0 });
9128
9300
  else
9129
9301
  result = arg;
9130
9302
  if (result)
@@ -9142,7 +9314,7 @@ var _Parser = class {
9142
9314
  ];
9143
9315
  for (const def of defs) {
9144
9316
  if (typeof def.parse === "function")
9145
- result = def.parse(this, { minPrec: 0 }, arg);
9317
+ result = def.parse(this, arg, { minPrec: 0 });
9146
9318
  else
9147
9319
  result = arg;
9148
9320
  if (result)
@@ -9154,7 +9326,7 @@ var _Parser = class {
9154
9326
  this.index = index;
9155
9327
  return result;
9156
9328
  }
9157
- matchPostfix(lhs) {
9329
+ parsePostfixOperator(lhs, until) {
9158
9330
  console.assert(lhs !== null);
9159
9331
  if (lhs === null)
9160
9332
  return null;
@@ -9164,7 +9336,7 @@ var _Parser = class {
9164
9336
  const start = this.index;
9165
9337
  for (const [def, n] of defs) {
9166
9338
  this.index = start + n;
9167
- const result = def.parse(this, lhs);
9339
+ const result = def.parse(this, lhs, until);
9168
9340
  if (result !== null)
9169
9341
  return result;
9170
9342
  }
@@ -9176,119 +9348,32 @@ var _Parser = class {
9176
9348
  * Not suitable for general purpose text, e.g. argument of a `\text{}
9177
9349
  * command. See `matchChar()` instead.
9178
9350
  */
9179
- matchString() {
9351
+ parseStringGroupContent() {
9352
+ const start = this.index;
9180
9353
  let result = "";
9181
- while (!this.atBoundary) {
9182
- const token = this.peek;
9354
+ let level = 0;
9355
+ while (!this.atBoundary || level > 0) {
9356
+ const token = this.nextToken();
9183
9357
  if (token === "<$>" || token === "<$$>") {
9358
+ this.index = start;
9184
9359
  return "";
9360
+ }
9361
+ if (token === "<{>") {
9362
+ level += 1;
9363
+ result += "\\{";
9364
+ } else if (token === "<}>") {
9365
+ level -= 1;
9366
+ result += "\\}";
9185
9367
  } else if (token === "<space>") {
9186
- this.next();
9187
9368
  result += " ";
9188
9369
  } else if (token[0] === "\\") {
9189
- result += this.next();
9190
- } else {
9191
- result += this.next();
9192
- }
9193
- }
9194
- return result;
9195
- }
9196
- /** Match a string as an argument (in a `{}` pair) */
9197
- matchStringArgument() {
9198
- const start = this.index;
9199
- this.skipSpaceTokens();
9200
- if (this.match("<{>")) {
9201
- this.addBoundary(["<}>"]);
9202
- while (this.match("<space>")) {
9203
- }
9204
- const arg = this.matchString();
9205
- if (this.matchBoundary())
9206
- return arg.trimEnd();
9207
- this.removeBoundary();
9208
- }
9209
- this.index = start;
9210
- return null;
9211
- }
9212
- /**
9213
- * Match an expression in a tabular format, where rows are separated by `\\`
9214
- * and columns by `&`.
9215
- *
9216
- * Return rows of sparse columns: empty rows are indicated with `Nothing`,
9217
- * and empty cells are also indicated with `Nothing`.
9218
- */
9219
- matchTabular() {
9220
- const result = [];
9221
- let row = [];
9222
- let expr = null;
9223
- while (!this.atBoundary) {
9224
- this.skipSpace();
9225
- if (this.match("&")) {
9226
- row.push(expr ?? "Nothing");
9227
- expr = null;
9228
- } else if (this.match("\\\\") || this.match("\\cr")) {
9229
- this.skipSpace();
9230
- this.matchLatexOptionalGroup();
9231
- if (expr !== null)
9232
- row.push(expr);
9233
- result.push(row);
9234
- row = [];
9235
- expr = null;
9370
+ result += token;
9236
9371
  } else {
9237
- const cell = [];
9238
- let peek = this.peek;
9239
- while (peek !== "&" && peek !== "\\\\" && peek !== "\\cr" && !this.atBoundary) {
9240
- expr = this.matchExpression({
9241
- condition: (p) => {
9242
- const peek2 = p.peek;
9243
- return peek2 === "&" || peek2 === "\\\\" || peek2 === "\\cr";
9244
- }
9245
- });
9246
- if (expr)
9247
- cell.push(expr);
9248
- else {
9249
- cell.push(["Error", ["'unexpected-token'", peek]]);
9250
- this.next();
9251
- }
9252
- this.skipSpace();
9253
- peek = this.peek;
9254
- }
9255
- if (cell.length > 1)
9256
- expr = ["Sequence", ...cell];
9257
- else
9258
- expr = cell[0] ?? "Nothing";
9372
+ result += token;
9259
9373
  }
9260
9374
  }
9261
- if (expr !== null)
9262
- row.push(expr);
9263
- if (row.length > 0)
9264
- result.push(row);
9265
9375
  return result;
9266
9376
  }
9267
- matchEnvironment() {
9268
- const index = this.index;
9269
- if (!this.match("\\begin"))
9270
- return null;
9271
- const name = this.matchStringArgument();
9272
- if (name === null)
9273
- return this.error("expected-environment-name", index);
9274
- this.addBoundary(["\\end", "<{>", ...name.split(""), "<}>"]);
9275
- const def = this._dictionary.environment.get(name);
9276
- if (!def) {
9277
- this.matchTabular();
9278
- this.skipSpace();
9279
- if (!this.matchBoundary())
9280
- return this.boundaryError("unbalanced-environment");
9281
- return this.error(["unknown-environment", { str: name }], index);
9282
- }
9283
- const expr = def.parse(this, [], []);
9284
- this.skipSpace();
9285
- if (!this.matchBoundary())
9286
- return this.boundaryError("unbalanced-environment");
9287
- if (expr !== null)
9288
- return this.decorate(expr, index);
9289
- this.index = index;
9290
- return null;
9291
- }
9292
9377
  /**
9293
9378
  * Apply an invisible operator between two expressions.
9294
9379
  *
@@ -9311,12 +9396,18 @@ var _Parser = class {
9311
9396
  * => lhs is a number, rhs is a number, but not a literal
9312
9397
  */
9313
9398
  applyInvisibleOperator(until, lhs) {
9314
- if (lhs === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until) || this.options.applyInvisibleOperator === null)
9399
+ if (lhs === null || this.options.applyInvisibleOperator === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until))
9315
9400
  return null;
9401
+ if (this.isFunctionHead(lhs)) {
9402
+ const args = this.parseArguments("enclosure", until);
9403
+ if (args === null)
9404
+ return null;
9405
+ return [lhs, ...args];
9406
+ }
9316
9407
  if (this.peekDefinitions("operator") !== null)
9317
9408
  return null;
9318
9409
  const start = this.index;
9319
- const rhs = this.matchExpression({ ...until, minPrec: 390 });
9410
+ const rhs = this.parseExpression({ ...until, minPrec: 390 });
9320
9411
  if (rhs === null || symbol(rhs) === "Nothing" || isEmptySequence(rhs)) {
9321
9412
  this.index = start;
9322
9413
  return null;
@@ -9325,13 +9416,9 @@ var _Parser = class {
9325
9416
  return applyAssociativeOperator("Sequence", lhs, rhs);
9326
9417
  if (typeof this.options.applyInvisibleOperator === "function")
9327
9418
  return this.options.applyInvisibleOperator(this, lhs, rhs);
9328
- const lhsSymbol = symbol(lhs);
9329
- if (lhsSymbol) {
9330
- const isFunction = this.options.parseUnknownIdentifier(lhsSymbol, this) === "function";
9331
- if (isFunction) {
9332
- const seq = getSequence(rhs);
9333
- return seq ? [lhs, ...seq] : lhsSymbol;
9334
- }
9419
+ if (this.isFunctionHead(lhs)) {
9420
+ const seq = getSequence(rhs);
9421
+ return seq ? [lhs, ...seq] : lhs;
9335
9422
  }
9336
9423
  const lhsNumber = machineValue(lhs);
9337
9424
  if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
@@ -9344,7 +9431,7 @@ var _Parser = class {
9344
9431
  }
9345
9432
  if (head(rhs) === "Delimiter") {
9346
9433
  if (head(op(rhs, 1)) === "Sequence")
9347
- return [lhsSymbol ?? lhs, ...ops(op(rhs, 1)) ?? []];
9434
+ return [lhs, ...ops(op(rhs, 1)) ?? []];
9348
9435
  if (!op(rhs, 1) || symbol(op(rhs, 1)) === "Nothing")
9349
9436
  return applyAssociativeOperator(
9350
9437
  "Sequence",
@@ -9356,7 +9443,13 @@ var _Parser = class {
9356
9443
  return applyAssociativeOperator("Sequence", lhs, rhs);
9357
9444
  return applyAssociativeOperator("Multiply", lhs, rhs);
9358
9445
  }
9359
- matchUnexpectedLatexCommand() {
9446
+ /**
9447
+ * This is an error handling method. We've encountered a LaTeX command
9448
+ * but were not able to match it to any entry in the LaTeX dictionary,
9449
+ * or ran into it in an unexpected context (postfix operator lacking an
9450
+ * argument, for example)
9451
+ */
9452
+ parseUnexpectedLatexCommand() {
9360
9453
  const start = this.index;
9361
9454
  let opDefs = this.peekDefinitions("operator");
9362
9455
  if (opDefs) {
@@ -9385,7 +9478,7 @@ var _Parser = class {
9385
9478
  if (def.name)
9386
9479
  return [
9387
9480
  def.name,
9388
- this.matchExpression() ?? this.error("missing", start)
9481
+ this.parseExpression() ?? this.error("missing", start)
9389
9482
  ];
9390
9483
  return this.error("unexpected-operator", start);
9391
9484
  }
@@ -9394,11 +9487,9 @@ var _Parser = class {
9394
9487
  const [def, n] = opDefs[0];
9395
9488
  this.index += n;
9396
9489
  if (typeof def.parse === "function") {
9397
- const result = def.parse(
9398
- this,
9399
- { minPrec: 0 },
9400
- this.error("missing", start)
9401
- );
9490
+ const result = def.parse(this, this.error("missing", start), {
9491
+ minPrec: 0
9492
+ });
9402
9493
  if (result)
9403
9494
  return result;
9404
9495
  }
@@ -9406,7 +9497,7 @@ var _Parser = class {
9406
9497
  return [
9407
9498
  def.name,
9408
9499
  this.error("missing", start),
9409
- this.matchExpression() ?? this.error("missing", start)
9500
+ this.parseExpression() ?? this.error("missing", start)
9410
9501
  ];
9411
9502
  return this.error("unexpected-operator", start);
9412
9503
  }
@@ -9414,10 +9505,10 @@ var _Parser = class {
9414
9505
  const command = this.peek;
9415
9506
  if (!command || command[0] !== "\\")
9416
9507
  return null;
9417
- this.next();
9508
+ this.nextToken();
9418
9509
  this.skipSpaceTokens();
9419
9510
  if (command === "\\end") {
9420
- const name = this.matchStringArgument();
9511
+ const name = this.parseStringGroup();
9421
9512
  if (name === null)
9422
9513
  return this.error("expected-environment-name", start);
9423
9514
  return this.error(["unbalanced-environment", { str: name }], start);
@@ -9429,7 +9520,7 @@ var _Parser = class {
9429
9520
  level += 1;
9430
9521
  if (this.peek === "]")
9431
9522
  level -= 1;
9432
- this.next();
9523
+ this.nextToken();
9433
9524
  }
9434
9525
  this.match("]");
9435
9526
  }
@@ -9455,7 +9546,7 @@ var _Parser = class {
9455
9546
  level += 1;
9456
9547
  if (this.peek === "<}>")
9457
9548
  level -= 1;
9458
- this.next();
9549
+ this.nextToken();
9459
9550
  }
9460
9551
  this.match("<}>");
9461
9552
  }
@@ -9463,15 +9554,20 @@ var _Parser = class {
9463
9554
  }
9464
9555
  /**
9465
9556
  * <primary> :=
9466
- * (<number> | <symbol> | <environment> | <matchfix-expr>) <subsup>* <postfix-operator>*
9557
+ * (<number> | <symbol> | <environment> | <matchfix-expr>)
9558
+ * <subsup>* <postfix-operator>*
9467
9559
  *
9468
- * <symbol> ::= (<symbol-id> | (<latex-command><latex-arguments>)) <arguments>
9560
+ * <symbol> ::=
9561
+ * (<symbol-id> | (<latex-command><latex-arguments>)) <arguments>
9469
9562
  *
9470
9563
  * <matchfix-expr> :=
9471
- * <matchfix-op-open> <expression> [<matchfix-op-separator> <expression>] <matchfix-op-close>
9564
+ * <matchfix-op-open>
9565
+ * <expression>
9566
+ * (<matchfix-op-separator> <expression>)*
9567
+ * <matchfix-op-close>
9472
9568
  *
9473
9569
  */
9474
- matchPrimary(until) {
9570
+ parsePrimary(until) {
9475
9571
  if (this.atBoundary)
9476
9572
  return null;
9477
9573
  if (this.atTerminator(until))
@@ -9481,7 +9577,7 @@ var _Parser = class {
9481
9577
  if (this.match("<}>"))
9482
9578
  return this.error("unexpected-closing-delimiter", start);
9483
9579
  if (this.match("<{>")) {
9484
- result = this.matchExpression({ condition: (p) => p.peek === "<}>" });
9580
+ result = this.parseExpression({ condition: (p) => p.peek === "<}>" });
9485
9581
  if (result === null)
9486
9582
  return this.error("expected-expression", start);
9487
9583
  if (!this.match("<}>")) {
@@ -9492,25 +9588,25 @@ var _Parser = class {
9492
9588
  }
9493
9589
  }
9494
9590
  if (result === null) {
9495
- const num = this.matchNumber();
9496
- if (num)
9591
+ const num = this.parseNumber();
9592
+ if (num !== null)
9497
9593
  result = { num };
9498
9594
  }
9499
- result ?? (result = this.matchEnclosure());
9500
- result ?? (result = this.matchEnvironment());
9595
+ result ?? (result = this.parseEnclosure());
9596
+ result ?? (result = this.parseEnvironment());
9501
9597
  if (result === null && this.matchAll(this._positiveInfinityTokens))
9502
9598
  result = { num: "+Infinity" };
9503
9599
  if (result === null && this.matchAll(this._negativeInfinityTokens))
9504
9600
  result = { num: "-Infinity" };
9505
9601
  if (result === null && this.matchAll(this._notANumberTokens))
9506
9602
  result = { num: "NaN" };
9507
- result ?? (result = this.matchFunction(until) ?? this.matchSymbol(until) ?? matchInvalidIdentifier(this));
9603
+ result ?? (result = this.parseGenericExpression(until) ?? this.parseFunction(until) ?? this.parseSymbol(until) ?? parseInvalidIdentifier(this));
9508
9604
  if (result !== null) {
9509
9605
  result = this.decorate(result, start);
9510
9606
  let postfix = null;
9511
9607
  let index = this.index;
9512
9608
  do {
9513
- postfix = this.matchPostfix(result);
9609
+ postfix = this.parsePostfixOperator(result, until);
9514
9610
  result = postfix ?? result;
9515
9611
  if (this.index === index && postfix !== null) {
9516
9612
  console.assert(this.index !== index, "No token consumed");
@@ -9519,9 +9615,8 @@ var _Parser = class {
9519
9615
  index = this.index;
9520
9616
  } while (postfix !== null);
9521
9617
  }
9522
- result ?? (result = this.matchUnexpectedLatexCommand());
9523
9618
  if (result !== null)
9524
- result = this.matchSupsub(result);
9619
+ result = this.parseSupsub(result);
9525
9620
  return this.decorate(result, start);
9526
9621
  }
9527
9622
  /**
@@ -9532,9 +9627,10 @@ var _Parser = class {
9532
9627
  * | <prefix-op> <primary>
9533
9628
  * | <primary> <infix-op> <expression>
9534
9629
  *
9535
- * Stop when an operator of precedence less than `until.minPrec` is encountered
9630
+ * Stop when an operator of precedence less than `until.minPrec`
9631
+ * is encountered
9536
9632
  */
9537
- matchExpression(until) {
9633
+ parseExpression(until) {
9538
9634
  const start = this.index;
9539
9635
  this.skipSpace();
9540
9636
  if (this.atBoundary) {
@@ -9544,9 +9640,9 @@ var _Parser = class {
9544
9640
  until ?? (until = { minPrec: 0 });
9545
9641
  if (until.minPrec === void 0)
9546
9642
  until.minPrec = 0;
9547
- let lhs = this.matchPrefixOperator({ ...until, minPrec: 0 });
9643
+ let lhs = this.parsePrefixOperator({ ...until, minPrec: 0 });
9548
9644
  if (lhs === null) {
9549
- lhs = this.matchPrimary(until);
9645
+ lhs = this.parsePrimary(until);
9550
9646
  if (head(lhs) === "Sequence" && nops(lhs) === 0)
9551
9647
  lhs = null;
9552
9648
  }
@@ -9554,7 +9650,7 @@ var _Parser = class {
9554
9650
  let done = false;
9555
9651
  while (!done && !this.atTerminator(until)) {
9556
9652
  this.skipSpace();
9557
- let result = this.matchInfixOperator(lhs, until);
9653
+ let result = this.parseInfixOperator(lhs, until);
9558
9654
  if (result === null) {
9559
9655
  result = this.applyInvisibleOperator(until, lhs);
9560
9656
  }
@@ -9565,6 +9661,7 @@ var _Parser = class {
9565
9661
  }
9566
9662
  }
9567
9663
  }
9664
+ lhs ?? (lhs = this.parseUnexpectedLatexCommand());
9568
9665
  return this.decorate(lhs, start);
9569
9666
  }
9570
9667
  /**
@@ -9599,18 +9696,19 @@ var _Parser = class {
9599
9696
  const latex = this.latex(fromToken, this.index);
9600
9697
  return latex ? ["Error", msg, ["Latex", { str: latex }]] : ["Error", msg];
9601
9698
  }
9699
+ isFunctionHead(expr) {
9700
+ if (expr === null)
9701
+ return false;
9702
+ const s = symbol(expr);
9703
+ if (!s)
9704
+ return this.computeEngine.box(expr).domain.isFunction;
9705
+ if (this.computeEngine && this.computeEngine.lookupFunction(s) !== void 0)
9706
+ return true;
9707
+ if (this.options.parseUnknownIdentifier?.(s, this) === "function")
9708
+ return true;
9709
+ return false;
9710
+ }
9602
9711
  };
9603
- function countPrimeLevel(parser) {
9604
- if (parser.match("\\tripleprime"))
9605
- return 3;
9606
- if (parser.match("\\doubleprime"))
9607
- return 2;
9608
- if (parser.match("\\prime"))
9609
- return 1;
9610
- if (parser.match("'"))
9611
- return 1;
9612
- return 0;
9613
- }
9614
9712
 
9615
9713
  // src/compute-engine/latex-syntax/serialize-number.ts
9616
9714
  function formatFractionalPart(m, options) {
@@ -9954,7 +10052,7 @@ var Serializer = class {
9954
10052
  const name = head(expr);
9955
10053
  if (typeof name === "string" && name !== "Delimiter" && name !== "Subscript") {
9956
10054
  const def = this.dictionary.name.get(name);
9957
- if (def && (def.kind === "identifier" || def.kind === "prefix" || def.kind === "infix" || def.kind === "postfix") && def.precedence < prec)
10055
+ if (def && (def.kind === "symbol" || def.kind === "prefix" || def.kind === "infix" || def.kind === "postfix") && def.precedence < prec)
9958
10056
  return this.wrapString(
9959
10057
  this.serialize(expr),
9960
10058
  this.options.applyFunctionStyle(expr, this.level)
@@ -10034,8 +10132,11 @@ var Serializer = class {
10034
10132
  if (typeof h === "string" && h.length > 0 && h[0] === "\\") {
10035
10133
  return joinLatex([h, ...args.map((x) => `{${this.serialize(x)}}`)]);
10036
10134
  }
10037
- if (typeof h === "string")
10135
+ if (typeof h === "string") {
10136
+ if (h.length === 1)
10137
+ return serializeIdentifier(h) + this.wrapArguments(expr);
10038
10138
  return serializeIdentifier(h, "upright") + this.wrapArguments(expr);
10139
+ }
10039
10140
  const style = this.options.applyFunctionStyle(expr, this.level);
10040
10141
  return "\\mathrm{Apply}" + this.wrapString(
10041
10142
  this.serialize(h) + ", " + this.serialize(["List", ...args]),
@@ -10062,10 +10163,12 @@ var Serializer = class {
10062
10163
  const symbolName = symbol(expr);
10063
10164
  if (symbolName !== null) {
10064
10165
  const def = this.dictionary.name.get(symbolName);
10065
- if (def?.kind === "identifier")
10166
+ if (def?.kind === "symbol")
10066
10167
  return this.serializeSymbol(expr, def);
10067
10168
  if (def?.kind === "function")
10068
10169
  return this.serializeFunction(expr, def);
10170
+ if (typeof def?.serialize === "function")
10171
+ return def.serialize(this, expr);
10069
10172
  }
10070
10173
  const dict = dictionary(expr);
10071
10174
  if (dict !== null)
@@ -10078,7 +10181,7 @@ var Serializer = class {
10078
10181
  return def.serialize(this, expr);
10079
10182
  if (def.kind === "infix" || def.kind === "postfix" || def.kind === "prefix")
10080
10183
  return serializeOperator(this, expr, def);
10081
- if (def.kind === "identifier")
10184
+ if (def.kind === "symbol")
10082
10185
  return this.serializeSymbol(expr, def);
10083
10186
  if (def.kind === "function")
10084
10187
  return this.serializeFunction(expr, def);
@@ -10342,7 +10445,7 @@ var LatexSyntax = class _LatexSyntax {
10342
10445
  ...DEFAULT_SERIALIZE_LATEX_OPTIONS,
10343
10446
  ...opts
10344
10447
  };
10345
- this.dictionary = indexLatexDictionary(
10448
+ this._dictionary = indexLatexDictionary(
10346
10449
  options.dictionary ?? _LatexSyntax.getDictionary(),
10347
10450
  (sig) => this.onError([sig])
10348
10451
  );
@@ -10363,16 +10466,16 @@ var LatexSyntax = class _LatexSyntax {
10363
10466
  }
10364
10467
  if (!DEFAULT_LATEX_DICTIONARY[category])
10365
10468
  return [];
10366
- return [...DEFAULT_LATEX_DICTIONARY[category]];
10469
+ return Object.freeze([...DEFAULT_LATEX_DICTIONARY[category]]);
10367
10470
  }
10368
10471
  parse(latex) {
10369
10472
  const parser = new _Parser(
10370
10473
  tokenize(latex, []),
10371
10474
  this.options,
10372
- this.dictionary,
10475
+ this._dictionary,
10373
10476
  this.computeEngine
10374
10477
  );
10375
- let expr = parser.matchExpression();
10478
+ let expr = parser.parseExpression();
10376
10479
  if (!parser.atEnd) {
10377
10480
  const opDefs = parser.peekDefinitions("infix");
10378
10481
  if (opDefs) {
@@ -10381,8 +10484,8 @@ var LatexSyntax = class _LatexSyntax {
10381
10484
  parser.index += n;
10382
10485
  const result = def.parse(
10383
10486
  parser,
10384
- { minPrec: 0 },
10385
- expr ?? parser.error("missing", start)
10487
+ expr ?? parser.error("missing", start),
10488
+ { minPrec: 0 }
10386
10489
  );
10387
10490
  if (result)
10388
10491
  return result;
@@ -10396,7 +10499,7 @@ var LatexSyntax = class _LatexSyntax {
10396
10499
  parser.index = start;
10397
10500
  }
10398
10501
  const index = parser.index;
10399
- const id = parser.matchIdentifier();
10502
+ const id = matchIdentifier(parser);
10400
10503
  if (id) {
10401
10504
  const idError = parser.error(["unexpected-identifier", id], index);
10402
10505
  return expr ? ["Sequence", expr, idError] : idError;
@@ -10418,9 +10521,9 @@ var LatexSyntax = class _LatexSyntax {
10418
10521
  return expr ? ["Sequence", expr, enclosureError] : enclosureError;
10419
10522
  }
10420
10523
  const rest = parser.index;
10421
- const token = parser.next();
10524
+ const token = parser.nextToken();
10422
10525
  while (!parser.atEnd)
10423
- parser.next();
10526
+ parser.nextToken();
10424
10527
  if (!token)
10425
10528
  return parser.error("syntax-error", rest);
10426
10529
  const error = parser.error(
@@ -10453,7 +10556,7 @@ var LatexSyntax = class _LatexSyntax {
10453
10556
  return this._serializer;
10454
10557
  this._serializer = new Serializer(
10455
10558
  this.options,
10456
- this.dictionary,
10559
+ this._dictionary,
10457
10560
  this.onError
10458
10561
  );
10459
10562
  return this._serializer;
@@ -13027,6 +13130,14 @@ function ancestors(dom) {
13027
13130
  gDomainLiterals[dom] = new Set(result);
13028
13131
  return result;
13029
13132
  }
13133
+ function domainSetsLibrary() {
13134
+ const table = {};
13135
+ for (const dom of Object.keys(DOMAIN_LITERAL)) {
13136
+ if (dom !== "Domain" && dom !== "Nothing" && dom !== "String" && dom !== "Symbol" && dom !== "List" && dom !== "Tuple" && dom !== "Sequence")
13137
+ table[dom] = { domain: "Set" };
13138
+ }
13139
+ return table;
13140
+ }
13030
13141
 
13031
13142
  // src/compute-engine/boxed-expression/abstract-boxed-expression.ts
13032
13143
  var import_complex6 = __toESM(require_complex());
@@ -15371,7 +15482,7 @@ function expandMultinomial(expr) {
15371
15482
  const ce = expr.engine;
15372
15483
  if (expr.op1.head === "Negate") {
15373
15484
  const sign2 = exp2 % 2 === 0 ? 1 : -1;
15374
- const result2 = expandMultinomial(ce.box(["Power", expr.op1.op1, expr.op2]));
15485
+ const result2 = expandMultinomial(ce.pow(expr.op1.op1, expr.op2));
15375
15486
  if (result2 === null)
15376
15487
  return null;
15377
15488
  if (sign2 > 0)
@@ -15596,15 +15707,14 @@ function assumeEquality(proposition) {
15596
15707
  const sols = findUnivariateRoots(proposition, lhs2);
15597
15708
  if (sols.length === 0) {
15598
15709
  ce.assumptions.set(
15599
- ce.box([
15600
- "Equal",
15710
+ ce.fn("Equal", [
15601
15711
  ce.add([proposition.op1.canonical, ce.neg(proposition.op2.canonical)]).simplify(),
15602
15712
  0
15603
15713
  ]),
15604
15714
  true
15605
15715
  );
15606
15716
  }
15607
- const val = sols.length === 1 ? sols[0] : ce.box(["List", ...sols]);
15717
+ const val = sols.length === 1 ? sols[0] : ce.fn("List", sols);
15608
15718
  const def = ce.lookupSymbol(lhs2);
15609
15719
  if (!def) {
15610
15720
  ce.defineSymbol(lhs2, { value: val });
@@ -16586,7 +16696,6 @@ var BoxedFunction = class _BoxedFunction extends AbstractBoxedExpression {
16586
16696
  return result;
16587
16697
  }
16588
16698
  solve(vars) {
16589
- console.log("solve this:", this.toString());
16590
16699
  if (vars.length !== 1)
16591
16700
  return null;
16592
16701
  const roots = findUnivariateRoots(this.simplify(), vars[0]);
@@ -16665,6 +16774,8 @@ function makeCanonicalFunction(ce, head2, ops2, metadata) {
16665
16774
  xs.push(y);
16666
16775
  }
16667
16776
  }
16777
+ if (!xs.every((x) => x.isValid))
16778
+ return new BoxedFunction(ce, head2, xs, { metadata, canonical: false });
16668
16779
  const sig = def.signature;
16669
16780
  if (sig.canonical) {
16670
16781
  try {
@@ -16695,21 +16806,22 @@ function makeCanonicalFunction(ce, head2, ops2, metadata) {
16695
16806
  return new BoxedFunction(ce, head2, xs, { metadata, def, canonical: true });
16696
16807
  }
16697
16808
  function apply(fn, args) {
16809
+ const ce = fn.engine;
16698
16810
  if (fn.head !== "Lambda")
16699
- return fn.engine._fn(fn.evaluate(), args);
16811
+ return ce._fn(fn.evaluate(), args);
16700
16812
  const subs2 = {
16701
- "__": fn.engine.tuple(args),
16702
- "_#": fn.engine.number(args.length)
16813
+ "__": ce.tuple(args),
16814
+ "_#": ce.number(args.length)
16703
16815
  };
16704
16816
  let n = 1;
16705
16817
  for (const op3 of args)
16706
16818
  subs2[`_${n++}`] = op3;
16707
16819
  subs2["_"] = subs2["_1"];
16708
- const savedContext = this.context;
16709
- this.context = fn.scope ?? null;
16710
- const result = fn.subs(subs2).evaluate();
16711
- this.context = savedContext;
16712
- return result;
16820
+ const savedContext = ce.context;
16821
+ ce.context = fn.scope ?? null;
16822
+ const result = fn.subs(subs2);
16823
+ ce.context = savedContext;
16824
+ return result.op1.evaluate();
16713
16825
  }
16714
16826
  function holdMap(xs, skip, associativeHead, f) {
16715
16827
  if (xs.length === 0)
@@ -18824,7 +18936,7 @@ var ARITHMETIC_LIBRARY = [
18824
18936
  return ce._NEGATIVE_INFINITY;
18825
18937
  if (ops2.length === 1)
18826
18938
  return ops2[0];
18827
- return ce.box(["Max", ...ops2]);
18939
+ return ce.fn("Max", ops2);
18828
18940
  },
18829
18941
  evaluate: (ce, ops2) => {
18830
18942
  if (ops2.length === 0)
@@ -18853,7 +18965,7 @@ var ARITHMETIC_LIBRARY = [
18853
18965
  return ce._NEGATIVE_INFINITY;
18854
18966
  if (ops2.length === 1)
18855
18967
  return ops2[0];
18856
- return ce.box(["Min", ...ops2]);
18968
+ return ce.fn("Min", ops2);
18857
18969
  },
18858
18970
  evaluate: (ce, ops2) => {
18859
18971
  if (ops2.length === 0)
@@ -19220,14 +19332,13 @@ var ARITHMETIC_LIBRARY = [
19220
19332
  },
19221
19333
  Half: {
19222
19334
  constant: true,
19223
- holdUntil: "never",
19335
+ holdUntil: "evaluate",
19224
19336
  value: ["Rational", 1, 2]
19225
19337
  },
19226
19338
  ImaginaryUnit: {
19227
19339
  domain: "ImaginaryNumber",
19228
19340
  constant: true,
19229
19341
  holdUntil: "evaluate",
19230
- // @todo maybe?
19231
19342
  wikidata: "Q193796",
19232
19343
  flags: { imaginary: true },
19233
19344
  value: ["Complex", 0, 1]
@@ -20055,8 +20166,7 @@ var CORE_LIBRARY = [
20055
20166
  signature: {
20056
20167
  domain: ["Function", ["Maybe", ["Sequence", "Anything"]], "String"],
20057
20168
  evaluate: (ce, ops2) => {
20058
- return ce.box([
20059
- "Latex",
20169
+ return ce.fn("Latex", [
20060
20170
  ce.string(tokensToString(ops2.map((x) => x.string ?? x.latex)))
20061
20171
  ]);
20062
20172
  }
@@ -20079,7 +20189,7 @@ var CORE_LIBRARY = [
20079
20189
  hold: "all",
20080
20190
  signature: {
20081
20191
  domain: ["Function", ["Maybe", ["Sequence", "Anything"]], "String"],
20082
- evaluate: (ce, ops2) => ce.box(["Latex", ce.string(joinLatex(ops2.map((x) => x.latex)))])
20192
+ evaluate: (ce, ops2) => ce.fn("Latex", [ce.string(joinLatex(ops2.map((x) => x.latex)))])
20083
20193
  }
20084
20194
  },
20085
20195
  SplitAsLatexTokens: {
@@ -20916,13 +21026,13 @@ var TRIGONOMETRY_LIBRARY = [
20916
21026
  "Number"
20917
21027
  ]);
20918
21028
  if (ops2.length !== 1)
20919
- return ce.box(["Degrees", ops2]);
21029
+ return ce.fn("Degrees", ops2, { canonical: false });
20920
21030
  const arg = ops2[0];
20921
21031
  if (arg.numericValue === null || !arg.isValid)
20922
- return ce.box(["Degrees", arg]);
21032
+ return ce.fn("Degrees", ops2, { canonical: false });
20923
21033
  return ce.div(ce.mul([arg, ce.symbol("Pi")]), ce.number(180));
20924
21034
  },
20925
- evaluate: (ce, ops2) => ce.mul([ops2[0], ce.box(["Divide", "Pi", 180])])
21035
+ evaluate: (ce, ops2) => ce.mul([ops2[0], ce.div(ce.symbol("Pi"), ce.number(180))])
20926
21036
  }
20927
21037
  },
20928
21038
  Hypot: {
@@ -21290,8 +21400,8 @@ var CONSTRUCTIBLE_VALUES = [
21290
21400
  [
21291
21401
  [1, 8],
21292
21402
  {
21293
- Sin: "$\\frac\\sqrt{2-\\sqrt2}{2}$",
21294
- Cos: "$\\frac {\\sqrt {2+{\\sqrt {2}}}}{2}$",
21403
+ Sin: "$\\frac{\\sqrt{2-\\sqrt2}}{2}$",
21404
+ Cos: "$\\frac{\\sqrt {2+{\\sqrt {2}}}}{2}$",
21295
21405
  Tan: "$\\sqrt{2} - 1$",
21296
21406
  Cot: "$\\sqrt{2} + 1$",
21297
21407
  Sec: "$\\sqrt{ 4 - 2\\sqrt{2}}$",
@@ -21442,6 +21552,8 @@ var TRIG_IDENTITIES = {
21442
21552
  ]
21443
21553
  };
21444
21554
  function constructibleValues(ce, head2, x) {
21555
+ if (!x)
21556
+ return void 0;
21445
21557
  const specialValues = ce.cache(
21446
21558
  "constructible-trigonometric-values",
21447
21559
  () => {
@@ -21518,6 +21630,8 @@ function processInverseFunction(ce, xs) {
21518
21630
  return newHead ? ce.symbol(newHead) : void 0;
21519
21631
  }
21520
21632
  function evalTrig(ce, mode, head2, op3) {
21633
+ if (!op3)
21634
+ return void 0;
21521
21635
  if (mode === "evaluate") {
21522
21636
  const result = constructibleValues(ce, head2, op3)?.evaluate();
21523
21637
  if (result)
@@ -21715,7 +21829,7 @@ var BoxedSymbolDefinitionImpl = class {
21715
21829
  this._flags = def.flags ? normalizeFlags(def.flags) : void 0;
21716
21830
  this._domain = def.domain ? ce.domain(def.domain) : void 0;
21717
21831
  this.constant = def.constant ?? false;
21718
- this.holdUntil = def.holdUntil ?? "simplify";
21832
+ this.holdUntil = def.holdUntil ?? "evaluate";
21719
21833
  if (this.constant) {
21720
21834
  this._defValue = def.value;
21721
21835
  this._value = null;
@@ -22390,7 +22504,19 @@ function isSymbolDefinition(def) {
22390
22504
  return !!def && typeof def === "object" && ("domain" in def || "value" in def || "constant" in def);
22391
22505
  }
22392
22506
  function isFunctionDefinition(def) {
22393
- return !!def && typeof def === "object" && ("complexity" in def || "numeric" in def || "signature" in def);
22507
+ if (def === void 0 || def === null)
22508
+ return false;
22509
+ if (typeof def !== "object")
22510
+ return false;
22511
+ if ("complexity" in def || "numeric" in def || "signature" in def)
22512
+ return true;
22513
+ if (!("domain" in def))
22514
+ return false;
22515
+ if (def.domain === void 0)
22516
+ return false;
22517
+ if (typeof def.domain === "string")
22518
+ return def.domain === "Function";
22519
+ return def.domain.isFunction;
22394
22520
  }
22395
22521
 
22396
22522
  // src/compute-engine/library/library.ts
@@ -22470,7 +22596,7 @@ var LIBRARIES = {
22470
22596
  // @todo // volume, speed, area
22471
22597
  "domains": [],
22472
22598
  "core": CORE_LIBRARY,
22473
- "collections": [SETS_LIBRARY, COLLECTIONS_LIBRARY],
22599
+ "collections": [SETS_LIBRARY, COLLECTIONS_LIBRARY, domainSetsLibrary()],
22474
22600
  // 'domains': getDomainsDictionary(),
22475
22601
  "linear-algebra": [],
22476
22602
  //@todo // 'linear-algebra': [
@@ -23371,17 +23497,20 @@ var BoxedSymbol = class _BoxedSymbol extends AbstractBoxedExpression {
23371
23497
  }
23372
23498
  simplify(options) {
23373
23499
  const def = this.symbolDefinition;
23374
- if ((def?.holdUntil === "never" || def?.holdUntil === "simplify") && def.value)
23500
+ if (def?.holdUntil === "simplify" && def.value)
23375
23501
  return def.value.simplify(options);
23376
23502
  return options?.rules ? this.replace(options.rules) ?? this : this;
23377
23503
  }
23378
23504
  evaluate(options) {
23379
23505
  const def = this.symbolDefinition;
23380
- if (def?.holdUntil !== "N")
23381
- return def?.value?.evaluate(options) ?? this;
23506
+ if (def && (def.holdUntil === "simplify" || def.holdUntil === "evaluate"))
23507
+ return def.value?.evaluate(options) ?? this;
23382
23508
  return this;
23383
23509
  }
23384
23510
  N(options) {
23511
+ const def = this.symbolDefinition;
23512
+ if (def && def.holdUntil === "never")
23513
+ return this;
23385
23514
  return this.symbolDefinition?.value?.N(options) ?? this;
23386
23515
  }
23387
23516
  replace(rules, options) {
@@ -23767,16 +23896,6 @@ var ComputeEngine = class _ComputeEngine {
23767
23896
  this._tolerance = NUMERIC_TOLERANCE;
23768
23897
  this._bignumTolerance = this.bignum(this._tolerance);
23769
23898
  }
23770
- /** @internal */
23771
- bignum(a) {
23772
- if (typeof a === "bigint")
23773
- return new this._bignum(a.toString());
23774
- return new this._bignum(a);
23775
- }
23776
- /** @internal */
23777
- complex(a, b) {
23778
- return new import_complex19.Complex(a, b);
23779
- }
23780
23899
  chop(n) {
23781
23900
  if (typeof n === "number" && Math.abs(n) <= this._tolerance)
23782
23901
  return 0;
@@ -23786,6 +23905,20 @@ var ComputeEngine = class _ComputeEngine {
23786
23905
  return 0;
23787
23906
  return n;
23788
23907
  }
23908
+ bignum(a) {
23909
+ if (typeof a === "bigint")
23910
+ return new this._bignum(a.toString());
23911
+ return new this._bignum(a);
23912
+ }
23913
+ complex(a, b) {
23914
+ return new import_complex19.Complex(a, b);
23915
+ }
23916
+ isBignum(a) {
23917
+ return a instanceof Decimal;
23918
+ }
23919
+ isComplex(a) {
23920
+ return a instanceof import_complex19.Complex;
23921
+ }
23789
23922
  get latexSyntax() {
23790
23923
  if (!this._latexSyntax)
23791
23924
  this._latexSyntax = new LatexSyntax({
@@ -23794,7 +23927,7 @@ var ComputeEngine = class _ComputeEngine {
23794
23927
  precision: this.precision,
23795
23928
  avoidExponentsInRange: [-6, this.precision],
23796
23929
  onError: (err) => {
23797
- throw new Error(err[0].message.toString());
23930
+ throw new Error(JSON.stringify(err[0].message));
23798
23931
  }
23799
23932
  });
23800
23933
  return this._latexSyntax;
@@ -24058,8 +24191,8 @@ var ComputeEngine = class _ComputeEngine {
24058
24191
  const bxs = xs;
24059
24192
  return bxs.every((x) => x.isCanonical) ? bxs : bxs.map((x) => x.canonical);
24060
24193
  }
24061
- fn(head2, ops2, metadata) {
24062
- return boxFunction(this, head2, ops2, { metadata, canonical: true });
24194
+ fn(head2, ops2, options) {
24195
+ return boxFunction(this, head2, ops2, options ?? { canonical: true });
24063
24196
  }
24064
24197
  /** @internal */
24065
24198
  _fn(head2, ops2, metadata) {
@@ -24473,20 +24606,21 @@ var ComputeEngine = class _ComputeEngine {
24473
24606
  };
24474
24607
 
24475
24608
  // src/compute-engine.ts
24476
- var version = "0.12.4";
24609
+ var version = "0.12.6";
24477
24610
  globalThis[Symbol.for("io.cortexjs.compute-engine")] = {
24478
24611
  ComputeEngine: ComputeEngine.prototype.constructor,
24479
- version: "0.12.4"
24612
+ version: "0.12.6"
24480
24613
  };
24481
24614
  export {
24482
24615
  ComputeEngine,
24483
24616
  isEnvironmentEntry,
24617
+ isExpressionEntry,
24484
24618
  isFunctionEntry,
24485
- isIdentifierEntry,
24486
24619
  isInfixEntry,
24487
24620
  isMatchfixEntry,
24488
24621
  isPostfixEntry,
24489
24622
  isPrefixEntry,
24623
+ isSymbolEntry,
24490
24624
  version
24491
24625
  };
24492
24626
  /*! Bundled license information: