diff --git a/headers/private/shared/ExpressionParser.h b/headers/private/shared/ExpressionParser.h
index 5052448..9c835b3 100644
a
|
b
|
class ExpressionParser {
|
59 | 59 | int32 argumentCount); |
60 | 60 | MAPM _ParseFunction(const Token& token); |
61 | 61 | MAPM _ParseAtom(); |
| 62 | MAPM _ParseFactorial(MAPM value); |
62 | 63 | |
63 | 64 | void _EatToken(int32 type); |
64 | 65 | |
diff --git a/src/kits/shared/ExpressionParser.cpp b/src/kits/shared/ExpressionParser.cpp
index 549a46b..1b2658d 100644
a
|
b
|
enum {
|
33 | 33 | TOKEN_MODULO, |
34 | 34 | |
35 | 35 | TOKEN_POWER, |
| 36 | TOKEN_FACTORIAL, |
36 | 37 | |
37 | 38 | TOKEN_OPENING_BRACKET, |
38 | 39 | TOKEN_CLOSING_BRACKET, |
… |
… |
class Tokenizer {
|
230 | 231 | case '^': |
231 | 232 | type = TOKEN_POWER; |
232 | 233 | break; |
| 234 | case '!': |
| 235 | type = TOKEN_FACTORIAL; |
| 236 | break; |
233 | 237 | |
234 | 238 | case '(': |
235 | 239 | type = TOKEN_OPENING_BRACKET; |
… |
… |
ExpressionParser::_ParseSum()
|
456 | 460 | |
457 | 461 | default: |
458 | 462 | fTokenizer->RewindToken(); |
459 | | return value; |
| 463 | return _ParseFactorial(value); |
460 | 464 | } |
461 | 465 | } |
462 | 466 | } |
… |
… |
ExpressionParser::_ParseProduct()
|
491 | 495 | |
492 | 496 | default: |
493 | 497 | fTokenizer->RewindToken(); |
494 | | return value; |
| 498 | return _ParseFactorial(value); |
495 | 499 | } |
496 | 500 | } |
497 | 501 | } |
… |
… |
ExpressionParser::_ParsePower()
|
506 | 510 | Token token = fTokenizer->NextToken(); |
507 | 511 | if (token.type != TOKEN_POWER) { |
508 | 512 | fTokenizer->RewindToken(); |
509 | | return value; |
| 513 | return _ParseFactorial(value); |
510 | 514 | } |
511 | 515 | value = value.pow(_ParseUnary()); |
512 | 516 | } |
… |
… |
MAPM
|
565 | 569 | ExpressionParser::_ParseFunction(const Token& token) |
566 | 570 | { |
567 | 571 | if (strcasecmp("e", token.string.String()) == 0) |
568 | | return MAPM(MM_E); |
| 572 | return _ParseFactorial(MAPM(MM_E)); |
569 | 573 | else if (strcasecmp("pi", token.string.String()) == 0) |
570 | | return MAPM(MM_PI); |
| 574 | return _ParseFactorial(MAPM(MM_PI)); |
571 | 575 | |
572 | 576 | // hard coded cases for different count of arguments |
573 | 577 | // supports functions with 3 arguments at most |
… |
… |
ExpressionParser::_ParseFunction(const Token& token)
|
576 | 580 | |
577 | 581 | if (strcasecmp("abs", token.string.String()) == 0) { |
578 | 582 | _InitArguments(values, 1); |
579 | | return values[0].abs(); |
| 583 | return _ParseFactorial(values[0].abs()); |
580 | 584 | } else if (strcasecmp("acos", token.string.String()) == 0) { |
581 | 585 | _InitArguments(values, 1); |
582 | 586 | if (values[0] < -1 || values[0] > 1) |
583 | 587 | throw ParseException("out of domain", token.position); |
584 | | return values[0].acos(); |
| 588 | return _ParseFactorial(values[0].acos()); |
585 | 589 | } else if (strcasecmp("asin", token.string.String()) == 0) { |
586 | 590 | _InitArguments(values, 1); |
587 | 591 | if (values[0] < -1 || values[0] > 1) |
588 | 592 | throw ParseException("out of domain", token.position); |
589 | | return values[0].asin(); |
| 593 | return _ParseFactorial(values[0].asin()); |
590 | 594 | } else if (strcasecmp("atan", token.string.String()) == 0) { |
591 | 595 | _InitArguments(values, 1); |
592 | | return values[0].atan(); |
| 596 | return _ParseFactorial(values[0].atan()); |
593 | 597 | } else if (strcasecmp("atan2", token.string.String()) == 0) { |
594 | 598 | _InitArguments(values, 2); |
595 | | return values[0].atan2(values[1]); |
| 599 | return _ParseFactorial(values[0].atan2(values[1])); |
| 600 | } else if (strcasecmp("cbrt", token.string.String()) == 0) { |
| 601 | _InitArguments(values, 1); |
| 602 | return _ParseFactorial(values[0].cbrt()); |
596 | 603 | } else if (strcasecmp("ceil", token.string.String()) == 0) { |
597 | 604 | _InitArguments(values, 1); |
598 | | return values[0].ceil(); |
| 605 | return _ParseFactorial(values[0].ceil()); |
599 | 606 | } else if (strcasecmp("cos", token.string.String()) == 0) { |
600 | 607 | _InitArguments(values, 1); |
601 | | return values[0].cos(); |
| 608 | return _ParseFactorial(values[0].cos()); |
602 | 609 | } else if (strcasecmp("cosh", token.string.String()) == 0) { |
603 | 610 | _InitArguments(values, 1); |
604 | | return values[0].cosh(); |
| 611 | return _ParseFactorial(values[0].cosh()); |
605 | 612 | } else if (strcasecmp("exp", token.string.String()) == 0) { |
606 | 613 | _InitArguments(values, 1); |
607 | | return values[0].exp(); |
| 614 | return _ParseFactorial(values[0].exp()); |
608 | 615 | } else if (strcasecmp("floor", token.string.String()) == 0) { |
609 | 616 | _InitArguments(values, 1); |
610 | | return values[0].floor(); |
| 617 | return _ParseFactorial(values[0].floor()); |
611 | 618 | } else if (strcasecmp("ln", token.string.String()) == 0) { |
612 | 619 | _InitArguments(values, 1); |
613 | 620 | if (values[0] <= 0) |
614 | 621 | throw ParseException("out of domain", token.position); |
615 | | return values[0].log(); |
| 622 | return _ParseFactorial(values[0].log()); |
616 | 623 | } else if (strcasecmp("log", token.string.String()) == 0) { |
617 | 624 | _InitArguments(values, 1); |
618 | 625 | if (values[0] <= 0) |
619 | 626 | throw ParseException("out of domain", token.position); |
620 | | return values[0].log10(); |
| 627 | return _ParseFactorial(values[0].log10()); |
621 | 628 | } else if (strcasecmp("pow", token.string.String()) == 0) { |
622 | 629 | _InitArguments(values, 2); |
623 | | return values[0].pow(values[1]); |
| 630 | return _ParseFactorial(values[0].pow(values[1])); |
624 | 631 | } else if (strcasecmp("sin", token.string.String()) == 0) { |
625 | 632 | _InitArguments(values, 1); |
626 | | return values[0].sin(); |
| 633 | return _ParseFactorial(values[0].sin()); |
627 | 634 | } else if (strcasecmp("sinh", token.string.String()) == 0) { |
628 | 635 | _InitArguments(values, 1); |
629 | | return values[0].sinh(); |
| 636 | return _ParseFactorial(values[0].sinh()); |
630 | 637 | } else if (strcasecmp("sqrt", token.string.String()) == 0) { |
631 | 638 | _InitArguments(values, 1); |
632 | 639 | if (values[0] < 0) |
633 | 640 | throw ParseException("out of domain", token.position); |
634 | | return values[0].sqrt(); |
| 641 | return _ParseFactorial(values[0].sqrt()); |
635 | 642 | } else if (strcasecmp("tan", token.string.String()) == 0) { |
636 | 643 | _InitArguments(values, 1); |
637 | | return values[0].tan(); |
| 644 | return _ParseFactorial(values[0].tan()); |
638 | 645 | } else if (strcasecmp("tanh", token.string.String()) == 0) { |
639 | 646 | _InitArguments(values, 1); |
640 | | return values[0].tanh(); |
| 647 | return _ParseFactorial(values[0].tanh()); |
641 | 648 | } |
642 | 649 | |
643 | 650 | throw ParseException("unknown identifier", token.position); |
… |
… |
ExpressionParser::_ParseAtom()
|
652 | 659 | throw ParseException("unexpected end of expression", token.position); |
653 | 660 | |
654 | 661 | if (token.type == TOKEN_CONSTANT) |
655 | | return token.value; |
| 662 | return _ParseFactorial(token.value); |
656 | 663 | |
657 | 664 | fTokenizer->RewindToken(); |
658 | 665 | |
… |
… |
ExpressionParser::_ParseAtom()
|
662 | 669 | |
663 | 670 | _EatToken(TOKEN_CLOSING_BRACKET); |
664 | 671 | |
| 672 | return _ParseFactorial(value); |
| 673 | } |
| 674 | |
| 675 | |
| 676 | MAPM |
| 677 | ExpressionParser::_ParseFactorial(MAPM value) |
| 678 | { |
| 679 | if (fTokenizer->NextToken().type == TOKEN_FACTORIAL) { |
| 680 | fTokenizer->RewindToken(); |
| 681 | _EatToken(TOKEN_FACTORIAL); |
| 682 | return value.factorial(); |
| 683 | } |
| 684 | |
| 685 | fTokenizer->RewindToken(); |
665 | 686 | return value; |
666 | 687 | } |
667 | 688 | |