@cortex-js/compute-engine 0.55.0 → 0.55.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/compile.esm.js +1564 -1412
  2. package/dist/compile.min.esm.js +29 -29
  3. package/dist/compile.min.umd.cjs +29 -29
  4. package/dist/compile.umd.cjs +1564 -1412
  5. package/dist/compute-engine.esm.js +741 -486
  6. package/dist/compute-engine.min.esm.js +65 -65
  7. package/dist/compute-engine.min.umd.cjs +65 -65
  8. package/dist/compute-engine.umd.cjs +741 -486
  9. package/dist/core.esm.js +740 -485
  10. package/dist/core.min.esm.js +63 -63
  11. package/dist/core.min.umd.cjs +63 -63
  12. package/dist/core.umd.cjs +740 -485
  13. package/dist/interval.esm.js +1564 -1412
  14. package/dist/interval.min.esm.js +6 -6
  15. package/dist/interval.min.umd.cjs +6 -6
  16. package/dist/interval.umd.cjs +1564 -1412
  17. package/dist/latex-syntax.esm.js +673 -492
  18. package/dist/latex-syntax.min.esm.js +6 -6
  19. package/dist/latex-syntax.min.umd.cjs +6 -6
  20. package/dist/latex-syntax.umd.cjs +673 -492
  21. package/dist/math-json.esm.js +2 -2
  22. package/dist/math-json.min.esm.js +2 -2
  23. package/dist/math-json.min.umd.cjs +2 -2
  24. package/dist/math-json.umd.cjs +2 -2
  25. package/dist/numerics.esm.js +2 -2
  26. package/dist/numerics.min.esm.js +2 -2
  27. package/dist/numerics.min.umd.cjs +2 -2
  28. package/dist/numerics.umd.cjs +2 -2
  29. package/dist/types/big-decimal/big-decimal.d.ts +1 -1
  30. package/dist/types/big-decimal/index.d.ts +1 -1
  31. package/dist/types/big-decimal/transcendentals.d.ts +1 -1
  32. package/dist/types/big-decimal/utils.d.ts +1 -1
  33. package/dist/types/common/ansi-codes.d.ts +1 -1
  34. package/dist/types/common/configuration-change.d.ts +1 -1
  35. package/dist/types/common/fuzzy-string-match.d.ts +1 -1
  36. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  37. package/dist/types/common/interruptible.d.ts +1 -1
  38. package/dist/types/common/one-of.d.ts +1 -1
  39. package/dist/types/common/signals.d.ts +1 -1
  40. package/dist/types/common/type/ast-nodes.d.ts +1 -1
  41. package/dist/types/common/type/boxed-type.d.ts +1 -1
  42. package/dist/types/common/type/lexer.d.ts +1 -1
  43. package/dist/types/common/type/parse.d.ts +1 -1
  44. package/dist/types/common/type/parser.d.ts +1 -1
  45. package/dist/types/common/type/primitive.d.ts +1 -1
  46. package/dist/types/common/type/reduce.d.ts +1 -1
  47. package/dist/types/common/type/serialize.d.ts +1 -1
  48. package/dist/types/common/type/subtype.d.ts +1 -1
  49. package/dist/types/common/type/type-builder.d.ts +1 -1
  50. package/dist/types/common/type/types.d.ts +1 -1
  51. package/dist/types/common/type/utils.d.ts +1 -1
  52. package/dist/types/common/utils.d.ts +1 -1
  53. package/dist/types/compile.d.ts +1 -1
  54. package/dist/types/compute-engine/assume.d.ts +1 -1
  55. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +1 -1
  56. package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
  57. package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
  58. package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
  59. package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
  60. package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
  61. package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
  62. package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
  63. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
  64. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
  65. package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +1 -1
  66. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
  67. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
  68. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
  69. package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
  70. package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
  71. package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
  72. package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
  73. package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
  74. package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
  75. package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
  76. package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
  77. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  78. package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
  79. package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
  80. package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
  81. package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +1 -1
  82. package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
  83. package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
  84. package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
  85. package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
  86. package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
  87. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  88. package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
  89. package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
  90. package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
  91. package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
  92. package/dist/types/compute-engine/boxed-expression/rules.d.ts +1 -1
  93. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
  94. package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
  95. package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
  96. package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
  97. package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
  98. package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
  99. package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
  100. package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
  101. package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
  102. package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
  103. package/dist/types/compute-engine/collection-utils.d.ts +1 -1
  104. package/dist/types/compute-engine/compilation/base-compiler.d.ts +1 -1
  105. package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
  106. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  107. package/dist/types/compute-engine/compilation/gpu-target.d.ts +1 -1
  108. package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
  109. package/dist/types/compute-engine/compilation/javascript-target.d.ts +1 -1
  110. package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
  111. package/dist/types/compute-engine/compilation/types.d.ts +1 -1
  112. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  113. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  114. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  115. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  126. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  131. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  132. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  133. package/dist/types/compute-engine/global-types.d.ts +1 -1
  134. package/dist/types/compute-engine/index.d.ts +1 -1
  135. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  136. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  142. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +1 -1
  143. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  144. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  145. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  146. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  147. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  148. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
  149. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +3 -1
  150. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  151. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
  152. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  153. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  154. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  155. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  156. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
  157. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
  158. package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +1 -1
  159. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
  160. package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
  161. package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
  162. package/dist/types/compute-engine/latex-syntax/parse.d.ts +11 -1
  163. package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
  164. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  165. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  166. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
  167. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  168. package/dist/types/compute-engine/latex-syntax/types.d.ts +1 -1
  169. package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
  170. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  171. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  172. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  173. package/dist/types/compute-engine/library/colors.d.ts +1 -1
  174. package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
  175. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  176. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  177. package/dist/types/compute-engine/library/core.d.ts +1 -1
  178. package/dist/types/compute-engine/library/fractals.d.ts +1 -1
  179. package/dist/types/compute-engine/library/library.d.ts +1 -1
  180. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  181. package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
  182. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  183. package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
  184. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  185. package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
  186. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  187. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  188. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  189. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  190. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  191. package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
  192. package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
  193. package/dist/types/compute-engine/library/units.d.ts +1 -1
  194. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  195. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
  196. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
  197. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
  198. package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
  199. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  200. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  201. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  202. package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
  203. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  204. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  205. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  206. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  207. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  208. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  209. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  210. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  211. package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
  212. package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
  213. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  214. package/dist/types/compute-engine/numerics/types.d.ts +1 -1
  215. package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
  216. package/dist/types/compute-engine/oeis.d.ts +1 -1
  217. package/dist/types/compute-engine/sequence.d.ts +1 -1
  218. package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
  219. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  220. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  221. package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
  222. package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
  223. package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
  224. package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
  225. package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
  226. package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
  227. package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
  228. package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
  229. package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
  230. package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
  231. package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
  232. package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
  233. package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
  234. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  235. package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
  236. package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
  237. package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
  238. package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
  239. package/dist/types/compute-engine/types-definitions.d.ts +1 -1
  240. package/dist/types/compute-engine/types-engine.d.ts +1 -1
  241. package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
  242. package/dist/types/compute-engine/types-expression.d.ts +1 -1
  243. package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
  244. package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
  245. package/dist/types/compute-engine/types-serialization.d.ts +1 -1
  246. package/dist/types/compute-engine/types.d.ts +1 -1
  247. package/dist/types/compute-engine.d.ts +1 -1
  248. package/dist/types/core.d.ts +1 -1
  249. package/dist/types/interval.d.ts +1 -1
  250. package/dist/types/latex-syntax.d.ts +2 -2
  251. package/dist/types/math-json/symbols.d.ts +1 -1
  252. package/dist/types/math-json/types.d.ts +1 -1
  253. package/dist/types/math-json/utils.d.ts +1 -1
  254. package/dist/types/math-json.d.ts +2 -2
  255. package/dist/types/numerics.d.ts +1 -1
  256. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /** Compute Engine 0.55.0 */
1
+ /** Compute Engine 0.55.2 */
2
2
 
3
3
  // src/compute-engine/interval/util.ts
4
4
  function ok(value) {
@@ -5473,1132 +5473,1726 @@ function expressionToDictionaryValue(expr) {
5473
5473
  return expr;
5474
5474
  }
5475
5475
 
5476
- // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
5477
- function parseSequence(parser, terminator, lhs, prec, sep) {
5478
- if (terminator && terminator.minPrec >= prec) return null;
5479
- const result = lhs ? [lhs] : ["Nothing"];
5480
- let done = false;
5481
- while (!done) {
5482
- done = true;
5483
- parser.skipSpace();
5484
- while (parser.match(sep)) {
5485
- result.push("Nothing");
5486
- parser.skipSpace();
5487
- }
5488
- parser.skipVisualSpace();
5489
- if (parser.atTerminator(terminator)) {
5490
- result.push("Nothing");
5491
- } else {
5492
- const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
5493
- result.push(rhs ?? "Nothing");
5494
- done = rhs === null;
5495
- }
5496
- if (!done) {
5497
- parser.skipSpace();
5498
- done = !parser.match(sep);
5499
- if (!done) parser.skipVisualSpace();
5500
- }
5501
- }
5502
- return result;
5503
- }
5504
- function serializeOps(sep = "") {
5505
- return (serializer, expr) => {
5506
- if (!expr) return "";
5507
- const xs = operands(expr);
5508
- if (xs.length === 0) return "";
5509
- if (xs.length === 1) return serializer.serialize(xs[0]);
5510
- sep = {
5511
- "&": "\\&",
5512
- ":": "\\colon",
5513
- "|": "\\mvert",
5514
- "-": "-",
5515
- "\xB7": "\\cdot",
5516
- // U+00B7 MIDDLE DOT
5517
- "\u2012": "-",
5518
- // U+2012 FIGURE DASH
5519
- "\u2013": "--",
5520
- // U+2013 EN DASH
5521
- "\u2014": "---",
5522
- // U+2014 EM DASH
5523
- "\u2015": "-",
5524
- // U+2015 HORIZONTAL BAR
5525
- "\u2022": "\\bullet",
5526
- // U+2022 BULLET
5527
- "\u2026": "\\ldots"
5528
- }[sep] ?? sep;
5529
- const ys = xs.reduce((acc, item) => {
5530
- acc.push(serializer.serialize(item), sep);
5531
- return acc;
5532
- }, []);
5533
- ys.pop();
5534
- return joinLatex(ys);
5535
- };
5536
- }
5537
- var DEFINITIONS_CORE = [
5538
- //
5476
+ // src/compute-engine/latex-syntax/dictionary/definitions-logic.ts
5477
+ var DEFINITIONS_LOGIC = [
5539
5478
  // Constants
5540
- //
5541
5479
  {
5542
- latexTrigger: ["\\placeholder"],
5480
+ name: "True",
5543
5481
  kind: "symbol",
5544
- parse: (parser) => {
5545
- while (parser.match("<space>")) {
5546
- }
5547
- if (parser.match("["))
5548
- while (!parser.match("]") && !parser.atBoundary) parser.nextToken();
5549
- while (parser.match("<space>")) {
5550
- }
5551
- if (parser.match("<{>"))
5552
- while (!parser.match("<}>") && !parser.atBoundary) parser.nextToken();
5553
- return "Nothing";
5554
- }
5482
+ latexTrigger: ["\\top"]
5483
+ // U+22A4
5555
5484
  },
5556
- { name: "ContinuationPlaceholder", latexTrigger: ["\\dots"] },
5557
- { latexTrigger: ["\\ldots"], parse: "ContinuationPlaceholder" },
5558
- { latexTrigger: [".", ".", "."], parse: "ContinuationPlaceholder" },
5559
- //
5560
- // Functions
5561
- //
5562
- // Anonymous function, i.e. `(x) \mapsto x^2`
5563
5485
  {
5564
- name: "Function",
5565
- latexTrigger: ["\\mapsto"],
5566
- kind: "infix",
5567
- precedence: ARROW_PRECEDENCE,
5568
- // MathML rightwards arrow
5569
- parse: (parser, lhs, _until) => {
5570
- let params = [];
5571
- if (operator(lhs) === "Delimiter") lhs = operand(lhs, 1) ?? "Nothing";
5572
- if (operator(lhs) === "Sequence") {
5573
- for (const x of operands(lhs)) {
5574
- if (!symbol(x)) return null;
5575
- params.push(symbol(x));
5576
- }
5577
- } else {
5578
- if (!symbol(lhs)) return null;
5579
- params = [symbol(lhs)];
5580
- }
5581
- let rhs = parser.parseExpression({ minPrec: ARROW_PRECEDENCE }) ?? "Nothing";
5582
- if (operator(rhs) === "Delimiter") rhs = operand(rhs, 1) ?? "Nothing";
5583
- if (operator(rhs) === "Sequence") rhs = ["Block", ...operands(rhs)];
5584
- return ["Function", rhs, ...params];
5585
- },
5586
- serialize: (serializer, expr) => {
5587
- const args = operands(expr);
5588
- if (args.length < 1) return "()\\mapsto()";
5589
- if (args.length === 1)
5590
- return joinLatex([
5591
- "()",
5592
- "\\mapsto",
5593
- serializer.serialize(operand(expr, 1))
5594
- ]);
5595
- if (args.length === 2) {
5596
- return joinLatex([
5597
- serializer.serialize(operand(expr, 2)),
5598
- "\\mapsto",
5599
- serializer.serialize(operand(expr, 1))
5600
- ]);
5601
- }
5602
- return joinLatex([
5603
- serializer.wrapString(
5604
- operands(expr)?.slice(1).map((x) => serializer.serialize(x)).join(", "),
5605
- "normal"
5606
- ),
5607
- "\\mapsto",
5608
- serializer.serialize(operand(expr, 1))
5609
- ]);
5610
- }
5486
+ kind: "symbol",
5487
+ latexTrigger: "\\mathrm{True}",
5488
+ parse: "True"
5611
5489
  },
5612
5490
  {
5613
- name: "Apply",
5614
- kind: "function",
5615
- symbolTrigger: "apply",
5616
- serialize: (serializer, expr) => {
5617
- const lhs = operand(expr, 1);
5618
- const h = operator(lhs);
5619
- if (h === "InverseFunction" || h === "Derivative") {
5620
- const style2 = serializer.options.applyFunctionStyle(
5621
- expr,
5622
- serializer.level
5623
- );
5624
- const args = operands(expr).slice(1);
5625
- return serializer.serializeFunction(
5626
- lhs,
5627
- serializer.dictionary.ids.get(h)
5628
- ) + serializer.wrapString(
5629
- args.map((x) => serializer.serialize(x)).join(", "),
5630
- style2
5631
- );
5632
- }
5633
- const rhs = operand(expr, 2);
5634
- if (typeof lhs === "string" || !rhs) {
5635
- const fn = operands(expr).slice(1);
5636
- return serializer.serialize(fn);
5637
- }
5638
- if (nops(expr) === 2) {
5639
- return joinLatex([
5640
- serializer.wrap(lhs, 20),
5641
- "\\lhd",
5642
- serializer.wrap(rhs, 20)
5643
- ]);
5644
- }
5645
- const style = serializer.options.applyFunctionStyle(
5646
- expr,
5647
- serializer.level
5648
- );
5649
- return joinLatex([
5650
- "\\operatorname{apply}",
5651
- serializer.wrapString(
5652
- serializer.serialize(h) + ", " + serializer.serialize(["List", ...operands(expr)]),
5653
- style
5654
- )
5655
- ]);
5656
- }
5491
+ kind: "symbol",
5492
+ latexTrigger: "\\operatorname{True}",
5493
+ parse: "True"
5657
5494
  },
5658
5495
  {
5659
- latexTrigger: "\\lhd",
5660
- kind: "infix",
5661
- precedence: 20,
5662
- parse: "Apply"
5496
+ kind: "symbol",
5497
+ latexTrigger: "\\mathsf{T}",
5498
+ parse: "True"
5663
5499
  },
5664
5500
  {
5665
- latexTrigger: "\\rhd",
5501
+ name: "False",
5502
+ kind: "symbol",
5503
+ latexTrigger: ["\\bot"]
5504
+ // ⊥ U+22A5
5505
+ },
5506
+ {
5507
+ kind: "symbol",
5508
+ latexTrigger: "\\operatorname{False}",
5509
+ parse: "False"
5510
+ },
5511
+ {
5512
+ kind: "symbol",
5513
+ latexTrigger: "\\mathsf{F}",
5514
+ parse: "False"
5515
+ },
5516
+ // Operators
5517
+ // Logic operators have lower precedence than comparisons (245)
5518
+ // so that `x = 1 \lor x = 2` parses as `(x = 1) \lor (x = 2)`
5519
+ // See https://github.com/cortex-js/compute-engine/issues/243
5520
+ {
5521
+ name: "And",
5666
5522
  kind: "infix",
5667
- precedence: 20,
5668
- parse: (parser, lhs, _until) => {
5669
- const rhs = parser.parseExpression({ minPrec: 21 }) ?? "Nothing";
5670
- return ["Apply", rhs, lhs];
5671
- }
5523
+ latexTrigger: ["\\land"],
5524
+ precedence: 235
5525
+ // serialize: '\\land',
5672
5526
  },
5527
+ { kind: "infix", latexTrigger: ["\\wedge"], parse: "And", precedence: 235 },
5528
+ { kind: "infix", latexTrigger: "\\&", parse: "And", precedence: 235 },
5673
5529
  {
5674
- name: "EvaluateAt",
5675
- openTrigger: ".",
5676
- closeTrigger: "|",
5677
- kind: "matchfix",
5678
- serialize: (serializer, expr) => {
5679
- const fn = operand(expr, 1);
5680
- if (!fn) return "";
5681
- const args = operands(expr).slice(1);
5682
- if (operator(fn) === "Function") {
5683
- const parameters = operands(fn).slice(1);
5684
- let body = operand(fn, 1);
5685
- if (operator(body) === "Block" && nops(body) === 1)
5686
- body = operand(body, 1);
5687
- if (parameters.length > 0) {
5688
- return `\\left.\\left(${serializer.serialize(
5689
- body
5690
- )}\\right)\\right|_{${parameters.map(
5691
- (x, i) => `${serializer.serialize(x)}=${serializer.serialize(args[i])}`
5692
- ).join(", ")}}`;
5693
- }
5694
- }
5695
- return `\\left.\\left(${serializer.serialize(fn)}\\right)\\right|_{${args.map((x) => serializer.serialize(x)).join(", ")}}`;
5696
- }
5530
+ kind: "infix",
5531
+ latexTrigger: "\\operatorname{and}",
5532
+ parse: "And",
5533
+ precedence: 235
5697
5534
  },
5698
- // The mathtools package includes several synonmyms for \colonequals. The
5699
- // preferred one as of summer 2022 is `\coloneq` (see § 3.7.3 https://ctan.math.illinois.edu/macros/latex/contrib/mathtools/mathtools.pdf)
5700
5535
  {
5701
- name: "Assign",
5702
- latexTrigger: "\\coloneq",
5536
+ name: "Or",
5703
5537
  kind: "infix",
5704
- associativity: "right",
5705
- precedence: ASSIGNMENT_PRECEDENCE,
5706
- serialize: (serializer, expr) => {
5707
- const id = unhold(operand(expr, 1));
5708
- if (operator(operand(expr, 2)) === "Function") {
5709
- const op_2 = operand(expr, 2);
5710
- const body = unhold(operand(op_2, 1));
5711
- const args = operands(op_2).slice(1);
5712
- return joinLatex([
5713
- serializer.serialize(id),
5714
- serializer.wrapString(
5715
- args.map((x) => serializer.serialize(x)).join(", "),
5716
- serializer.options.applyFunctionStyle(expr, serializer.level)
5717
- ),
5718
- "\\coloneq",
5719
- serializer.serialize(body)
5720
- ]);
5721
- }
5722
- return joinLatex([
5723
- serializer.serialize(id),
5724
- "\\coloneq",
5725
- serializer.serialize(operand(expr, 2))
5726
- ]);
5727
- },
5728
- parse: parseAssign
5538
+ latexTrigger: ["\\lor"],
5539
+ precedence: 230
5729
5540
  },
5541
+ { kind: "infix", latexTrigger: ["\\vee"], parse: "Or", precedence: 230 },
5542
+ { kind: "infix", latexTrigger: "\\parallel", parse: "Or", precedence: 230 },
5730
5543
  {
5731
- latexTrigger: "\\coloneqq",
5732
5544
  kind: "infix",
5733
- associativity: "right",
5734
- precedence: ASSIGNMENT_PRECEDENCE,
5735
- parse: parseAssign
5545
+ latexTrigger: "\\operatorname{or}",
5546
+ parse: "Or",
5547
+ precedence: 230
5736
5548
  },
5737
- // From the colonequals package:
5738
5549
  {
5739
- latexTrigger: "\\colonequals",
5550
+ name: "Xor",
5740
5551
  kind: "infix",
5741
- associativity: "right",
5742
- precedence: ASSIGNMENT_PRECEDENCE,
5743
- parse: parseAssign
5552
+ latexTrigger: ["\\veebar"],
5553
+ precedence: 232
5744
5554
  },
5555
+ // Possible alt: \oplus ⊕ U+2295
5745
5556
  {
5746
- latexTrigger: [":", "="],
5747
- kind: "infix",
5748
- associativity: "right",
5749
- precedence: ASSIGNMENT_PRECEDENCE,
5750
- parse: parseAssign
5557
+ name: "Not",
5558
+ kind: "prefix",
5559
+ latexTrigger: ["\\lnot"],
5560
+ precedence: 880
5751
5561
  },
5752
- // General colon operator (type annotation, mapping notation)
5753
- // Precedence below assignment (260) so `:=` takes priority,
5754
- // and below arrows (270) so `f: A \to B` parses as `Colon(f, To(A, B))`
5755
5562
  {
5756
- name: "Colon",
5757
- latexTrigger: ":",
5563
+ kind: "prefix",
5564
+ latexTrigger: ["\\neg"],
5565
+ parse: "Not",
5566
+ precedence: 880
5567
+ },
5568
+ {
5569
+ name: "Nand",
5758
5570
  kind: "infix",
5759
- associativity: "right",
5760
- precedence: 250,
5761
- serialize: (serializer, expr) => joinLatex([
5762
- serializer.serialize(operand(expr, 1)),
5763
- "\\colon",
5764
- serializer.serialize(operand(expr, 2))
5765
- ])
5571
+ latexTrigger: ["\\barwedge"],
5572
+ precedence: 232
5573
+ // serialize: '\\mid',
5766
5574
  },
5767
5575
  {
5768
- latexTrigger: "\\colon",
5576
+ name: "Nor",
5769
5577
  kind: "infix",
5770
- associativity: "right",
5771
- precedence: 250,
5772
- parse: "Colon"
5578
+ latexTrigger: ["\u22BD"],
5579
+ // bar vee
5580
+ precedence: 232
5581
+ // serialize: '\\downarrow',
5773
5582
  },
5583
+ // Functions
5774
5584
  {
5775
- name: "BaseForm",
5776
- serialize: (serializer, expr) => {
5777
- const radix = machineValue(operand(expr, 2)) ?? NaN;
5778
- if (isFinite(radix) && radix >= 2 && radix <= 36) {
5779
- const num = machineValue(operand(expr, 1)) ?? NaN;
5780
- if (isFinite(num) && Number.isInteger(num)) {
5781
- let digits = Number(num).toString(radix);
5782
- let groupLength = 0;
5783
- if (radix === 2) {
5784
- groupLength = 4;
5785
- } else if (radix === 10) {
5786
- groupLength = 4;
5787
- } else if (radix === 16) {
5788
- groupLength = 2;
5789
- } else if (radix > 16) {
5790
- groupLength = 4;
5791
- }
5792
- if (groupLength > 0) {
5793
- const oldDigits = digits;
5794
- digits = "";
5795
- for (let i = 0; i < oldDigits.length; i++) {
5796
- if (i > 0 && i % groupLength === 0) digits = "\\, " + digits;
5797
- digits = oldDigits[oldDigits.length - i - 1] + digits;
5798
- }
5799
- }
5800
- return `(\\text{${digits}}_{${radix}}`;
5801
- }
5802
- }
5803
- return "\\operatorname{BaseForm}(" + serializer.serialize(operand(expr, 1)) + ", " + serializer.serialize(operand(expr, 2)) + ")";
5804
- }
5585
+ kind: "function",
5586
+ symbolTrigger: "and",
5587
+ parse: "And"
5805
5588
  },
5806
5589
  {
5807
- name: "Sequence",
5808
- // Use a space as a separator, otherwise a sequence of numbers
5809
- // could be interpreted as a single number.
5810
- serialize: serializeOps(" ")
5590
+ kind: "function",
5591
+ symbolTrigger: "or",
5592
+ parse: "Or"
5811
5593
  },
5812
5594
  {
5813
- name: "InvisibleOperator",
5814
- serialize: serializeOps("")
5595
+ kind: "function",
5596
+ symbolTrigger: "not",
5597
+ parse: "Not"
5815
5598
  },
5599
+ // Relations
5816
5600
  {
5817
- // The first argument is a function expression.
5818
- // The second (optional) argument is a string specifying the
5819
- // delimiters and separator.
5820
- name: "Delimiter",
5821
- serialize: (serializer, expr) => {
5822
- const style = serializer.options.groupStyle(expr, serializer.level + 1);
5823
- const arg1 = operand(expr, 1);
5824
- let delims = {
5825
- Set: "{,}",
5826
- List: "[,]",
5827
- Tuple: "(,)",
5828
- Single: "(,)",
5829
- Pair: "(,)",
5830
- Triple: "(,)",
5831
- Sequence: "(,)",
5832
- String: '""'
5833
- }[operator(arg1)];
5834
- const items = delims ? arg1 : ["Sequence", arg1];
5835
- delims ??= "(,)";
5836
- if (nops(expr) > 1) {
5837
- const op2 = stringValue(operand(expr, 2));
5838
- if (typeof op2 === "string" && op2.length <= 3) delims = op2;
5839
- }
5840
- let [open, sep, close] = ["", "", ""];
5841
- if (delims.length === 3) [open, sep, close] = delims;
5842
- else if (delims.length === 2) [open, close] = delims;
5843
- else if (delims.length === 1) sep = delims;
5844
- const body = arg1 ? items ? serializeOps(sep)(serializer, items) : serializer.serialize(arg1) : "";
5845
- return serializer.wrapString(body, style, open + close);
5846
- }
5601
+ name: "Implies",
5602
+ kind: "infix",
5603
+ precedence: 220,
5604
+ associativity: "right",
5605
+ latexTrigger: ["\\implies"],
5606
+ serialize: "\\implies"
5847
5607
  },
5848
5608
  {
5849
- name: "Tuple",
5850
- serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
5609
+ latexTrigger: ["\\Rightarrow"],
5610
+ kind: "infix",
5611
+ precedence: 220,
5612
+ associativity: "right",
5613
+ parse: "Implies"
5851
5614
  },
5852
5615
  {
5853
- name: "Pair",
5854
- serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
5616
+ latexTrigger: ["\\rightarrow"],
5617
+ kind: "infix",
5618
+ precedence: 220,
5619
+ associativity: "right",
5620
+ parse: "Implies"
5855
5621
  },
5856
5622
  {
5857
- name: "Triple",
5858
- serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
5623
+ latexTrigger: ["\\Longrightarrow"],
5624
+ kind: "infix",
5625
+ precedence: 220,
5626
+ associativity: "right",
5627
+ parse: "Implies"
5859
5628
  },
5860
5629
  {
5861
- name: "Single",
5862
- serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
5630
+ latexTrigger: ["\\longrightarrow"],
5631
+ kind: "infix",
5632
+ precedence: 220,
5633
+ associativity: "right",
5634
+ parse: "Implies"
5863
5635
  },
5864
5636
  {
5865
- name: "Domain",
5866
- serialize: (serializer, expr) => {
5867
- if (operator(expr) === "Error") return serializer.serialize(expr);
5868
- return `\\mathbf{${serializer.serialize(operand(expr, 1))}}`;
5637
+ // Non-strict mode: => for implies
5638
+ latexTrigger: ["=", ">"],
5639
+ kind: "infix",
5640
+ precedence: 220,
5641
+ associativity: "right",
5642
+ parse: (parser, lhs, until) => {
5643
+ if (parser.options.strict !== false) return null;
5644
+ const rhs = parser.parseExpression({ ...until, minPrec: 220 });
5645
+ if (rhs === null) return null;
5646
+ return ["Implies", lhs, rhs];
5869
5647
  }
5870
5648
  },
5871
5649
  {
5872
- latexTrigger: ["\\mathtip"],
5873
- parse: (parser) => {
5874
- const op1 = parser.parseGroup();
5875
- parser.parseGroup();
5876
- return op1;
5877
- }
5650
+ name: "Equivalent",
5651
+ // MathML: identical to, Mathematica: Congruent
5652
+ latexTrigger: ["\\iff"],
5653
+ kind: "infix",
5654
+ associativity: "right",
5655
+ precedence: 219
5878
5656
  },
5879
5657
  {
5880
- latexTrigger: ["\\texttip"],
5881
- parse: (parser) => {
5882
- const op1 = parser.parseGroup();
5883
- parser.parseGroup();
5884
- return op1;
5885
- }
5658
+ latexTrigger: ["\\Leftrightarrow"],
5659
+ kind: "infix",
5660
+ associativity: "right",
5661
+ precedence: 219,
5662
+ parse: "Equivalent"
5886
5663
  },
5887
5664
  {
5888
- latexTrigger: ["\\error"],
5889
- parse: (parser) => ["Error", parser.parseGroup()]
5665
+ latexTrigger: ["\\leftrightarrow"],
5666
+ kind: "infix",
5667
+ associativity: "right",
5668
+ precedence: 219,
5669
+ parse: "Equivalent"
5890
5670
  },
5891
5671
  {
5892
- name: "Error",
5893
- serialize: (serializer, expr) => {
5894
- const op1 = operand(expr, 1);
5895
- if (stringValue(op1) === "missing")
5896
- return `\\error{${serializer.options.missingSymbol ?? "\\placeholder{}"}}`;
5897
- const where = errorContextAsLatex(serializer, expr) || "\\blacksquare";
5898
- const code = operator(op1) === "ErrorCode" ? stringValue(operand(op1, 1)) : stringValue(op1);
5899
- if (code === "incompatible-type") {
5900
- if (symbol(operand(op1, 3)) === "Undefined") {
5901
- return `\\mathtip{\\error{${where}}}{\\notin ${serializer.serialize(
5902
- operand(op1, 2)
5903
- )}}`;
5904
- }
5905
- return `\\mathtip{\\error{${where}}}{\\in ${serializer.serialize(
5906
- operand(op1, 3)
5907
- )}\\notin ${serializer.serialize(operand(op1, 2))}}`;
5908
- }
5909
- if (typeof code === "string") return `\\error{${where}}`;
5910
- return `\\error{${where}}`;
5911
- }
5912
- },
5913
- {
5914
- name: "ErrorCode",
5915
- serialize: (serializer, expr) => {
5916
- const code = stringValue(operand(expr, 1));
5917
- if (code === "missing")
5918
- return serializer.options.missingSymbol ?? "\\placeholder{}";
5919
- if (code === "unexpected-command" || code === "unexpected-operator" || code === "unexpected-token" || code === "invalid-symbol" || code === "unknown-environment" || code === "unexpected-base" || code === "incompatible-type") {
5920
- return "";
5921
- }
5922
- return `\\texttip{\\error{\\blacksquare}}{\\mathtt{${code}}}`;
5923
- }
5672
+ latexTrigger: ["\\Longleftrightarrow"],
5673
+ kind: "infix",
5674
+ associativity: "right",
5675
+ precedence: 219,
5676
+ parse: "Equivalent"
5924
5677
  },
5925
5678
  {
5926
- name: "FromLatex",
5927
- serialize: (_serializer, expr) => {
5928
- return `\\texttt{${sanitizeLatex(stringValue(operand(expr, 1)))}}`;
5929
- }
5679
+ latexTrigger: ["\\longleftrightarrow"],
5680
+ kind: "infix",
5681
+ associativity: "right",
5682
+ precedence: 219,
5683
+ parse: "Equivalent"
5930
5684
  },
5931
5685
  {
5932
- name: "Latex",
5933
- serialize: (serializer, expr) => {
5934
- if (expr === null) return "";
5935
- return joinLatex(
5936
- mapArgs(expr, (x) => stringValue(x) ?? serializer.serialize(x))
5937
- );
5686
+ // Non-strict mode: <=> for equivalence
5687
+ latexTrigger: ["<", "=", ">"],
5688
+ kind: "infix",
5689
+ precedence: 219,
5690
+ associativity: "right",
5691
+ parse: (parser, lhs, until) => {
5692
+ if (parser.options.strict !== false) return null;
5693
+ const rhs = parser.parseExpression({ ...until, minPrec: 219 });
5694
+ if (rhs === null) return null;
5695
+ return ["Equivalent", lhs, rhs];
5938
5696
  }
5939
5697
  },
5940
5698
  {
5941
- name: "LatexString",
5942
- serialize: (serializer, expr) => {
5943
- if (expr === null) return "";
5944
- return joinLatex(mapArgs(expr, (x) => serializer.serialize(x)));
5699
+ latexTrigger: ["\\equiv"],
5700
+ kind: "infix",
5701
+ associativity: "right",
5702
+ precedence: 219,
5703
+ parse: (parser, lhs, terminator) => {
5704
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 219 });
5705
+ const index = parser.index;
5706
+ const modulus = parser.parseExpression({ ...terminator, minPrec: 219 });
5707
+ if (modulus !== null && operator(modulus) === "Mod")
5708
+ return ["Congruent", lhs, rhs, missingIfEmpty(operand(modulus, 1))];
5709
+ parser.index = index;
5710
+ return ["Equivalent", lhs, missingIfEmpty(rhs)];
5945
5711
  }
5946
5712
  },
5947
- { name: "LatexTokens", serialize: serializeLatexTokens },
5948
5713
  {
5949
- name: "At",
5950
- kind: "postfix",
5951
- precedence: 810,
5952
- latexTrigger: ["["],
5953
- parse: parseAt("]"),
5954
- serialize: (serializer, expr) => joinLatex(["\\lbrack", serializeOps(", ")(serializer, expr), "\\rbrack"])
5714
+ name: "Proves",
5715
+ kind: "infix",
5716
+ latexTrigger: ["\\vdash"],
5717
+ precedence: 220,
5718
+ associativity: "right",
5719
+ serialize: "\\vdash"
5955
5720
  },
5956
5721
  {
5957
- kind: "postfix",
5958
- precedence: 810,
5959
- latexTrigger: ["\\lbrack"],
5960
- parse: parseAt("\\rbrack")
5722
+ name: "Entails",
5723
+ kind: "infix",
5724
+ latexTrigger: ["\\vDash"],
5725
+ precedence: 220,
5726
+ associativity: "right",
5727
+ serialize: "\\vDash"
5961
5728
  },
5962
5729
  {
5963
- kind: "postfix",
5964
- precedence: 810,
5965
- latexTrigger: ["\\left", "\\lbrack"],
5966
- parse: parseAt("\\right", "\\rbrack")
5730
+ name: "Satisfies",
5731
+ kind: "infix",
5732
+ latexTrigger: ["\\models"],
5733
+ precedence: 220,
5734
+ associativity: "right",
5735
+ serialize: "\\models"
5967
5736
  },
5737
+ // Quantifiers: for all, exists
5968
5738
  {
5969
- kind: "postfix",
5970
- latexTrigger: ["_"],
5971
- parse: (parser, lhs, _until) => {
5972
- let rhs = parser.parseGroup() ?? parser.parseToken();
5973
- if (rhs === null && parser.options.strict === false && parser.peek === "(")
5974
- rhs = parser.parseEnclosure();
5975
- const sym = symbol(lhs);
5976
- if (rhs !== null && (sym && parser.getSymbolType(sym).matches("indexed_collection") || operator(lhs) === "List")) {
5977
- if (operator(rhs) === "Delimiter") rhs = operand(rhs, 1) ?? "Nothing";
5978
- if (operator(rhs) === "Sequence") return ["At", lhs, ...operands(rhs)];
5979
- return ["At", lhs, rhs];
5980
- }
5981
- return ["Subscript", lhs, rhs];
5982
- }
5739
+ name: "ForAll",
5740
+ kind: "prefix",
5741
+ latexTrigger: ["\\forall"],
5742
+ precedence: 200,
5743
+ // Has to be lower than COMPARISON_PRECEDENCE
5744
+ serialize: serializeQuantifier("\\forall"),
5745
+ parse: parseQuantifier("ForAll")
5983
5746
  },
5984
5747
  {
5985
- name: "List",
5986
- kind: "matchfix",
5987
- openTrigger: "[",
5988
- closeTrigger: "]",
5989
- parse: parseBrackets,
5990
- serialize: serializeList
5748
+ name: "Exists",
5749
+ kind: "prefix",
5750
+ latexTrigger: ["\\exists"],
5751
+ precedence: 200,
5752
+ // Has to be lower than COMPARISON_PRECEDENCE,
5753
+ serialize: serializeQuantifier("\\exists"),
5754
+ parse: parseQuantifier("Exists")
5991
5755
  },
5992
5756
  {
5993
- kind: "matchfix",
5994
- openTrigger: "(",
5995
- closeTrigger: ")",
5996
- parse: parseParenDelimiter
5757
+ name: "ExistsUnique",
5758
+ kind: "prefix",
5759
+ latexTrigger: ["\\exists", "!"],
5760
+ precedence: 200,
5761
+ // Has to be lower than COMPARISON_PRECEDENCE,
5762
+ serialize: serializeQuantifier("\\exists!"),
5763
+ parse: parseQuantifier("ExistsUnique")
5997
5764
  },
5998
5765
  {
5999
- latexTrigger: [","],
6000
- kind: "infix",
6001
- precedence: 20,
6002
- // Unlike the matchfix version of List,
6003
- // when the comma operator is used, the lhs and rhs are flattened,
6004
- // i.e. `1,2,3` -> `["Delimiter", ["List", 1, 2, 3], ","]`,
6005
- // and `1, (2, 3)` -> `["Delimiter",
6006
- // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "()", ","]]],
6007
- parse: (parser, lhs, terminator) => {
6008
- const seq = parseSequence(parser, terminator, lhs, 20, ",");
6009
- if (seq === null) return null;
6010
- return ["Delimiter", ["Sequence", ...seq], { str: "," }];
6011
- }
5766
+ name: "NotForAll",
5767
+ kind: "prefix",
5768
+ latexTrigger: ["\\lnot", "\\forall"],
5769
+ precedence: 200,
5770
+ // Has to be lower than COMPARISON_PRECEDENCE
5771
+ serialize: serializeQuantifier("\\lnot\\forall"),
5772
+ parse: parseQuantifier("NotForAll")
6012
5773
  },
6013
- // Entry to handle the case of a single comma
6014
- // with a missing lhs.
6015
5774
  {
6016
- latexTrigger: [","],
5775
+ name: "NotExists",
6017
5776
  kind: "prefix",
6018
- precedence: 20,
6019
- parse: (parser, terminator) => {
6020
- const seq = parseSequence(parser, terminator, null, 20, ",");
6021
- if (seq === null) return null;
6022
- return ["Delimiter", ["Sequence", ...seq], { str: "," }];
6023
- }
5777
+ latexTrigger: ["\\lnot", "\\exists"],
5778
+ precedence: 200,
5779
+ // Has to be lower than COMPARISON_PRECEDENCE,
5780
+ serialize: serializeQuantifier("\\lnot\\exists"),
5781
+ parse: parseQuantifier("NotExists")
6024
5782
  },
6025
5783
  {
6026
- name: "Range",
6027
- latexTrigger: [".", "."],
6028
- kind: "infix",
6029
- // associativity: 'left',
6030
- precedence: 800,
6031
- parse: parseRange,
5784
+ name: "KroneckerDelta",
5785
+ kind: "prefix",
5786
+ latexTrigger: ["\\delta", "_"],
5787
+ precedence: 200,
6032
5788
  serialize: (serializer, expr) => {
6033
5789
  const args = operands(expr);
6034
- if (args.length === 0) return "";
6035
- if (args.length === 1)
6036
- return "1.." + serializer.serialize(operand(expr, 1));
6037
- if (args.length === 2)
6038
- return serializer.wrap(operand(expr, 1), 10) + ".." + serializer.wrap(operand(expr, 2), 10);
6039
- if (args.length === 3) {
6040
- const step = machineValue(operand(expr, 3));
6041
- const start = machineValue(operand(expr, 1));
6042
- if (step !== null && start !== null) {
6043
- return serializer.wrap(operand(expr, 1), 10) + ".." + serializer.wrap(start + step, 10) + ".." + serializer.wrap(operand(expr, 2), 10);
6044
- }
6045
- return serializer.wrap(operand(expr, 1), 10) + "..(" + (serializer.wrap(operand(expr, 1), ADDITION_PRECEDENCE) + "+" + serializer.wrap(operand(expr, 3), ADDITION_PRECEDENCE)) + ").." + serializer.wrap(operand(expr, 2), 10);
5790
+ if (args.length === 0) return "\\delta";
5791
+ if (args.every((x) => symbol(x)))
5792
+ return `\\delta_{${args.map((arg) => serializer.serialize(arg)).join("")}}`;
5793
+ return `\\delta_{${args.map((arg) => serializer.serialize(arg)).join(", ")}}`;
5794
+ },
5795
+ parse: (parser) => {
5796
+ const group = parser.parseGroup();
5797
+ if (group === null) {
5798
+ const token = parser.parseToken();
5799
+ if (!token) return null;
5800
+ return ["KroneckerDelta", token];
6046
5801
  }
6047
- return "";
5802
+ const seq = getSequence(group);
5803
+ if (seq && seq.length <= 2) return ["KroneckerDelta", ...seq];
5804
+ if (operator(group) === "InvisibleOperator")
5805
+ return ["KroneckerDelta", ...operands(group)];
5806
+ if (group !== null) return ["KroneckerDelta", group];
5807
+ return null;
6048
5808
  }
6049
5809
  },
5810
+ // Iverson brackets. Also called the "indicator function"
5811
+ // Must have a single argument, a relational expression, i.e.
5812
+ // `[ a = b ]` or `[ x \leq 0 ]`
5813
+ // Otherwise, it gets rejected, it could be something else, like a list or
5814
+ // tuple.
6050
5815
  {
6051
- latexTrigger: [";"],
6052
- kind: "infix",
6053
- precedence: 19,
6054
- parse: (parser, lhs, terminator) => {
6055
- const seq = parseSequence(parser, terminator, lhs, 19, ";");
6056
- if (seq === null) return null;
6057
- if (seq.some((e) => operator(e) === "Assign"))
6058
- return buildBlockFromSequence(seq);
6059
- return ["Delimiter", ["Sequence", ...seq], "';'"];
5816
+ name: "Boole",
5817
+ kind: "matchfix",
5818
+ openTrigger: "[",
5819
+ closeTrigger: "]",
5820
+ // serialize: (serializer: Serializer, expr: MathJsonExpression) => {
5821
+ // const args = ops(expr);
5822
+ // return `[${serializer.serialize(arg)}]`;
5823
+ // },
5824
+ parse: (_parser, body) => {
5825
+ const h = operator(body);
5826
+ if (!h) return null;
5827
+ if (!DEFINITIONS_INEQUALITIES.some((x) => x.name === h)) return null;
5828
+ return ["Boole", body];
6060
5829
  }
6061
5830
  },
6062
- // \text{where} — variable binding infix
6063
5831
  {
6064
- latexTrigger: ["\\text"],
6065
- kind: "infix",
6066
- associativity: "none",
6067
- precedence: 21,
6068
- // Above ; (19) and , (20), very low binding
6069
- parse: (parser, lhs, until) => {
6070
- const start = parser.index;
6071
- if (!matchTextKeyword(parser, "where")) {
6072
- parser.index = start;
6073
- return null;
6074
- }
6075
- return parseWhereExpression(parser, lhs, until);
5832
+ kind: "matchfix",
5833
+ openTrigger: "\\llbracket",
5834
+ closeTrigger: "\\rrbracket",
5835
+ parse: (_parser, body) => {
5836
+ const h = operator(body);
5837
+ if (!h) return null;
5838
+ if (!DEFINITIONS_INEQUALITIES.some((x) => x.name === h)) return null;
5839
+ return ["Boole", body];
6076
5840
  }
6077
5841
  },
6078
- // \operatorname{where}
6079
- {
6080
- symbolTrigger: "where",
6081
- kind: "infix",
6082
- associativity: "none",
6083
- precedence: 21,
6084
- parse: (parser, lhs, until) => parseWhereExpression(parser, lhs, until)
6085
- },
6086
- // Block serializer — used by both `where` and semicolon blocks
5842
+ // Predicate application in First-Order Logic.
5843
+ // ["Predicate", "P", "x", "y"] serializes to "P(x, y)"
6087
5844
  {
6088
- name: "Block",
5845
+ name: "Predicate",
6089
5846
  serialize: (serializer, expr) => {
6090
5847
  const args = operands(expr);
6091
- if (!args || args.length === 0) return "";
6092
- const parts = args.filter((a) => operator(a) !== "Declare").map((a) => serializer.serialize(a));
6093
- return parts.join("; ");
5848
+ if (args.length === 0) return "";
5849
+ const pred = args[0];
5850
+ const predStr = typeof pred === "string" ? pred : serializer.serialize(pred);
5851
+ if (args.length === 1) return predStr;
5852
+ const argStrs = args.slice(1).map((arg) => serializer.serialize(arg));
5853
+ return `${predStr}(${argStrs.join(", ")})`;
5854
+ }
5855
+ }
5856
+ ];
5857
+ function serializeQuantifier(quantifierSymbol) {
5858
+ return (serializer, expr) => {
5859
+ const args = operands(expr);
5860
+ if (args.length === 0) return quantifierSymbol;
5861
+ if (args.length === 1)
5862
+ return `${quantifierSymbol} ${serializer.serialize(args[0])}`;
5863
+ const boundVar = serializer.serialize(args[0]);
5864
+ const body = serializer.serialize(args[1]);
5865
+ return `${quantifierSymbol} ${boundVar}, ${body}`;
5866
+ };
5867
+ }
5868
+ function tightBindingCondition(p, terminator) {
5869
+ return p.peek === "\\to" || p.peek === "\\rightarrow" || p.peek === "\\implies" || p.peek === "\\Rightarrow" || p.peek === "\\iff" || p.peek === "\\Leftrightarrow" || p.peek === "\\land" || p.peek === "\\wedge" || p.peek === "\\lor" || p.peek === "\\vee" || (terminator.condition?.(p) ?? false);
5870
+ }
5871
+ function parseQuantifier(kind) {
5872
+ return (parser, terminator) => {
5873
+ const index = parser.index;
5874
+ const useTightBinding = parser.options.quantifierScope !== "loose";
5875
+ const symbol2 = parser.parseSymbol(terminator);
5876
+ if (symbol2) {
5877
+ parser.skipSpace();
5878
+ if (parser.match(",") || parser.match("\\mid") || parser.match(".") || parser.match(":") || parser.match("\\colon")) {
5879
+ const bodyTerminator = useTightBinding ? {
5880
+ ...terminator,
5881
+ condition: (p) => tightBindingCondition(p, terminator)
5882
+ } : terminator;
5883
+ parser.enterQuantifierScope();
5884
+ const body2 = parser.parseExpression(bodyTerminator);
5885
+ parser.exitQuantifierScope();
5886
+ return [kind, symbol2, missingIfEmpty(body2)];
5887
+ }
5888
+ parser.enterQuantifierScope();
5889
+ const body = parser.parseEnclosure();
5890
+ parser.exitQuantifierScope();
5891
+ if (body) return [kind, symbol2, missingIfEmpty(body)];
5892
+ }
5893
+ parser.index = index;
5894
+ const condTerminator = {
5895
+ ...terminator,
5896
+ condition: (p) => p.peek === ":" || p.peek === "\\colon" || (terminator.condition?.(p) ?? false)
5897
+ };
5898
+ const condition = parser.parseExpression(condTerminator);
5899
+ if (condition === null) return null;
5900
+ parser.skipSpace();
5901
+ if (parser.matchAny([",", "\\mid", ":", "\\colon"])) {
5902
+ const bodyTerminator = useTightBinding ? {
5903
+ ...terminator,
5904
+ condition: (p) => tightBindingCondition(p, terminator)
5905
+ } : terminator;
5906
+ parser.enterQuantifierScope();
5907
+ const body = parser.parseExpression(bodyTerminator);
5908
+ parser.exitQuantifierScope();
5909
+ return [kind, condition, missingIfEmpty(body)];
5910
+ }
5911
+ if (parser.match("(")) {
5912
+ parser.enterQuantifierScope();
5913
+ const body = parser.parseExpression(terminator);
5914
+ parser.exitQuantifierScope();
5915
+ if (!parser.match(")")) return null;
5916
+ return [kind, condition, missingIfEmpty(body)];
5917
+ }
5918
+ return null;
5919
+ };
5920
+ }
5921
+
5922
+ // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
5923
+ function parseSequence(parser, terminator, lhs, prec, sep) {
5924
+ if (terminator && terminator.minPrec >= prec) return null;
5925
+ const result = lhs ? [lhs] : ["Nothing"];
5926
+ let done = false;
5927
+ while (!done) {
5928
+ done = true;
5929
+ parser.skipSpace();
5930
+ while (parser.match(sep)) {
5931
+ result.push("Nothing");
5932
+ parser.skipSpace();
5933
+ }
5934
+ parser.skipVisualSpace();
5935
+ if (parser.atTerminator(terminator)) {
5936
+ result.push("Nothing");
5937
+ } else {
5938
+ const rhs = parser.parseExpression({ ...terminator, minPrec: prec });
5939
+ result.push(rhs ?? "Nothing");
5940
+ done = rhs === null;
5941
+ }
5942
+ if (!done) {
5943
+ parser.skipSpace();
5944
+ done = !parser.match(sep);
5945
+ if (!done) parser.skipVisualSpace();
5946
+ }
5947
+ }
5948
+ return result;
5949
+ }
5950
+ function serializeOps(sep = "") {
5951
+ return (serializer, expr) => {
5952
+ if (!expr) return "";
5953
+ const xs = operands(expr);
5954
+ if (xs.length === 0) return "";
5955
+ if (xs.length === 1) return serializer.serialize(xs[0]);
5956
+ sep = {
5957
+ "&": "\\&",
5958
+ ":": "\\colon",
5959
+ "|": "\\mvert",
5960
+ "-": "-",
5961
+ "\xB7": "\\cdot",
5962
+ // U+00B7 MIDDLE DOT
5963
+ "\u2012": "-",
5964
+ // U+2012 FIGURE DASH
5965
+ "\u2013": "--",
5966
+ // U+2013 EN DASH
5967
+ "\u2014": "---",
5968
+ // U+2014 EM DASH
5969
+ "\u2015": "-",
5970
+ // U+2015 HORIZONTAL BAR
5971
+ "\u2022": "\\bullet",
5972
+ // U+2022 BULLET
5973
+ "\u2026": "\\ldots"
5974
+ }[sep] ?? sep;
5975
+ const ys = xs.reduce((acc, item) => {
5976
+ acc.push(serializer.serialize(item), sep);
5977
+ return acc;
5978
+ }, []);
5979
+ ys.pop();
5980
+ return joinLatex(ys);
5981
+ };
5982
+ }
5983
+ var DEFINITIONS_CORE = [
5984
+ //
5985
+ // Constants
5986
+ //
5987
+ {
5988
+ latexTrigger: ["\\placeholder"],
5989
+ kind: "symbol",
5990
+ parse: (parser) => {
5991
+ while (parser.match("<space>")) {
5992
+ }
5993
+ if (parser.match("["))
5994
+ while (!parser.match("]") && !parser.atBoundary) parser.nextToken();
5995
+ while (parser.match("<space>")) {
5996
+ }
5997
+ if (parser.match("<{>"))
5998
+ while (!parser.match("<}>") && !parser.atBoundary) parser.nextToken();
5999
+ return "Nothing";
6094
6000
  }
6095
6001
  },
6096
- // Serializer for If expressions (separate from the parser entry
6097
- // because name-based entries affect kind-based indexing)
6002
+ { name: "ContinuationPlaceholder", latexTrigger: ["\\dots"] },
6003
+ { latexTrigger: ["\\ldots"], parse: "ContinuationPlaceholder" },
6004
+ { latexTrigger: [".", ".", "."], parse: "ContinuationPlaceholder" },
6005
+ //
6006
+ // Functions
6007
+ //
6008
+ // Anonymous function, i.e. `(x) \mapsto x^2`
6098
6009
  {
6099
- name: "If",
6010
+ name: "Function",
6011
+ latexTrigger: ["\\mapsto"],
6012
+ kind: "infix",
6013
+ precedence: ARROW_PRECEDENCE,
6014
+ // MathML rightwards arrow
6015
+ parse: (parser, lhs, _until) => {
6016
+ let params = [];
6017
+ if (operator(lhs) === "Delimiter") lhs = operand(lhs, 1) ?? "Nothing";
6018
+ if (operator(lhs) === "Sequence") {
6019
+ for (const x of operands(lhs)) {
6020
+ if (!symbol(x)) return null;
6021
+ params.push(symbol(x));
6022
+ }
6023
+ } else {
6024
+ if (!symbol(lhs)) return null;
6025
+ params = [symbol(lhs)];
6026
+ }
6027
+ let rhs = parser.parseExpression({ minPrec: ARROW_PRECEDENCE }) ?? "Nothing";
6028
+ if (operator(rhs) === "Delimiter") rhs = operand(rhs, 1) ?? "Nothing";
6029
+ if (operator(rhs) === "Sequence") rhs = ["Block", ...operands(rhs)];
6030
+ return ["Function", rhs, ...params];
6031
+ },
6100
6032
  serialize: (serializer, expr) => {
6101
6033
  const args = operands(expr);
6102
- if (!args || args.length < 3) return "";
6034
+ if (args.length < 1) return "()\\mapsto()";
6035
+ if (args.length === 1)
6036
+ return joinLatex([
6037
+ "()",
6038
+ "\\mapsto",
6039
+ serializer.serialize(operand(expr, 1))
6040
+ ]);
6041
+ if (args.length === 2) {
6042
+ return joinLatex([
6043
+ serializer.serialize(operand(expr, 2)),
6044
+ "\\mapsto",
6045
+ serializer.serialize(operand(expr, 1))
6046
+ ]);
6047
+ }
6103
6048
  return joinLatex([
6104
- "\\text{if }",
6105
- serializer.serialize(args[0]),
6106
- "\\text{ then }",
6107
- serializer.serialize(args[1]),
6108
- "\\text{ else }",
6109
- serializer.serialize(args[2])
6049
+ serializer.wrapString(
6050
+ operands(expr)?.slice(1).map((x) => serializer.serialize(x)).join(", "),
6051
+ "normal"
6052
+ ),
6053
+ "\\mapsto",
6054
+ serializer.serialize(operand(expr, 1))
6110
6055
  ]);
6111
6056
  }
6112
6057
  },
6113
- // Serializer for Loop expressions
6114
6058
  {
6115
- name: "Loop",
6059
+ name: "Apply",
6060
+ kind: "function",
6061
+ symbolTrigger: "apply",
6116
6062
  serialize: (serializer, expr) => {
6117
- const args = operands(expr);
6118
- if (!args || args.length < 2) return "";
6119
- const body = args[0];
6120
- const indexing = args[1];
6121
- if (operator(indexing) === "Element") {
6122
- const index = operand(indexing, 1);
6123
- const range = operand(indexing, 2);
6124
- if (operator(range) === "Range") {
6125
- const lo = operand(range, 1);
6126
- const hi = operand(range, 2);
6127
- return joinLatex([
6128
- "\\text{for }",
6129
- serializer.serialize(index),
6130
- "\\text{ from }",
6131
- serializer.serialize(lo),
6132
- "\\text{ to }",
6133
- serializer.serialize(hi),
6134
- "\\text{ do }",
6135
- serializer.serialize(body)
6136
- ]);
6137
- }
6063
+ const lhs = operand(expr, 1);
6064
+ const h = operator(lhs);
6065
+ if (h === "InverseFunction" || h === "Derivative") {
6066
+ const style2 = serializer.options.applyFunctionStyle(
6067
+ expr,
6068
+ serializer.level
6069
+ );
6070
+ const args = operands(expr).slice(1);
6071
+ return serializer.serializeFunction(
6072
+ lhs,
6073
+ serializer.dictionary.ids.get(h)
6074
+ ) + serializer.wrapString(
6075
+ args.map((x) => serializer.serialize(x)).join(", "),
6076
+ style2
6077
+ );
6078
+ }
6079
+ const rhs = operand(expr, 2);
6080
+ if (typeof lhs === "string" || !rhs) {
6081
+ const fn = operands(expr).slice(1);
6082
+ return serializer.serialize(fn);
6083
+ }
6084
+ if (nops(expr) === 2) {
6085
+ return joinLatex([
6086
+ serializer.wrap(lhs, 20),
6087
+ "\\lhd",
6088
+ serializer.wrap(rhs, 20)
6089
+ ]);
6138
6090
  }
6091
+ const style = serializer.options.applyFunctionStyle(
6092
+ expr,
6093
+ serializer.level
6094
+ );
6139
6095
  return joinLatex([
6140
- "\\operatorname{Loop}(",
6141
- serializer.serialize(body),
6142
- ", ",
6143
- serializer.serialize(indexing),
6144
- ")"
6096
+ "\\operatorname{apply}",
6097
+ serializer.wrapString(
6098
+ serializer.serialize(h) + ", " + serializer.serialize(["List", ...operands(expr)]),
6099
+ style
6100
+ )
6145
6101
  ]);
6146
6102
  }
6147
6103
  },
6148
- // Serializer for Break
6149
- { name: "Break", serialize: () => "\\text{break}" },
6150
- // Serializer for Continue
6151
- { name: "Continue", serialize: () => "\\text{continue}" },
6152
- // Serializer for Return
6153
6104
  {
6154
- name: "Return",
6155
- serialize: (serializer, expr) => {
6156
- const arg = operand(expr, 1);
6157
- if (!arg || symbol(arg) === "Nothing") return "\\text{return}";
6158
- return joinLatex(["\\text{return }", serializer.serialize(arg)]);
6159
- }
6105
+ latexTrigger: "\\lhd",
6106
+ kind: "infix",
6107
+ precedence: 20,
6108
+ parse: "Apply"
6160
6109
  },
6161
- // Also match `\operatorname{if}` / `\mathrm{if}`
6162
6110
  {
6163
- symbolTrigger: "if",
6164
- kind: "prefix",
6165
- precedence: 245,
6166
- parse: (parser, until) => {
6167
- return parseIfExpression(parser, until);
6111
+ latexTrigger: "\\rhd",
6112
+ kind: "infix",
6113
+ precedence: 20,
6114
+ parse: (parser, lhs, _until) => {
6115
+ const rhs = parser.parseExpression({ minPrec: 21 }) ?? "Nothing";
6116
+ return ["Apply", rhs, lhs];
6168
6117
  }
6169
6118
  },
6170
- // \operatorname{for}
6171
- {
6172
- symbolTrigger: "for",
6173
- kind: "prefix",
6174
- precedence: 245,
6175
- parse: (parser, until) => parseForExpression(parser, until)
6176
- },
6177
- // \operatorname{break}
6178
- {
6179
- symbolTrigger: "break",
6180
- kind: "prefix",
6181
- precedence: 245,
6182
- parse: () => ["Break"]
6183
- },
6184
- // \operatorname{continue}
6185
6119
  {
6186
- symbolTrigger: "continue",
6187
- kind: "prefix",
6188
- precedence: 245,
6189
- parse: () => ["Continue"]
6190
- },
6191
- // \operatorname{return}
6192
- {
6193
- symbolTrigger: "return",
6194
- kind: "prefix",
6195
- precedence: 245,
6196
- parse: (parser, until) => [
6197
- "Return",
6198
- parser.parseExpression(until) ?? "Nothing"
6199
- ]
6120
+ name: "EvaluateAt",
6121
+ openTrigger: ".",
6122
+ closeTrigger: "|",
6123
+ kind: "matchfix",
6124
+ serialize: (serializer, expr) => {
6125
+ const fn = operand(expr, 1);
6126
+ if (!fn) return "";
6127
+ const args = operands(expr).slice(1);
6128
+ if (operator(fn) === "Function") {
6129
+ const parameters = operands(fn).slice(1);
6130
+ let body = operand(fn, 1);
6131
+ if (operator(body) === "Block" && nops(body) === 1)
6132
+ body = operand(body, 1);
6133
+ if (parameters.length > 0) {
6134
+ return `\\left.\\left(${serializer.serialize(
6135
+ body
6136
+ )}\\right)\\right|_{${parameters.map(
6137
+ (x, i) => `${serializer.serialize(x)}=${serializer.serialize(args[i])}`
6138
+ ).join(", ")}}`;
6139
+ }
6140
+ }
6141
+ return `\\left.\\left(${serializer.serialize(fn)}\\right)\\right|_{${args.map((x) => serializer.serialize(x)).join(", ")}}`;
6142
+ }
6200
6143
  },
6144
+ // The mathtools package includes several synonmyms for \colonequals. The
6145
+ // preferred one as of summer 2022 is `\coloneq` (see § 3.7.3 https://ctan.math.illinois.edu/macros/latex/contrib/mathtools/mathtools.pdf)
6201
6146
  {
6202
- name: "String",
6203
- latexTrigger: ["\\text"],
6204
- parse: (parser, until) => {
6205
- const start = parser.index;
6206
- if (matchTextKeyword(parser, "if"))
6207
- return parseIfExpression(parser, until);
6208
- parser.index = start;
6209
- if (matchTextKeyword(parser, "for"))
6210
- return parseForExpression(parser, until);
6211
- parser.index = start;
6212
- if (matchTextKeyword(parser, "break"))
6213
- return ["Break"];
6214
- parser.index = start;
6215
- if (matchTextKeyword(parser, "continue"))
6216
- return ["Continue"];
6217
- parser.index = start;
6218
- if (matchTextKeyword(parser, "return"))
6219
- return [
6220
- "Return",
6221
- parser.parseExpression(until) ?? "Nothing"
6222
- ];
6223
- parser.index = start;
6224
- return parseTextRun(parser);
6225
- },
6147
+ name: "Assign",
6148
+ latexTrigger: "\\coloneq",
6149
+ kind: "infix",
6150
+ associativity: "right",
6151
+ precedence: ASSIGNMENT_PRECEDENCE,
6226
6152
  serialize: (serializer, expr) => {
6227
- const args = operands(expr);
6228
- if (args.length === 0) return "\\text{}";
6153
+ const id = unhold(operand(expr, 1));
6154
+ if (operator(operand(expr, 2)) === "Function") {
6155
+ const op_2 = operand(expr, 2);
6156
+ const body = unhold(operand(op_2, 1));
6157
+ const args = operands(op_2).slice(1);
6158
+ return joinLatex([
6159
+ serializer.serialize(id),
6160
+ serializer.wrapString(
6161
+ args.map((x) => serializer.serialize(x)).join(", "),
6162
+ serializer.options.applyFunctionStyle(expr, serializer.level)
6163
+ ),
6164
+ "\\coloneq",
6165
+ serializer.serialize(body)
6166
+ ]);
6167
+ }
6229
6168
  return joinLatex([
6230
- "\\text{",
6231
- args.map((x) => serializer.serialize(x)).join(""),
6232
- "}"
6169
+ serializer.serialize(id),
6170
+ "\\coloneq",
6171
+ serializer.serialize(operand(expr, 2))
6233
6172
  ]);
6234
- }
6173
+ },
6174
+ parse: parseAssign
6235
6175
  },
6236
6176
  {
6237
- name: "Subscript",
6238
- latexTrigger: ["_"],
6177
+ latexTrigger: "\\coloneqq",
6239
6178
  kind: "infix",
6240
- serialize: (serializer, expr) => {
6241
- if (nops(expr) === 2) {
6242
- return serializer.serialize(operand(expr, 1)) + "_{" + serializer.serialize(operand(expr, 2)) + "}";
6243
- }
6244
- return "_{" + serializer.serialize(operand(expr, 1)) + "}";
6245
- }
6179
+ associativity: "right",
6180
+ precedence: ASSIGNMENT_PRECEDENCE,
6181
+ parse: parseAssign
6246
6182
  },
6247
- { name: "Superplus", latexTrigger: ["^", "+"], kind: "postfix" },
6248
- { name: "Subplus", latexTrigger: ["_", "+"], kind: "postfix" },
6183
+ // From the colonequals package:
6249
6184
  {
6250
- name: "Superminus",
6251
- latexTrigger: ["^", "-"],
6252
- kind: "postfix",
6253
- parse: (parser, lhs) => {
6254
- if (parser.options.strict === false && /^[0-9]$/.test(parser.peek))
6255
- return null;
6256
- return ["Superminus", lhs];
6257
- }
6185
+ latexTrigger: "\\colonequals",
6186
+ kind: "infix",
6187
+ associativity: "right",
6188
+ precedence: ASSIGNMENT_PRECEDENCE,
6189
+ parse: parseAssign
6258
6190
  },
6259
- { name: "Subminus", latexTrigger: ["_", "-"], kind: "postfix" },
6260
6191
  {
6261
- latexTrigger: ["^", "*"],
6262
- kind: "postfix",
6263
- parse: (_parser, lhs) => ["Superstar", lhs]
6192
+ latexTrigger: [":", "="],
6193
+ kind: "infix",
6194
+ associativity: "right",
6195
+ precedence: ASSIGNMENT_PRECEDENCE,
6196
+ parse: parseAssign
6264
6197
  },
6265
- // { name: 'Superstar', latexTrigger: ['^', '\\star'], kind: 'postfix' },
6198
+ // General colon operator (type annotation, mapping notation)
6199
+ // Precedence below assignment (260) so `:=` takes priority,
6200
+ // and below arrows (270) so `f: A \to B` parses as `Colon(f, To(A, B))`
6266
6201
  {
6267
- latexTrigger: ["_", "*"],
6268
- kind: "postfix",
6269
- parse: (_parser, lhs) => ["Substar", lhs]
6202
+ name: "Colon",
6203
+ latexTrigger: ":",
6204
+ kind: "infix",
6205
+ associativity: "right",
6206
+ precedence: 250,
6207
+ serialize: (serializer, expr) => joinLatex([
6208
+ serializer.serialize(operand(expr, 1)),
6209
+ "\\colon",
6210
+ serializer.serialize(operand(expr, 2))
6211
+ ])
6270
6212
  },
6271
- { name: "Substar", latexTrigger: ["_", "\\star"], kind: "postfix" },
6272
- { name: "Superdagger", latexTrigger: ["^", "\\dagger"], kind: "postfix" },
6273
6213
  {
6274
- latexTrigger: ["^", "\\dag"],
6275
- kind: "postfix",
6276
- parse: (_parser, lhs) => ["Superdagger", lhs]
6214
+ latexTrigger: "\\colon",
6215
+ kind: "infix",
6216
+ associativity: "right",
6217
+ precedence: 250,
6218
+ parse: "Colon"
6277
6219
  },
6278
6220
  {
6279
- name: "Prime",
6280
- latexTrigger: ["^", "\\prime"],
6281
- // Note: we don't need a precedence because the trigger is '^'
6282
- // and '^' (and '_') are treated specially by the parser.
6283
- kind: "postfix",
6284
- parse: (parser, lhs) => parsePrime(parser, lhs, 1),
6221
+ name: "BaseForm",
6285
6222
  serialize: (serializer, expr) => {
6286
- const n2 = machineValue(operand(expr, 2)) ?? 1;
6287
- const base = serializer.serialize(operand(expr, 1));
6288
- if (n2 === 1) return base + "^\\prime";
6289
- if (n2 === 2) return base + "^\\doubleprime";
6290
- if (n2 === 3) return base + "^\\tripleprime";
6291
- return base + "^{(" + serializer.serialize(operand(expr, 2)) + ")}";
6223
+ const radix = machineValue(operand(expr, 2)) ?? NaN;
6224
+ if (isFinite(radix) && radix >= 2 && radix <= 36) {
6225
+ const num = machineValue(operand(expr, 1)) ?? NaN;
6226
+ if (isFinite(num) && Number.isInteger(num)) {
6227
+ let digits = Number(num).toString(radix);
6228
+ let groupLength = 0;
6229
+ if (radix === 2) {
6230
+ groupLength = 4;
6231
+ } else if (radix === 10) {
6232
+ groupLength = 4;
6233
+ } else if (radix === 16) {
6234
+ groupLength = 2;
6235
+ } else if (radix > 16) {
6236
+ groupLength = 4;
6237
+ }
6238
+ if (groupLength > 0) {
6239
+ const oldDigits = digits;
6240
+ digits = "";
6241
+ for (let i = 0; i < oldDigits.length; i++) {
6242
+ if (i > 0 && i % groupLength === 0) digits = "\\, " + digits;
6243
+ digits = oldDigits[oldDigits.length - i - 1] + digits;
6244
+ }
6245
+ }
6246
+ return `(\\text{${digits}}_{${radix}}`;
6247
+ }
6248
+ }
6249
+ return "\\operatorname{BaseForm}(" + serializer.serialize(operand(expr, 1)) + ", " + serializer.serialize(operand(expr, 2)) + ")";
6292
6250
  }
6293
6251
  },
6294
6252
  {
6295
- latexTrigger: "^{\\prime\\prime}",
6296
- kind: "postfix",
6297
- parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6253
+ name: "Sequence",
6254
+ // Use a space as a separator, otherwise a sequence of numbers
6255
+ // could be interpreted as a single number.
6256
+ serialize: serializeOps(" ")
6298
6257
  },
6299
6258
  {
6300
- latexTrigger: "^{\\prime\\prime\\prime}",
6301
- kind: "postfix",
6302
- parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6259
+ name: "InvisibleOperator",
6260
+ serialize: serializeOps("")
6303
6261
  },
6304
6262
  {
6305
- latexTrigger: ["^", "\\doubleprime"],
6306
- kind: "postfix",
6307
- parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6263
+ // The first argument is a function expression.
6264
+ // The second (optional) argument is a string specifying the
6265
+ // delimiters and separator.
6266
+ name: "Delimiter",
6267
+ serialize: (serializer, expr) => {
6268
+ const style = serializer.options.groupStyle(expr, serializer.level + 1);
6269
+ const arg1 = operand(expr, 1);
6270
+ let delims = {
6271
+ Set: "{,}",
6272
+ List: "[,]",
6273
+ Tuple: "(,)",
6274
+ Single: "(,)",
6275
+ Pair: "(,)",
6276
+ Triple: "(,)",
6277
+ Sequence: "(,)",
6278
+ String: '""'
6279
+ }[operator(arg1)];
6280
+ const items = delims ? arg1 : ["Sequence", arg1];
6281
+ delims ??= "(,)";
6282
+ if (nops(expr) > 1) {
6283
+ const op2 = stringValue(operand(expr, 2));
6284
+ if (typeof op2 === "string" && op2.length <= 3) delims = op2;
6285
+ }
6286
+ let [open, sep, close] = ["", "", ""];
6287
+ if (delims.length === 3) [open, sep, close] = delims;
6288
+ else if (delims.length === 2) [open, close] = delims;
6289
+ else if (delims.length === 1) sep = delims;
6290
+ const body = arg1 ? items ? serializeOps(sep)(serializer, items) : serializer.serialize(arg1) : "";
6291
+ return serializer.wrapString(body, style, open + close);
6292
+ }
6308
6293
  },
6309
6294
  {
6310
- latexTrigger: ["^", "\\tripleprime"],
6311
- kind: "postfix",
6312
- parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6295
+ name: "Tuple",
6296
+ serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
6313
6297
  },
6314
6298
  {
6315
- latexTrigger: "'",
6316
- kind: "postfix",
6317
- precedence: 810,
6318
- parse: (parser, lhs) => parsePrime(parser, lhs, 1)
6299
+ name: "Pair",
6300
+ serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
6319
6301
  },
6320
6302
  {
6321
- latexTrigger: "\\prime",
6322
- kind: "postfix",
6323
- precedence: 810,
6324
- parse: (parser, lhs) => parsePrime(parser, lhs, 1)
6303
+ name: "Triple",
6304
+ serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
6325
6305
  },
6326
6306
  {
6327
- latexTrigger: "\\doubleprime",
6328
- kind: "postfix",
6329
- precedence: 810,
6330
- parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6307
+ name: "Single",
6308
+ serialize: (serializer, expr) => joinLatex(["(", serializeOps(",")(serializer, expr), ")"])
6331
6309
  },
6332
6310
  {
6333
- latexTrigger: "\\tripleprime",
6334
- kind: "postfix",
6335
- precedence: 810,
6336
- parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6311
+ name: "Domain",
6312
+ serialize: (serializer, expr) => {
6313
+ if (operator(expr) === "Error") return serializer.serialize(expr);
6314
+ return `\\mathbf{${serializer.serialize(operand(expr, 1))}}`;
6315
+ }
6337
6316
  },
6338
- // Lagrange Notation for n-th order derivatives,
6339
- // i.e. f^{(n)} -> Derivative(f, n)
6340
6317
  {
6341
- latexTrigger: ["^", "<{>", "("],
6342
- kind: "postfix",
6343
- parse: (parser, lhs, until) => {
6344
- const sym = symbol(lhs);
6345
- if (!sym || !parser.getSymbolType(sym).matches("function")) return null;
6346
- parser.addBoundary([")"]);
6347
- const expr = parser.parseExpression(until);
6348
- if (!parser.matchBoundary()) return null;
6349
- if (!parser.match("<}>")) return null;
6350
- return ["Derivative", lhs, expr];
6318
+ latexTrigger: ["\\mathtip"],
6319
+ parse: (parser) => {
6320
+ const op1 = parser.parseGroup();
6321
+ parser.parseGroup();
6322
+ return op1;
6351
6323
  }
6352
6324
  },
6353
6325
  {
6354
- name: "InverseFunction",
6355
- latexTrigger: "^{-1",
6356
- // Note: the closing brace is not included
6357
- kind: "postfix",
6358
- parse: (parser, lhs) => {
6359
- if (operator(lhs) === "Matrix") {
6360
- parser.match("<}>");
6361
- return ["Inverse", lhs];
6362
- }
6363
- const sym = symbol(lhs);
6364
- if (!sym) return null;
6365
- const symType = parser.getSymbolType(sym);
6366
- if (symType.matches(new BoxedType("matrix"))) {
6367
- parser.match("<}>");
6368
- return ["Inverse", lhs];
6369
- }
6370
- if (!symType.matches("function")) return null;
6371
- let primeCount = 0;
6372
- while (!parser.atEnd && !parser.match("<}>")) {
6373
- if (parser.match("'")) primeCount++;
6374
- else if (parser.match("\\prime")) primeCount++;
6375
- else if (parser.match("\\doubleprime")) primeCount += 2;
6376
- else if (parser.match("\\tripleprime")) primeCount += 3;
6377
- else return null;
6378
- }
6379
- if (primeCount === 1)
6380
- return ["Derivative", ["InverseFunction", lhs]];
6381
- if (primeCount > 0)
6382
- return [
6383
- "Derivative",
6384
- ["InverseFunction", lhs],
6385
- primeCount
6386
- ];
6387
- return ["InverseFunction", lhs];
6388
- },
6389
- serialize: (serializer, expr) => serializer.serialize(operand(expr, 1)) + "^{-1}"
6326
+ latexTrigger: ["\\texttip"],
6327
+ parse: (parser) => {
6328
+ const op1 = parser.parseGroup();
6329
+ parser.parseGroup();
6330
+ return op1;
6331
+ }
6390
6332
  },
6391
- // Lagrange notation
6392
6333
  {
6393
- name: "Derivative",
6394
- // @todo: Leibniz notation: {% latex " \\frac{d^n}{dx^n} f(x)" %}
6395
- // @todo: Euler modified notation: This notation is used by Mathematica. The Euler notation uses `D` instead of
6396
- // `\partial`: `\partial_{x} f`, `\partial_{x,y} f`
6397
- // Newton notation (\dot{v}, \ddot{v}) is implemented below
6398
- serialize: (serializer, expr) => {
6399
- const degree = machineValue(operand(expr, 2)) ?? 1;
6400
- const base = serializer.serialize(operand(expr, 1));
6401
- if (degree === 1) return base + "^{\\prime}";
6402
- if (degree === 2) return base + "^{\\doubleprime}";
6403
- if (degree === 3) return base + "^{\\tripleprime}";
6404
- return base + "^{(" + serializer.serialize(operand(expr, 2)) + ")}";
6405
- }
6334
+ latexTrigger: ["\\error"],
6335
+ parse: (parser) => ["Error", parser.parseGroup()]
6406
6336
  },
6407
- // Serializer for D (partial derivative) - outputs Leibniz notation
6408
6337
  {
6409
- name: "D",
6338
+ name: "Error",
6410
6339
  serialize: (serializer, expr) => {
6411
- if (operator(expr) !== "D") return "D";
6412
- const fn = operand(expr, 1);
6413
- const variable = operand(expr, 2);
6414
- if (!fn || !variable) return "D";
6415
- let order2 = 1;
6416
- let innerFn = fn;
6417
- while (operator(innerFn) === "D") {
6418
- const innerVar = operand(innerFn, 2);
6419
- if (symbol(innerVar) === symbol(variable)) {
6420
- order2++;
6421
- innerFn = operand(innerFn, 1);
6422
- } else {
6423
- break;
6340
+ const op1 = operand(expr, 1);
6341
+ if (stringValue(op1) === "missing")
6342
+ return `\\error{${serializer.options.missingSymbol ?? "\\placeholder{}"}}`;
6343
+ const where = errorContextAsLatex(serializer, expr) || "\\blacksquare";
6344
+ const code = operator(op1) === "ErrorCode" ? stringValue(operand(op1, 1)) : stringValue(op1);
6345
+ if (code === "incompatible-type") {
6346
+ if (symbol(operand(op1, 3)) === "Undefined") {
6347
+ return `\\mathtip{\\error{${where}}}{\\notin ${serializer.serialize(
6348
+ operand(op1, 2)
6349
+ )}}`;
6424
6350
  }
6351
+ return `\\mathtip{\\error{${where}}}{\\in ${serializer.serialize(
6352
+ operand(op1, 3)
6353
+ )}\\notin ${serializer.serialize(operand(op1, 2))}}`;
6425
6354
  }
6426
- let bodyToSerialize = innerFn;
6427
- if (operator(innerFn) === "Function") {
6428
- bodyToSerialize = operand(innerFn, 1) ?? innerFn;
6429
- }
6430
- const fnLatex = serializer.serialize(bodyToSerialize);
6431
- const varLatex = serializer.serialize(variable);
6432
- if (order2 === 1) {
6433
- return `\\frac{\\mathrm{d}}{\\mathrm{d}${varLatex}}${fnLatex}`;
6434
- }
6435
- return `\\frac{\\mathrm{d}^{${order2}}}{\\mathrm{d}${varLatex}^{${order2}}}${fnLatex}`;
6355
+ if (typeof code === "string") return `\\error{${where}}`;
6356
+ return `\\error{${where}}`;
6436
6357
  }
6437
6358
  },
6438
- // Newton notation for time derivatives: \dot{x}, \ddot{x}, etc.
6439
6359
  {
6440
- name: "NewtonDerivative1",
6441
- latexTrigger: ["\\dot"],
6442
- kind: "prefix",
6443
- precedence: 740,
6444
- parse: (parser) => {
6445
- const body = parser.parseGroup();
6446
- if (body === null) return null;
6447
- const t = parser.options.timeDerivativeVariable;
6448
- return ["D", body, t];
6360
+ name: "ErrorCode",
6361
+ serialize: (serializer, expr) => {
6362
+ const code = stringValue(operand(expr, 1));
6363
+ if (code === "missing")
6364
+ return serializer.options.missingSymbol ?? "\\placeholder{}";
6365
+ if (code === "unexpected-command" || code === "unexpected-operator" || code === "unexpected-token" || code === "invalid-symbol" || code === "unknown-environment" || code === "unexpected-base" || code === "incompatible-type") {
6366
+ return "";
6367
+ }
6368
+ return `\\texttip{\\error{\\blacksquare}}{\\mathtt{${code}}}`;
6449
6369
  }
6450
6370
  },
6451
6371
  {
6452
- name: "NewtonDerivative2",
6453
- latexTrigger: ["\\ddot"],
6454
- kind: "prefix",
6455
- precedence: 740,
6456
- parse: (parser) => {
6457
- const body = parser.parseGroup();
6458
- if (body === null) return null;
6459
- const t = parser.options.timeDerivativeVariable;
6460
- return ["D", ["D", body, t], t];
6372
+ name: "FromLatex",
6373
+ serialize: (_serializer, expr) => {
6374
+ return `\\texttt{${sanitizeLatex(stringValue(operand(expr, 1)))}}`;
6461
6375
  }
6462
6376
  },
6463
6377
  {
6464
- name: "NewtonDerivative3",
6465
- latexTrigger: ["\\dddot"],
6466
- kind: "prefix",
6467
- precedence: 740,
6468
- parse: (parser) => {
6469
- const body = parser.parseGroup();
6470
- if (body === null) return null;
6471
- const t = parser.options.timeDerivativeVariable;
6472
- return ["D", ["D", ["D", body, t], t], t];
6378
+ name: "Latex",
6379
+ serialize: (serializer, expr) => {
6380
+ if (expr === null) return "";
6381
+ return joinLatex(
6382
+ mapArgs(expr, (x) => stringValue(x) ?? serializer.serialize(x))
6383
+ );
6473
6384
  }
6474
6385
  },
6475
6386
  {
6476
- name: "NewtonDerivative4",
6477
- latexTrigger: ["\\ddddot"],
6478
- kind: "prefix",
6479
- precedence: 740,
6480
- parse: (parser) => {
6481
- const body = parser.parseGroup();
6482
- if (body === null) return null;
6483
- const t = parser.options.timeDerivativeVariable;
6484
- return ["D", ["D", ["D", ["D", body, t], t], t], t];
6387
+ name: "LatexString",
6388
+ serialize: (serializer, expr) => {
6389
+ if (expr === null) return "";
6390
+ return joinLatex(mapArgs(expr, (x) => serializer.serialize(x)));
6485
6391
  }
6486
6392
  },
6487
- // Euler notation for derivatives: D_x f, D^2_x f, D_x^2 f
6488
- // Uses latexTrigger to intercept before symbol parsing combines D with subscript
6393
+ { name: "LatexTokens", serialize: serializeLatexTokens },
6489
6394
  {
6490
- name: "EulerDerivative",
6491
- latexTrigger: ["D"],
6492
- kind: "expression",
6493
- parse: (parser) => {
6494
- let degree = 1;
6495
- let variable = null;
6496
- let done = false;
6497
- while (!done) {
6498
- if (parser.match("_")) {
6499
- variable = parser.parseGroup() ?? parser.parseToken();
6500
- if (!variable) return null;
6501
- } else if (parser.match("^")) {
6502
- const degExpr = parser.parseGroup() ?? parser.parseToken();
6503
- degree = machineValue(degExpr) ?? 1;
6504
- } else {
6505
- done = true;
6506
- }
6507
- }
6508
- if (!variable) return null;
6509
- parser.skipSpace();
6510
- const fn = parser.parseExpression({ minPrec: 740 });
6511
- if (!fn) return null;
6512
- let result = fn;
6513
- for (let i = 0; i < degree; i++) {
6514
- result = ["D", result, variable];
6395
+ name: "At",
6396
+ kind: "postfix",
6397
+ precedence: 810,
6398
+ latexTrigger: ["["],
6399
+ parse: parseAt("]"),
6400
+ serialize: (serializer, expr) => joinLatex(["\\lbrack", serializeOps(", ")(serializer, expr), "\\rbrack"])
6401
+ },
6402
+ {
6403
+ kind: "postfix",
6404
+ precedence: 810,
6405
+ latexTrigger: ["\\lbrack"],
6406
+ parse: parseAt("\\rbrack")
6407
+ },
6408
+ {
6409
+ kind: "postfix",
6410
+ precedence: 810,
6411
+ latexTrigger: ["\\left", "\\lbrack"],
6412
+ parse: parseAt("\\right", "\\rbrack")
6413
+ },
6414
+ {
6415
+ kind: "postfix",
6416
+ latexTrigger: ["_"],
6417
+ parse: (parser, lhs, _until) => {
6418
+ let rhs = parser.parseGroup() ?? parser.parseToken();
6419
+ if (rhs === null && parser.options.strict === false && parser.peek === "(")
6420
+ rhs = parser.parseEnclosure();
6421
+ const sym = symbol(lhs);
6422
+ if (rhs !== null && (sym && parser.getSymbolType(sym).matches("indexed_collection") || operator(lhs) === "List")) {
6423
+ if (operator(rhs) === "Delimiter") rhs = operand(rhs, 1) ?? "Nothing";
6424
+ if (operator(rhs) === "Sequence") return ["At", lhs, ...operands(rhs)];
6425
+ return ["At", lhs, rhs];
6515
6426
  }
6516
- return result;
6427
+ return ["Subscript", lhs, rhs];
6517
6428
  }
6518
6429
  },
6519
6430
  {
6520
- kind: "environment",
6521
- name: "Which",
6522
- symbolTrigger: "cases",
6523
- parse: parseCasesEnvironment,
6524
- serialize: (serialize, expr) => {
6525
- const rows = [];
6431
+ name: "List",
6432
+ kind: "matchfix",
6433
+ openTrigger: "[",
6434
+ closeTrigger: "]",
6435
+ parse: parseBrackets,
6436
+ serialize: serializeList
6437
+ },
6438
+ {
6439
+ kind: "matchfix",
6440
+ openTrigger: "(",
6441
+ closeTrigger: ")",
6442
+ parse: parseParenDelimiter
6443
+ },
6444
+ {
6445
+ latexTrigger: [","],
6446
+ kind: "infix",
6447
+ precedence: 20,
6448
+ // Unlike the matchfix version of List,
6449
+ // when the comma operator is used, the lhs and rhs are flattened,
6450
+ // i.e. `1,2,3` -> `["Delimiter", ["List", 1, 2, 3], ","]`,
6451
+ // and `1, (2, 3)` -> `["Delimiter",
6452
+ // ["Sequence", 1, ["Delimiter", ["List", 2, 3], "()", ","]]],
6453
+ parse: (parser, lhs, terminator) => {
6454
+ const seq = parseSequence(parser, terminator, lhs, 20, ",");
6455
+ if (seq === null) return null;
6456
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
6457
+ }
6458
+ },
6459
+ // Entry to handle the case of a single comma
6460
+ // with a missing lhs.
6461
+ {
6462
+ latexTrigger: [","],
6463
+ kind: "prefix",
6464
+ precedence: 20,
6465
+ parse: (parser, terminator) => {
6466
+ const seq = parseSequence(parser, terminator, null, 20, ",");
6467
+ if (seq === null) return null;
6468
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
6469
+ }
6470
+ },
6471
+ {
6472
+ name: "Range",
6473
+ latexTrigger: [".", "."],
6474
+ kind: "infix",
6475
+ // associativity: 'left',
6476
+ precedence: 800,
6477
+ parse: parseRange,
6478
+ serialize: (serializer, expr) => {
6526
6479
  const args = operands(expr);
6527
- if (args.length > 0) {
6528
- for (let i = 0; i <= args.length - 2; i += 2) {
6529
- const row = [];
6530
- row.push(serialize.serialize(args[i + 1]));
6531
- row.push(serialize.serialize(args[i]));
6532
- rows.push(row.join("&"));
6480
+ if (args.length === 0) return "";
6481
+ if (args.length === 1)
6482
+ return "1.." + serializer.serialize(operand(expr, 1));
6483
+ if (args.length === 2)
6484
+ return serializer.wrap(operand(expr, 1), 10) + ".." + serializer.wrap(operand(expr, 2), 10);
6485
+ if (args.length === 3) {
6486
+ const step = machineValue(operand(expr, 3));
6487
+ const start = machineValue(operand(expr, 1));
6488
+ if (step !== null && start !== null) {
6489
+ return serializer.wrap(operand(expr, 1), 10) + ".." + serializer.wrap(start + step, 10) + ".." + serializer.wrap(operand(expr, 2), 10);
6533
6490
  }
6491
+ return serializer.wrap(operand(expr, 1), 10) + "..(" + (serializer.wrap(operand(expr, 1), ADDITION_PRECEDENCE) + "+" + serializer.wrap(operand(expr, 3), ADDITION_PRECEDENCE)) + ").." + serializer.wrap(operand(expr, 2), 10);
6534
6492
  }
6535
- return joinLatex(["\\begin{cases}", rows.join("\\\\"), "\\end{cases}"]);
6493
+ return "";
6536
6494
  }
6537
6495
  },
6538
6496
  {
6539
- kind: "environment",
6540
- symbolTrigger: "dcases",
6541
- parse: parseCasesEnvironment
6497
+ latexTrigger: [";"],
6498
+ kind: "infix",
6499
+ precedence: 19,
6500
+ parse: (parser, lhs, terminator) => {
6501
+ const seq = parseSequence(parser, terminator, lhs, 19, ";");
6502
+ if (seq === null) return null;
6503
+ if (seq.some((e) => operator(e) === "Assign"))
6504
+ return buildBlockFromSequence(seq);
6505
+ return ["Delimiter", ["Sequence", ...seq], "';'"];
6506
+ }
6542
6507
  },
6508
+ // \text{where} — variable binding infix
6543
6509
  {
6544
- kind: "environment",
6545
- symbolTrigger: "rcases",
6546
- parse: parseCasesEnvironment
6547
- }
6548
- ];
6549
- function parseTextRun(parser, style) {
6550
- if (!parser.match("<{>")) return "''";
6551
- const runs = [];
6552
- let text = "";
6553
- let runinStyle = null;
6554
- const flush = () => {
6555
- if (runinStyle !== null && text) {
6556
- runs.push(["Annotated", `'${text}'`, dictionaryFromEntries(runinStyle)]);
6557
- } else if (text) {
6558
- runs.push(`'${text}'`);
6510
+ latexTrigger: ["\\text"],
6511
+ kind: "infix",
6512
+ associativity: "none",
6513
+ precedence: 21,
6514
+ // Above ; (19) and , (20), very low binding
6515
+ parse: (parser, lhs, until) => {
6516
+ const start = parser.index;
6517
+ if (!matchTextKeyword(parser, "where")) {
6518
+ parser.index = start;
6519
+ return null;
6520
+ }
6521
+ return parseWhereExpression(parser, lhs, until);
6559
6522
  }
6560
- text = "";
6561
- runinStyle = null;
6562
- };
6563
- while (!parser.atEnd && !parser.match("<}>")) {
6564
- if (parser.peek === "<{>") {
6565
- flush();
6566
- runs.push(parseTextRun(parser));
6567
- } else if (parser.match("\\textbf")) {
6568
- flush();
6569
- runs.push(parseTextRun(parser, { fontWeight: "bold" }));
6570
- } else if (parser.match("\\textmd")) {
6571
- flush();
6572
- runs.push(parseTextRun(parser, { fontStyle: "normal" }));
6573
- } else if (parser.match("\\textup")) {
6574
- flush();
6575
- runs.push(parseTextRun(parser, { fontStyle: "normal" }));
6576
- } else if (parser.match("\\textsl")) {
6577
- flush();
6578
- runs.push(parseTextRun(parser, { fontStyle: "italic" }));
6579
- } else if (parser.match("\\textit")) {
6580
- flush();
6581
- runs.push(parseTextRun(parser, { fontStyle: "italic" }));
6582
- } else if (parser.match("\\texttt")) {
6583
- flush();
6584
- runs.push(parseTextRun(parser, { fontFamily: "monospace" }));
6585
- } else if (parser.match("\\textsf")) {
6586
- flush();
6587
- runs.push(parseTextRun(parser, { fontFamily: "sans-serif" }));
6588
- } else if (parser.match("\\textcolor")) {
6589
- const pos = parser.index;
6590
- const color = parser.parseStringGroup();
6591
- const body2 = parser.parseExpression();
6592
- if (color !== null && body2 !== null) {
6593
- runs.push(["Annotated", body2, { dict: { color } }]);
6594
- } else {
6595
- parser.index = pos;
6596
- text += "\\textcolor";
6523
+ },
6524
+ // \operatorname{where}
6525
+ {
6526
+ symbolTrigger: "where",
6527
+ kind: "infix",
6528
+ associativity: "none",
6529
+ precedence: 21,
6530
+ parse: (parser, lhs, until) => parseWhereExpression(parser, lhs, until)
6531
+ },
6532
+ // \text{and} logical conjunction infix
6533
+ {
6534
+ latexTrigger: ["\\text"],
6535
+ kind: "infix",
6536
+ associativity: "right",
6537
+ precedence: 235,
6538
+ // Same as \land
6539
+ parse: (parser, lhs, until) => {
6540
+ const start = parser.index;
6541
+ if (!matchTextKeyword(parser, "and")) {
6542
+ parser.index = start;
6543
+ return null;
6597
6544
  }
6598
- } else if (parser.match("\\color")) {
6599
- const color = parser.parseStringGroup();
6600
- if (color !== null) {
6601
- flush();
6545
+ const rhs = parser.parseExpression({ ...until, minPrec: 235 });
6546
+ return ["And", lhs, rhs ?? "Nothing"];
6547
+ }
6548
+ },
6549
+ // \text{or} — logical disjunction infix
6550
+ {
6551
+ latexTrigger: ["\\text"],
6552
+ kind: "infix",
6553
+ associativity: "right",
6554
+ precedence: 230,
6555
+ // Same as \lor
6556
+ parse: (parser, lhs, until) => {
6557
+ const start = parser.index;
6558
+ if (!matchTextKeyword(parser, "or")) {
6559
+ parser.index = start;
6560
+ return null;
6561
+ }
6562
+ const rhs = parser.parseExpression({ ...until, minPrec: 230 });
6563
+ return ["Or", lhs, rhs ?? "Nothing"];
6564
+ }
6565
+ },
6566
+ // \text{iff} — biconditional (if and only if)
6567
+ {
6568
+ latexTrigger: ["\\text"],
6569
+ kind: "infix",
6570
+ associativity: "right",
6571
+ precedence: 219,
6572
+ // Same as \iff
6573
+ parse: (parser, lhs, until) => {
6574
+ const start = parser.index;
6575
+ if (!matchTextKeyword(parser, "iff")) {
6576
+ parser.index = start;
6577
+ return null;
6578
+ }
6579
+ const rhs = parser.parseExpression({ ...until, minPrec: 219 });
6580
+ return ["Equivalent", lhs, rhs ?? "Nothing"];
6581
+ }
6582
+ },
6583
+ // \text{if and only if} — verbose biconditional
6584
+ {
6585
+ latexTrigger: ["\\text"],
6586
+ kind: "infix",
6587
+ associativity: "right",
6588
+ precedence: 219,
6589
+ parse: (parser, lhs, until) => {
6590
+ const start = parser.index;
6591
+ if (!matchTextKeyword(parser, "if and only if")) {
6592
+ parser.index = start;
6593
+ return null;
6594
+ }
6595
+ const rhs = parser.parseExpression({ ...until, minPrec: 219 });
6596
+ return ["Equivalent", lhs, rhs ?? "Nothing"];
6597
+ }
6598
+ },
6599
+ // \text{such that} — constraint separator (like : in set-builder notation)
6600
+ {
6601
+ latexTrigger: ["\\text"],
6602
+ kind: "infix",
6603
+ associativity: "right",
6604
+ precedence: 21,
6605
+ // Low precedence to capture full condition (same as 'where')
6606
+ parse: (parser, lhs, until) => {
6607
+ const start = parser.index;
6608
+ if (!matchTextKeyword(parser, "such that")) {
6609
+ parser.index = start;
6610
+ return null;
6611
+ }
6612
+ const rhs = parser.parseExpression({ ...until, minPrec: 21 });
6613
+ return ["Colon", lhs, rhs ?? "Nothing"];
6614
+ }
6615
+ },
6616
+ // \text{for all} — universal quantifier
6617
+ {
6618
+ latexTrigger: ["\\text"],
6619
+ kind: "prefix",
6620
+ precedence: 200,
6621
+ // Same as \forall
6622
+ parse: (parser, until) => {
6623
+ const start = parser.index;
6624
+ if (!matchTextKeyword(parser, "for all")) {
6625
+ parser.index = start;
6626
+ return null;
6627
+ }
6628
+ return parseQuantifier("ForAll")(parser, until);
6629
+ }
6630
+ },
6631
+ // \text{there exists} — existential quantifier
6632
+ {
6633
+ latexTrigger: ["\\text"],
6634
+ kind: "prefix",
6635
+ precedence: 200,
6636
+ // Same as \exists
6637
+ parse: (parser, until) => {
6638
+ const start = parser.index;
6639
+ if (!matchTextKeyword(parser, "there exists")) {
6640
+ parser.index = start;
6641
+ return null;
6642
+ }
6643
+ return parseQuantifier("Exists")(parser, until);
6644
+ }
6645
+ },
6646
+ // Block serializer — used by both `where` and semicolon blocks
6647
+ {
6648
+ name: "Block",
6649
+ serialize: (serializer, expr) => {
6650
+ const args = operands(expr);
6651
+ if (!args || args.length === 0) return "";
6652
+ const parts = args.filter((a) => operator(a) !== "Declare").map((a) => serializer.serialize(a));
6653
+ return parts.join("; ");
6654
+ }
6655
+ },
6656
+ // Serializer for If expressions (separate from the parser entry
6657
+ // because name-based entries affect kind-based indexing)
6658
+ {
6659
+ name: "If",
6660
+ serialize: (serializer, expr) => {
6661
+ const args = operands(expr);
6662
+ if (!args || args.length < 3) return "";
6663
+ return joinLatex([
6664
+ "\\text{if }",
6665
+ serializer.serialize(args[0]),
6666
+ "\\text{ then }",
6667
+ serializer.serialize(args[1]),
6668
+ "\\text{ else }",
6669
+ serializer.serialize(args[2])
6670
+ ]);
6671
+ }
6672
+ },
6673
+ // Serializer for Loop expressions
6674
+ {
6675
+ name: "Loop",
6676
+ serialize: (serializer, expr) => {
6677
+ const args = operands(expr);
6678
+ if (!args || args.length < 2) return "";
6679
+ const body = args[0];
6680
+ const indexing = args[1];
6681
+ if (operator(indexing) === "Element") {
6682
+ const index = operand(indexing, 1);
6683
+ const range = operand(indexing, 2);
6684
+ if (operator(range) === "Range") {
6685
+ const lo = operand(range, 1);
6686
+ const hi = operand(range, 2);
6687
+ return joinLatex([
6688
+ "\\text{for }",
6689
+ serializer.serialize(index),
6690
+ "\\text{ from }",
6691
+ serializer.serialize(lo),
6692
+ "\\text{ to }",
6693
+ serializer.serialize(hi),
6694
+ "\\text{ do }",
6695
+ serializer.serialize(body)
6696
+ ]);
6697
+ }
6698
+ }
6699
+ return joinLatex([
6700
+ "\\operatorname{Loop}(",
6701
+ serializer.serialize(body),
6702
+ ", ",
6703
+ serializer.serialize(indexing),
6704
+ ")"
6705
+ ]);
6706
+ }
6707
+ },
6708
+ // Serializer for Break
6709
+ { name: "Break", serialize: () => "\\text{break}" },
6710
+ // Serializer for Continue
6711
+ { name: "Continue", serialize: () => "\\text{continue}" },
6712
+ // Serializer for Return
6713
+ {
6714
+ name: "Return",
6715
+ serialize: (serializer, expr) => {
6716
+ const arg = operand(expr, 1);
6717
+ if (!arg || symbol(arg) === "Nothing") return "\\text{return}";
6718
+ return joinLatex(["\\text{return }", serializer.serialize(arg)]);
6719
+ }
6720
+ },
6721
+ // Also match `\operatorname{if}` / `\mathrm{if}`
6722
+ {
6723
+ symbolTrigger: "if",
6724
+ kind: "prefix",
6725
+ precedence: 245,
6726
+ parse: (parser, until) => {
6727
+ return parseIfExpression(parser, until);
6728
+ }
6729
+ },
6730
+ // \operatorname{for}
6731
+ {
6732
+ symbolTrigger: "for",
6733
+ kind: "prefix",
6734
+ precedence: 245,
6735
+ parse: (parser, until) => parseForExpression(parser, until)
6736
+ },
6737
+ // \operatorname{break}
6738
+ {
6739
+ symbolTrigger: "break",
6740
+ kind: "prefix",
6741
+ precedence: 245,
6742
+ parse: () => ["Break"]
6743
+ },
6744
+ // \operatorname{continue}
6745
+ {
6746
+ symbolTrigger: "continue",
6747
+ kind: "prefix",
6748
+ precedence: 245,
6749
+ parse: () => ["Continue"]
6750
+ },
6751
+ // \operatorname{return}
6752
+ {
6753
+ symbolTrigger: "return",
6754
+ kind: "prefix",
6755
+ precedence: 245,
6756
+ parse: (parser, until) => [
6757
+ "Return",
6758
+ parser.parseExpression(until) ?? "Nothing"
6759
+ ]
6760
+ },
6761
+ // Text serializer — reconstructs \text{...} with inline $...$ for math
6762
+ {
6763
+ name: "Text",
6764
+ serialize: (serializer, expr) => {
6765
+ const args = operands(expr);
6766
+ if (args.length === 0) return "";
6767
+ let firstStr = -1;
6768
+ let lastStr = -1;
6769
+ for (let i = 0; i < args.length; i++) {
6770
+ if (stringValue(args[i]) !== null) {
6771
+ if (firstStr < 0) firstStr = i;
6772
+ lastStr = i;
6773
+ }
6774
+ }
6775
+ if (firstStr < 0)
6776
+ return joinLatex(args.map((a) => serializer.serialize(a)));
6777
+ const parts = [];
6778
+ for (let i = 0; i < firstStr; i++)
6779
+ parts.push(serializer.serialize(args[i]));
6780
+ let textContent = "";
6781
+ for (let i = firstStr; i <= lastStr; i++) {
6782
+ const s = stringValue(args[i]);
6783
+ if (s !== null) textContent += sanitizeLatex(s);
6784
+ else if (operator(args[i]) === "Annotated" || operator(args[i]) === "Text")
6785
+ textContent += serializer.serialize(args[i]);
6786
+ else textContent += "$" + serializer.serialize(args[i]) + "$";
6787
+ }
6788
+ parts.push("\\text{" + textContent + "}");
6789
+ for (let i = lastStr + 1; i < args.length; i++)
6790
+ parts.push(serializer.serialize(args[i]));
6791
+ return joinLatex(parts);
6792
+ }
6793
+ },
6794
+ {
6795
+ name: "String",
6796
+ latexTrigger: ["\\text"],
6797
+ parse: (parser, until) => {
6798
+ const start = parser.index;
6799
+ if (matchTextKeyword(parser, "if"))
6800
+ return parseIfExpression(parser, until);
6801
+ parser.index = start;
6802
+ if (matchTextKeyword(parser, "for"))
6803
+ return parseForExpression(parser, until);
6804
+ parser.index = start;
6805
+ if (matchTextKeyword(parser, "break"))
6806
+ return ["Break"];
6807
+ parser.index = start;
6808
+ if (matchTextKeyword(parser, "continue"))
6809
+ return ["Continue"];
6810
+ parser.index = start;
6811
+ if (matchTextKeyword(parser, "return"))
6812
+ return [
6813
+ "Return",
6814
+ parser.parseExpression(until) ?? "Nothing"
6815
+ ];
6816
+ parser.index = start;
6817
+ return parseTextRun(parser);
6818
+ },
6819
+ serialize: (serializer, expr) => {
6820
+ const args = operands(expr);
6821
+ if (args.length === 0) return "\\text{}";
6822
+ return joinLatex([
6823
+ "\\text{",
6824
+ args.map((x) => serializer.serialize(x)).join(""),
6825
+ "}"
6826
+ ]);
6827
+ }
6828
+ },
6829
+ {
6830
+ name: "Subscript",
6831
+ latexTrigger: ["_"],
6832
+ kind: "infix",
6833
+ serialize: (serializer, expr) => {
6834
+ if (nops(expr) === 2) {
6835
+ return serializer.serialize(operand(expr, 1)) + "_{" + serializer.serialize(operand(expr, 2)) + "}";
6836
+ }
6837
+ return "_{" + serializer.serialize(operand(expr, 1)) + "}";
6838
+ }
6839
+ },
6840
+ { name: "Superplus", latexTrigger: ["^", "+"], kind: "postfix" },
6841
+ { name: "Subplus", latexTrigger: ["_", "+"], kind: "postfix" },
6842
+ {
6843
+ name: "Superminus",
6844
+ latexTrigger: ["^", "-"],
6845
+ kind: "postfix",
6846
+ parse: (parser, lhs) => {
6847
+ if (parser.options.strict === false && /^[0-9]$/.test(parser.peek))
6848
+ return null;
6849
+ return ["Superminus", lhs];
6850
+ }
6851
+ },
6852
+ { name: "Subminus", latexTrigger: ["_", "-"], kind: "postfix" },
6853
+ {
6854
+ latexTrigger: ["^", "*"],
6855
+ kind: "postfix",
6856
+ parse: (_parser, lhs) => ["Superstar", lhs]
6857
+ },
6858
+ // { name: 'Superstar', latexTrigger: ['^', '\\star'], kind: 'postfix' },
6859
+ {
6860
+ latexTrigger: ["_", "*"],
6861
+ kind: "postfix",
6862
+ parse: (_parser, lhs) => ["Substar", lhs]
6863
+ },
6864
+ { name: "Substar", latexTrigger: ["_", "\\star"], kind: "postfix" },
6865
+ { name: "Superdagger", latexTrigger: ["^", "\\dagger"], kind: "postfix" },
6866
+ {
6867
+ latexTrigger: ["^", "\\dag"],
6868
+ kind: "postfix",
6869
+ parse: (_parser, lhs) => ["Superdagger", lhs]
6870
+ },
6871
+ {
6872
+ name: "Prime",
6873
+ latexTrigger: ["^", "\\prime"],
6874
+ // Note: we don't need a precedence because the trigger is '^'
6875
+ // and '^' (and '_') are treated specially by the parser.
6876
+ kind: "postfix",
6877
+ parse: (parser, lhs) => parsePrime(parser, lhs, 1),
6878
+ serialize: (serializer, expr) => {
6879
+ const n2 = machineValue(operand(expr, 2)) ?? 1;
6880
+ const base = serializer.serialize(operand(expr, 1));
6881
+ if (n2 === 1) return base + "^\\prime";
6882
+ if (n2 === 2) return base + "^\\doubleprime";
6883
+ if (n2 === 3) return base + "^\\tripleprime";
6884
+ return base + "^{(" + serializer.serialize(operand(expr, 2)) + ")}";
6885
+ }
6886
+ },
6887
+ {
6888
+ latexTrigger: "^{\\prime\\prime}",
6889
+ kind: "postfix",
6890
+ parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6891
+ },
6892
+ {
6893
+ latexTrigger: "^{\\prime\\prime\\prime}",
6894
+ kind: "postfix",
6895
+ parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6896
+ },
6897
+ {
6898
+ latexTrigger: ["^", "\\doubleprime"],
6899
+ kind: "postfix",
6900
+ parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6901
+ },
6902
+ {
6903
+ latexTrigger: ["^", "\\tripleprime"],
6904
+ kind: "postfix",
6905
+ parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6906
+ },
6907
+ {
6908
+ latexTrigger: "'",
6909
+ kind: "postfix",
6910
+ precedence: 810,
6911
+ parse: (parser, lhs) => parsePrime(parser, lhs, 1)
6912
+ },
6913
+ {
6914
+ latexTrigger: "\\prime",
6915
+ kind: "postfix",
6916
+ precedence: 810,
6917
+ parse: (parser, lhs) => parsePrime(parser, lhs, 1)
6918
+ },
6919
+ {
6920
+ latexTrigger: "\\doubleprime",
6921
+ kind: "postfix",
6922
+ precedence: 810,
6923
+ parse: (parser, lhs) => parsePrime(parser, lhs, 2)
6924
+ },
6925
+ {
6926
+ latexTrigger: "\\tripleprime",
6927
+ kind: "postfix",
6928
+ precedence: 810,
6929
+ parse: (parser, lhs) => parsePrime(parser, lhs, 3)
6930
+ },
6931
+ // Lagrange Notation for n-th order derivatives,
6932
+ // i.e. f^{(n)} -> Derivative(f, n)
6933
+ {
6934
+ latexTrigger: ["^", "<{>", "("],
6935
+ kind: "postfix",
6936
+ parse: (parser, lhs, until) => {
6937
+ const sym = symbol(lhs);
6938
+ if (!sym || !parser.getSymbolType(sym).matches("function")) return null;
6939
+ parser.addBoundary([")"]);
6940
+ const expr = parser.parseExpression(until);
6941
+ if (!parser.matchBoundary()) return null;
6942
+ if (!parser.match("<}>")) return null;
6943
+ return ["Derivative", lhs, expr];
6944
+ }
6945
+ },
6946
+ {
6947
+ name: "InverseFunction",
6948
+ latexTrigger: "^{-1",
6949
+ // Note: the closing brace is not included
6950
+ kind: "postfix",
6951
+ parse: (parser, lhs) => {
6952
+ if (operator(lhs) === "Matrix") {
6953
+ parser.match("<}>");
6954
+ return ["Inverse", lhs];
6955
+ }
6956
+ const sym = symbol(lhs);
6957
+ if (!sym) return null;
6958
+ const symType = parser.getSymbolType(sym);
6959
+ if (symType.matches(new BoxedType("matrix"))) {
6960
+ parser.match("<}>");
6961
+ return ["Inverse", lhs];
6962
+ }
6963
+ if (!symType.matches("function")) return null;
6964
+ let primeCount = 0;
6965
+ while (!parser.atEnd && !parser.match("<}>")) {
6966
+ if (parser.match("'")) primeCount++;
6967
+ else if (parser.match("\\prime")) primeCount++;
6968
+ else if (parser.match("\\doubleprime")) primeCount += 2;
6969
+ else if (parser.match("\\tripleprime")) primeCount += 3;
6970
+ else return null;
6971
+ }
6972
+ if (primeCount === 1)
6973
+ return ["Derivative", ["InverseFunction", lhs]];
6974
+ if (primeCount > 0)
6975
+ return [
6976
+ "Derivative",
6977
+ ["InverseFunction", lhs],
6978
+ primeCount
6979
+ ];
6980
+ return ["InverseFunction", lhs];
6981
+ },
6982
+ serialize: (serializer, expr) => serializer.serialize(operand(expr, 1)) + "^{-1}"
6983
+ },
6984
+ // Lagrange notation
6985
+ {
6986
+ name: "Derivative",
6987
+ // @todo: Leibniz notation: {% latex " \\frac{d^n}{dx^n} f(x)" %}
6988
+ // @todo: Euler modified notation: This notation is used by Mathematica. The Euler notation uses `D` instead of
6989
+ // `\partial`: `\partial_{x} f`, `\partial_{x,y} f`
6990
+ // Newton notation (\dot{v}, \ddot{v}) is implemented below
6991
+ serialize: (serializer, expr) => {
6992
+ const degree = machineValue(operand(expr, 2)) ?? 1;
6993
+ const base = serializer.serialize(operand(expr, 1));
6994
+ if (degree === 1) return base + "^{\\prime}";
6995
+ if (degree === 2) return base + "^{\\doubleprime}";
6996
+ if (degree === 3) return base + "^{\\tripleprime}";
6997
+ return base + "^{(" + serializer.serialize(operand(expr, 2)) + ")}";
6998
+ }
6999
+ },
7000
+ // Serializer for D (partial derivative) - outputs Leibniz notation
7001
+ {
7002
+ name: "D",
7003
+ serialize: (serializer, expr) => {
7004
+ if (operator(expr) !== "D") return "D";
7005
+ const fn = operand(expr, 1);
7006
+ const variable = operand(expr, 2);
7007
+ if (!fn || !variable) return "D";
7008
+ let order2 = 1;
7009
+ let innerFn = fn;
7010
+ while (operator(innerFn) === "D") {
7011
+ const innerVar = operand(innerFn, 2);
7012
+ if (symbol(innerVar) === symbol(variable)) {
7013
+ order2++;
7014
+ innerFn = operand(innerFn, 1);
7015
+ } else {
7016
+ break;
7017
+ }
7018
+ }
7019
+ let bodyToSerialize = innerFn;
7020
+ if (operator(innerFn) === "Function") {
7021
+ bodyToSerialize = operand(innerFn, 1) ?? innerFn;
7022
+ }
7023
+ const fnLatex = serializer.serialize(bodyToSerialize);
7024
+ const varLatex = serializer.serialize(variable);
7025
+ if (order2 === 1) {
7026
+ return `\\frac{\\mathrm{d}}{\\mathrm{d}${varLatex}}${fnLatex}`;
7027
+ }
7028
+ return `\\frac{\\mathrm{d}^{${order2}}}{\\mathrm{d}${varLatex}^{${order2}}}${fnLatex}`;
7029
+ }
7030
+ },
7031
+ // Newton notation for time derivatives: \dot{x}, \ddot{x}, etc.
7032
+ {
7033
+ name: "NewtonDerivative1",
7034
+ latexTrigger: ["\\dot"],
7035
+ kind: "prefix",
7036
+ precedence: 740,
7037
+ parse: (parser) => {
7038
+ const body = parser.parseGroup();
7039
+ if (body === null) return null;
7040
+ const t = parser.options.timeDerivativeVariable;
7041
+ return ["D", body, t];
7042
+ }
7043
+ },
7044
+ {
7045
+ name: "NewtonDerivative2",
7046
+ latexTrigger: ["\\ddot"],
7047
+ kind: "prefix",
7048
+ precedence: 740,
7049
+ parse: (parser) => {
7050
+ const body = parser.parseGroup();
7051
+ if (body === null) return null;
7052
+ const t = parser.options.timeDerivativeVariable;
7053
+ return ["D", ["D", body, t], t];
7054
+ }
7055
+ },
7056
+ {
7057
+ name: "NewtonDerivative3",
7058
+ latexTrigger: ["\\dddot"],
7059
+ kind: "prefix",
7060
+ precedence: 740,
7061
+ parse: (parser) => {
7062
+ const body = parser.parseGroup();
7063
+ if (body === null) return null;
7064
+ const t = parser.options.timeDerivativeVariable;
7065
+ return ["D", ["D", ["D", body, t], t], t];
7066
+ }
7067
+ },
7068
+ {
7069
+ name: "NewtonDerivative4",
7070
+ latexTrigger: ["\\ddddot"],
7071
+ kind: "prefix",
7072
+ precedence: 740,
7073
+ parse: (parser) => {
7074
+ const body = parser.parseGroup();
7075
+ if (body === null) return null;
7076
+ const t = parser.options.timeDerivativeVariable;
7077
+ return ["D", ["D", ["D", ["D", body, t], t], t], t];
7078
+ }
7079
+ },
7080
+ // Euler notation for derivatives: D_x f, D^2_x f, D_x^2 f
7081
+ // Uses latexTrigger to intercept before symbol parsing combines D with subscript
7082
+ {
7083
+ name: "EulerDerivative",
7084
+ latexTrigger: ["D"],
7085
+ kind: "expression",
7086
+ parse: (parser) => {
7087
+ let degree = 1;
7088
+ let variable = null;
7089
+ let done = false;
7090
+ while (!done) {
7091
+ if (parser.match("_")) {
7092
+ variable = parser.parseGroup() ?? parser.parseToken();
7093
+ if (!variable) return null;
7094
+ } else if (parser.match("^")) {
7095
+ const degExpr = parser.parseGroup() ?? parser.parseToken();
7096
+ degree = machineValue(degExpr) ?? 1;
7097
+ } else {
7098
+ done = true;
7099
+ }
7100
+ }
7101
+ if (!variable) return null;
7102
+ parser.skipSpace();
7103
+ const fn = parser.parseExpression({ minPrec: 740 });
7104
+ if (!fn) return null;
7105
+ let result = fn;
7106
+ for (let i = 0; i < degree; i++) {
7107
+ result = ["D", result, variable];
7108
+ }
7109
+ return result;
7110
+ }
7111
+ },
7112
+ {
7113
+ kind: "environment",
7114
+ name: "Which",
7115
+ symbolTrigger: "cases",
7116
+ parse: parseCasesEnvironment,
7117
+ serialize: (serialize, expr) => {
7118
+ const rows = [];
7119
+ const args = operands(expr);
7120
+ if (args.length > 0) {
7121
+ for (let i = 0; i <= args.length - 2; i += 2) {
7122
+ const row = [];
7123
+ row.push(serialize.serialize(args[i + 1]));
7124
+ row.push(serialize.serialize(args[i]));
7125
+ rows.push(row.join("&"));
7126
+ }
7127
+ }
7128
+ return joinLatex(["\\begin{cases}", rows.join("\\\\"), "\\end{cases}"]);
7129
+ }
7130
+ },
7131
+ {
7132
+ kind: "environment",
7133
+ symbolTrigger: "dcases",
7134
+ parse: parseCasesEnvironment
7135
+ },
7136
+ {
7137
+ kind: "environment",
7138
+ symbolTrigger: "rcases",
7139
+ parse: parseCasesEnvironment
7140
+ }
7141
+ ];
7142
+ function parseTextRun(parser, style) {
7143
+ if (!parser.match("<{>")) return "''";
7144
+ const runs = [];
7145
+ let text = "";
7146
+ let runinStyle = null;
7147
+ const flush = () => {
7148
+ if (runinStyle !== null && text) {
7149
+ runs.push(["Annotated", `'${text}'`, dictionaryFromEntries(runinStyle)]);
7150
+ } else if (text) {
7151
+ runs.push(`'${text}'`);
7152
+ }
7153
+ text = "";
7154
+ runinStyle = null;
7155
+ };
7156
+ while (!parser.atEnd && !parser.match("<}>")) {
7157
+ if (parser.peek === "<{>") {
7158
+ flush();
7159
+ runs.push(parseTextRun(parser));
7160
+ } else if (parser.match("\\textbf")) {
7161
+ flush();
7162
+ runs.push(parseTextRun(parser, { fontWeight: "bold" }));
7163
+ } else if (parser.match("\\textmd")) {
7164
+ flush();
7165
+ runs.push(parseTextRun(parser, { fontStyle: "normal" }));
7166
+ } else if (parser.match("\\textup")) {
7167
+ flush();
7168
+ runs.push(parseTextRun(parser, { fontStyle: "normal" }));
7169
+ } else if (parser.match("\\textsl")) {
7170
+ flush();
7171
+ runs.push(parseTextRun(parser, { fontStyle: "italic" }));
7172
+ } else if (parser.match("\\textit")) {
7173
+ flush();
7174
+ runs.push(parseTextRun(parser, { fontStyle: "italic" }));
7175
+ } else if (parser.match("\\texttt")) {
7176
+ flush();
7177
+ runs.push(parseTextRun(parser, { fontFamily: "monospace" }));
7178
+ } else if (parser.match("\\textsf")) {
7179
+ flush();
7180
+ runs.push(parseTextRun(parser, { fontFamily: "sans-serif" }));
7181
+ } else if (parser.match("\\textcolor")) {
7182
+ const pos = parser.index;
7183
+ const color = parser.parseStringGroup();
7184
+ if (color !== null) {
7185
+ flush();
7186
+ const body2 = parseTextRun(parser);
7187
+ runs.push(["Annotated", body2, dictionaryFromEntries({ color })]);
7188
+ } else {
7189
+ parser.index = pos;
7190
+ text += "\\textcolor";
7191
+ }
7192
+ } else if (parser.match("\\color")) {
7193
+ const color = parser.parseStringGroup();
7194
+ if (color !== null) {
7195
+ flush();
6602
7196
  runinStyle = { color };
6603
7197
  }
6604
7198
  } else if (parser.match("<space>")) {
@@ -6608,6 +7202,7 @@ function parseTextRun(parser, style) {
6608
7202
  const expr = parser.parseExpression() ?? "Nothing";
6609
7203
  parser.skipSpace();
6610
7204
  if (parser.match("<$>")) {
7205
+ flush();
6611
7206
  runs.push(expr);
6612
7207
  } else {
6613
7208
  text += "$";
@@ -6618,6 +7213,7 @@ function parseTextRun(parser, style) {
6618
7213
  const expr = parser.parseExpression() ?? "Nothing";
6619
7214
  parser.skipSpace();
6620
7215
  if (parser.match("<$$>")) {
7216
+ flush();
6621
7217
  runs.push(expr);
6622
7218
  } else {
6623
7219
  text += "$$";
@@ -6968,14 +7564,20 @@ function matchTextKeyword(parser, keyword) {
6968
7564
  }
6969
7565
  while (parser.match("<space>")) {
6970
7566
  }
6971
- let text = "";
6972
- while (!parser.atEnd && parser.peek !== "<}>" && parser.peek !== "<space>") {
6973
- const tok = parser.peek;
6974
- if (/^[a-zA-Z]$/.test(tok)) {
6975
- text += tok;
6976
- parser.nextToken();
7567
+ for (let i = 0; i < keyword.length; i++) {
7568
+ if (keyword[i] === " ") {
7569
+ if (!parser.match("<space>")) {
7570
+ parser.index = start;
7571
+ return false;
7572
+ }
7573
+ while (parser.match("<space>")) {
7574
+ }
6977
7575
  } else {
6978
- break;
7576
+ if (parser.peek !== keyword[i]) {
7577
+ parser.index = start;
7578
+ return false;
7579
+ }
7580
+ parser.nextToken();
6979
7581
  }
6980
7582
  }
6981
7583
  while (parser.match("<space>")) {
@@ -6984,10 +7586,6 @@ function matchTextKeyword(parser, keyword) {
6984
7586
  parser.index = start;
6985
7587
  return false;
6986
7588
  }
6987
- if (text !== keyword) {
6988
- parser.index = start;
6989
- return false;
6990
- }
6991
7589
  return true;
6992
7590
  }
6993
7591
  function matchKeyword(parser, keyword) {
@@ -7229,487 +7827,41 @@ var DEFINITIONS_SYMBOLS = [
7229
7827
  return {
7230
7828
  kind: "symbol",
7231
7829
  name: symbol2,
7232
- latexTrigger: [latex],
7233
- parse: symbol2
7234
- };
7235
- }),
7236
- ...SYMBOLS.map(([symbol2, _latex, codepoint]) => {
7237
- return {
7238
- kind: "symbol",
7239
- latexTrigger: [String.fromCodePoint(codepoint)],
7240
- parse: symbol2
7241
- };
7242
- })
7243
- ];
7244
-
7245
- // src/compute-engine/latex-syntax/dictionary/definitions-algebra.ts
7246
- var DEFINITIONS_ALGEBRA = [
7247
- {
7248
- name: "To",
7249
- latexTrigger: ["\\to"],
7250
- kind: "infix",
7251
- precedence: 270
7252
- // MathML rightwards arrow
7253
- },
7254
- {
7255
- // Non-strict mode: -> for maps-to arrow
7256
- latexTrigger: ["-", ">"],
7257
- kind: "infix",
7258
- precedence: 270,
7259
- parse: (parser, lhs, until) => {
7260
- if (parser.options.strict !== false) return null;
7261
- const rhs = parser.parseExpression({ ...until, minPrec: 270 });
7262
- if (rhs === null) return null;
7263
- return ["To", lhs, rhs];
7264
- }
7265
- }
7266
- ];
7267
-
7268
- // src/compute-engine/latex-syntax/dictionary/definitions-logic.ts
7269
- var DEFINITIONS_LOGIC = [
7270
- // Constants
7271
- {
7272
- name: "True",
7273
- kind: "symbol",
7274
- latexTrigger: ["\\top"]
7275
- // ⊤ U+22A4
7276
- },
7277
- {
7278
- kind: "symbol",
7279
- latexTrigger: "\\mathrm{True}",
7280
- parse: "True"
7281
- },
7282
- {
7283
- kind: "symbol",
7284
- latexTrigger: "\\operatorname{True}",
7285
- parse: "True"
7286
- },
7287
- {
7288
- kind: "symbol",
7289
- latexTrigger: "\\mathsf{T}",
7290
- parse: "True"
7291
- },
7292
- {
7293
- name: "False",
7294
- kind: "symbol",
7295
- latexTrigger: ["\\bot"]
7296
- // ⊥ U+22A5
7297
- },
7298
- {
7299
- kind: "symbol",
7300
- latexTrigger: "\\operatorname{False}",
7301
- parse: "False"
7302
- },
7303
- {
7304
- kind: "symbol",
7305
- latexTrigger: "\\mathsf{F}",
7306
- parse: "False"
7307
- },
7308
- // Operators
7309
- // Logic operators have lower precedence than comparisons (245)
7310
- // so that `x = 1 \lor x = 2` parses as `(x = 1) \lor (x = 2)`
7311
- // See https://github.com/cortex-js/compute-engine/issues/243
7312
- {
7313
- name: "And",
7314
- kind: "infix",
7315
- latexTrigger: ["\\land"],
7316
- precedence: 235
7317
- // serialize: '\\land',
7318
- },
7319
- { kind: "infix", latexTrigger: ["\\wedge"], parse: "And", precedence: 235 },
7320
- { kind: "infix", latexTrigger: "\\&", parse: "And", precedence: 235 },
7321
- {
7322
- kind: "infix",
7323
- latexTrigger: "\\operatorname{and}",
7324
- parse: "And",
7325
- precedence: 235
7326
- },
7327
- {
7328
- name: "Or",
7329
- kind: "infix",
7330
- latexTrigger: ["\\lor"],
7331
- precedence: 230
7332
- },
7333
- { kind: "infix", latexTrigger: ["\\vee"], parse: "Or", precedence: 230 },
7334
- { kind: "infix", latexTrigger: "\\parallel", parse: "Or", precedence: 230 },
7335
- {
7336
- kind: "infix",
7337
- latexTrigger: "\\operatorname{or}",
7338
- parse: "Or",
7339
- precedence: 230
7340
- },
7341
- {
7342
- name: "Xor",
7343
- kind: "infix",
7344
- latexTrigger: ["\\veebar"],
7345
- precedence: 232
7346
- },
7347
- // Possible alt: \oplus ⊕ U+2295
7348
- {
7349
- name: "Not",
7350
- kind: "prefix",
7351
- latexTrigger: ["\\lnot"],
7352
- precedence: 880
7353
- },
7354
- {
7355
- kind: "prefix",
7356
- latexTrigger: ["\\neg"],
7357
- parse: "Not",
7358
- precedence: 880
7359
- },
7360
- {
7361
- name: "Nand",
7362
- kind: "infix",
7363
- latexTrigger: ["\\barwedge"],
7364
- precedence: 232
7365
- // serialize: '\\mid',
7366
- },
7367
- {
7368
- name: "Nor",
7369
- kind: "infix",
7370
- latexTrigger: ["\u22BD"],
7371
- // bar vee
7372
- precedence: 232
7373
- // serialize: '\\downarrow',
7374
- },
7375
- // Functions
7376
- {
7377
- kind: "function",
7378
- symbolTrigger: "and",
7379
- parse: "And"
7380
- },
7381
- {
7382
- kind: "function",
7383
- symbolTrigger: "or",
7384
- parse: "Or"
7385
- },
7386
- {
7387
- kind: "function",
7388
- symbolTrigger: "not",
7389
- parse: "Not"
7390
- },
7391
- // Relations
7392
- {
7393
- name: "Implies",
7394
- kind: "infix",
7395
- precedence: 220,
7396
- associativity: "right",
7397
- latexTrigger: ["\\implies"],
7398
- serialize: "\\implies"
7399
- },
7400
- {
7401
- latexTrigger: ["\\Rightarrow"],
7402
- kind: "infix",
7403
- precedence: 220,
7404
- associativity: "right",
7405
- parse: "Implies"
7406
- },
7407
- {
7408
- latexTrigger: ["\\rightarrow"],
7409
- kind: "infix",
7410
- precedence: 220,
7411
- associativity: "right",
7412
- parse: "Implies"
7413
- },
7414
- {
7415
- latexTrigger: ["\\Longrightarrow"],
7416
- kind: "infix",
7417
- precedence: 220,
7418
- associativity: "right",
7419
- parse: "Implies"
7420
- },
7421
- {
7422
- latexTrigger: ["\\longrightarrow"],
7423
- kind: "infix",
7424
- precedence: 220,
7425
- associativity: "right",
7426
- parse: "Implies"
7427
- },
7428
- {
7429
- // Non-strict mode: => for implies
7430
- latexTrigger: ["=", ">"],
7431
- kind: "infix",
7432
- precedence: 220,
7433
- associativity: "right",
7434
- parse: (parser, lhs, until) => {
7435
- if (parser.options.strict !== false) return null;
7436
- const rhs = parser.parseExpression({ ...until, minPrec: 220 });
7437
- if (rhs === null) return null;
7438
- return ["Implies", lhs, rhs];
7439
- }
7440
- },
7441
- {
7442
- name: "Equivalent",
7443
- // MathML: identical to, Mathematica: Congruent
7444
- latexTrigger: ["\\iff"],
7445
- kind: "infix",
7446
- associativity: "right",
7447
- precedence: 219
7448
- },
7449
- {
7450
- latexTrigger: ["\\Leftrightarrow"],
7451
- kind: "infix",
7452
- associativity: "right",
7453
- precedence: 219,
7454
- parse: "Equivalent"
7455
- },
7456
- {
7457
- latexTrigger: ["\\leftrightarrow"],
7458
- kind: "infix",
7459
- associativity: "right",
7460
- precedence: 219,
7461
- parse: "Equivalent"
7462
- },
7463
- {
7464
- latexTrigger: ["\\Longleftrightarrow"],
7465
- kind: "infix",
7466
- associativity: "right",
7467
- precedence: 219,
7468
- parse: "Equivalent"
7469
- },
7830
+ latexTrigger: [latex],
7831
+ parse: symbol2
7832
+ };
7833
+ }),
7834
+ ...SYMBOLS.map(([symbol2, _latex, codepoint]) => {
7835
+ return {
7836
+ kind: "symbol",
7837
+ latexTrigger: [String.fromCodePoint(codepoint)],
7838
+ parse: symbol2
7839
+ };
7840
+ })
7841
+ ];
7842
+
7843
+ // src/compute-engine/latex-syntax/dictionary/definitions-algebra.ts
7844
+ var DEFINITIONS_ALGEBRA = [
7470
7845
  {
7471
- latexTrigger: ["\\longleftrightarrow"],
7846
+ name: "To",
7847
+ latexTrigger: ["\\to"],
7472
7848
  kind: "infix",
7473
- associativity: "right",
7474
- precedence: 219,
7475
- parse: "Equivalent"
7849
+ precedence: 270
7850
+ // MathML rightwards arrow
7476
7851
  },
7477
7852
  {
7478
- // Non-strict mode: <=> for equivalence
7479
- latexTrigger: ["<", "=", ">"],
7853
+ // Non-strict mode: -> for maps-to arrow
7854
+ latexTrigger: ["-", ">"],
7480
7855
  kind: "infix",
7481
- precedence: 219,
7482
- associativity: "right",
7856
+ precedence: 270,
7483
7857
  parse: (parser, lhs, until) => {
7484
7858
  if (parser.options.strict !== false) return null;
7485
- const rhs = parser.parseExpression({ ...until, minPrec: 219 });
7859
+ const rhs = parser.parseExpression({ ...until, minPrec: 270 });
7486
7860
  if (rhs === null) return null;
7487
- return ["Equivalent", lhs, rhs];
7488
- }
7489
- },
7490
- {
7491
- latexTrigger: ["\\equiv"],
7492
- kind: "infix",
7493
- associativity: "right",
7494
- precedence: 219,
7495
- parse: (parser, lhs, terminator) => {
7496
- const rhs = parser.parseExpression({ ...terminator, minPrec: 219 });
7497
- const index = parser.index;
7498
- const modulus = parser.parseExpression({ ...terminator, minPrec: 219 });
7499
- if (modulus !== null && operator(modulus) === "Mod")
7500
- return ["Congruent", lhs, rhs, missingIfEmpty(operand(modulus, 1))];
7501
- parser.index = index;
7502
- return ["Equivalent", lhs, missingIfEmpty(rhs)];
7503
- }
7504
- },
7505
- {
7506
- name: "Proves",
7507
- kind: "infix",
7508
- latexTrigger: ["\\vdash"],
7509
- precedence: 220,
7510
- associativity: "right",
7511
- serialize: "\\vdash"
7512
- },
7513
- {
7514
- name: "Entails",
7515
- kind: "infix",
7516
- latexTrigger: ["\\vDash"],
7517
- precedence: 220,
7518
- associativity: "right",
7519
- serialize: "\\vDash"
7520
- },
7521
- {
7522
- name: "Satisfies",
7523
- kind: "infix",
7524
- latexTrigger: ["\\models"],
7525
- precedence: 220,
7526
- associativity: "right",
7527
- serialize: "\\models"
7528
- },
7529
- // Quantifiers: for all, exists
7530
- {
7531
- name: "ForAll",
7532
- kind: "prefix",
7533
- latexTrigger: ["\\forall"],
7534
- precedence: 200,
7535
- // Has to be lower than COMPARISON_PRECEDENCE
7536
- serialize: serializeQuantifier("\\forall"),
7537
- parse: parseQuantifier("ForAll")
7538
- },
7539
- {
7540
- name: "Exists",
7541
- kind: "prefix",
7542
- latexTrigger: ["\\exists"],
7543
- precedence: 200,
7544
- // Has to be lower than COMPARISON_PRECEDENCE,
7545
- serialize: serializeQuantifier("\\exists"),
7546
- parse: parseQuantifier("Exists")
7547
- },
7548
- {
7549
- name: "ExistsUnique",
7550
- kind: "prefix",
7551
- latexTrigger: ["\\exists", "!"],
7552
- precedence: 200,
7553
- // Has to be lower than COMPARISON_PRECEDENCE,
7554
- serialize: serializeQuantifier("\\exists!"),
7555
- parse: parseQuantifier("ExistsUnique")
7556
- },
7557
- {
7558
- name: "NotForAll",
7559
- kind: "prefix",
7560
- latexTrigger: ["\\lnot", "\\forall"],
7561
- precedence: 200,
7562
- // Has to be lower than COMPARISON_PRECEDENCE
7563
- serialize: serializeQuantifier("\\lnot\\forall"),
7564
- parse: parseQuantifier("NotForAll")
7565
- },
7566
- {
7567
- name: "NotExists",
7568
- kind: "prefix",
7569
- latexTrigger: ["\\lnot", "\\exists"],
7570
- precedence: 200,
7571
- // Has to be lower than COMPARISON_PRECEDENCE,
7572
- serialize: serializeQuantifier("\\lnot\\exists"),
7573
- parse: parseQuantifier("NotExists")
7574
- },
7575
- {
7576
- name: "KroneckerDelta",
7577
- kind: "prefix",
7578
- latexTrigger: ["\\delta", "_"],
7579
- precedence: 200,
7580
- serialize: (serializer, expr) => {
7581
- const args = operands(expr);
7582
- if (args.length === 0) return "\\delta";
7583
- if (args.every((x) => symbol(x)))
7584
- return `\\delta_{${args.map((arg) => serializer.serialize(arg)).join("")}}`;
7585
- return `\\delta_{${args.map((arg) => serializer.serialize(arg)).join(", ")}}`;
7586
- },
7587
- parse: (parser) => {
7588
- const group = parser.parseGroup();
7589
- if (group === null) {
7590
- const token = parser.parseToken();
7591
- if (!token) return null;
7592
- return ["KroneckerDelta", token];
7593
- }
7594
- const seq = getSequence(group);
7595
- if (seq && seq.length <= 2) return ["KroneckerDelta", ...seq];
7596
- if (operator(group) === "InvisibleOperator")
7597
- return ["KroneckerDelta", ...operands(group)];
7598
- if (group !== null) return ["KroneckerDelta", group];
7599
- return null;
7600
- }
7601
- },
7602
- // Iverson brackets. Also called the "indicator function"
7603
- // Must have a single argument, a relational expression, i.e.
7604
- // `[ a = b ]` or `[ x \leq 0 ]`
7605
- // Otherwise, it gets rejected, it could be something else, like a list or
7606
- // tuple.
7607
- {
7608
- name: "Boole",
7609
- kind: "matchfix",
7610
- openTrigger: "[",
7611
- closeTrigger: "]",
7612
- // serialize: (serializer: Serializer, expr: MathJsonExpression) => {
7613
- // const args = ops(expr);
7614
- // return `[${serializer.serialize(arg)}]`;
7615
- // },
7616
- parse: (_parser, body) => {
7617
- const h = operator(body);
7618
- if (!h) return null;
7619
- if (!DEFINITIONS_INEQUALITIES.some((x) => x.name === h)) return null;
7620
- return ["Boole", body];
7621
- }
7622
- },
7623
- {
7624
- kind: "matchfix",
7625
- openTrigger: "\\llbracket",
7626
- closeTrigger: "\\rrbracket",
7627
- parse: (_parser, body) => {
7628
- const h = operator(body);
7629
- if (!h) return null;
7630
- if (!DEFINITIONS_INEQUALITIES.some((x) => x.name === h)) return null;
7631
- return ["Boole", body];
7632
- }
7633
- },
7634
- // Predicate application in First-Order Logic.
7635
- // ["Predicate", "P", "x", "y"] serializes to "P(x, y)"
7636
- {
7637
- name: "Predicate",
7638
- serialize: (serializer, expr) => {
7639
- const args = operands(expr);
7640
- if (args.length === 0) return "";
7641
- const pred = args[0];
7642
- const predStr = typeof pred === "string" ? pred : serializer.serialize(pred);
7643
- if (args.length === 1) return predStr;
7644
- const argStrs = args.slice(1).map((arg) => serializer.serialize(arg));
7645
- return `${predStr}(${argStrs.join(", ")})`;
7861
+ return ["To", lhs, rhs];
7646
7862
  }
7647
7863
  }
7648
7864
  ];
7649
- function serializeQuantifier(quantifierSymbol) {
7650
- return (serializer, expr) => {
7651
- const args = operands(expr);
7652
- if (args.length === 0) return quantifierSymbol;
7653
- if (args.length === 1)
7654
- return `${quantifierSymbol} ${serializer.serialize(args[0])}`;
7655
- const boundVar = serializer.serialize(args[0]);
7656
- const body = serializer.serialize(args[1]);
7657
- return `${quantifierSymbol} ${boundVar}, ${body}`;
7658
- };
7659
- }
7660
- function tightBindingCondition(p, terminator) {
7661
- return p.peek === "\\to" || p.peek === "\\rightarrow" || p.peek === "\\implies" || p.peek === "\\Rightarrow" || p.peek === "\\iff" || p.peek === "\\Leftrightarrow" || p.peek === "\\land" || p.peek === "\\wedge" || p.peek === "\\lor" || p.peek === "\\vee" || (terminator.condition?.(p) ?? false);
7662
- }
7663
- function parseQuantifier(kind) {
7664
- return (parser, terminator) => {
7665
- const index = parser.index;
7666
- const useTightBinding = parser.options.quantifierScope !== "loose";
7667
- const symbol2 = parser.parseSymbol(terminator);
7668
- if (symbol2) {
7669
- parser.skipSpace();
7670
- if (parser.match(",") || parser.match("\\mid") || parser.match(".") || parser.match(":") || parser.match("\\colon")) {
7671
- const bodyTerminator = useTightBinding ? {
7672
- ...terminator,
7673
- condition: (p) => tightBindingCondition(p, terminator)
7674
- } : terminator;
7675
- parser.enterQuantifierScope();
7676
- const body2 = parser.parseExpression(bodyTerminator);
7677
- parser.exitQuantifierScope();
7678
- return [kind, symbol2, missingIfEmpty(body2)];
7679
- }
7680
- parser.enterQuantifierScope();
7681
- const body = parser.parseEnclosure();
7682
- parser.exitQuantifierScope();
7683
- if (body) return [kind, symbol2, missingIfEmpty(body)];
7684
- }
7685
- parser.index = index;
7686
- const condTerminator = {
7687
- ...terminator,
7688
- condition: (p) => p.peek === ":" || p.peek === "\\colon" || (terminator.condition?.(p) ?? false)
7689
- };
7690
- const condition = parser.parseExpression(condTerminator);
7691
- if (condition === null) return null;
7692
- parser.skipSpace();
7693
- if (parser.matchAny([",", "\\mid", ":", "\\colon"])) {
7694
- const bodyTerminator = useTightBinding ? {
7695
- ...terminator,
7696
- condition: (p) => tightBindingCondition(p, terminator)
7697
- } : terminator;
7698
- parser.enterQuantifierScope();
7699
- const body = parser.parseExpression(bodyTerminator);
7700
- parser.exitQuantifierScope();
7701
- return [kind, condition, missingIfEmpty(body)];
7702
- }
7703
- if (parser.match("(")) {
7704
- parser.enterQuantifierScope();
7705
- const body = parser.parseExpression(terminator);
7706
- parser.exitQuantifierScope();
7707
- if (!parser.match(")")) return null;
7708
- return [kind, condition, missingIfEmpty(body)];
7709
- }
7710
- return null;
7711
- };
7712
- }
7713
7865
 
7714
7866
  // src/compute-engine/latex-syntax/dictionary/definitions-sets.ts
7715
7867
  function parseIntervalBody(body, openLeft, openRight) {
@@ -12045,7 +12197,7 @@ var ZWJ = "\\u{200D}";
12045
12197
  var FLAG_SEQUENCE = "\\p{RI}\\p{RI}";
12046
12198
  var TAG_MOD = `(?:[\\u{E0020}-\\u{E007E}]+\\u{E007F})`;
12047
12199
  var EMOJI_MOD = `(?:\\p{EMod}|${VS16}${KEYCAP}?|${TAG_MOD})`;
12048
- var EMOJI_NOT_SYMBOL = `(?:(?=\\P{XIDC})\\p{Emoji})`;
12200
+ var EMOJI_NOT_SYMBOL = `(?:(?=\\P{XIDC})(?=[^\\x23\\x2a\\x30-\\x39])\\p{Emoji})`;
12049
12201
  var ZWJ_ELEMENT = `(?:${EMOJI_NOT_SYMBOL}${EMOJI_MOD}*|\\p{Emoji}${EMOJI_MOD}+|${FLAG_SEQUENCE})`;
12050
12202
  var POSSIBLE_EMOJI = `(?:${ZWJ_ELEMENT})(${ZWJ}${ZWJ_ELEMENT})*`;
12051
12203
  var SOME_EMOJI = new RegExp(`(?:${POSSIBLE_EMOJI})+`, "u");
@@ -13177,7 +13329,7 @@ var IntervalArithmetic = {
13177
13329
  };
13178
13330
 
13179
13331
  // src/interval.ts
13180
- var version = "0.55.0";
13332
+ var version = "0.55.2";
13181
13333
  export {
13182
13334
  IntervalArithmetic,
13183
13335
  _mul,