A world-class math input for the web
1import {
2 CaretParser,
3 Strand,
4 CharToken,
5 EditorState,
6 MissingNode,
7 TokensTag,
8 UnparseableNode,
9} from "@caret-js/core";
10import { expect, test } from "vitest";
11import {
12 AddNode,
13 DecimalNode,
14 defaultParselets,
15 DivideNode,
16 EquationNode,
17 ExponentNode,
18 FractionToken,
19 FunctionCallNode,
20 MultiplyNode,
21 NegativeNode,
22 ParenthesesToken,
23 PositiveNode,
24 SubSupToken,
25 SubtractNode,
26 VariableNode,
27} from ".";
28import { ParenthesesChildTag } from "./parselets/parentheses";
29import { MultiplicationStyleTag } from "./parselets/adjacentMultiplication";
30
31test("Parse 3.14", () => {
32 const three = new CharToken("3");
33 const point = new CharToken(".");
34 const one = new CharToken("1");
35 const four = new CharToken("4");
36
37 const editorState = new EditorState(new Strand([three, point, one, four]));
38
39 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
40 const parseResult = parser.parse();
41
42 expect(parseResult).toStrictEqual(
43 DecimalNode.from("3.14").addTag(new TokensTag([three, point, one, four]))
44 );
45});
46
47test("Parse x", () => {
48 const x = new CharToken("x");
49
50 const editorState = new EditorState(new Strand([x]));
51
52 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
53 const parseResult = parser.parse();
54
55 expect(parseResult).toStrictEqual(
56 VariableNode.from("x").addTag(new TokensTag([x]))
57 );
58});
59
60test("Parse x+1", () => {
61 const x = new CharToken("x");
62 const plus = new CharToken("+");
63 const one = new CharToken("1");
64
65 const editorState = new EditorState(new Strand([x, plus, one]));
66
67 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
68 const parseResult = parser.parse();
69
70 expect(parseResult).toStrictEqual(
71 AddNode.from([
72 VariableNode.from("x").addTag(new TokensTag([x])),
73 DecimalNode.from("1").addTag(new TokensTag([one])),
74 ]).addTag(new TokensTag([plus]))
75 );
76});
77
78test("Parse 3x", () => {
79 const three = new CharToken("3");
80 const x = new CharToken("x");
81
82 const editorState = new EditorState(new Strand([three, x]));
83
84 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
85 const parseResult = parser.parse();
86
87 expect(parseResult).toStrictEqual(
88 MultiplyNode.from([
89 DecimalNode.from("3").addTag(new TokensTag([three])),
90 VariableNode.from("x").addTag(new TokensTag([x])),
91 ]).addTag(new MultiplicationStyleTag("implicit"))
92 );
93});
94
95test("Parse -x", () => {
96 const negative = new CharToken("-");
97 const x = new CharToken("x");
98
99 const editorState = new EditorState(new Strand([negative, x]));
100
101 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
102 const parseResult = parser.parse();
103
104 expect(parseResult).toStrictEqual(
105 NegativeNode.from(VariableNode.from("x").addTag(new TokensTag([x]))).addTag(
106 new TokensTag([negative])
107 )
108 );
109});
110
111test("Parse +x", () => {
112 const plus = new CharToken("+");
113 const x = new CharToken("x");
114
115 const editorState = new EditorState(new Strand([plus, x]));
116
117 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
118 const parseResult = parser.parse();
119
120 expect(parseResult).toStrictEqual(
121 PositiveNode.from(VariableNode.from("x").addTag(new TokensTag([x]))).addTag(
122 new TokensTag([plus])
123 )
124 );
125});
126
127test("Parse -3.14", () => {
128 const negative = new CharToken("-");
129 const three = new CharToken("3");
130 const point = new CharToken(".");
131 const one = new CharToken("1");
132 const four = new CharToken("4");
133
134 const editorState = new EditorState(
135 new Strand([negative, three, point, one, four])
136 );
137
138 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
139 const parseResult = parser.parse();
140
141 expect(parseResult).toStrictEqual(
142 DecimalNode.from("-3.14").addTag(
143 new TokensTag([negative, three, point, one, four])
144 )
145 );
146});
147
148test("Parse +3.14", () => {
149 const plus = new CharToken("+");
150 const three = new CharToken("3");
151 const point = new CharToken(".");
152 const one = new CharToken("1");
153 const four = new CharToken("4");
154
155 const editorState = new EditorState(
156 new Strand([plus, three, point, one, four])
157 );
158
159 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
160 const parseResult = parser.parse();
161
162 expect(parseResult).toStrictEqual(
163 PositiveNode.from(
164 DecimalNode.from("3.14").addTag(new TokensTag([three, point, one, four]))
165 ).addTag(new TokensTag([plus]))
166 );
167});
168
169test("Parse --2", () => {
170 const minus1 = new CharToken("-");
171 const minus2 = new CharToken("-");
172 const two = new CharToken("2");
173
174 const editorState = new EditorState(new Strand([minus1, minus2, two]));
175
176 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
177 const parseResult = parser.parse();
178
179 expect(parseResult).toStrictEqual(
180 NegativeNode.from(
181 DecimalNode.from("-2").addTag(new TokensTag([minus2, two]))
182 ).addTag(new TokensTag([minus1]))
183 );
184});
185
186test("Parse 1-2+3", () => {
187 const one = new CharToken("1");
188 const minus = new CharToken("-");
189 const two = new CharToken("2");
190 const plus = new CharToken("+");
191 const three = new CharToken("3");
192
193 const editorState = new EditorState(
194 new Strand([one, minus, two, plus, three])
195 );
196
197 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
198 const parseResult = parser.parse();
199
200 expect(parseResult).toStrictEqual(
201 AddNode.from([
202 SubtractNode.from(
203 DecimalNode.from("1").addTag(new TokensTag([one])),
204 DecimalNode.from("2").addTag(new TokensTag([two]))
205 ).addTag(new TokensTag([minus])),
206 DecimalNode.from("3").addTag(new TokensTag([three])),
207 ]).addTag(new TokensTag([plus]))
208 );
209});
210
211test("Parse a(b+1)", () => {
212 const a = new CharToken("a");
213 const b = new CharToken("b");
214 const plus = new CharToken("+");
215 const one = new CharToken("1");
216 const parens = new ParenthesesToken(new Strand([b, plus, one]));
217
218 const editorState = new EditorState(new Strand([a, parens]));
219
220 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
221 const parseResult = parser.parse();
222
223 expect(parseResult).toStrictEqual(
224 MultiplyNode.from([
225 new VariableNode("a").addTag(new TokensTag([a])),
226 new AddNode([
227 new VariableNode("b").addTag(new TokensTag([b])),
228 new DecimalNode("1").addTag(new TokensTag([one])),
229 ])
230 .addTag(new TokensTag([plus, parens]))
231 .addTag(new ParenthesesChildTag()),
232 ]).addTag(new MultiplicationStyleTag("implicit"))
233 );
234});
235
236test("Parse f(x)", () => {
237 const f = new CharToken("f");
238 const x = new CharToken("x");
239 const parens = new ParenthesesToken(new Strand([x]));
240
241 const editorState = new EditorState(new Strand([f, parens]));
242
243 const parser = new CaretParser(
244 editorState,
245 [],
246 [...defaultParselets({ funcNames: new Set(["f"]) })]
247 );
248 const parseResult = parser.parse();
249
250 expect(parseResult).toStrictEqual(
251 FunctionCallNode.from("f", [
252 VariableNode.from("x")
253 .addTag(new TokensTag([x, parens]))
254 .addTag(new ParenthesesChildTag()),
255 ]).addTag(new TokensTag([f]))
256 );
257});
258
259test("Parse f(x+1)", () => {
260 const f = new CharToken("f");
261 const x = new CharToken("x");
262 const plus = new CharToken("+");
263 const one = new CharToken("1");
264 const parens = new ParenthesesToken(new Strand([x, plus, one]));
265
266 const editorState = new EditorState(new Strand([f, parens]));
267
268 const parser = new CaretParser(
269 editorState,
270 [],
271 [...defaultParselets({ funcNames: new Set(["f"]) })]
272 );
273 const parseResult = parser.parse();
274
275 expect(parseResult).toStrictEqual(
276 FunctionCallNode.from("f", [
277 AddNode.from([
278 VariableNode.from("x").addTag(new TokensTag([x])),
279 DecimalNode.from("1").addTag(new TokensTag([one])),
280 ])
281 .addTag(new TokensTag([plus, parens]))
282 .addTag(new ParenthesesChildTag()),
283 ]).addTag(new TokensTag([f]))
284 );
285});
286
287test("Parse xf(x)", () => {
288 const x1 = new CharToken("x");
289 const f = new CharToken("f");
290 const x2 = new CharToken("x");
291 const parens = new ParenthesesToken(new Strand([x2]));
292
293 const editorState = new EditorState(new Strand([x1, f, parens]));
294
295 const parser = new CaretParser(
296 editorState,
297 [],
298 [...defaultParselets({ funcNames: new Set(["f"]) })]
299 );
300 const parseResult = parser.parse();
301
302 expect(parseResult).toStrictEqual(
303 MultiplyNode.from([
304 VariableNode.from("x").addTag(new TokensTag([x1])),
305 FunctionCallNode.from("f", [
306 VariableNode.from("x")
307 .addTag(new TokensTag([x2, parens]))
308 .addTag(new ParenthesesChildTag()),
309 ]).addTag(new TokensTag([f])),
310 ]).addTag(new MultiplicationStyleTag("implicit"))
311 );
312});
313
314test("Parse x+", () => {
315 const x = new CharToken("x");
316 const plus = new CharToken("+");
317
318 const editorState = new EditorState(new Strand([x, plus]));
319
320 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
321 const parseResult = parser.parse();
322
323 expect(parseResult).toStrictEqual(
324 AddNode.from([
325 VariableNode.from("x").addTag(new TokensTag([x])),
326 MissingNode.from(),
327 ]).addTag(new TokensTag([plus]))
328 );
329});
330
331test("Parse x-", () => {
332 const x = new CharToken("x");
333 const minus = new CharToken("-");
334
335 const editorState = new EditorState(new Strand([x, minus]));
336
337 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
338 const parseResult = parser.parse();
339
340 expect(parseResult).toStrictEqual(
341 SubtractNode.from(
342 VariableNode.from("x").addTag(new TokensTag([x])),
343 MissingNode.from()
344 ).addTag(new TokensTag([minus]))
345 );
346});
347
348test("Parse x^2y^2", () => {
349 const x = new CharToken("x");
350 const two1 = new CharToken("2");
351 const subsup1 = new SubSupToken(null, new Strand([two1]));
352 const y = new CharToken("y");
353 const two2 = new CharToken("2");
354 const subsup2 = new SubSupToken(null, new Strand([two2]));
355
356 const editorState = new EditorState(new Strand([x, subsup1, y, subsup2]));
357
358 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
359 const parseResult = parser.parse();
360
361 expect(parseResult).toStrictEqual(
362 MultiplyNode.from([
363 ExponentNode.from(
364 VariableNode.from("x").addTag(new TokensTag([x])),
365 DecimalNode.from("2").addTag(new TokensTag([two1]))
366 ).addTag(new TokensTag([subsup1])),
367 ExponentNode.from(
368 VariableNode.from("y").addTag(new TokensTag([y])),
369 DecimalNode.from("2").addTag(new TokensTag([two2]))
370 ).addTag(new TokensTag([subsup2])),
371 ]).addTag(new MultiplicationStyleTag("implicit"))
372 );
373});
374
375test("Parse 2x+3y", () => {
376 const two = new CharToken("2");
377 const x = new CharToken("x");
378 const plus = new CharToken("+");
379 const three = new CharToken("3");
380 const y = new CharToken("y");
381
382 const editorState = new EditorState(new Strand([two, x, plus, three, y]));
383
384 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
385 const parseResult = parser.parse();
386
387 expect(parseResult).toStrictEqual(
388 AddNode.from([
389 MultiplyNode.from([
390 DecimalNode.from("2").addTag(new TokensTag([two])),
391 VariableNode.from("x").addTag(new TokensTag([x])),
392 ]).addTag(new MultiplicationStyleTag("implicit")),
393 MultiplyNode.from([
394 DecimalNode.from("3").addTag(new TokensTag([three])),
395 VariableNode.from("y").addTag(new TokensTag([y])),
396 ]).addTag(new MultiplicationStyleTag("implicit")),
397 ]).addTag(new TokensTag([plus]))
398 );
399});
400
401test("Parse y=1/2x+3", () => {
402 const y = new CharToken("y");
403 const equals = new CharToken("=");
404 const one = new CharToken("1");
405 const two = new CharToken("2");
406 const fraction = new FractionToken(new Strand([one]), new Strand([two]));
407 const x = new CharToken("x");
408 const plus = new CharToken("+");
409 const three = new CharToken("3");
410
411 const editorState = new EditorState(
412 new Strand([y, equals, fraction, x, plus, three])
413 );
414
415 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
416 const parseResult = parser.parse();
417
418 expect(parseResult).toStrictEqual(
419 EquationNode.from([
420 VariableNode.from("y").addTag(new TokensTag([y])),
421 AddNode.from([
422 MultiplyNode.from([
423 DivideNode.from(
424 DecimalNode.from("1").addTag(new TokensTag([one])),
425 DecimalNode.from("2").addTag(new TokensTag([two]))
426 ).addTag(new TokensTag([fraction])),
427 VariableNode.from("x").addTag(new TokensTag([x])),
428 ]).addTag(new MultiplicationStyleTag("implicit")),
429 DecimalNode.from("3").addTag(new TokensTag([three])),
430 ]).addTag(new TokensTag([plus])),
431 ]).addTag(new TokensTag([equals]))
432 );
433});
434
435test("Parse (2x+-1)(x-3)", () => {
436 const two = new CharToken("2");
437 const x1 = new CharToken("x");
438 const plus = new CharToken("+");
439 const negative = new CharToken("-");
440 const one = new CharToken("1");
441 const parens1 = new ParenthesesToken(
442 new Strand([two, x1, plus, negative, one])
443 );
444 const x2 = new CharToken("x");
445 const minus = new CharToken("-");
446 const three = new CharToken("3");
447 const parens2 = new ParenthesesToken(new Strand([x2, minus, three]));
448
449 const editorState = new EditorState(new Strand([parens1, parens2]));
450
451 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
452 const parseResult = parser.parse();
453
454 expect(parseResult).toStrictEqual(
455 MultiplyNode.from([
456 AddNode.from([
457 MultiplyNode.from([
458 DecimalNode.from("2").addTag(new TokensTag([two])),
459 VariableNode.from("x").addTag(new TokensTag([x1])),
460 ]).addTag(new MultiplicationStyleTag("implicit")),
461 DecimalNode.from("-1").addTag(new TokensTag([negative, one])),
462 ])
463 .addTag(new TokensTag([plus, parens1]))
464 .addTag(new ParenthesesChildTag()),
465 SubtractNode.from(
466 VariableNode.from("x").addTag(new TokensTag([x2])),
467 DecimalNode.from("3").addTag(new TokensTag([three]))
468 )
469 .addTag(new TokensTag([minus, parens2]))
470 .addTag(new ParenthesesChildTag()),
471 ]).addTag(new MultiplicationStyleTag("implicit"))
472 );
473});
474
475test("Parse -x^2", () => {
476 const negative = new CharToken("-");
477 const x = new CharToken("x");
478 const two = new CharToken("2");
479 const subsup = new SubSupToken(null, new Strand([two]));
480
481 const editorState = new EditorState(new Strand([negative, x, subsup]));
482
483 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
484 const parseResult = parser.parse();
485
486 expect(parseResult).toStrictEqual(
487 NegativeNode.from(
488 ExponentNode.from(
489 VariableNode.from("x").addTag(new TokensTag([x])),
490 DecimalNode.from("2").addTag(new TokensTag([two]))
491 ).addTag(new TokensTag([subsup]))
492 ).addTag(new TokensTag([negative]))
493 );
494});
495
496test("Parse x*y-z", () => {
497 /*
498 This currently fails because on the right-hand side of the * we are restarting parsing to get the y.
499 We want to continue parsing anything that binds stronger or the same as *, which includes implicit multiplication.
500 As a result, the "y-z" is being parsed as Multiply(y, Negative(z)). This does NOT happen if you parse "y-z" alone.
501 The difference is that we are parsing with a high precedence where Subtract(y, z) is not allowed but Multiply(y, Negative(z)) is.
502 */
503
504 const x = new CharToken("x");
505 const multiply = new CharToken("*");
506 const y = new CharToken("y");
507 const subtract = new CharToken("-");
508 const z = new CharToken("z");
509
510 const editorState = new EditorState(
511 new Strand([x, multiply, y, subtract, z])
512 );
513
514 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
515 const parseResult = parser.parse();
516
517 expect(parseResult).toStrictEqual(
518 SubtractNode.from(
519 MultiplyNode.from([
520 VariableNode.from("x").addTag(new TokensTag([x])),
521 VariableNode.from("y").addTag(new TokensTag([y])),
522 ])
523 .addTag(new TokensTag([multiply]))
524 .addTag(new MultiplicationStyleTag("dot")),
525 VariableNode.from("z").addTag(new TokensTag([z]))
526 ).addTag(new TokensTag([subtract]))
527 );
528});
529
530test("Parse 1.2.3", () => {
531 const one = new CharToken("1");
532 const point1 = new CharToken(".");
533 const two = new CharToken("2");
534 const point2 = new CharToken(".");
535 const three = new CharToken("3");
536
537 const editorState = new EditorState(
538 new Strand([one, point1, two, point2, three])
539 );
540
541 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
542 const parseResult = parser.parse();
543
544 expect(parseResult).toStrictEqual(
545 UnparseableNode.from(
546 DecimalNode.from("1.2").addTag(new TokensTag([one, point1, two])),
547 [point2, three]
548 )
549 );
550});
551
552test("Parse 1.2.", () => {
553 const one = new CharToken("1");
554 const point1 = new CharToken(".");
555 const two = new CharToken("2");
556 const point2 = new CharToken(".");
557
558 const editorState = new EditorState(new Strand([one, point1, two, point2]));
559
560 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
561 const parseResult = parser.parse();
562
563 expect(parseResult).toStrictEqual(
564 UnparseableNode.from(
565 DecimalNode.from("1.2").addTag(new TokensTag([one, point1, two])),
566 [point2]
567 )
568 );
569});
570
571test("Parse -.", () => {
572 const negative = new CharToken("-");
573 const point = new CharToken(".");
574
575 const editorState = new EditorState(new Strand([negative, point]));
576
577 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
578 const parseResult = parser.parse();
579
580 expect(parseResult).toStrictEqual(
581 NegativeNode.from(new UnparseableNode(null, [point])).addTag(
582 new TokensTag([negative])
583 )
584 );
585});
586
587test("Parse 1()", () => {
588 const one = new CharToken("1");
589 const parens = new ParenthesesToken(new Strand([]));
590
591 const editorState = new EditorState(new Strand([one, parens]));
592
593 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
594 const parseResult = parser.parse();
595
596 expect(parseResult).toStrictEqual(
597 MultiplyNode.from([
598 DecimalNode.from("1").addTag(new TokensTag([one])),
599 new MissingNode()
600 .addTag(new TokensTag([parens]))
601 .addTag(new ParenthesesChildTag()),
602 ]).addTag(new MultiplicationStyleTag("implicit"))
603 );
604});
605
606test("Parse +--++-+--3", () => {
607 const plus1 = new CharToken("+");
608 const minus1 = new CharToken("-");
609 const minus2 = new CharToken("-");
610 const plus2 = new CharToken("+");
611 const plus3 = new CharToken("+");
612 const minus3 = new CharToken("-");
613 const plus4 = new CharToken("+");
614 const minus4 = new CharToken("-");
615 const minus5 = new CharToken("-");
616 const three = new CharToken("3");
617
618 const editorState = new EditorState(
619 new Strand([
620 plus1,
621 minus1,
622 minus2,
623 plus2,
624 plus3,
625 minus3,
626 plus4,
627 minus4,
628 minus5,
629 three,
630 ])
631 );
632
633 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
634 const parseResult = parser.parse();
635
636 expect(parseResult).toStrictEqual(
637 PositiveNode.from(
638 NegativeNode.from(
639 NegativeNode.from(
640 PositiveNode.from(
641 PositiveNode.from(
642 NegativeNode.from(
643 PositiveNode.from(
644 NegativeNode.from(
645 DecimalNode.from("-3").addTag(
646 new TokensTag([minus5, three])
647 )
648 ).addTag(new TokensTag([minus4]))
649 ).addTag(new TokensTag([plus4]))
650 ).addTag(new TokensTag([minus3]))
651 ).addTag(new TokensTag([plus3]))
652 ).addTag(new TokensTag([plus2]))
653 ).addTag(new TokensTag([minus2]))
654 ).addTag(new TokensTag([minus1]))
655 ).addTag(new TokensTag([plus1]))
656 );
657});
658
659test("Parse ab-cd", () => {
660 const a = new CharToken("a");
661 const b = new CharToken("b");
662 const minus = new CharToken("-");
663 const c = new CharToken("c");
664 const d = new CharToken("d");
665
666 const editorState = new EditorState(new Strand([a, b, minus, c, d]));
667
668 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
669 const parseResult = parser.parse();
670
671 expect(parseResult).toStrictEqual(
672 SubtractNode.from(
673 MultiplyNode.from([
674 VariableNode.from("a").addTag(new TokensTag([a])),
675 VariableNode.from("b").addTag(new TokensTag([b])),
676 ]).addTag(new MultiplicationStyleTag("implicit")),
677 MultiplyNode.from([
678 VariableNode.from("c").addTag(new TokensTag([c])),
679 VariableNode.from("d").addTag(new TokensTag([d])),
680 ]).addTag(new MultiplicationStyleTag("implicit"))
681 ).addTag(new TokensTag([minus]))
682 );
683});
684
685test("Parse 1x-1y", () => {
686 const one1 = new CharToken("1");
687 const x = new CharToken("x");
688 const minus = new CharToken("-");
689 const one2 = new CharToken("1");
690 const y = new CharToken("y");
691
692 const editorState = new EditorState(new Strand([one1, x, minus, one2, y]));
693
694 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
695 const parseResult = parser.parse();
696
697 expect(parseResult).toStrictEqual(
698 SubtractNode.from(
699 MultiplyNode.from([
700 DecimalNode.from("1").addTag(new TokensTag([one1])),
701 VariableNode.from("x").addTag(new TokensTag([x])),
702 ]).addTag(new MultiplicationStyleTag("implicit")),
703 MultiplyNode.from([
704 DecimalNode.from("1").addTag(new TokensTag([one2])),
705 VariableNode.from("y").addTag(new TokensTag([y])),
706 ]).addTag(new MultiplicationStyleTag("implicit"))
707 ).addTag(new TokensTag([minus]))
708 );
709});
710
711test("Parse x1y", () => {
712 const x = new CharToken("x");
713 const one = new CharToken("1");
714 const y = new CharToken("y");
715
716 const editorState = new EditorState(new Strand([x, one, y]));
717
718 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
719 const parseResult = parser.parse();
720
721 expect(parseResult).toStrictEqual(
722 UnparseableNode.from(VariableNode.from("x").addTag(new TokensTag([x])), [
723 one,
724 y,
725 ])
726 );
727});
728
729test.skip("Parse xy1", () => {
730 const x = new CharToken("x");
731 const y = new CharToken("y");
732 const one = new CharToken("1");
733
734 const editorState = new EditorState(new Strand([x, y, one]));
735
736 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
737 const parseResult = parser.parse();
738
739 expect(parseResult).toStrictEqual(
740 UnparseableNode.from(
741 MultiplyNode.from([
742 VariableNode.from("x").addTag(new TokensTag([x])),
743 VariableNode.from("y").addTag(new TokensTag([y])),
744 ]).addTag(new MultiplicationStyleTag("implicit")),
745 [one]
746 )
747 );
748});
749
750test.skip("Parse x+y1", () => {
751 const x = new CharToken("x");
752 const plus = new CharToken("+");
753 const y = new CharToken("y");
754 const one = new CharToken("1");
755
756 const editorState = new EditorState(new Strand([x, plus, y, one]));
757
758 const parser = new CaretParser(editorState, [], [...defaultParselets()]);
759 const parseResult = parser.parse();
760
761 expect(parseResult).toStrictEqual(
762 UnparseableNode.from(
763 AddNode.from([
764 VariableNode.from("x").addTag(new TokensTag([x])),
765 VariableNode.from("y").addTag(new TokensTag([y])),
766 ]).addTag(new TokensTag([plus])),
767 [one]
768 )
769 );
770});