A world-class math input for the web
at main 770 lines 23 kB view raw
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});