Mercurial > projects > dang
comparison parser/Parser.d @ 152:893f23a9de93
Formatting change
author | Anders Halager <halager@gmail.com> |
---|---|
date | Mon, 21 Jul 2008 21:30:44 +0200 |
parents | aeeef0dea14e |
children | 0ea5d2f3e96b |
comparison
equal
deleted
inserted
replaced
151:aeeef0dea14e | 152:893f23a9de93 |
---|---|
497 } | 497 } |
498 | 498 |
499 return a; | 499 return a; |
500 } | 500 } |
501 | 501 |
502 enum : uint | 502 enum : uint |
503 { | 503 { |
504 Single, | 504 Single, |
505 Scope, | 505 Scope, |
506 All | 506 All |
507 } | 507 } |
508 | 508 |
509 struct Att | 509 struct Att |
510 { | 510 { |
511 Attribute a; | 511 Attribute a; |
512 uint nested; | 512 uint nested; |
513 } | 513 } |
514 | 514 |
515 /** | 515 /** |
516 Parse statements. | 516 Parse statements. |
517 | 517 |
518 This is the place to attack! | 518 This is the place to attack! |
519 */ | 519 */ |
520 Stmt parseStatement() | 520 Stmt parseStatement() |
521 { | 521 { |
522 Token t = peek; | 522 Token t = peek; |
523 | 523 |
524 if (t.isReturn) | 524 if (t.isReturn) |
525 { | 525 { |
526 Token ret = next(); | 526 Token ret = next(); |
527 Exp exp; | 527 Exp exp; |
528 if (peek.type != Tok.Seperator) | 528 if (peek.type != Tok.Seperator) |
529 exp = parseExpression(); | 529 exp = parseExpression(); |
530 require(Tok.Seperator); | 530 require(Tok.Seperator); |
531 return action.actOnReturnStmt(ret, exp); | 531 return action.actOnReturnStmt(ret, exp); |
532 | 532 } |
533 /* | 533 /* |
534 if (cond) | 534 if (cond) |
535 single statement | compound statement | 535 single statement | compound statement |
536 [else | 536 [else |
537 single statement | compound statement] | 537 single statement | compound statement] |
538 */ | 538 */ |
539 } | 539 else if (t.isIf) |
540 else if (t.isIf) | 540 { |
541 { | 541 Token _if = next(); |
542 Token _if = next(); | 542 |
543 | 543 require(Tok.OpenParentheses); |
544 require(Tok.OpenParentheses); | 544 Exp cond = parseExpression(); |
545 Exp cond = parseExpression(); | 545 require(Tok.CloseParentheses); |
546 require(Tok.CloseParentheses); | 546 |
547 | 547 Stmt thenB = parseSingleOrCompoundStatement(); |
548 Stmt thenB = parseSingleOrCompoundStatement(); | 548 |
549 | 549 // if there is no else part we use the if as token, to have |
550 // if there is no else part we use the if as token, to have | 550 // something than can be passed along |
551 // something than can be passed along | 551 Token _else = _if; |
552 Token _else = _if; | 552 Stmt elseB; |
553 Stmt elseB; | 553 if (peek.type == Tok.Else) |
554 if (peek.type == Tok.Else) | 554 { |
555 { | 555 _else = next(); |
556 _else = next(); | 556 elseB = parseSingleOrCompoundStatement(); |
557 elseB = parseSingleOrCompoundStatement(); | 557 } |
558 } | 558 |
559 | 559 return action.actOnIfStmt(_if, cond, thenB, _else, elseB); |
560 return action.actOnIfStmt(_if, cond, thenB, _else, elseB); | 560 |
561 | 561 } |
562 /* | 562 /* |
563 while (cond) | 563 while (cond) |
564 single statement | compound statement | 564 single statement | compound statement |
565 */ | 565 */ |
566 } | 566 else if (t.isWhile) |
567 else if (t.isWhile) | 567 { |
568 { | 568 Token _while = next(); |
569 Token _while = next(); | 569 require(Tok.OpenParentheses); |
570 require(Tok.OpenParentheses); | 570 Exp cond = parseExpression(); |
571 Exp cond = parseExpression(); | 571 require(Tok.CloseParentheses); |
572 require(Tok.CloseParentheses); | 572 Stmt bodyStmt = parseSingleOrCompoundStatement(); |
573 Stmt bodyStmt = parseSingleOrCompoundStatement(); | 573 return action.actOnWhileStmt(_while, cond, bodyStmt); |
574 return action.actOnWhileStmt(_while, cond, bodyStmt); | 574 |
575 | 575 } |
576 /* | 576 else if (t.isFor) |
577 One of four things: | 577 { |
578 A declaration of a function/variable `type id ...` | 578 Token _for = next(); |
579 A direct assignment `id = exp;` | 579 require(Tok.OpenParentheses); |
580 An indirect assignment `id.id = exp` | 580 Stmt init; |
581 Some sort of free standing expression | 581 if ( isa(Tok.Seperator)) |
582 | 582 require(Tok.Seperator); |
583 The assignments should be handled as binary expressions? | 583 else |
584 */ | 584 init = parseStatement(); |
585 } | 585 |
586 else if (t.isFor) | 586 Exp cond; |
587 { | 587 if ( !isa(Tok.Seperator)) |
588 Token _for = next(); | 588 cond = parseExpression(); |
589 require(Tok.OpenParentheses); | 589 require(Tok.Seperator); |
590 Stmt init; | 590 |
591 if ( isa(Tok.Seperator)) | 591 Exp incre; |
592 require(Tok.Seperator); | 592 if ( !isa(Tok.CloseParentheses)) |
593 else | 593 incre = parseExpression(); |
594 init = parseStatement(); | 594 require(Tok.CloseParentheses); |
595 | 595 |
596 Exp cond; | 596 Stmt bodyStmt = parseSingleOrCompoundStatement(); |
597 if ( !isa(Tok.Seperator)) | 597 return action.actOnForStmt(_for, init, cond, incre, bodyStmt); |
598 cond = parseExpression(); | 598 } |
599 require(Tok.Seperator); | 599 else if (t.isBasicType || t.isIdentifier) |
600 | 600 { |
601 Exp incre; | 601 Token iden = peek; |
602 if ( !isa(Tok.CloseParentheses)) | 602 Token n = peek(1); |
603 incre = parseExpression(); | 603 // Must be an decl, if we start with a basic type, or two |
604 require(Tok.CloseParentheses); | 604 // identifiers in a row |
605 | 605 if ( n.type == Tok.Star || n.type == Tok.OpenBracket) |
606 Stmt bodyStmt = parseSingleOrCompoundStatement(); | 606 { |
607 return action.actOnForStmt(_for, init, cond, incre, bodyStmt); | 607 int len = peekParseType; |
608 } | 608 if(peek(len).type == Tok.Identifier && len != 0) |
609 else if (t.isBasicType || t.isIdentifier) | 609 return action.actOnDeclStmt(parseVarDecl()); |
610 { | 610 |
611 Token iden = peek; | 611 Exp exp = parseExpression(); |
612 Token n = peek(1); | 612 require(Tok.Seperator); |
613 // Must be an decl, if we start with a basic type, or two | 613 return action.actOnExprStmt(exp); |
614 // identifiers in a row | 614 } |
615 if ( n.type == Tok.Star || n.type == Tok.OpenBracket) | 615 |
616 { | 616 if (n.isIdentifier()) |
617 int len = peekParseType; | 617 return action.actOnDeclStmt(parseVarDecl()); |
618 if(peek(len).type == Tok.Identifier && len != 0) | 618 |
619 return action.actOnDeclStmt(parseVarDecl()); | 619 // Expression: a.b, a = b, a(b) etc. |
620 | 620 Exp exp = parseExpression(); |
621 Exp exp = parseExpression(); | 621 require(Tok.Seperator); |
622 require(Tok.Seperator); | 622 return action.actOnExprStmt(exp); |
623 return action.actOnExprStmt(exp); | 623 } |
624 } | 624 else if (t.isSwitch) |
625 | 625 { |
626 if (n.isIdentifier()) | 626 next(); |
627 return action.actOnDeclStmt(parseVarDecl()); | 627 require(Tok.OpenParentheses); |
628 | 628 auto target = parseExpression(); |
629 // Expression: a.b, a = b, a(b) etc. | 629 auto res = action.actOnStartOfSwitchStmt(t, target); |
630 Exp exp = parseExpression(); | 630 require(Tok.CloseParentheses); |
631 require(Tok.Seperator); | 631 require(Tok.OpenBrace); |
632 return action.actOnExprStmt(exp); | 632 while (true) |
633 } | 633 { |
634 else if (t.isSwitch) | 634 Stmt[] statements; |
635 { | 635 if (isa(Tok.Default)) |
636 next(); | |
637 require(Tok.OpenParentheses); | |
638 auto target = parseExpression(); | |
639 auto res = action.actOnStartOfSwitchStmt(t, target); | |
640 require(Tok.CloseParentheses); | |
641 require(Tok.OpenBrace); | |
642 while (true) | |
643 { | 636 { |
644 Stmt[] statements; | 637 Token _default = next(); |
645 if (isa(Tok.Default)) | |
646 { | |
647 Token _default = next(); | |
648 require(Tok.Colon); | |
649 statements.length = 0; | |
650 while (peek.type != Tok.Case | |
651 && peek.type != Tok.Default | |
652 && peek.type != Tok.CloseBrace) | |
653 statements ~= parseStatement(); | |
654 action.actOnDefaultStmt(res, _default, statements); | |
655 continue; | |
656 } | |
657 | |
658 Token _case = peek; | |
659 if (_case.type != Tok.Case) | |
660 break; | |
661 next(); | |
662 | |
663 Exp[] literals; | |
664 do | |
665 { | |
666 Exp e = parseExpression(); | |
667 literals ~= e; | |
668 } | |
669 while (skip(Tok.Comma)); | |
670 require(Tok.Colon); | 638 require(Tok.Colon); |
671 | 639 statements.length = 0; |
672 while (peek.type != Tok.Case | 640 while (peek.type != Tok.Case |
673 && peek.type != Tok.Default | 641 && peek.type != Tok.Default |
674 && peek.type != Tok.CloseBrace) | 642 && peek.type != Tok.CloseBrace) |
675 statements ~= parseStatement(); | 643 statements ~= parseStatement(); |
676 | 644 action.actOnDefaultStmt(res, _default, statements); |
677 action.actOnCaseStmt(res, _case, literals, statements); | 645 continue; |
678 | |
679 if (peek.type == Tok.CloseBrace) | |
680 break; | |
681 } | 646 } |
682 require(Tok.CloseBrace); | 647 |
683 return res; | 648 Token _case = peek; |
684 } | 649 if (_case.type != Tok.Case) |
685 else | 650 break; |
686 { | 651 next(); |
687 if (t.type == Tok.Star) | 652 |
688 { | 653 Exp[] literals; |
689 auto exp = parseExpression(); | 654 do |
690 require(Tok.Seperator); | 655 { |
691 return action.actOnExprStmt(exp); | 656 Exp e = parseExpression(); |
692 } | 657 literals ~= e; |
693 messages.report(UnexpectedBeginStmt, t.location).arg(t.getType); | 658 } |
694 return null; | 659 while (skip(Tok.Comma)); |
695 } | 660 require(Tok.Colon); |
696 messages.report(UnexpectedTok, t.location); | 661 |
697 return null; | 662 while (peek.type != Tok.Case |
698 } | 663 && peek.type != Tok.Default |
699 | 664 && peek.type != Tok.CloseBrace) |
700 Decl parseVarDecl() | 665 statements ~= parseStatement(); |
701 { | 666 |
702 // manually hardcoded to only support "type id [= exp];" | 667 action.actOnCaseStmt(res, _case, literals, statements); |
703 // as that is the only thing the codegen understands | 668 |
704 Id type = parseType; | 669 if (peek.type == Tok.CloseBrace) |
705 Id id = Id(next()); | 670 break; |
706 Exp init; | 671 } |
707 if (skip(Tok.Assign)) | 672 require(Tok.CloseBrace); |
708 init = parseExpression(); | 673 return res; |
709 require(Tok.Seperator); | 674 } |
710 Attribute att; | 675 else if (t.type == Tok.Star) |
711 Decl d = action.actOnDeclarator(type, id, init, att); | 676 { |
712 return d; | 677 auto exp = parseExpression(); |
713 } | 678 require(Tok.Seperator); |
714 | 679 return action.actOnExprStmt(exp); |
715 /** | 680 } |
716 Parses a function/method given the already parsed return type and name | 681 else |
717 */ | 682 { |
718 Decl parseFunc(ref Id type, ref Id name, Attribute att) | 683 messages.report(UnexpectedBeginStmt, t.location).arg(t.getType); |
719 { | 684 return null; |
720 Decl func = action.actOnStartOfFunctionDef(type, name, att); | 685 } |
721 parseFuncArgs(func); | 686 } |
722 | 687 |
723 if(peek.type == Tok.Seperator) | 688 Decl parseVarDecl() |
724 { | 689 { |
725 next(); | 690 // manually hardcoded to only support "type id [= exp];" |
726 return func; | 691 // as that is the only thing the codegen understands |
727 } | 692 Id type = parseType; |
728 Stmt stmt = parseCompoundStatement(); | 693 Id id = Id(next()); |
729 | 694 Exp init; |
730 return action.actOnEndOfFunction(func, stmt); | 695 if (skip(Tok.Assign)) |
731 } | 696 init = parseExpression(); |
732 | 697 require(Tok.Seperator); |
733 /** | 698 Attribute att; |
734 Parse the function arguments, assumes current token is (. | 699 Decl d = action.actOnDeclarator(type, id, init, att); |
735 | 700 return d; |
736 Both the intitial paren and the ending paren is consumed. | 701 } |
737 */ | 702 |
738 void parseFuncArgs(Decl func) | 703 /** |
739 { | 704 Parses a function/method given the already parsed return type and name |
740 require(Tok.OpenParentheses); // Remove the "(" token. | 705 */ |
741 | 706 Decl parseFunc(ref Id type, ref Id name, Attribute att) |
742 while(peek.type != Tok.CloseParentheses) | 707 { |
743 { | 708 Decl func = action.actOnStartOfFunctionDef(type, name, att); |
744 auto t = parseType(); | 709 parseFuncArgs(func); |
745 Id i; | 710 |
746 if(peek.type == Tok.Identifier) | 711 if(peek.type == Tok.Seperator) |
747 i = parseIdentifier(); | 712 { |
748 action.addFuncArg(func, t, i); | 713 next(); |
749 | 714 return func; |
750 if(peek.type == Tok.Comma) | 715 } |
751 next(); | 716 Stmt stmt = parseCompoundStatement(); |
752 } | 717 |
753 | 718 return action.actOnEndOfFunction(func, stmt); |
754 require(Tok.CloseParentheses); // Remove the ")" | 719 } |
755 } | 720 |
756 | 721 /** |
757 /** | 722 Parse the function arguments, assumes current token is (. |
758 Parse either a block, or a single statement as allowed after if, while | 723 |
759 and for. | 724 Both the intitial paren and the ending paren is consumed. |
760 */ | 725 */ |
761 Stmt parseSingleOrCompoundStatement() | 726 void parseFuncArgs(Decl func) |
762 { | 727 { |
763 if (peek.type == Tok.OpenBrace) | 728 require(Tok.OpenParentheses); // Remove the "(" token. |
764 return parseCompoundStatement(); | 729 |
765 return parseStatement(); | 730 while(peek.type != Tok.CloseParentheses) |
766 } | 731 { |
767 | 732 auto t = parseType(); |
768 /** | 733 Id i; |
769 Parses a function-body or similar, expects an opening brace to be the | 734 if(peek.type == Tok.Identifier) |
770 current token. | 735 i = parseIdentifier(); |
771 | 736 action.addFuncArg(func, t, i); |
772 Will consume both the starting { and ending } | 737 |
773 */ | 738 if(peek.type == Tok.Comma) |
774 Stmt parseCompoundStatement() | 739 next(); |
775 { | 740 } |
776 Token lbrace = require(Tok.OpenBrace); | 741 |
777 SmallArray!(Stmt, 32) stmts; // Try to use the stack only | 742 require(Tok.CloseParentheses); // Remove the ")" |
778 while ( !isa(Tok.CloseBrace) && !isa(Tok.EOF) ) | 743 } |
779 stmts ~= parseStatement(); | 744 |
780 Token rbrace = require(Tok.CloseBrace); | 745 /** |
781 return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe()); | 746 Parse either a block, or a single statement as allowed after if, while |
782 } | 747 and for. |
783 | 748 */ |
784 Id parseIdentifier() | 749 Stmt parseSingleOrCompoundStatement() |
785 { | 750 { |
786 Token tok = next(); | 751 if (peek.type == Tok.OpenBrace) |
787 | 752 return parseCompoundStatement(); |
788 if (tok.type is Tok.Identifier) | 753 return parseStatement(); |
789 return Id(tok); | 754 } |
790 | 755 |
791 messages.report(UnexpectedTokSingle, tok.location) | 756 /** |
792 .arg(tok.getType) | 757 Parses a function-body or similar, expects an opening brace to be the |
793 .arg(Tok.Identifier); | 758 current token. |
794 } | 759 |
795 | 760 Will consume both the starting { and ending } |
796 ModuleName parseModuleName() | 761 */ |
797 { | 762 Stmt parseCompoundStatement() |
798 auto id = parseIdentifier(); | 763 { |
799 ModuleName mod; | 764 Token lbrace = require(Tok.OpenBrace); |
800 while (skip(Tok.Dot)) | 765 SmallArray!(Stmt, 32) stmts; // Try to use the stack only |
801 { | 766 while ( !isa(Tok.CloseBrace) && !isa(Tok.EOF) ) |
802 mod.packages ~= id; | 767 stmts ~= parseStatement(); |
803 if (peek.type != Tok.Identifier) { | 768 Token rbrace = require(Tok.CloseBrace); |
804 messages.report(ExpectedIdAfterPackage, peek.location); | 769 return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe()); |
805 goto Lerror; | 770 } |
806 } | 771 |
807 id = parseIdentifier(); | 772 Id parseIdentifier() |
808 } | 773 { |
809 mod.id = id; | 774 Token tok = next(); |
810 return mod; | 775 |
776 if (tok.type is Tok.Identifier) | |
777 return Id(tok); | |
778 | |
779 messages.report(UnexpectedTokSingle, tok.location) | |
780 .arg(tok.getType) | |
781 .arg(Tok.Identifier); | |
782 } | |
783 | |
784 ModuleName parseModuleName() | |
785 { | |
786 auto id = parseIdentifier(); | |
787 ModuleName mod; | |
788 while (skip(Tok.Dot)) | |
789 { | |
790 mod.packages ~= id; | |
791 if (peek.type != Tok.Identifier) { | |
792 messages.report(ExpectedIdAfterPackage, peek.location); | |
793 goto Lerror; | |
794 } | |
795 id = parseIdentifier(); | |
796 } | |
797 mod.id = id; | |
798 return mod; | |
811 Lerror: | 799 Lerror: |
812 while (!skip(Tok.Seperator)) | 800 while (!skip(Tok.Seperator)) |
813 next(); | 801 next(); |
814 return mod; | 802 return mod; |
815 } | 803 } |
816 | 804 |
817 | 805 |
818 /** | 806 /** |
819 Parse a type - this includes pointer and array(at some point) types. | 807 Parse a type - this includes pointer and array(at some point) types. |
820 */ | 808 */ |
821 Id parseType() | 809 Id parseType() |
822 { | 810 { |
823 Token type = next(); | 811 Token type = next(); |
824 | 812 |
825 Id currentType; | 813 Id currentType; |
826 | 814 |
827 if ( !(type.isBasicType || type.type == Tok.Identifier) ) | 815 if ( !(type.isBasicType || type.type == Tok.Identifier) ) |
828 messages.report(InvalidType, type.location); | 816 messages.report(InvalidType, type.location); |
829 | 817 |
830 currentType = Id(type); | 818 currentType = Id(type); |
831 type = peek; | 819 type = peek; |
832 | 820 |
833 while(type.type == Tok.Star || type.type == Tok.OpenBracket) | 821 while(type.type == Tok.Star || type.type == Tok.OpenBracket) |
834 { | 822 { |
835 if(type.type == Tok.Star) | 823 if(type.type == Tok.Star) |
836 { | 824 { |
837 currentType = PointerId(currentType); | 825 currentType = PointerId(currentType); |
838 next(); | 826 next(); |
839 } | 827 } |
840 else | 828 else |
841 { | 829 { |
842 next(); | 830 next(); |
843 if(peek.type == Tok.Integer) | 831 if(peek.type == Tok.Integer) |
844 currentType = StaticArrayId( | 832 currentType = StaticArrayId( |
845 currentType, | 833 currentType, |
846 action.actOnNumericConstant( | 834 action.actOnNumericConstant( |
847 require(Tok.Integer))); | 835 require(Tok.Integer))); |
848 require(Tok.CloseBracket); | 836 require(Tok.CloseBracket); |
849 | 837 |
850 } | 838 } |
851 type = peek; | 839 type = peek; |
852 } | 840 } |
853 | 841 |
854 return currentType; | 842 return currentType; |
855 } | 843 } |
856 | 844 |
857 int peekParseType() | 845 int peekParseType() |
858 { | 846 { |
859 int i; | 847 int i; |
860 Token type = peek(i); | 848 Token type = peek(i); |
861 | 849 |
862 Id currentType; | 850 Id currentType; |
863 | 851 |
864 if ( !(type.isBasicType || type.type == Tok.Identifier) ) | 852 if ( !(type.isBasicType || type.type == Tok.Identifier) ) |
865 return 0; | 853 return 0; |
866 | 854 |
867 currentType = Id(type); | 855 currentType = Id(type); |
868 type = peek(++i); | 856 type = peek(++i); |
869 | 857 |
870 while(type.type == Tok.Star || type.type == Tok.OpenBracket) | 858 while(type.type == Tok.Star || type.type == Tok.OpenBracket) |
871 { | 859 { |
872 if(type.type == Tok.Star) | 860 if(type.type == Tok.Star) |
873 { | 861 { |
874 i++; | 862 i++; |
875 } | 863 } |
876 else | 864 else |
877 { | 865 { |
878 if(peek(i++).type != Tok.OpenBracket) | 866 if(peek(i++).type != Tok.OpenBracket) |
879 return 0; | 867 return 0; |
880 if(peek(i).type == Tok.Integer) | 868 if(peek(i).type == Tok.Integer) |
881 { | 869 { |
882 i++; | 870 i++; |
883 if(peek(i++).type != Tok.CloseBracket) | 871 if(peek(i++).type != Tok.CloseBracket) |
884 return 0; | 872 return 0; |
885 } | 873 } |
886 else | 874 else |
887 if(peek(i++).type != Tok.CloseBracket) | 875 if(peek(i++).type != Tok.CloseBracket) |
888 return 0; | 876 return 0; |
889 | 877 |
890 } | 878 } |
891 type = peek(i); | 879 type = peek(i); |
892 } | 880 } |
893 | 881 |
894 return i; | 882 return i; |
895 } | 883 } |
896 | 884 |
897 private: | 885 private: |
898 // -- Expression parsing -- // | 886 // -- Expression parsing -- // |
899 Exp parsePostfixExp(Exp target) | 887 Exp parsePostfixExp(Exp target) |
900 { | 888 { |
901 switch(peek.type) | 889 switch(peek.type) |
902 { | 890 { |
903 case Tok.Dot: | 891 case Tok.Dot: |
904 switch(peek(1).type) | 892 switch(peek(1).type) |
905 { | 893 { |
906 case Tok.Identifier: | 894 case Tok.Identifier: |
907 Token op = next(); | 895 Token op = next(); |
908 Id member = Id(next()); | 896 Id member = Id(next()); |
909 Exp exp = action.actOnMemberReference(target, op.location, member); | 897 Exp exp = action.actOnMemberReference(target, op.location, member); |
910 return parsePostfixExp(exp); | 898 return parsePostfixExp(exp); |
911 default: | 899 default: |
912 Token t = peek(1); | 900 Token t = peek(1); |
913 messages.report(ExpectedIdAfterDot, t.location); | 901 messages.report(ExpectedIdAfterDot, t.location); |
914 } | 902 } |
915 case Tok.OpenBracket: | 903 case Tok.OpenBracket: |
916 Token open = next(); | 904 Token open = next(); |
917 Exp index = parseExpression(); | 905 Exp index = parseExpression(); |
918 Token close = require(Tok.CloseBracket); | 906 Token close = require(Tok.CloseBracket); |
919 return action.actOnIndexEpr(target, open, index, close); | 907 return action.actOnIndexEpr(target, open, index, close); |
920 default: | 908 default: |
921 return target; | 909 return target; |
922 } | 910 } |
923 } | 911 } |
924 | 912 |
925 Exp parseExpression(int p = 0) | 913 Exp parseExpression(int p = 0) |
926 { | 914 { |
927 auto exp = P(); | 915 auto exp = P(); |
928 Token n = peek(); | 916 Token n = peek(); |
929 BinOp* op = null; | 917 BinOp* op = null; |
930 while ((op = binary(n.type)) != null && op.prec >= p) | 918 while ((op = binary(n.type)) != null && op.prec >= p) |
931 { | 919 { |
932 next(); | 920 next(); |
933 int q = op.leftAssoc? 1 + op.prec : op.prec; | 921 int q = op.leftAssoc? 1 + op.prec : op.prec; |
934 auto exp2 = parseExpression(q); | 922 auto exp2 = parseExpression(q); |
935 exp = action.actOnBinaryOp(n.location, op.operator, exp, exp2); | 923 exp = action.actOnBinaryOp(n.location, op.operator, exp, exp2); |
936 n = peek(); | 924 n = peek(); |
937 } | 925 } |
938 | 926 |
939 return exp; | 927 return exp; |
940 } | 928 } |
941 | 929 |
942 Exp P() | 930 Exp P() |
943 { | 931 { |
944 Token n = next(); | 932 Token n = next(); |
945 if (auto op = unary(n.type)) | 933 if (auto op = unary(n.type)) |
946 return action.actOnUnaryOp(n, parseExpression(op.prec)); | 934 return action.actOnUnaryOp(n, parseExpression(op.prec)); |
947 else if (n.type == Tok.OpenParentheses) | 935 else if (n.type == Tok.OpenParentheses) |
948 { | 936 { |
949 auto e = parseExpression(0); | 937 auto e = parseExpression(0); |
950 require(Tok.CloseParentheses); | 938 require(Tok.CloseParentheses); |
951 return e; | 939 return e; |
952 } | 940 } |
953 else if (n.type == Tok.Identifier) | 941 else if (n.type == Tok.Identifier) |
954 { | 942 { |
955 Exp value = action.actOnIdentifierExp(Id(n)); | 943 Exp value = action.actOnIdentifierExp(Id(n)); |
956 Exp iden = parsePostfixExp(value); | 944 Exp iden = parsePostfixExp(value); |
957 switch(peek.type) | 945 switch(peek.type) |
958 { | 946 { |
959 case Tok.OpenParentheses: | 947 case Tok.OpenParentheses: |
960 Token lp = next(); | 948 Token lp = next(); |
961 SmallArray!(Exp, 8) args; | 949 SmallArray!(Exp, 8) args; |
962 while(peek.type != Tok.CloseParentheses) | 950 while(peek.type != Tok.CloseParentheses) |
963 { | 951 { |
964 if(peek.type == Tok.Comma) | 952 if(peek.type == Tok.Comma) |
965 next(); | 953 next(); |
966 args ~= parseExpression(); | 954 args ~= parseExpression(); |
967 } | 955 } |
968 | 956 |
969 Token rp = next(); | 957 Token rp = next(); |
970 return action.actOnCallExpr(iden, lp, args.unsafe(), rp); | 958 return action.actOnCallExpr(iden, lp, args.unsafe(), rp); |
971 | 959 |
972 default: | 960 default: |
973 return iden; | 961 return iden; |
974 } | 962 } |
975 } | 963 } |
976 else if (n.type == Tok.Cast) | 964 else if (n.type == Tok.Cast) |
977 return parseCast(n); | 965 return parseCast(n); |
978 else if (n.type == Tok.Integer) | 966 else if (n.type == Tok.Integer) |
979 return action.actOnNumericConstant(n); | 967 return action.actOnNumericConstant(n); |
980 else if (n.type == Tok.String) | 968 else if (n.type == Tok.String) |
981 return action.actOnStringExp(n); | 969 return action.actOnStringExp(n); |
982 | 970 |
983 messages.report(ExpectedExp, n.location) | 971 messages.report(ExpectedExp, n.location) |
984 .fatal(ExitLevel.Parser); | 972 .fatal(ExitLevel.Parser); |
985 return null; | 973 return null; |
986 } | 974 } |
987 | 975 |
988 Exp parseCast(ref Token _cast) | 976 Exp parseCast(ref Token _cast) |
989 { | 977 { |
990 require(Tok.OpenParentheses); | 978 require(Tok.OpenParentheses); |
991 auto n = next(); | 979 auto n = next(); |
992 if(!n.isBasicType && !n.isIdentifier) | 980 if(!n.isBasicType && !n.isIdentifier) |
993 messages.report(ExpectedCastType, n.location); | 981 messages.report(ExpectedCastType, n.location); |
994 | 982 |
995 require(Tok.CloseParentheses); | 983 require(Tok.CloseParentheses); |
996 auto exp = P(); | 984 auto exp = P(); |
997 return action.actOnCastExpr(_cast, Id(n), exp); | 985 return action.actOnCastExpr(_cast, Id(n), exp); |
998 } | 986 } |
999 | 987 |
1000 struct UnOp | 988 struct UnOp |
1001 { | 989 { |
1002 Tok tokenType; | 990 Tok tokenType; |
1003 int prec; | 991 int prec; |
1004 } | 992 } |
1005 | 993 |
1006 static const UnOp[] _unary = | 994 static const UnOp[] _unary = |
1007 [ | 995 [ |
1008 {Tok.Minus, 4}, | 996 {Tok.Minus, 4}, |
1009 {Tok.Star, 4} | 997 {Tok.Star, 4} |
1010 ]; | 998 ]; |
1011 UnOp* unary(Tok t) | 999 UnOp* unary(Tok t) |
1012 { | 1000 { |
1013 foreach (ref op; _unary) | 1001 foreach (ref op; _unary) |
1014 if (op.tokenType == t) | 1002 if (op.tokenType == t) |
1015 return &op; | 1003 return &op; |
1016 return null; | 1004 return null; |
1017 } | 1005 } |
1018 | 1006 |
1019 struct BinOp | 1007 struct BinOp |
1020 { | 1008 { |
1021 Tok tokenType; | 1009 Tok tokenType; |
1022 int prec; | 1010 int prec; |
1023 bool leftAssoc; | 1011 bool leftAssoc; |
1024 Operator operator; | 1012 Operator operator; |
1025 } | 1013 } |
1026 | 1014 |
1027 static const BinOp[] _binary = | 1015 static const BinOp[] _binary = |
1028 [ | 1016 [ |
1029 {Tok.Assign, 1, false, Operator.Assign}, | 1017 {Tok.Assign, 1, false, Operator.Assign}, |
1030 {Tok.PlusAssign, 1, false, Operator.AddAssign}, | 1018 {Tok.PlusAssign, 1, false, Operator.AddAssign}, |
1031 {Tok.MinusAssign, 1, false, Operator.SubAssign}, | 1019 {Tok.MinusAssign, 1, false, Operator.SubAssign}, |
1032 {Tok.StarAssign, 1, false, Operator.MulAssign}, | 1020 {Tok.StarAssign, 1, false, Operator.MulAssign}, |
1033 {Tok.SlashAssign, 1, false, Operator.DivAssign}, | 1021 {Tok.SlashAssign, 1, false, Operator.DivAssign}, |
1034 {Tok.PercentAssign, 1, false, Operator.ModAssign}, | 1022 {Tok.PercentAssign, 1, false, Operator.ModAssign}, |
1035 | 1023 |
1036 // =, += etc. 1 | 1024 // =, += etc. 1 |
1037 // (need special-case for the ternary operator at this level) | 1025 // (need special-case for the ternary operator at this level) |
1038 // ||, 2 | 1026 // ||, 2 |
1039 // &&, 3 | 1027 // &&, 3 |
1040 // |, 4 | 1028 // |, 4 |
1041 // &, 5 | 1029 // &, 5 |
1042 // ^, 6 | 1030 // ^, 6 |
1043 // ==, !=, is, !is, 7 | 1031 // ==, !=, is, !is, 7 |
1044 // <, <= etc, 7 | 1032 // <, <= etc, 7 |
1045 // in, 7 | 1033 // in, 7 |
1046 // <<, >>, >>>, 8 | 1034 // <<, >>, >>>, 8 |
1047 // +, -, ~, 9 | 1035 // +, -, ~, 9 |
1048 // *, /, %, 10 | 1036 // *, /, %, 10 |
1049 // unary operators here | 1037 // unary operators here |
1050 | 1038 |
1051 {Tok.Eq, 2, true, Operator.Eq}, | 1039 {Tok.Eq, 2, true, Operator.Eq}, |
1052 {Tok.Ne, 2, true, Operator.Ne}, | 1040 {Tok.Ne, 2, true, Operator.Ne}, |
1053 | 1041 |
1054 {Tok.Lt, 2, true, Operator.Lt}, | 1042 {Tok.Lt, 2, true, Operator.Lt}, |
1055 {Tok.Le, 2, true, Operator.Le}, | 1043 {Tok.Le, 2, true, Operator.Le}, |
1056 {Tok.Gt, 2, true, Operator.Gt}, | 1044 {Tok.Gt, 2, true, Operator.Gt}, |
1057 {Tok.Ge, 2, true, Operator.Ge}, | 1045 {Tok.Ge, 2, true, Operator.Ge}, |
1058 | 1046 |
1059 {Tok.Plus, 3, true, Operator.Add}, | 1047 {Tok.Plus, 3, true, Operator.Add}, |
1060 {Tok.Minus, 3, true, Operator.Sub}, | 1048 {Tok.Minus, 3, true, Operator.Sub}, |
1061 | 1049 |
1062 {Tok.Star, 5, true, Operator.Mul}, | 1050 {Tok.Star, 5, true, Operator.Mul}, |
1063 {Tok.Slash, 5, true, Operator.Div}, | 1051 {Tok.Slash, 5, true, Operator.Div}, |
1064 {Tok.Percent, 5, true, Operator.Mod}, | 1052 {Tok.Percent, 5, true, Operator.Mod}, |
1065 | 1053 |
1066 {Tok.LeftShift, 8, true, Operator.LeftShift}, | 1054 {Tok.LeftShift, 8, true, Operator.LeftShift}, |
1067 {Tok.RightShift, 8, true, Operator.RightShift}, | 1055 {Tok.RightShift, 8, true, Operator.RightShift}, |
1068 {Tok.UnsignedRightShift, 8, true, Operator.UnsignedRightShift} | 1056 {Tok.UnsignedRightShift, 8, true, Operator.UnsignedRightShift} |
1069 ]; | 1057 ]; |
1070 BinOp* binary(Tok t) | 1058 BinOp* binary(Tok t) |
1071 { | 1059 { |
1072 foreach (ref op; _binary) | 1060 foreach (ref op; _binary) |
1073 if (op.tokenType == t) | 1061 if (op.tokenType == t) |
1074 return &op; | 1062 return &op; |
1075 return null; | 1063 return null; |
1076 } | 1064 } |
1077 | 1065 |
1078 private: | 1066 private: |
1079 | 1067 |
1080 Token require(Tok t) | 1068 Token require(Tok t) |
1081 { | 1069 { |
1082 if (peek().type != t) | 1070 if (peek().type != t) |
1083 messages.report(UnexpectedTokSingle, peek.location) | 1071 messages.report(UnexpectedTokSingle, peek.location) |
1084 .arg(peek.getType) | 1072 .arg(peek.getType) |
1085 .arg(t); | 1073 .arg(t); |
1086 return next(); | 1074 return next(); |
1087 } | 1075 } |
1088 | 1076 |
1089 bool skip(Tok t) | 1077 bool skip(Tok t) |
1090 { | 1078 { |
1091 if (peek().type != t) | 1079 if (peek().type != t) |
1092 return false; | 1080 return false; |
1093 next(); | 1081 next(); |
1094 return true; | 1082 return true; |
1095 } | 1083 } |
1096 | 1084 |
1097 bool isa(Tok t) | 1085 bool isa(Tok t) |
1098 { | 1086 { |
1099 return peek.type == t; | 1087 return peek.type == t; |
1100 } | 1088 } |
1101 | 1089 |
1102 Token next() | 1090 Token next() |
1103 { | 1091 { |
1104 return lexer.next; | 1092 return lexer.next; |
1105 } | 1093 } |
1106 | 1094 |
1107 Token peek(int i = 0) | 1095 Token peek(int i = 0) |
1108 { | 1096 { |
1109 return lexer.peek(i); | 1097 return lexer.peek(i); |
1110 } | 1098 } |
1111 | 1099 |
1112 Lexer lexer; | 1100 Lexer lexer; |
1113 SourceManager sm; | 1101 SourceManager sm; |
1114 } | 1102 } |
1115 | 1103 |