Changeset 14 for trunk/dparse.d
- Timestamp:
- 01/12/05 04:48:37 (7 years ago)
- Files:
-
- trunk/dparse.d (modified) (153 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dparse.d
r13 r14 1 // d tags- D module parser1 // dparse - D module parser 2 2 // (C) Copyright 2004-2005 James Dunne 3 3 … … 6 6 // so, you may provide your modifications publicly, but you are not required to. 7 7 8 // TODO list: 9 // - correct parsing of type declarations in identifiers and functions 10 // - interface parsing 11 // - version {} blocks 12 // - correct extern (type) { } blocks, "extern (type):" and "extern (type) decl" work. 13 // - complete access modifiers on functions 8 // A minimal parser that skips over actual code. Only concerned with parsing for declarations. 14 9 15 10 module dparse; … … 20 15 21 16 import dlexer; 22 23 class Type; 24 class Expression; 25 class Declaration; 26 class Statement; 27 class Import; 28 class Initializer; 29 class FuncDeclaration; 30 class CtorDeclaration; 31 class DtorDeclaration; 32 class StaticCtorDeclaration; 33 class StaticDtorDeclaration; 34 class InvariantDeclaration; 35 class UnitTestDeclaration; 36 class NewDeclaration; 37 class DeleteDeclaration; 38 class DebugCondition; 39 class VersionCondition; 40 class Module; 41 class ModuleDeclaration; 42 class TemplateDeclaration; 43 class TemplateInstance; 44 class StaticAssert; 45 46 class EnumDeclaration; 47 class Dsymbol; 48 49 // A dynamically growing array with some stack properties: 50 class Array { 51 void*[] p; 52 int count; 53 54 this() { 55 count = 0; 56 p.length = 0; 57 } 58 59 int dim() { 60 return p.length; 61 } 62 63 void dim(int i) { 64 p.length = i; 65 } 66 67 void reserve(int i) { 68 if (p.length - count < i) 69 p.length = count + i; 70 } 71 72 void *pop() { 73 return p[--count]; 74 } 75 76 void push(void *s) { 77 reserve(1); 78 p[count++] = s; 79 } 80 81 void append(Array* a) { 82 p.length = count; 83 p ~= a; 84 count = p.length; 85 } 86 } 17 import dtypes; 18 19 const int TRUE = 1; 20 const int FALSE = 0; 87 21 88 22 class DParse : DLexer { 89 public:90 ModuleDeclaration* md;91 92 // Load up the module source code:93 this(char[] filename, char[] src) {94 // Load up the source for the lexer:95 super(filename, src);96 nextToken(); // start the scanner97 }98 99 23 private: 100 // Is this token a basic type?101 bool isType(uint value) {102 switch (value) {103 case TOKwchar: case TOKdchar:104 case TOKbit: case TOKchar:105 case TOKint8: case TOKuns8:106 case TOKint16: case TOKuns16:107 case TOKint32: case TOKuns32:108 case TOKint64: case TOKuns64:109 case TOKfloat32: case TOKfloat64: case TOKfloat80:110 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:111 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:112 case TOKvoid:113 return true;114 default:115 return false;116 }117 return false;118 }119 120 24 // Check for a certain token: 121 25 void check(uint value) { … … 131 35 } 132 36 37 uint linkage; 38 133 39 public: 40 ArrayT!(Identifier) moduleident; 41 42 // Load up the module source code: 43 this(char[] filename, char[] src) { 44 // Load up the source for the lexer: 45 super(filename, src); 46 linkage = LINKd; 47 nextToken(); // start the scanner 48 } 134 49 135 50 Array parseModule() { … … 143 58 goto Lerr; 144 59 } else { 145 Array a = null;146 Identifier *id;60 ArrayT!(Identifier) a = null; 61 Identifier id; 147 62 148 63 id = token.ident; 149 64 while (nextToken() == TOKdot) { 150 65 if (!a) 151 a = new Array ();66 a = new ArrayT!(Identifier); 152 67 a.push(id); 153 68 nextToken(); … … 159 74 } 160 75 161 m d = new ModuleDeclaration(a, id);76 moduleident = a; 162 77 163 78 if (token.value != TOKsemicolon) 164 error( "';' expected following module declaration instead of %s", token.toString());79 error(format("';' expected following module declaration instead of %s", token.toString())); 165 80 nextToken(); 166 81 } … … 181 96 } 182 97 183 Array parseDeclDefs(int once) 184 { 185 Dsymbol *s; 98 Array parseDeclDefs(int once) { 99 Dsymbol s; 186 100 Array decldefs; 187 101 Array a; … … 198 112 199 113 case TOKstruct: 114 s = parseAggregate(); 115 break; 116 200 117 case TOKunion: 118 s = parseAggregate(); 119 break; 120 201 121 case TOKclass: 122 s = parseAggregate(); 123 break; 124 202 125 case TOKinterface: 203 126 s = parseAggregate(); … … 209 132 210 133 case TOKtemplate: 211 s = cast(Dsymbol *) parseTemplateDeclaration();212 break; 213 134 s = cast(Dsymbol) parseTemplateDeclaration(); 135 break; 136 214 137 case TOKmixin: 215 138 s = parseMixin(); 216 139 break; 217 140 218 141 case TOKinstance: // Deprecated 219 if (isDeclaration( &token, 2, TOKreserved, null)) {142 if (isDeclaration(token, 2, TOKreserved, null)) { 220 143 //printf("it's a declaration\n"); 221 144 goto Ldeclaration; … … 227 150 //printf("it's an alias\n"); 228 151 ti = parseTemplateInstance(); 229 s = cast(Dsymbol *) ti;152 s = cast(Dsymbol) ti; 230 153 if (ti) { 231 154 if (token.value == TOKidentifier) { 232 s = cast(Dsymbol *)new AliasDeclaration(loc, token.ident, ti);233 155 s = new AliasDeclaration(loc, token.ident, ti); 156 234 157 nextToken(); 235 158 } … … 239 162 } 240 163 break; 241 164 242 165 case TOKwchar: case TOKdchar: 243 166 case TOKbit: case TOKchar: … … 260 183 decldefs.append(a); 261 184 continue; 262 185 263 186 case TOKthis: 264 187 s = parseCtor(); 265 188 break; 266 189 267 190 case TOKtilde: 268 191 s = parseDtor(); 269 192 break; 270 193 271 194 case TOKinvariant: 272 s = parseInvariant(); 273 break; 274 195 parseInvariant(); 196 s = null; 197 break; 198 275 199 case TOKunittest: 276 s = parseUnitTest(); 277 break; 278 200 parseUnitTest(); 201 s = null; 202 break; 203 279 204 case TOKnew: 280 205 s = parseNew(); 281 206 break; 282 207 283 208 case TOKdelete: 284 209 s = parseDelete(); 285 210 break; 286 211 287 212 case TOKeof: 288 213 case TOKrcurly: 289 214 return decldefs; 290 215 291 216 case TOKstatic: 292 217 nextToken(); … … 302 227 } 303 228 break; 304 229 305 230 case TOKconst: 306 231 stc = STCconst; … … 324 249 stc = STCdeprecated; 325 250 goto Lstc; 326 251 327 252 Lstc: 328 253 nextToken(); … … 354 279 s = new StorageClassDeclaration(stc, a); 355 280 break; 356 357 281 358 282 case TOKprivate: 359 283 prot = PROTprivate; … … 371 295 prot = PROTexport; 372 296 goto Lprot; 373 297 374 298 Lprot: 375 299 nextToken(); … … 377 301 s = new ProtDeclaration(prot, a); 378 302 break; 379 303 380 304 case TOKalign: 381 305 { 382 306 uint n; 383 307 384 308 s = null; 385 309 nextToken(); … … 395 319 check(TOKrparen); 396 320 } else 397 n = global.structalign; // default398 321 n = 4; //global.structalign; // default 322 399 323 a = parseBlock(); 400 324 s = new AlignDeclaration(n, a); 401 325 break; 402 326 } 403 327 404 328 case TOKpragma: 405 329 { 406 Identifier *ident;330 Identifier ident; 407 331 Array args = null; 408 332 409 333 nextToken(); 410 334 check(TOKlparen); … … 419 343 else 420 344 check(TOKrparen); // pragma(identifier) 421 345 422 346 if (token.value == TOKsemicolon) 423 347 a = null; 424 348 else 425 349 a = parseBlock(); 426 s = new PragmaDeclaration(ident, args, a); 350 /+s = new PragmaDeclaration(ident, args, a);+/ 351 s = null; 427 352 break; 428 353 } 429 354 430 355 case TOKextern: 431 356 { 432 357 uint link = LINKdefault; 433 358 uint linksave; 434 359 435 360 s = null; 436 361 nextToken(); … … 438 363 nextToken(); 439 364 if (token.value == TOKidentifier) { 440 Identifier *id = token.ident;365 Identifier id = token.ident; 441 366 442 367 nextToken(); … … 473 398 break; 474 399 } 475 400 476 401 case TOKdebug: 477 402 { 478 DebugCondition *condition;479 Array *aelse;480 403 DebugCondition condition; 404 Array aelse; 405 481 406 nextToken(); 482 407 if (token.value == TOKassign) { … … 496 421 break; 497 422 } 498 423 499 424 if (token.value == TOKlparen) { 500 425 nextToken(); … … 502 427 check(TOKrparen); 503 428 } else 504 condition = new DebugCondition( mod,1, null);429 condition = new DebugCondition(1, null); 505 430 a = parseBlock(); 506 431 aelse = null; … … 512 437 break; 513 438 } 514 439 515 440 case TOKversion: 516 441 { 517 VersionCondition *condition;518 Array *aelse;519 442 VersionCondition condition; 443 Array aelse; 444 520 445 nextToken(); 521 446 if (token.value == TOKassign) { … … 535 460 break; 536 461 } 537 462 538 463 if (token.value == TOKlparen) { 539 464 nextToken(); … … 553 478 break; 554 479 } 555 480 556 481 case TOKsemicolon: // empty declaration 557 482 nextToken(); 558 483 continue; 559 484 560 485 default: 561 486 error("Declaration expected, not '%s'\n", token.toString()); … … 572 497 return decldefs; 573 498 } 574 499 575 500 /******************************************** 576 501 * Parse declarations after an align, protection, or extern decl. 577 502 */ 578 579 Array * 580 parseBlock() 581 { 582 Array *a = null; 583 Dsymbol *s; 584 503 504 Array parseBlock() { 505 Array a = null; 506 Dsymbol s; 507 585 508 //printf("parseBlock()\n"); 586 509 switch (token.value) { … … 589 512 nextToken(); 590 513 break; 591 514 592 515 case TOKlcurly: 593 516 nextToken(); … … 598 521 nextToken(); 599 522 break; 600 523 601 524 case TOKcolon: 602 525 nextToken(); … … 606 529 #endif+/ 607 530 break; 608 531 609 532 default: 610 533 a = parseDeclDefs(1); … … 613 536 return a; 614 537 } 615 538 616 539 /********************************** 617 540 * Parse a static assertion. 618 541 */ 619 542 620 StaticAssert *parseStaticAssert() {543 StaticAssert parseStaticAssert() { 621 544 Loc loc = this.loc; 622 Expression *exp;623 545 Expression exp; 546 624 547 //printf("parseStaticAssert()\n"); 625 548 nextToken(); … … 635 558 */ 636 559 637 DebugCondition * 638 parseDebugCondition() 639 { 560 DebugCondition parseDebugCondition() { 640 561 uint level = 1; 641 Identifier *id = null;642 562 Identifier id = null; 563 643 564 if (token.value == TOKidentifier) 644 565 id = token.ident; … … 648 569 error("identifier or integer expected, not %s", token.toString()); 649 570 nextToken(); 650 651 return new DebugCondition( mod,level, id);652 } 653 571 572 return new DebugCondition(level, id); 573 } 574 654 575 /************************************** 655 576 * Parse a version conditional 656 577 */ 657 658 VersionCondition *parseVersionCondition() 659 { 578 579 VersionCondition parseVersionCondition() { 660 580 uint level = 1; 661 Identifier *id = null;662 581 Identifier id = null; 582 663 583 if (token.value == TOKidentifier) 664 584 id = token.ident; … … 668 588 error("identifier or integer expected, not %s", token.toString()); 669 589 nextToken(); 670 671 return new VersionCondition( mod,level, id);672 } 673 590 591 return new VersionCondition(level, id); 592 } 593 674 594 /***************************************** 675 595 * Parse a constructor definition: … … 677 597 * Current token is 'this'. 678 598 */ 679 680 CtorDeclaration *parseCtor() 681 { 682 CtorDeclaration *f; 683 Array *arguments; 599 600 CtorDeclaration parseCtor() { 601 CtorDeclaration f; 602 Array arguments; 684 603 int varargs; 685 604 Loc loc = this.loc; 686 605 687 606 nextToken(); 688 arguments = parseParameters( &varargs);607 arguments = parseParameters(varargs); 689 608 f = new CtorDeclaration(loc, 0, arguments, varargs); 690 609 parseContracts(f); 691 610 return f; 692 611 } 693 612 694 613 /***************************************** 695 614 * Parse a destructor definition: … … 697 616 * Current token is '~'. 698 617 */ 699 700 DtorDeclaration *parseDtor() 701 { 702 DtorDeclaration *f; 618 619 DtorDeclaration parseDtor() { 620 DtorDeclaration f; 703 621 Loc loc = this.loc; 704 622 705 623 nextToken(); 706 624 check(TOKthis); 707 625 check(TOKlparen); 708 626 check(TOKrparen); 709 627 710 628 f = new DtorDeclaration(loc, 0); 711 629 parseContracts(f); 712 630 return f; 713 631 } 714 632 715 633 /***************************************** 716 634 * Parse a static constructor definition: … … 718 636 * Current token is 'this'. 719 637 */ 720 721 StaticCtorDeclaration * 722 parseStaticCtor() 723 { 724 StaticCtorDeclaration *f; 638 639 StaticCtorDeclaration parseStaticCtor() { 640 StaticCtorDeclaration f; 725 641 Loc loc = this.loc; 726 642 727 643 nextToken(); 728 644 check(TOKlparen); 729 645 check(TOKrparen); 730 646 731 647 f = new StaticCtorDeclaration(loc, 0); 732 648 parseContracts(f); 733 649 return f; 734 650 } 735 651 736 652 /***************************************** 737 653 * Parse a static destructor definition: … … 739 655 * Current token is '~'. 740 656 */ 741 742 StaticDtorDeclaration * 743 parseStaticDtor() 744 { 745 StaticDtorDeclaration *f; 657 658 StaticDtorDeclaration parseStaticDtor() { 659 StaticDtorDeclaration f; 746 660 Loc loc = this.loc; 747 661 748 662 nextToken(); 749 663 check(TOKthis); 750 664 check(TOKlparen); 751 665 check(TOKrparen); 752 666 753 667 f = new StaticDtorDeclaration(loc, 0); 754 668 parseContracts(f); 755 669 return f; 756 670 } 757 671 758 672 /***************************************** 759 673 * Parse an invariant definition: … … 761 675 * Current token is 'invariant'. 762 676 */ 763 764 InvariantDeclaration * 765 parseInvariant() 766 { 767 InvariantDeclaration *f; 677 678 InvariantDeclaration parseInvariant() { 679 InvariantDeclaration f; 768 680 Loc loc = this.loc; 769 681 770 682 nextToken(); 771 683 //check(TOKlparen); // don't require () 772 684 //check(TOKrparen); 773 685 774 686 f = new InvariantDeclaration(loc, 0); 775 687 f.fbody = parseStatement(PScurly); 776 688 return f; 777 689 } 778 690 779 691 /***************************************** 780 692 * Parse a unittest definition: … … 782 694 * Current token is 'unittest'. 783 695 */ 784 785 UnitTestDeclaration * 786 parseUnitTest() 787 { 788 UnitTestDeclaration *f; 789 Statement *sbody; 696 697 UnitTestDeclaration parseUnitTest() { 698 UnitTestDeclaration f; 699 Statement sbody; 790 700 Loc loc = this.loc; 791 701 792 702 nextToken(); 793 703 794 704 sbody = parseStatement(PScurly); 795 705 796 706 f = new UnitTestDeclaration(loc, this.loc); 797 707 f.fbody = sbody; … … 805 715 */ 806 716 807 NewDeclaration * 808 parseNew() 809 { 810 NewDeclaration *f; 811 Array *arguments; 717 NewDeclaration parseNew() { 718 NewDeclaration f; 719 Array arguments; 812 720 int varargs; 813 721 Loc loc = this.loc; 814 722 815 723 nextToken(); 816 arguments = parseParameters( &varargs);724 arguments = parseParameters(varargs); 817 725 f = new NewDeclaration(loc, 0, arguments, varargs); 818 726 parseContracts(f); … … 826 734 */ 827 735 828 DeleteDeclaration * 829 parseDelete() 830 { 831 DeleteDeclaration *f; 832 Array *arguments; 736 DeleteDeclaration parseDelete() { 737 DeleteDeclaration f; 738 Array arguments; 833 739 int varargs; 834 740 Loc loc = this.loc; 835 741 836 742 nextToken(); 837 arguments = parseParameters( &varargs);743 arguments = parseParameters(varargs); 838 744 if (varargs) 839 745 error("... not allowed in delete function parameter list"); … … 842 748 return f; 843 749 } 844 750 845 751 /********************************************** 846 752 * Parse parameter list. 847 753 */ 848 849 Array * 850 parseParameters(int *pvarargs) 851 { 852 Array *arguments = new Array; 754 755 Array parseParameters(out int pvarargs) { 756 Array arguments = new Array; 853 757 int varargs = 0; 854 758 int hasdefault = 0; 855 759 856 760 check(TOKlparen); 857 761 while (1) { 858 Type *tb;859 Identifier *ai;860 Type *at;861 Argument *a;762 Type tb; 763 Identifier ai; 764 Type at; 765 Argument a; 862 766 uint inoutt; 863 Expression *ae;864 767 Expression ae; 768 865 769 ai = null; 866 770 inoutt = In; // parameter is "in" by default … … 868 772 case TOKrparen: 869 773 break; 870 774 871 775 case TOKdotdotdot: 872 776 varargs = 1; 873 777 nextToken(); 874 778 break; 875 779 876 780 case TOKin: 877 781 inoutt = In; 878 782 nextToken(); 879 783 goto L1; 880 784 881 785 case TOKout: 882 786 inoutt = Out; 883 787 nextToken(); 884 788 goto L1; 885 789 886 790 case TOKinout: 887 791 inoutt = InOut; 888 792 nextToken(); 889 793 goto L1; 890 794 891 795 default: 892 796 L1: … … 914 818 } 915 819 check(TOKrparen); 916 *pvarargs = varargs;820 pvarargs = varargs; 917 821 return arguments; 918 822 } 919 823 920 824 /************************************* 921 825 */ 922 923 EnumDeclaration * 924 parseEnum() 925 { 926 EnumDeclaration *e; 927 Identifier *id; 928 Type *t; 929 826 827 EnumDeclaration parseEnum() { 828 EnumDeclaration e; 829 Identifier id; 830 Type t; 831 930 832 //printf("parseEnum()\n"); 931 833 nextToken(); … … 935 837 } else 936 838 id = null; 937 839 938 840 if (token.value == TOKcolon) { 939 841 nextToken(); … … 941 843 } else 942 844 t = null; 943 845 944 846 e = new EnumDeclaration(id, t); 945 847 if (token.value == TOKsemicolon && id) … … 947 849 else if (token.value == TOKlcurly) { 948 850 //printf("enum definition\n"); 949 e.members = new Array ;851 e.members = new ArrayT!(EnumMember); 950 852 nextToken(); 951 853 while (token.value != TOKrcurly) { 952 854 if (token.value == TOKidentifier) { 953 EnumMember *em;954 Expression *value;955 Identifier *ident;956 855 EnumMember em; 856 Expression value; 857 Identifier ident; 858 957 859 ident = token.ident; 958 860 value = null; … … 975 877 } else 976 878 error("enum declaration is invalid"); 977 879 978 880 return e; 979 881 } 980 981 Dsymbol * 982 parseAggregate() 983 { 984 AggregateDeclaration *a = null; 882 883 Dsymbol parseAggregate() { 884 AggregateDeclaration a = null; 985 885 int anon = 0; 986 886 uint tok; 987 Identifier *id;988 Array *tpl = null;989 887 Identifier id; 888 Array tpl = null; 889 990 890 //printf("parseAggregate()\n"); 991 891 tok = token.value; … … 996 896 id = token.ident; 997 897 nextToken(); 998 898 999 899 if (token.value == TOKlparen) { // Class template declaration. 1000 900 1001 901 // Gather template parameter list 1002 902 tpl = parseTemplateParameterList(); 1003 903 } 1004 904 } 1005 905 1006 906 switch (tok) { 1007 907 case TOKclass: 1008 908 case TOKinterface: 1009 909 { 1010 Array *baseclasses = null;1011 BaseClass *b;1012 910 Array baseclasses = null; 911 BaseClass b; 912 1013 913 if (!id) 1014 914 error("anonymous classes not allowed"); 1015 915 1016 916 // Collect base class(es) 1017 917 b = null; 1018 918 if (token.value == TOKcolon) { 1019 919 uint protection = PROTpublic; 1020 920 1021 921 baseclasses = new Array; 1022 922 while (1) { … … 1051 951 error("members expected"); 1052 952 } 1053 953 1054 954 if (tok == TOKclass) 1055 955 a = new ClassDeclaration(loc, id, baseclasses); … … 1058 958 break; 1059 959 } 1060 960 1061 961 case TOKstruct: 1062 962 if (id) … … 1065 965 anon = 1; 1066 966 break; 1067 967 1068 968 case TOKunion: 1069 969 if (id) … … 1072 972 anon = 2; 1073 973 break; 1074 974 1075 975 default: 1076 976 assert(0); 1077 977 break; 1078 978 } 979 1079 980 if (a && token.value == TOKsemicolon) { 1080 981 nextToken(); … … 1082 983 //printf("aggregate definition\n"); 1083 984 nextToken(); 1084 Array *decl = parseDeclDefs(0);1085 985 Array decl = parseDeclDefs(0); 986 1086 987 if (token.value != TOKrcurly) 1087 988 error("struct member expected"); … … 1097 998 a = new StructDeclaration(loc, null); 1098 999 } 1099 1000 1100 1001 if (tpl) { 1101 Array *decldefs;1102 TemplateDeclaration *tempdecl;1103 1002 Array decldefs; 1003 TemplateDeclaration tempdecl; 1004 1104 1005 // Wrap a template around the aggregate declaration 1105 1006 decldefs = new Array; … … 1108 1009 return tempdecl; 1109 1010 } 1110 1011 1111 1012 return a; 1112 1013 } 1113 1014 1114 1015 /************************************** 1115 1016 * Parse a TemplateDeclaration. 1116 1017 */ 1117 1118 TemplateDeclaration * 1119 parseTemplateDeclaration() 1120 { 1121 TemplateDeclaration *tempdecl; 1122 Identifier *id; 1123 Array *tpl; 1124 Array *decldefs; 1018 1019 TemplateDeclaration parseTemplateDeclaration() { 1020 TemplateDeclaration tempdecl; 1021 Identifier id; 1022 Array tpl; 1023 Array decldefs; 1125 1024 Loc loc = this.loc; 1126 1025 1127 1026 nextToken(); 1128 1027 if (token.value != TOKidentifier) { … … 1135 1034 if (!tpl) 1136 1035 goto Lerr; 1137 1036 1138 1037 if (token.value != TOKlcurly) { 1139 1038 error("members of template declaration expected"); … … 1148 1047 nextToken(); 1149 1048 } 1150 1049 1151 1050 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs); 1152 1051 return tempdecl; 1153 1052 1154 1053 Lerr: 1155 1054 return null; 1156 1055 } 1157 1056 1158 1057 /****************************************** 1159 1058 * Parse template parameter list. 1160 1059 */ 1161 1162 Array * 1163 parseTemplateParameterList() 1164 { 1165 Array *tpl; 1166 1060 1061 Array parseTemplateParameterList() { 1062 Array tpl; 1063 1167 1064 if (token.value != TOKlparen) { 1168 1065 error("parenthesized TemplateParameterList expected following TemplateIdentifier"); … … 1171 1068 tpl = new Array; 1172 1069 nextToken(); 1173 1070 1174 1071 // Get TemplateParameterList 1175 1072 if (token.value != TOKrparen) { 1176 1073 while (1) { 1177 TemplateParameter *tp;1178 Identifier *tp_ident = null;1179 Type *tp_spectype = null;1180 Type *tp_valtype = null;1181 Type *tp_defaulttype = null;1182 Expression *tp_specvalue = null;1183 Expression *tp_defaultvalue = null;1184 Token *t;1185 1074 TemplateParameter tp; 1075 Identifier tp_ident; 1076 Type tp_spectype; 1077 Type tp_valtype; 1078 Type tp_defaulttype; 1079 Expression tp_specvalue; 1080 Expression tp_defaultvalue; 1081 Token t; 1082 1186 1083 // Get TemplateParameter 1187 1084 1188 1085 // First, look ahead to see if it is a TypeParameter or a ValueParameter 1189 t = peek( &token);1086 t = peek(token); 1190 1087 if (token.value == TOKalias) { // AliasParameter 1191 1088 nextToken(); … … 1250 1147 check(TOKrparen); 1251 1148 return tpl; 1252 1149 1253 1150 Lerr: 1254 1151 return null; 1255 1152 } 1256 1153 1257 1154 /************************************** 1258 1155 * Parse a TemplateInstance. 1259 1156 */ 1260 1261 TemplateInstance * 1262 parseTemplateInstance() 1263 { 1264 TemplateInstance *tempinst; 1265 Identifier *id; 1157 1158 TemplateInstance parseTemplateInstance() { 1159 TemplateInstance tempinst; 1160 Identifier id; 1266 1161 1267 1162 //printf("parseTemplateInstance()\n"); 1268 1163 nextToken(); 1269 1164 if (token.value == TOKdot) { 1270 id = Id empty;1165 id = Id.empty; 1271 1166 } else if (token.value == TOKidentifier) { 1272 1167 id = token.ident; … … 1287 1182 nextToken(); 1288 1183 } 1289 tempinst.tiargs =parseTemplateArgumentList();1290 1291 if (!global.params.useDeprecated)1292 error("instance is deprecated, use %s", tempinst.toString());1184 /+tempinst.tiargs = +/parseTemplateArgumentList(); 1185 1186 //if (!global.params.useDeprecated) 1187 // error("instance is deprecated, use %s", tempinst.toString()); 1293 1188 return tempinst; 1294 1189 1295 1190 Lerr: 1296 1191 return null; 1297 1192 } 1298 1193 1299 1194 /****************************************** 1300 1195 * Parse template mixin. … … 1304 1199 * mixin Foo!(args) identifier; 1305 1200 */ 1306 1307 Dsymbol * 1308 parseMixin() 1309 { 1310 TemplateMixin *tm; 1311 Identifier *id; 1312 TypeTypeof *tqual; 1313 Array *tiargs; 1314 Array *idents; 1315 1201 1202 TemplateMixin parseMixin() { 1203 TemplateMixin tm; 1204 Identifier id; 1205 TypeTypeof tqual; 1206 Array tiargs; 1207 ArrayT!(Identifier) idents; 1208 1316 1209 //printf("parseMixin()\n"); 1317 1210 nextToken(); 1318 1211 1319 1212 tqual = null; 1320 1213 if (token.value == TOKdot) { 1321 id = Id empty;1214 id = Id.empty; 1322 1215 } else { 1323 1216 if (token.value == TOKtypeof) { 1324 Expression *exp;1325 1217 Expression exp; 1218 1326 1219 nextToken(); 1327 1220 check(TOKlparen); … … 1337 1230 id = token.ident; 1338 1231 } 1339 1340 idents = new Array ;1232 1233 idents = new ArrayT!(Identifier); 1341 1234 while (1) { 1342 1235 nextToken(); … … 1344 1237 if (token.value == TOKnot) { 1345 1238 nextToken(); 1346 tiargs =parseTemplateArgumentList();1347 } 1348 1239 /+tiargs = +/parseTemplateArgumentList(); 1240 } 1241 1349 1242 if (token.value != TOKdot) 1350 1243 break; 1351 1244 1352 1245 if (tiargs) { 1353 TemplateInstance *tempinst = new TemplateInstance(loc, id);1246 TemplateInstance tempinst = new TemplateInstance(loc, id); 1354 1247 1355 1248 tempinst.tiargs = tiargs; 1356 id = cast(Identifier *) tempinst;1249 id = cast(Identifier) tempinst; 1357 1250 tiargs = null; 1358 1251 } 1359 1252 idents.push(id); 1360 1253 1361 1254 nextToken(); 1362 1255 if (token.value != TOKidentifier) { … … 1367 1260 } 1368 1261 idents.push(id); 1369 1262 1370 1263 if (token.value == TOKidentifier) { 1371 1264 id = token.ident; … … 1373 1266 } else 1374 1267 id = null; 1375 1268 1376 1269 tm = new TemplateMixin(loc, id, tqual, idents, tiargs); 1377 1270 if (token.value != TOKsemicolon) 1378 1271 error("';' expected after mixin"); 1379 1272 nextToken(); 1380 1273 1381 1274 return tm; 1382 1275 1383 1276 Lerr: 1384 1277 return null; 1385 1278 } 1386 1279 1387 1280 /****************************************** 1388 1281 * Parse template argument list. … … 1392 1285 * current token is one after closing ')' 1393 1286 */ 1394 1395 Array * 1396 parseTemplateArgumentList() 1397 { 1398 Array *tiargs = new Array; 1399 1287 1288 void parseTemplateArgumentList() { 1289 /+ArrayT!(Object) tiargs = new Array;+/ 1290 1400 1291 if (token.value != TOKlparen) { 1401 1292 error("!(TemplateArgumentList) expected following TemplateIdentifier"); 1402 return tiargs;1293 return/+ tiargs+/; 1403 1294 } 1404 1295 nextToken(); 1405 1296 1406 1297 // Get TemplateArgumentList 1407 1298 if (token.value != TOKrparen) { 1408 1299 while (1) { 1409 1300 // See if it is an Expression or a Type 1410 if (isDeclaration(&token, 0, TOKreserved, null)) { // Type1411 Type *ta;1412 1301 /+if (isDeclaration(&token, 0, TOKreserved, null)) { // Type 1302 Type ta; 1303 1413 1304 // Get TemplateArgument 1414 1305 ta = parseBasicType(); … … 1416 1307 tiargs.push(ta); 1417 1308 } else { // Expression 1418 Expression *ea;1419 1309 Expression ea; 1310 1420 1311 ea = parseAssignExp(); 1421 1312 tiargs.push(ea); 1422 } 1313 }+/ 1423 1314 if (token.value != TOKcomma) 1424 1315 break; … … 1427 1318 } 1428 1319 check(TOKrparen, "template argument list"); 1429 return tiargs; 1430 } 1431 1432 Import * 1433 parseImport(Array * decldefs) 1434 { 1435 Import *s; 1436 Identifier *id; 1437 Array *a; 1320 return/+ tiargs+/; 1321 } 1322 1323 Import parseImport(Array decldefs) { 1324 Import s; 1325 Identifier id; 1326 ArrayT!(Identifier) a; 1438 1327 Loc loc; 1439 1328 1440 1329 //printf("parseImport()\n"); 1441 1330 do { … … 1445 1334 break; 1446 1335 } 1447 1336 1448 1337 loc = this.loc; 1449 1338 a = null; … … 1451 1340 while (nextToken() == TOKdot) { 1452 1341 if (!a) 1453 a = new Array ;1342 a = new ArrayT!(Identifier); 1454 1343 a.push(id); 1455 1344 nextToken(); … … 1460 1349 id = token.ident; 1461 1350 } 1462 1351 1463 1352 s = new Import(loc, a, token.ident); 1464 1353 decldefs.push(s); 1465 1354 } while (token.value == TOKcomma); 1466 1355 1467 1356 if (token.value == TOKsemicolon) 1468 1357 nextToken(); … … 1471 1360 nextToken(); 1472 1361 } 1473 1362 1474 1363 return null; 1475 1364 } 1476 1477 Type *parseBasicType() 1478 { 1479 Type *t; 1480 Identifier *id; 1481 TypeQualified *tid; 1482 TemplateInstance *tempinst; 1365 1366 Type parseBasicType() { 1367 Type t; 1368 Identifier id; 1369 TypeQualified tid; 1370 TemplateInstance tempinst; 1483 1371 1484 1372 //printf("parseBasicType()\n"); … … 1509 1397 nextToken(); 1510 1398 break; 1511 1399 1512 1400 case TOKidentifier: 1513 1401 id = token.ident; … … 1516 1404 nextToken(); 1517 1405 tempinst = new TemplateInstance(loc, id); 1518 tempinst.tiargs =parseTemplateArgumentList();1406 /+tempinst.tiargs = +/parseTemplateArgumentList(); 1519 1407 tid = new TypeInstance(loc, tempinst); 1520 1408 goto Lident2; … … 1534 1422 nextToken(); 1535 1423 tempinst = new TemplateInstance(loc, id); 1536 tempinst.tiargs =parseTemplateArgumentList();1537 tid.addIdent(cast(Identifier *) tempinst);1424 /+tempinst.tiargs = +/parseTemplateArgumentList(); 1425 /+tid.addIdent(cast(Identifier) tempinst);+/ 1538 1426 } else 1539 tid.addIdent(id);1427 /+tid.addIdent(id);+/ { } 1540 1428 } 1541 1429 t = tid; 1542 1430 break; 1543 1431 1544 1432 case TOKdot: 1545 id = Id empty;1433 id = Id.empty; 1546 1434 goto Lident; 1547 1435 1548 1436 case TOKinstance: 1549 1437 { // Deprecated … … 1554 1442 break; 1555 1443 } 1556 1444 1557 1445 tid = new TypeInstance(loc, tempinst); 1558 1446 goto Lident2; 1559 1447 } 1560 1448 1561 1449 case TOKtypeof: 1562 1450 { 1563 Expression *exp;1564 1451 Expression exp; 1452 1565 1453 nextToken(); 1566 1454 check(TOKlparen); … … 1570 1458 goto Lident2; 1571 1459 } 1572 1460 1573 1461 default: 1574 1462 error("basic type expected, not %s", token.toString()); … … 1578 1466 return t; 1579 1467 } 1580 1581 Type * 1582 parseBasicType2(Type * t) 1583 { 1584 Expression *e; 1585 Type *ts; 1586 Type *ta; 1587 1468 1469 Type parseBasicType2(Type t) { 1470 Expression e; 1471 Type ts; 1472 Type ta; 1473 1588 1474 //printf("parseBasicType2()\n"); 1589 1475 while (1) { … … 1602 1488 t = new TypeDArray(t); // [] 1603 1489 nextToken(); 1604 } else if (isDeclaration( &token, 0, TOKrbracket, null)) { // It's an associative array declaration1605 Type *index;1606 1490 } else if (isDeclaration(token, 0, TOKrbracket, null)) { // It's an associative array declaration 1491 Type index; 1492 1607 1493 //printf("it's an associative array\n"); 1608 1494 index = parseBasicType(); … … 1617 1503 } 1618 1504 continue; 1619 1505 1620 1506 case TOKdelegate: 1621 1507 case TOKfunction: … … 1623 1509 // t delegate(parameter list) 1624 1510 // t function(parameter list) 1625 Array *arguments;1511 Array arguments; 1626 1512 int varargs; 1627 1513 uint save = token.value; 1628 1629 nextToken(); 1630 arguments = parseParameters( &varargs);1514 1515 nextToken(); 1516 arguments = parseParameters(varargs); 1631 1517 t = new TypeFunction(arguments, t, varargs, linkage); 1632 1518 if (save == TOKdelegate) … … 1636 1522 continue; 1637 1523 } 1638 1524 1639 1525 default: 1640 1526 ts = t; … … 1645 1531 return ts; 1646 1532 } 1647 1648 Type * 1649 parseDeclarator(Type * t, Identifier ** pident) 1650 { 1651 Expression *e; 1652 Type *ts; 1653 Type *ta; 1654 Type **pt; 1655 1533 1534 Type parseDeclarator(Type t, Identifier *pident) { 1535 Expression e; 1536 Type ts; 1537 Type ta; 1538 Type *pt; 1539 1656 1540 //printf("parseDeclarator(t = %p)\n", t); 1657 1541 while (1) { … … 1670 1554 t = new TypeDArray(t); // [] 1671 1555 nextToken(); 1672 } else if (isDeclaration( &token, 0, TOKrbracket, null)) { // It's an associative array declaration1673 Type *index;1674 1556 } else if (isDeclaration(token, 0, TOKrbracket, null)) { // It's an associative array declaration 1557 Type index; 1558 1675 1559 //printf("it's an associative array\n"); 1676 1560 index = parseBasicType(); … … 1685 1569 } 1686 1570 continue; 1687 1571 1688 1572 case TOKidentifier: 1689 1573 if (pident) … … 1694 1578 nextToken(); 1695 1579 break; 1696 1580 1697 1581 case TOKlparen: 1698 1582 nextToken(); … … 1700 1584 check(TOKrparen); 1701 1585 break; 1702 1586 1703 1587 case TOKdelegate: 1704 1588 case TOKfunction: … … 1706 1590 // t delegate(parameter list) 1707 1591 // t function(parameter list) 1708 Array *arguments;1592 Array arguments; 1709 1593 int varargs; 1710 1594 uint save = token.value; 1711 1712 nextToken(); 1713 arguments = parseParameters( &varargs);1595 1596 nextToken(); 1597 arguments = parseParameters(varargs); 1714 1598 t = new TypeFunction(arguments, t, varargs, linkage); 1715 1599 if (save == TOKdelegate) … … 1725 1609 break; 1726 1610 } 1727 1611 1728 1612 while (1) { 1729 1613 switch (token.value) { … … 1735 1619 ta = new TypeDArray(t); // [] 1736 1620 nextToken(); 1737 } else if (isDeclaration( &token, 0, TOKrbracket, null)) { // It's an associative array declaration1738 Type *index;1739 1621 } else if (isDeclaration(token, 0, TOKrbracket, null)) { // It's an associative array declaration 1622 Type index; 1623 1740 1624 //printf("it's an associative array\n"); 1741 1625 index = parseBasicType(); … … 1749 1633 check(TOKrbracket); 1750 1634 } 1751 for (pt = &ts; *pt != t; pt = &( *pt).next) {}1635 for (pt = &ts; *pt != t; pt = &((*pt).next)) {} 1752 1636 *pt = ta; 1753 1637 continue; 1754 1638 case TOKlparen: 1755 1639 { 1756 Array *arguments;1640 Array arguments; 1757 1641 int varargs; 1758 1759 arguments = parseParameters( &varargs);1642 1643 arguments = parseParameters(varargs); 1760 1644 ta = new TypeFunction(arguments, t, varargs, linkage); 1761 for (pt = &ts; *pt != t; pt = &( *pt).next) {}1645 for (pt = &ts; *pt != t; pt = &((*pt).next)) {} 1762 1646 *pt = ta; 1763 1647 continue; … … 1766 1650 break; 1767 1651 } 1768 1652 1769 1653 return ts; 1770 1654 } … … 1774 1658 */ 1775 1659 1776 Array * 1777 parseDeclaration() 1778 { 1660 Array parseDeclaration() { 1779 1661 uint storage_class; 1780 1662 uint sc; 1781 Type *ts;1782 Type *t;1783 Type *tfirst;1784 Identifier *ident;1785 Array *a;1663 Type ts; 1664 Type t; 1665 Type tfirst; 1666 Identifier ident; 1667 Array a; 1786 1668 uint tok; 1787 1669 1788 1670 //printf("parseDeclaration()\n"); 1789 1671 switch (token.value) { … … 1793 1675 nextToken(); 1794 1676 break; 1795 1677 1796 1678 default: 1797 1679 tok = TOKreserved; 1798 1680 break; 1799 1681 } 1800 1682 1801 1683 storage_class = STCundefined; 1802 1684 while (1) { … … 1829 1711 if (storage_class & sc) 1830 1712 error("redundant storage class '%s'", token.toString()); 1831 storage_class = cast(STC)(storage_class | sc);1713 storage_class = (storage_class | sc); 1832 1714 nextToken(); 1833 1715 continue; … … 1835 1717 break; 1836 1718 } 1837 1719 1838 1720 a = new Array; 1839 1721 ts = parseBasicType(); 1840 1722 ts = parseBasicType2(ts); 1841 1723 tfirst = null; 1842 1724 1843 1725 while (1) { 1844 1726 Loc loc = this.loc; 1845 1727 1846 1728 ident = null; 1847 1729 t = parseDeclarator(ts, &ident); … … 1853 1735 if (!ident) 1854 1736 error("no identifier for declarator"); 1855 1737 1856 1738 if (tok == TOKtypedef || tok == TOKalias) { 1857 Declaration *v;1858 Initializer *init;1859 1739 Declaration v; 1740 Initializer init; 1741 1860 1742 init = null; 1861 1743 if (token.value == TOKassign) { … … 1876 1758 nextToken(); 1877 1759 break; 1878 1760 1879 1761 case TOKcomma: 1880 1762 nextToken(); 1881 1763 continue; 1882 1764 1883 1765 default: 1884 1766 error("semicolon expected to close %s declaration", Token.toChars(tok)); … … 1886 1768 } 1887 1769 } else if (t.ty == Tfunction) { 1888 FuncDeclaration *f;1889 1770 FuncDeclaration f; 1771 1890 1772 f = new FuncDeclaration(loc, 0, ident, storage_class, t); 1891 1773 a.push(f); 1892 1774 parseContracts(f); 1893 1775 } else { 1894 VarDeclaration *v;1895 Initializer *init;1896 1776 VarDeclaration v; 1777 Initializer init; 1778 1897 1779 init = null; 1898 1780 if (token.value == TOKassign) { … … 1907 1789 nextToken(); 1908 1790 break; 1909 1791 1910 1792 case TOKcomma: 1911 1793 nextToken(); 1912 1794 continue; 1913 1795 1914 1796 default: 1915 1797 error("semicolon expected, not '%s'", token.toString()); … … 1921 1803 return a; 1922 1804 } 1923 1805 1924 1806 /***************************************** 1925 1807 * Parse contracts following function declaration. 1926 1808 */ 1927 1928 void 1929 parseContracts(FuncDeclaration * f) 1930 { 1931 Type *tb; 1809 1810 void parseContracts(FuncDeclaration f) { 1811 Type tb; 1932 1812 uint linksave = linkage; 1933 1813 1934 1814 // The following is irrelevant, as it is overridden by sc.linkage in 1935 1815 // TypeFunction.semantic … … 1941 1821 error("missing body { ... } after in or out"); 1942 1822 f.fbody = parseStatement(PSsemi); 1943 f.endloc = endloc;1823 /+f.endloc = endloc;+/ 1944 1824 break; 1945 1825 … … 1947 1827 nextToken(); 1948 1828 f.fbody = parseStatement(PScurly); 1949 f.endloc = endloc;1829 /+f.endloc = endloc;+/ 1950 1830 break; 1951 1831 … … 1989 1869 */ 1990 1870 1991 Initializer * 1992 parseInitializer() 1993 { 1994 StructInitializer *ist; 1995 ArrayInitializer *ia; 1996 ExpInitializer *ie; 1997 Expression *e; 1998 Identifier *id; 1999 Initializer *value; 1871 Initializer parseInitializer() { 1872 StructInitializer ist; 1873 ArrayInitializer ia; 1874 ExpInitializer ie; 1875 Expression e; 1876 Identifier id; 1877 Initializer value; 2000 1878 int comma; 2001 1879 Loc loc = this.loc; 2002 Token *t;1880 Token t; 2003 1881 2004 1882 switch (token.value) { … … 2012 1890 if (comma == 1) 2013 1891 error("comma expected separating field initializers"); 2014 t = peek( &token);1892 t = peek(token); 2015 1893 if (t.value == TOKcolon) { 2016 1894 id = token.ident; … … 2097 1975 } 2098 1976 return ia; 2099 1977 2100 1978 default: 2101 1979 e = parseAssignExp(); … … 2104 1982 } 2105 1983 } 2106 2107 1984 1985 2108 1986 /***************************************** 2109 1987 * Input: 2110 1988 * flags PSxxxx 2111 1989 */ 2112 2113 Statement *parseStatement(int flags)1990 1991 Statement parseStatement(int flags) 2114 1992 { 2115 Statement *s;2116 Token *t;1993 Statement s; 1994 Token t; 2117 1995 Loc loc = this.loc; 2118 1996 2119 1997 //printf("parseStatement()\n"); 2120 1998 … … 2125 2003 case TOKidentifier: 2126 2004 // Need to look ahead to see if it is a declaration, label, or expression 2127 t = peek( &token);2005 t = peek(token); 2128 2006 if (t.value == TOKcolon) { // It's a label 2129 Identifier *ident;2007 Identifier ident; 2130 2008 2131 2009 ident = token.ident; 2132 2010 nextToken(); 2133 2011 nextToken(); 2134 s = parseStatement(PSsemi); 2135 s = new LabelStatement(loc, ident, s); 2012 /+s = +/parseStatement(PSsemi); 2013 /+s = new LabelStatement(loc, ident, s);+/ 2014 s = null; 2136 2015 break; 2137 2016 } … … 2139 2018 case TOKdot: 2140 2019 case TOKtypeof: 2141 if (isDeclaration( &token, 2, TOKreserved, null))2020 if (isDeclaration(token, 2, TOKreserved, null)) 2142 2021 goto Ldeclaration; 2143 2022 else … … 2179 2058 Lexp: 2180 2059 { 2181 Expression *exp;2060 Expression exp; 2182 2061 2183 2062 exp = parseExpression(); 2184 2063 check(TOKsemicolon, "statement"); 2185 s = new ExpStatement(loc, exp);2064 /+s = new ExpStatement(loc, exp);+/ 2186 2065 break; 2187 2066 } … … 2193 2072 * 3) Expression 2194 2073 */ 2195 if (isDeclaration( &token, 2, TOKreserved, null)) {2074 if (isDeclaration(token, 2, TOKreserved, null)) { 2196 2075 //printf("it's a declaration\n"); 2197 2076 goto Ldeclaration; 2198 2077 } else { 2199 if (isTemplateInstance( &token, &t) && t.value == TOKidentifier) { // case 22200 TemplateInstance *ti;2201 AliasDeclaration *a;2078 if (isTemplateInstance(token, &t) && t.value == TOKidentifier) { // case 2 2079 TemplateInstance ti; 2080 AliasDeclaration a; 2202 2081 2203 2082 ti = parseTemplateInstance(); … … 2217 2096 case TOKstatic: 2218 2097 { // Look ahead to see if it's static assert() 2219 Token *t;2220 2221 t = peek( &token);2098 Token t; 2099 2100 t = peek(token); 2222 2101 if (t.value == TOKassert) { 2223 2102 nextToken(); 2224 s = new StaticAssertStatement(parseStaticAssert()); 2103 /+s = new StaticAssertStatement(parseStaticAssert());+/ 2104 s = null; 2225 2105 break; 2226 2106 } … … 2246 2126 Ldeclaration: 2247 2127 { 2248 Array *a;2128 Array a; 2249 2129 2250 2130 a = parseDeclaration(); 2251 2131 if (a.dim > 1) { 2252 Array *as = new Array;2132 ArrayT!(Statement) as = new ArrayT!(Statement)(); 2253 2133 2254 2134 as.reserve(a.dim); 2255 2135 for (int i = 0; i < a.dim; i++) { 2256 Dsymbol *d = cast(Dsymbol *) a.data[i];2136 Dsymbol d = cast(Dsymbol) a.data[i]; 2257 2137 2258 2138 s = new DeclarationStatement(loc, d); … … 2261 2141 s = new CompoundStatement(loc, as); 2262 2142 } else if (a.dim == 1) { 2263 Dsymbol *d = cast(Dsymbol *) a.data[0];2143 Dsymbol d = cast(Dsymbol) a.data[0]; 2264 2144 2265 2145 s = new DeclarationStatement(loc, d); 2266 2146 } else 2267 2147 assert(0); 2268 if (flags & PSscope)2269 s = new ScopeStatement(loc, s);2270 2148 break; 2271 2149 } … … 2276 2154 case TOKinterface: 2277 2155 { 2278 Dsymbol *d;2156 Dsymbol d; 2279 2157 2280 2158 d = parseAggregate(); … … 2285 2163 case TOKenum: 2286 2164 { 2287 Dsymbol *d;2165 Dsymbol d; 2288 2166 2289 2167 d = parseEnum(); … … 2294 2172 case TOKmixin: 2295 2173 { 2296 Dsymbol *d;2174 Dsymbol d; 2297 2175 2298 2176 d = parseMixin(); … … 2303 2181 case TOKlcurly: 2304 2182 { 2305 Array *statements; 2306 2307 nextToken(); 2308 statements = new Array; 2183 nextToken(); 2309 2184 while (token.value != TOKrcurly) { 2310 statements.push(parseStatement(PSsemi | PScurlyscope)); 2311 } 2312 endloc = this.loc; 2313 s = new CompoundStatement(loc, statements); 2314 if (flags & (PSscope | PScurlyscope)) 2315 s = new ScopeStatement(loc, s); 2185 parseStatement(PSsemi | PScurlyscope); 2186 } 2316 2187 nextToken(); 2317 2188 break; … … 2320 2191 case TOKwhile: 2321 2192 { 2322 Expression *condition;2323 Statement *sbody;2324 2325 2193 nextToken(); 2326 2194 check(TOKlparen); 2327 condition =parseExpression();2195 parseExpression(); 2328 2196 check(TOKrparen); 2329 sbody =parseStatement(PSscope);2330 s = n ew WhileStatement(loc, condition, sbody);2197 parseStatement(PSscope); 2198 s = null; 2331 2199 break; 2332 2200 } … … 2341 2209 case TOKdo: 2342 2210 { 2343 Statement *sbody; 2344 Expression *condition; 2345 2346 nextToken(); 2347 sbody = parseStatement(PSscope); 2211 nextToken(); 2212 parseStatement(PSscope); 2348 2213 check(TOKwhile); 2349 2214 check(TOKlparen); 2350 condition =parseExpression();2215 parseExpression(); 2351 2216 check(TOKrparen); 2352 s = n ew DoStatement(loc, sbody, condition);2217 s = null; 2353 2218 break; 2354 2219 } … … 2356 2221 case TOKfor: 2357 2222 { 2358 Statement *init;2359 Expression *condition;2360 Expression *increment;2361 Statement *sbody;2362 2363 2223 nextToken(); 2364 2224 check(TOKlparen); 2365 2225 if (token.value == TOKsemicolon) { 2366 init = null;2367 2226 nextToken(); 2368 2227 } else { 2369 init =parseStatement(0);2228 parseStatement(0); 2370 2229 } 2371 2230 if (token.value == TOKsemicolon) { 2372 condition = null;2373 2231 nextToken(); 2374 2232 } else { 2375 condition =parseExpression();2233 parseExpression(); 2376 2234 check(TOKsemicolon, "for condition"); 2377 2235 } 2378 2236 if (token.value == TOKrparen) { 2379 increment = null;2380 2237 nextToken(); 2381 2238 } else { 2382 increment =parseExpression();2239 parseExpression(); 2383 2240 check(TOKrparen); 2384 2241 } 2385 sbody =parseStatement(0);2386 s = n ew ForStatement(loc, init, condition, increment, sbody);2242 parseStatement(0); 2243 s = null; 2387 2244 break; 2388 2245 } … … 2390 2247 case TOKforeach: 2391 2248 { 2392 Array *arguments;2393 2394 Statement *d;2395 Statement *sbody;2396 Expression *aggr;2397 2398 2249 nextToken(); 2399 2250 check(TOKlparen); 2400 2251 2401 arguments = new Array;2402 2403 2252 while (1) { 2404 Type *tb;2405 Identifier *ai = null;2406 Type *at;2253 Type tb; 2254 Identifier ai = null; 2255 Type at; 2407 2256 uint inoutt; 2408 Argument *a;2257 Argument a; 2409 2258 2410 2259 inoutt = In; … … 2417 2266 if (!ai) 2418 2267 error("no identifier for declarator"); 2419 a = new Argument(inoutt, at, ai, null);2420 arguments.push(a);2421 2268 if (token.value == TOKcomma) { 2422 2269 nextToken(); … … 2427 2274 check(TOKsemicolon); 2428 2275 2429 aggr =parseExpression();2276 parseExpression(); 2430 2277 check(TOKrparen); 2431 sbody =parseStatement(0);2432 s = n ew ForeachStatement(loc, arguments, aggr, sbody);2278 parseStatement(0); 2279 s = null; 2433 2280 break; 2434 2281 } … … 2436 2283 case TOKif: 2437 2284 { 2438 Expression *condition;2439 Statement *ifbody;2440 Statement *elsebody;2441 2442 2285 nextToken(); 2443 2286 check(TOKlparen); 2444 condition =parseExpression();2287 parseExpression(); 2445 2288 check(TOKrparen); 2446 ifbody =parseStatement(PSscope);2289 parseStatement(PSscope); 2447 2290 if (token.value == TOKelse) { 2448 2291 nextToken(); 2449 elsebody = parseStatement(PSscope); 2450 } else 2451 elsebody = null; 2452 s = new IfStatement(loc, condition, ifbody, elsebody); 2292 parseStatement(PSscope); 2293 } 2294 s = null; 2453 2295 break; 2454 2296 } … … 2456 2298 case TOKdebug: 2457 2299 { 2458 Condition *condition;2459 Statement *ifbody;2460 Statement *elsebody;2461 2462 2300 nextToken(); 2463 2301 if (token.value == TOKlparen) { 2464 2302 nextToken(); 2465 condition =parseDebugCondition();2303 parseDebugCondition(); 2466 2304 check(TOKrparen); 2467 } else 2468 condition = new DebugCondition(mod, 1, null); 2469 ifbody = parseStatement(PSsemi); 2305 } 2306 parseStatement(PSsemi); 2470 2307 if (token.value == TOKelse) { 2471 2308 nextToken(); 2472 elsebody = parseStatement(PSsemi); 2473 } else 2474 elsebody = null; 2475 s = new ConditionalStatement(loc, condition, ifbody, elsebody); 2309 parseStatement(PSsemi); 2310 } 2311 s = null; 2476 2312 break; 2477 2313 } … … 2479 2315 case TOKversion: 2480 2316 { 2481 Condition *condition;2482 Statement *ifbody;2483 Statement *elsebody;2484 2317 /+ Condition condition; 2318 Statement ifbody; 2319 Statement elsebody; 2320 +/ 2485 2321 nextToken(); 2486 2322 if (token.value == TOKlparen) { 2487 2323 nextToken(); 2488 condition =parseVersionCondition();2324 /+condition = +/parseVersionCondition(); 2489 2325 check(TOKrparen); 2490 2326 } else { 2491 2327 error("(condition) expected after version"); 2492 condition = null;2493 } 2494 ifbody =parseStatement(PSsemi);2328 /+condition = null;+/ 2329 } 2330 /+ifbody = +/parseStatement(PSsemi); 2495 2331 if (token.value == TOKelse) { 2496 2332 nextToken(); 2497 elsebody = parseStatement(PSsemi); 2498 } else 2499 elsebody = null; 2500 s = new ConditionalStatement(loc, condition, ifbody, elsebody); 2333 /+elsebody = +/parseStatement(PSsemi); 2334 }/+ else 2335 elsebody = null;+/ 2336 /+s = new ConditionalStatement(loc, condition, ifbody, elsebody);+/ 2337 s = null; 2501 2338 break; 2502 2339 } … … 2504 2341 case TOKpragma: 2505 2342 { 2506 Identifier *ident;2507 Array *args = null;2508 Statement *sbody;2509 2510 2343 nextToken(); 2511 2344 check(TOKlparen); … … 2514 2347 goto Lerror; 2515 2348 } 2516 ident = token.ident;2517 2349 nextToken(); 2518 2350 if (token.value == TOKcomma) 2519 args =parseArguments(); // pragma(identifier, args...);2351 parseArguments(); // pragma(identifier, args...); 2520 2352 else 2521 2353 check(TOKrparen); // pragma(identifier); 2522 sbody =parseStatement(PSsemi);2523 s = n ew PragmaStatement(loc, ident, args, sbody);2354 parseStatement(PSsemi); 2355 s = null; 2524 2356 break; 2525 2357 } … … 2527 2359 case TOKswitch: 2528 2360 { 2529 Expression *condition;2530 Statement *sbody;2531 2361 2532 2362 nextToken(); 2533 2363 check(TOKlparen); 2534 condition =parseExpression();2364 parseExpression(); 2535 2365 check(TOKrparen); 2536 sbody =parseStatement(PSscope);2537 s = n ew SwitchStatement(loc, condition, sbody);2366 parseStatement(PSscope); 2367 s = null; 2538 2368 break; 2539 2369 } … … 2541 2371 case TOKcase: 2542 2372 { 2543 Expression *exp; 2544 Array *statements; 2545 Array cases; // array of Expression's 2373 Expression exp; 2374 Array statements; 2546 2375 2547 2376 while (1) { 2548 2377 nextToken(); 2549 2378 exp = parseAssignExp(); 2550 cases.push(exp);2551 2379 if (token.value != TOKcomma) 2552 2380 break; … … 2554 2382 check(TOKcolon); 2555 2383 2556 statements = new Array;2557 2384 while (token.value != TOKcase && token.value != TOKdefault && token.value != TOKrcurly) { 2558 statements.push(parseStatement(PSsemi | PScurlyscope)); 2559 } 2560 s = new CompoundStatement(loc, statements); 2561 s = new ScopeStatement(loc, s); 2562 2563 // Keep cases in order by building the case statements backwards 2564 for (int i = cases.dim; i; i--) { 2565 exp = cast(Expression *) cases.data[i - 1]; 2566 s = new CaseStatement(loc, exp, s); 2567 } 2385 parseStatement(PSsemi | PScurlyscope); 2386 } 2387 s = null; 2568 2388 break; 2569 2389 } … … 2571 2391 case TOKdefault: 2572 2392 { 2573 Array *statements;2393 Array statements; 2574 2394 2575 2395 nextToken(); 2576 2396 check(TOKcolon); 2577 2397 2578 statements = new Array;2579 2398 while (token.value != TOKcase && token.value != TOKdefault && token.value != TOKrcurly) { 2580 statements.push(parseStatement(PSsemi | PScurlyscope)); 2581 } 2582 s = new CompoundStatement(loc, statements); 2583 s = new ScopeStatement(loc, s); 2584 s = new DefaultStatement(loc, s); 2399 parseStatement(PSsemi | PScurlyscope); 2400 } 2401 s = null; 2585 2402 break; 2586 2403 } … … 2588 2405 case TOKreturn: 2589 2406 { 2590 Expression *exp;2407 Expression exp; 2591 2408 2592 2409 nextToken(); … … 2596 2413 exp = parseExpression(); 2597 2414 check(TOKsemicolon, "return statement"); 2598 s = n ew ReturnStatement(loc, exp);2415 s = null; 2599 2416 break; 2600 2417 } … … 2602 2419 case TOKbreak: 2603 2420 { 2604 Identifier *ident;2421 Identifier ident; 2605 2422 2606 2423 nextToken(); … … 2611 2428 ident = null; 2612 2429 check(TOKsemicolon, "break statement"); 2613 s = n ew BreakStatement(loc, ident);2430 s = null; 2614 2431 break; 2615 2432 } … … 2617 2434 case TOKcontinue: 2618 2435 { 2619 Identifier *ident;2436 Identifier ident; 2620 2437 2621 2438 nextToken(); … … 2626 2443 ident = null; 2627 2444 check(TOKsemicolon, "continue statement"); 2628 s = n ew ContinueStatement(loc, ident);2445 s = null; 2629 2446 break; 2630 2447 } … … 2632 2449 case TOKgoto: 2633 2450 { 2634 Identifier *ident;2451 Identifier ident; 2635 2452 2636 2453 nextToken(); 2637 2454 if (token.value == TOKdefault) { 2638 2455 nextToken(); 2639 s = n ew GotoDefaultStatement(loc);2456 s = null; 2640 2457 } else if (token.value == TOKcase) { 2641 2458 Expression *exp = null; … … 2643 2460 nextToken(); 2644 2461 if (token.value != TOKsemicolon) 2645 exp =parseExpression();2646 s = n ew GotoCaseStatement(loc, exp);2462 parseExpression(); 2463 s = null; 2647 2464 } else { 2648 2465 if (token.value != TOKidentifier) { 2649 2466 error("Identifier expected following goto"); 2650 ident = null;2651 2467 } else { 2652 ident = token.ident;2653 2468 nextToken(); 2654 2469 } 2655 s = n ew GotoStatement(loc, ident);2470 s = null; 2656 2471 } 2657 2472 check(TOKsemicolon, "goto statement"); … … 2661 2476 case TOKsynchronized: 2662 2477 { 2663 Expression *exp;2664 Statement *sbody;2478 Expression exp; 2479 Statement sbody; 2665 2480 2666 2481 nextToken(); 2667 2482 if (token.value == TOKlparen) { 2668 2483 nextToken(); 2669 exp =parseExpression();2484 parseExpression(); 2670 2485 check(TOKrparen); 2671 2486 } else 2672 2487 exp = null; 2673 sbody =parseStatement(PSscope);2674 s = n ew SynchronizedStatement(loc, exp, sbody);2488 parseStatement(PSscope); 2489 s = null; 2675 2490 break; 2676 2491 } … … 2678 2493 case TOKwith: 2679 2494 { 2680 Expression *exp;2681 Statement *sbody;2682 2683 2495 nextToken(); 2684 2496 check(TOKlparen); 2685 exp =parseExpression();2497 parseExpression(); 2686 2498 check(TOKrparen); 2687 sbody =parseStatement(PSscope);2688 s = n ew WithStatement(loc, exp, sbody);2499 parseStatement(PSscope); 2500 s = null; 2689 2501 break; 2690 2502 } … … 2692 2504 case TOKtry: 2693 2505 { 2694 Statement *sbody; 2695 Array *catches = null; 2696 Statement *finalbody = null; 2697 2698 nextToken(); 2699 sbody = parseStatement(PSscope); 2506 2507 nextToken(); 2508 parseStatement(PSscope); 2700 2509 while (token.value == TOKcatch) { 2701 Statement *handler; 2702 Catch *c; 2703 Type *t; 2704 Identifier *id; 2510 Statement handler; 2511 Type t; 2512 Identifier id; 2705 2513 2706 2514 nextToken(); … … 2715 2523 check(TOKrparen); 2716 2524 } 2717 handler = parseStatement(0); 2718 c = new Catch(loc, t, id, handler); 2719 if (!catches) 2720 catches = new Array; 2721 catches.push(c); 2525 parseStatement(0); 2722 2526 } 2723 2527 2724 2528 if (token.value == TOKfinally) { 2725 2529 nextToken(); 2726 finalbody = parseStatement(0); 2727 } 2728 2729 s = sbody; 2730 if (!catches && !finalbody) 2731 error("catch or finally expected following try"); 2732 else { 2733 if (catches) 2734 s = new TryCatchStatement(loc, sbody, catches); 2735 if (finalbody) 2736 s = new TryFinallyStatement(loc, s, finalbody); 2530 parseStatement(0); 2737 2531 } 2738 2532 break; … … 2741 2535 case TOKthrow: 2742 2536 { 2743 Expression *exp; 2744 2745 nextToken(); 2746 exp = parseExpression(); 2537 nextToken(); 2538 parseExpression(); 2747 2539 check(TOKsemicolon, "throw statement"); 2748 s = n ew ThrowStatement(loc, exp);2540 s = null; 2749 2541 break; 2750 2542 } … … 2752 2544 case TOKvolatile: 2753 2545 nextToken(); 2754 s =parseStatement(PSsemi | PSscope);2755 s = n ew VolatileStatement(loc, s);2546 parseStatement(PSsemi | PSscope); 2547 s = null; 2756 2548 break; 2757 2549 2758 2550 case TOKasm: 2759 2551 { 2760 Array *statements;2761 Identifier *label;2762 Loc labelloc;2763 Token *toklist;2764 Token **ptoklist;2765 2766 2552 // Parse the asm block into a sequence of AsmStatements, 2767 2553 // each AsmStatement is one instruction. … … 2771 2557 nextToken(); 2772 2558 check(TOKlcurly); 2773 toklist = null;2774 ptoklist = &toklist;2775 label = null;2776 statements = new Array;2777 2559 while (1) { 2778 2560 switch (token.value) { 2779 2561 case TOKidentifier: 2780 if (!toklist) { 2781 // Look ahead to see if it is a label 2782 t = peek(&token); 2783 if (t.value == TOKcolon) { // It's a label 2784 label = token.ident; 2785 labelloc = this.loc; 2786 nextToken(); 2787 nextToken(); 2788 continue; 2789 } 2562 // Look ahead to see if it is a label 2563 t = peek(token); 2564 if (t.value == TOKcolon) { // It's a label 2565 nextToken(); 2566 nextToken(); 2567 continue; 2790 2568 } 2791 2569 goto Ldefault; 2792 2570 2793 2571 case TOKrcurly: 2794 if (toklist || label) {2795 error("asm statements must end in ';'");2796 }2797 2572 break; 2798 2573 2799 2574 case TOKsemicolon: 2800 2575 s = null; 2801 if (toklist || label) { // Create AsmStatement from list of tokens we've saved2802 s = new AsmStatement(this.loc, toklist);2803 toklist = null;2804 ptoklist = &toklist;2805 if (label) {2806 s = new LabelStatement(labelloc, label, s);2807 label = null;2808 }2809 statements.push(s);2810 }2811 2576 nextToken(); 2812 2577 continue; … … 2818 2583 default: 2819 2584 Ldefault: 2820 *ptoklist = new Token();2821 memcpy(*ptoklist, &token, sizeof(Token));2822 ptoklist = &(*ptoklist).next;2823 *ptoklist = null;2824 2825 2585 nextToken(); 2826 2586 continue; … … 2828 2588 break; 2829 2589 } 2830 s = n ew CompoundStatement(loc, statements);2590 s = null; 2831 2591 nextToken(); 2832 2592 break; … … 2846 2606 } 2847 2607 2608 /************************************ 2609 * Determine if the scanner is sitting on the start of a declaration. 2610 * Input: 2611 * needId 0 no identifier 2612 * 1 identifier optional 2613 * 2 must have identifier 2614 */ 2615 2616 bool isDeclaration(Token t, int needId, uint endtok, Token *pt) { 2617 bool haveId = 0; 2618 2619 if (!isBasicType(&t)) 2620 return false; 2621 if (!isDeclarator(&t, haveId, endtok)) 2622 return false; 2623 if ( needId == 1 || 2624 (needId == 0 && !haveId) || 2625 (needId == 2 && haveId)) 2626 { if (pt) 2627 *pt = t; 2628 return true; 2629 } 2630 else 2631 return false; 2632 } 2633 2634 int isBasicType(Token *pt) 2635 { 2636 // This code parallels parseBasicType() 2637 Token t = *pt; 2638 Token t2; 2639 int parens; 2640 2641 switch (t.value) { 2642 case TOKwchar: case TOKdchar: 2643 case TOKbit: case TOKchar: 2644 case TOKint8: case TOKuns8: 2645 case TOKint16: case TOKuns16: 2646 case TOKint32: case TOKuns32: 2647 case TOKint64: case TOKuns64: 2648 case TOKfloat32: case TOKfloat64: case TOKfloat80: 2649 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 2650 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 2651 case TOKvoid: 2652 t = peek(t); 2653 break; 2654 2655 case TOKidentifier: 2656 t = peek(t); 2657 if (t.value == TOKnot) 2658 { 2659 goto L4; 2660 } 2661 goto L3; 2662 while (1) 2663 { 2664 L2: 2665 t = peek(t); 2666 L3: 2667 if (t.value == TOKdot) 2668 { 2669 Ldot: 2670 t = peek(t); 2671 if (t.value != TOKidentifier) 2672 goto Lfalse; 2673 t = peek(t); 2674 if (t.value != TOKnot) 2675 goto L3; 2676 L4: 2677 t = peek(t); 2678 if (t.value != TOKlparen) 2679 goto Lfalse; 2680 if (!skipParens(t, &t)) 2681 goto Lfalse; 2682 } 2683 else 2684 break; 2685 } 2686 break; 2687 2688 case TOKdot: 2689 goto Ldot; 2690 2691 case TOKinstance: // Deprecated 2692 // Handle cases like: 2693 // instance Foo(int).bar x; 2694 // But remember that: 2695 // instance Foo(int) x; 2696 // is not a type, but is an AliasDeclaration declaration. 2697 if (!isTemplateInstance(t, &t)) 2698 goto Lfalse; // invalid syntax for template instance 2699 if (t.value == TOKdot) 2700 goto Ldot; 2701 goto Lfalse; 2702 2703 case TOKtypeof: 2704 /* typeof(exp).identifier... 2705 */ 2706 t = peek(t); 2707 if (t.value != TOKlparen) 2708 goto Lfalse; 2709 if (!skipParens(t, &t)) 2710 goto Lfalse; 2711 goto L2; 2712 2713 default: 2714 goto Lfalse; 2715 } 2716 *pt = t; 2717 return TRUE; 2718 2719 Lfalse: 2720 return FALSE; 2721 } 2722 2723 int isDeclarator(Token *pt, out bool haveId, uint endtok) 2724 { // This code parallels parseDeclarator() 2725 Token t = *pt; 2726 int parens; 2727 2728 if (t.value == TOKassign) 2729 return FALSE; 2730 2731 while (1) { 2732 parens = FALSE; 2733 switch (t.value) 2734 { 2735 case TOKmul: 2736 case TOKand: 2737 t = peek(t); 2738 continue; 2739 2740 case TOKlbracket: 2741 t = peek(t); 2742 if (t.value == TOKrbracket) 2743 { 2744 t = peek(t); 2745 } 2746 else if (isDeclaration(t, 0, TOKrbracket, &t)) 2747 { // It's an associative array declaration 2748 t = peek(t); 2749 } 2750 else 2751 { 2752 // [ expression ] 2753 if (!isExpression(&t)) 2754 return FALSE; 2755 if (t.value != TOKrbracket) 2756 return FALSE; 2757 t = peek(t); 2758 } 2759 continue; 2760 2761 case TOKidentifier: 2762 haveId = true; 2763 t = peek(t); 2764 break; 2765 2766 case TOKlparen: 2767 t = peek(t); 2768 2769 if (t.value == TOKrparen) 2770 return FALSE; // () is not a declarator 2771 2772 /* Regard ( identifier ) as not a declarator 2773 * BUG: what about ( *identifier ) in 2774 * f(*p)(x); 2775 * where f is a class instance with overloaded () ? 2776 * Should we just disallow C-style function pointer declarations? 2777 */ 2778 if (t.value == TOKidentifier) 2779 { Token t2 = peek(t); 2780 if (t2.value == TOKrparen) 2781 return FALSE; 2782 } 2783 2784 2785 if (!isDeclarator(&t, haveId, TOKrparen)) 2786 return FALSE; 2787 t = peek(t); 2788 parens = TRUE; 2789 break; 2790 2791 case TOKdelegate: 2792 case TOKfunction: 2793 t = peek(t); 2794 if (!isParameters(&t)) 2795 return FALSE; 2796 continue; 2797 } 2798 break; 2799 } 2800 2801 while (1) { 2802 switch (t.value) 2803 { 2804 // #if CARRAYDECL 2805 case TOKlbracket: 2806 parens = FALSE; 2807 t = peek(t); 2808 if (t.value == TOKrbracket) 2809 { 2810 t = peek(t); 2811 } 2812 else if (isDeclaration(t, 0, TOKrbracket, &t)) 2813 { // It's an associative array declaration 2814 t = peek(t); 2815 } 2816 else 2817 { 2818 // [ expression ] 2819 if (!isExpression(&t)) 2820 return FALSE; 2821 if (t.value != TOKrbracket) 2822 return FALSE; 2823 t = peek(t); 2824 } 2825 continue; 2826 // #endif 2827 2828 case TOKlparen: 2829 parens = FALSE; 2830 if (!isParameters(&t)) 2831 return FALSE; 2832 continue; 2833 2834 // Valid tokens that follow a declaration 2835 case TOKrparen: 2836 case TOKrbracket: 2837 case TOKassign: 2838 case TOKcomma: 2839 case TOKsemicolon: 2840 case TOKlcurly: 2841 // The !parens is to disallow unnecessary parentheses 2842 if (!parens && (endtok == TOKreserved || endtok == t.value)) 2843 { *pt = t; 2844 return TRUE; 2845 } 2846 return FALSE; 2847 2848 default: 2849 return FALSE; 2850 } 2851 } 2852 } 2853 2854 2855 int isParameters(Token *pt) 2856 { // This code parallels parseParameters() 2857 Token t = *pt; 2858 bool tmp; 2859 2860 if (t.value != TOKlparen) 2861 return FALSE; 2862 t = peek(t); 2863 while (1) 2864 { 2865 switch (t.value) 2866 { 2867 case TOKrparen: 2868 break; 2869 2870 case TOKdotdotdot: 2871 t = peek(t); 2872 break; 2873 2874 case TOKin: 2875 case TOKout: 2876 case TOKinout: 2877 t = peek(t); 2878 default: 2879 if (!isBasicType(&t)) 2880 return FALSE; 2881 tmp = FALSE; 2882 if (!isDeclarator(&t, tmp, TOKreserved)) 2883 return FALSE; 2884 if (t.value == TOKcomma) 2885 { t = peek(t); 2886 continue; 2887 } 2888 break; 2889 } 2890 break; 2891 } 2892 if (t.value != TOKrparen) 2893 return FALSE; 2894 t = peek(t); 2895 *pt = t; 2896 return TRUE; 2897 } 2898 2899 int isExpression(Token *pt) 2900 { 2901 // This is supposed to determine if something is an expression. 2902 // What it actually does is scan until a closing right bracket 2903 // is found. 2904 2905 Token t = *pt; 2906 int nest = 0; 2907 2908 for (;; t = peek(t)) 2909 { 2910 switch (t.value) 2911 { 2912 case TOKlbracket: 2913 nest++; 2914 continue; 2915 2916 case TOKrbracket: 2917 if (--nest >= 0) 2918 continue; 2919 break; 2920 2921 case TOKeof: 2922 return FALSE; 2923 2924 default: 2925 continue; 2926 } 2927 break; 2928 } 2929 2930 *pt = t; 2931 return TRUE; 2932 } 2933 2934 /********************************************** 2935 * Skip over 2936 * instance foo.bar(parameters...) 2937 * Output: 2938 * if (pt), *pt is set to the token following the closing ) 2939 * Returns: 2940 * 1 it's valid instance syntax 2941 * 0 invalid instance syntax 2942 */ 2943 2944 int isTemplateInstance(Token t, Token *pt) 2945 { 2946 t = peek(t); 2947 if (t.value != TOKdot) 2948 { 2949 if (t.value != TOKidentifier) 2950 goto Lfalse; 2951 t = peek(t); 2952 } 2953 while (t.value == TOKdot) 2954 { 2955 t = peek(t); 2956 if (t.value != TOKidentifier) 2957 goto Lfalse; 2958 t = peek(t); 2959 } 2960 if (t.value != TOKlparen) 2961 goto Lfalse; 2962 2963 // Skip over the template arguments 2964 while (1) 2965 { 2966 while (1) 2967 { 2968 t = peek(t); 2969 switch (t.value) 2970 { 2971 case TOKlparen: 2972 if (!skipParens(t, &t)) 2973 goto Lfalse; 2974 continue; 2975 case TOKrparen: 2976 break; 2977 case TOKcomma: 2978 break; 2979 case TOKeof: 2980 case TOKsemicolon: 2981 goto Lfalse; 2982 default: 2983 continue; 2984 } 2985 break; 2986 } 2987 2988 if (t.value != TOKcomma) 2989 break; 2990 } 2991 if (t.value != TOKrparen) 2992 goto Lfalse; 2993 t = peek(t); 2994 if (pt) 2995 *pt = t; 2996 return 1; 2997 2998 Lfalse: 2999 return 0; 3000 } 3001 3002 /******************************************* 3003 * Skip parens, brackets. 3004 * Input: 3005 * t is on opening ( 3006 * Output: 3007 * *pt is set to closing token, which is ')' on success 3008 * Returns: 3009 * !=0 successful 3010 * 0 some parsing error 3011 */ 3012 3013 int skipParens(Token t, Token *pt) 3014 { 3015 int parens = 0; 3016 3017 while (1) 3018 { 3019 switch (t.value) 3020 { 3021 case TOKlparen: 3022 parens++; 3023 break; 3024 3025 case TOKrparen: 3026 parens--; 3027 if (parens < 0) 3028 goto Lfalse; 3029 if (parens == 0) 3030 goto Ldone; 3031 break; 3032 3033 case TOKeof: 3034 case TOKsemicolon: 3035 goto Lfalse; 3036 3037 default: 3038 break; 3039 } 3040 t = peek(t); 3041 } 3042 3043 Ldone: 3044 if (*pt) 3045 *pt = t; 3046 return 1; 3047 3048 Lfalse: 3049 return 0; 3050 } 3051 3052 /********************************* Expression Parser ***************************/ 3053 3054 Expression parsePrimaryExp() { 3055 Expression e; 3056 Type t; 3057 Identifier id; 3058 Loc loc = this.loc; 3059 3060 switch (token.value) { 3061 case TOKidentifier: 3062 id = token.ident; 3063 nextToken(); 3064 if (token.value == TOKnot) { 3065 // identifier!(template-argument-list) 3066 TemplateInstance tempinst; 3067 3068 tempinst = new TemplateInstance(loc, id); 3069 nextToken(); 3070 tempinst.tiargs = parseTemplateArgumentList(); 3071 e = new ScopeExp(loc, tempinst); 3072 } else 3073 e = new IdentifierExp(loc, id); 3074 break; 3075 3076 case TOKdot: 3077 // Signal global scope '.' operator with "" identifier 3078 e = new IdentifierExp(loc, Id.empty); 3079 break; 3080 3081 case TOKthis: 3082 e = new ThisExp(loc); 3083 nextToken(); 3084 break; 3085 3086 case TOKsuper: 3087 e = new SuperExp(loc); 3088 nextToken(); 3089 break; 3090 3091 case TOKint32v: 3092 e = new IntegerExp(loc, token.int32value, Type.tint32); 3093 nextToken(); 3094 break; 3095 3096 case TOKuns32v: 3097 e = new IntegerExp(loc, token.uns32value, Type.tuns32); 3098 nextToken(); 3099 break; 3100 3101 case TOKint64v: 3102 e = new IntegerExp(loc, token.int64value, Type.tint64); 3103 nextToken(); 3104 break; 3105 3106 case TOKuns64v: 3107 e = new IntegerExp(loc, token.uns64value, Type.tuns64); 3108 nextToken(); 3109 break; 3110 3111 case TOKfloat32v: 3112 e = new RealExp(loc, token.float80value, Type.tfloat32); 3113 nextToken(); 3114 break; 3115 3116 case TOKfloat64v: 3117 e = new RealExp(loc, token.float80value, Type.tfloat64); 3118 nextToken(); 3119 break; 3120 3121 case TOKfloat80v: 3122 e = new RealExp(loc, token.float80value, Type.tfloat80); 3123 nextToken(); 3124 break; 3125 3126 case TOKimaginary32v: 3127 e = new ImaginaryExp(loc, token.float80value, Type.timaginary32); 3128 nextToken(); 3129 break; 3130 3131 case TOKimaginary64v: 3132 e = new ImaginaryExp(loc, token.float80value, Type.timaginary64); 3133 nextToken(); 3134 break; 3135 3136 case TOKimaginary80v: 3137 e = new ImaginaryExp(loc, token.float80value, Type.timaginary80); 3138 nextToken(); 3139 break; 3140 3141 case TOKnull: 3142 e = new NullExp(loc); 3143 nextToken(); 3144 break; 3145 3146 case TOKtrue: 3147 e = new IntegerExp(loc, 1, Type.tbit); 3148 nextToken(); 3149 break; 3150 3151 case TOKfalse: 3152 e = new IntegerExp(loc, 0, Type.tbit); 3153 nextToken(); 3154 break; 3155 3156 case TOKcharv: 3157 e = new IntegerExp(loc, token.uns32value, Type.tchar); 3158 nextToken(); 3159 break; 3160 3161 case TOKwcharv: 3162 e = new IntegerExp(loc, token.uns32value, Type.twchar); 3163 nextToken(); 3164 break; 3165 3166 case TOKdcharv: 3167 e = new IntegerExp(loc, token.uns32value, Type.tdchar); 3168 nextToken(); 3169 break; 3170 3171 case TOKstring: 3172 { char[] s; 3173 3174 // cat adjacent strings 3175 s = token.ustring; 3176 while (1) { 3177 nextToken(); 3178 if (token.value == TOKstring) { 3179 s ~= token.ustring; 3180 } else 3181 break; 3182 } 3183 e = new StringExp(loc, s, len); 3184 break; 3185 } 3186 3187 case TOKvoid: t = Type.tvoid; goto LabelX; 3188 case TOKint8: t = Type.tint8; goto LabelX; 3189 case TOKuns8: t = Type.tuns8; goto LabelX; 3190 case TOKint16: t = Type.tint16; goto LabelX; 3191 case TOKuns16: t = Type.tuns16; goto LabelX; 3192 case TOKint32: t = Type.tint32; goto LabelX; 3193 case TOKuns32: t = Type.tuns32; goto LabelX; 3194 case TOKint64: t = Type.tint64; goto LabelX; 3195 case TOKuns64: t = Type.tuns64; goto LabelX; 3196 case TOKfloat32: t = Type.tfloat32; goto LabelX; 3197 case TOKfloat64: t = Type.tfloat64; goto LabelX; 3198 case TOKfloat80: t = Type.tfloat80; goto LabelX; 3199 case TOKimaginary32: t = Type.timaginary32; goto LabelX; 3200 case TOKimaginary64: t = Type.timaginary64; goto LabelX; 3201 case TOKimaginary80: t = Type.timaginary80; goto LabelX; 3202 case TOKcomplex32: t = Type.tcomplex32; goto LabelX; 3203 case TOKcomplex64: t = Type.tcomplex64; goto LabelX; 3204 case TOKcomplex80: t = Type.tcomplex80; goto LabelX; 3205 case TOKbit: t = Type.tbit; goto LabelX; 3206 case TOKchar: t = Type.tchar; goto LabelX; 3207 case TOKwchar: t = Type.twchar; goto LabelX; 3208 case TOKdchar: t = Type.tdchar; goto LabelX; 3209 LabelX: 3210 nextToken(); 3211 L1: 3212 check(TOKdot, t.toString()); 3213 if (token.value != TOKidentifier) 3214 { error("found '%s' when expecting identifier following '%s.'", token.toString(), t.toString()); 3215 goto Lerr; 3216 } 3217 e = new TypeDotIdExp(loc, t, token.ident); 3218 nextToken(); 3219 break; 3220 3221 case TOKtypeof: 3222 { Expression exp; 3223 3224 nextToken(); 3225 check(TOKlparen); 3226 exp = parseExpression(); 3227 check(TOKrparen); 3228 t = new TypeTypeof(loc, exp); 3229 goto L1; 3230 } 3231 3232 case TOKtypeid: 3233 { Type t; 3234 3235 nextToken(); 3236 check(TOKlparen, "typeid"); 3237 t = parseBasicType(); 3238 t = parseDeclarator(t,NULL); // ( type ) 3239 check(TOKrparen); 3240 e = new TypeidExp(loc, t); 3241 break; 3242 } 3243 3244 case TOKassert: 3245 nextToken(); 3246 check(TOKlparen, "assert"); 3247 e = parseAssignExp(); 3248 check(TOKrparen); 3249 e = new AssertExp(loc, e); 3250 break; 3251 3252 case TOKinstance: // Deprecated 3253 { TemplateInstance tempinst; 3254 3255 tempinst = parseTemplateInstance(); 3256 if (!tempinst) 3257 return NULL; 3258 e = new ScopeExp(loc, tempinst); 3259 break; 3260 } 3261 3262 case TOKfunction: 3263 case TOKdelegate: 3264 { 3265 /* function type(parameters) { body } 3266 * delegate type(parameters) { body } 3267 */ 3268 Array arguments; 3269 int varargs; 3270 FuncLiteralDeclaration fd; 3271 Type t; 3272 uint save = token.value; 3273 3274 nextToken(); 3275 if (token.value == TOKlcurly) 3276 { // default to void() 3277 t = Type.tvoid; 3278 varargs = 0; 3279 arguments = new Array(); 3280 } else { 3281 if (token.value == TOKlparen) 3282 t = Type.tvoid; // default to void return type 3283 else { 3284 t = parseBasicType(); 3285 t = parseBasicType2(t); // function return type 3286 } 3287 arguments = parseParameters(&varargs); 3288 } 3289 t = new TypeFunction(arguments, t, varargs, linkage); 3290 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL); 3291 parseContracts(fd); 3292 e = new FuncExp(loc, fd); 3293 break; 3294 } 3295 3296 default: 3297 error("expression expected, not '%s'", token.toString()); 3298 Lerr: 3299 // Anything for e, as long as it's not NULL 3300 e = new IntegerExp(loc, 0, Type.tint32); 3301 nextToken(); 3302 break; 3303 } 3304 return parsePostExp(e); 3305 } 3306 3307 Expression parsePostExp(Expression e) 3308 { 3309 Loc loc; 3310 3311 while (1) { 3312 loc = this.loc; 3313 switch (token.value) { 3314 case TOKdot: 3315 nextToken(); 3316 if (token.value == TOKidentifier) 3317 { Identifier id = token.ident; 3318 3319 nextToken(); 3320 if (token.value == TOKnot) 3321 { // identifier!(template-argument-list) 3322 TemplateInstance tempinst; 3323 3324 tempinst = new TemplateInstance(loc, id); 3325 nextToken(); 3326 tempinst.tiargs = parseTemplateArgumentList(); 3327 e = new DotTemplateInstanceExp(loc, e, tempinst); 3328 } 3329 else 3330 e = new DotIdExp(loc, e, id); 3331 continue; 3332 } 3333 else 3334 error("identifier expected following '.', not '%s'", token.toString()); 3335 break; 3336 3337 case TOKplusplus: 3338 e = new PostIncExp(loc, e); 3339 break; 3340 3341 case TOKminusminus: 3342 e = new PostDecExp(loc, e); 3343 break; 3344 3345 case TOKlparen: 3346 e = new CallExp(loc, e, parseArguments()); 3347 continue; 3348 3349 case TOKlbracket: 3350 { // array dereferences: 3351 // array[index] 3352 // array[] 3353 // array[lwr .. upr] 3354 Expression index; 3355 Expression upr; 3356 3357 nextToken(); 3358 if (token.value == TOKrbracket) 3359 { // array[] 3360 e = new SliceExp(loc, e, NULL, NULL); 3361 nextToken(); 3362 } 3363 else 3364 { 3365 index = parseAssignExp(); 3366 if (token.value == TOKslice) 3367 { // array[lwr .. upr] 3368 nextToken(); 3369 upr = parseAssignExp(); 3370 e = new SliceExp(loc, e, index, upr); 3371 } 3372 else 3373 { // array[index, i2, i3, i4, ...] 3374 Array arguments = new Array(); 3375 arguments.push(index); 3376 if (token.value == TOKcomma) 3377 { 3378 nextToken(); 3379 while (1) 3380 { Expression arg; 3381 3382 arg = parseAssignExp(); 3383 arguments.push(arg); 3384 if (token.value == TOKrbracket) 3385 break; 3386 check(TOKcomma); 3387 } 3388 } 3389 e = new ArrayExp(loc, e, arguments); 3390 } 3391 check(TOKrbracket); 3392 } 3393 continue; 3394 } 3395 3396 default: 3397 return e; 3398 } 3399 nextToken(); 3400 } 3401 } 3402 3403 Expression parseUnaryExp() 3404 { Expression e; 3405 Loc loc = this.loc; 3406 3407 switch (token.value) 3408 { 3409 case TOKand: 3410 nextToken(); 3411 e = parseUnaryExp(); 3412 e = new AddrExp(loc, e); 3413 break; 3414 3415 case TOKplusplus: 3416 nextToken(); 3417 e = parseUnaryExp(); 3418 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32)); 3419 break; 3420 3421 case TOKminusminus: 3422 nextToken(); 3423 e = parseUnaryExp(); 3424 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32)); 3425 break; 3426 3427 case TOKmul: 3428 nextToken(); 3429 e = parseUnaryExp(); 3430 e = new PtrExp(loc, e); 3431 break; 3432 3433 case TOKmin: 3434 nextToken(); 3435 e = parseUnaryExp(); 3436 e = new NegExp(loc, e); 3437 break; 3438 3439 case TOKadd: 3440 nextToken(); 3441 e = parseUnaryExp(); 3442 e = new UAddExp(loc, e); 3443 break; 3444 3445 case TOKnot: 3446 nextToken(); 3447 e = parseUnaryExp(); 3448 e = new NotExp(loc, e); 3449 break; 3450 3451 case TOKtilde: 3452 nextToken(); 3453 e = parseUnaryExp(); 3454 e = new ComExp(loc, e); 3455 break; 3456 3457 case TOKdelete: 3458 nextToken(); 3459 e = parseUnaryExp(); 3460 e = new DeleteExp(loc, e); 3461 break; 3462 3463 case TOKnew: 3464 { Type t; 3465 Array newargs; 3466 Array arguments = NULL; 3467 3468 nextToken(); 3469 newargs = NULL; 3470 if (token.value == TOKlparen) { 3471 newargs = parseArguments(); 3472 } 3473 3474 // #if LTORARRAYDECL 3475 t = parseBasicType(); 3476 t = parseBasicType2(t); 3477 if (t.ty == Taarray) 3478 { 3479 Type index = (cast(TypeAArray)t).index; 3480 3481 if (index.ty == Tident) 3482 { 3483 TypeIdentifier ti = cast(TypeIdentifier)index; 3484 int i; 3485 Expression e; 3486 Identifier id = ti.ident; 3487 3488 e = new IdentifierExp(loc, id); 3489 for (i = 0; i < ti.idents.dim; i++) 3490 { 3491 id = cast(Identifier)ti.idents.data[i]; 3492 e = new DotIdExp(loc, e, id); 3493 } 3494 3495 arguments = new Array(); 3496 arguments.push(e); 3497 t = new TypeDArray(t.next); 3498 } 3499 else 3500 { 3501 error("need size of rightmost array, not type %s", index.toString()); 3502 return new NullExp(loc); 3503 } 3504 } 3505 else if (t.ty == Tsarray) 3506 { 3507 TypeSArray tsa = cast(TypeSArray)t; 3508 Expression e = tsa.dim; 3509 3510 arguments = new Array(); 3511 arguments.push(e); 3512 t = new TypeDArray(t.next); 3513 } 3514 else if (token.value == TOKlparen) 3515 { 3516 arguments = parseArguments(); 3517 } 3518 /+ #else 3519 t = parseBasicType(); 3520 while (token.value == TOKmul) 3521 { t = new TypePointer(t); 3522 nextToken(); 3523 } 3524 if (token.value == TOKlbracket) 3525 { 3526 Expression *e; 3527 3528 nextToken(); 3529 e = parseAssignExp(); 3530 arguments = new Array(); 3531 arguments.push(e); 3532 check(TOKrbracket); 3533 t = parseDeclarator(t, NULL); 3534 t = new TypeDArray(t); 3535 } 3536 else if (token.value == TOKlparen) 3537 arguments = parseArguments(); 3538 #endif 3539 +/ 3540 e = new NewExp(loc, newargs, t, arguments); 3541 break; 3542 } 3543 // #if DCASTSYNTAX 3544 case TOKcast: // cast(type) expression 3545 { Type *t; 3546 3547 nextToken(); 3548 check(TOKlparen); 3549 t = parseBasicType(); 3550 t = parseDeclarator(t,NULL); // ( type ) 3551 check(TOKrparen); 3552 3553 // if .identifier 3554 if (token.value == TOKdot) 3555 { 3556 nextToken(); 3557 if (token.value != TOKidentifier) 3558 { error("Identifier expected following cast(type)."); 3559 return NULL; 3560 } 3561 // cast(type).ident 3562 e = new TypeDotIdExp(loc, t, token.ident); 3563 nextToken(); 3564 } 3565 else 3566 { 3567 e = parseUnaryExp(); 3568 e = new CastExp(loc, e, t); 3569 } 3570
