1 2/* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/D-Programming-Language/dmd/blob/master/src/parse.c 9 */ 10 11// This is the D parser 12 13#include "root/dsystem.h" // strlen(),memcpy() 14#include "root/rmem.h" 15 16#include "mars.h" 17#include "lexer.h" 18#include "parse.h" 19#include "init.h" 20#include "attrib.h" 21#include "cond.h" 22#include "mtype.h" 23#include "template.h" 24#include "staticassert.h" 25#include "expression.h" 26#include "statement.h" 27#include "module.h" 28#include "dsymbol.h" 29#include "import.h" 30#include "declaration.h" 31#include "aggregate.h" 32#include "enum.h" 33#include "id.h" 34#include "version.h" 35#include "aliasthis.h" 36#include "nspace.h" 37#include "hdrgen.h" 38 39Expression *typeToExpression(Type *t); 40 41// Support C cast syntax: 42// (type)(expression) 43#define CCASTSYNTAX 1 44 45// Support postfix C array declarations, such as 46// int a[3][4]; 47#define CARRAYDECL 1 48 49Parser::Parser(Module *module, const utf8_t *base, size_t length, bool doDocComment) 50 : Lexer(module ? module->srcfile->toChars() : NULL, base, 0, length, doDocComment, false) 51{ 52 //printf("Parser::Parser()\n"); 53 mod = module; 54 md = NULL; 55 linkage = LINKd; 56 endloc = Loc(); 57 inBrackets = 0; 58 lookingForElse = Loc(); 59 //nextToken(); // start up the scanner 60} 61 62/********************* 63 * Use this constructor for string mixins. 64 * Input: 65 * loc location in source file of mixin 66 */ 67Parser::Parser(Loc loc, Module *module, const utf8_t *base, size_t length, bool doDocComment) 68 : Lexer(module ? module->srcfile->toChars() : NULL, base, 0, length, doDocComment, false) 69{ 70 //printf("Parser::Parser()\n"); 71 scanloc = loc; 72 73 if (loc.filename) 74 { 75 /* Create a pseudo-filename for the mixin string, as it may not even exist 76 * in the source file. 77 */ 78 char *filename = (char *)mem.xmalloc(strlen(loc.filename) + 7 + sizeof(loc.linnum) * 3 + 1); 79 sprintf(filename, "%s-mixin-%d", loc.filename, (int)loc.linnum); 80 scanloc.filename = filename; 81 } 82 83 mod = module; 84 md = NULL; 85 linkage = LINKd; 86 endloc = Loc(); 87 inBrackets = 0; 88 lookingForElse = Loc(); 89 //nextToken(); // start up the scanner 90} 91 92Dsymbols *Parser::parseModule() 93{ 94 const utf8_t *comment = token.blockComment; 95 bool isdeprecated = false; 96 Expression *msg = NULL; 97 Expressions *udas = NULL; 98 Dsymbols *decldefs; 99 100 Token *tk; 101 if (skipAttributes(&token, &tk) && tk->value == TOKmodule) 102 { 103 while (token.value != TOKmodule) 104 { 105 switch (token.value) 106 { 107 case TOKdeprecated: 108 { 109 // deprecated (...) module ... 110 if (isdeprecated) 111 { 112 error("there is only one deprecation attribute allowed for module declaration"); 113 } 114 else 115 { 116 isdeprecated = true; 117 } 118 nextToken(); 119 if (token.value == TOKlparen) 120 { 121 check(TOKlparen); 122 msg = parseAssignExp(); 123 check(TOKrparen); 124 } 125 break; 126 } 127 case TOKat: 128 { 129 Expressions *exps = NULL; 130 StorageClass stc = parseAttribute(&exps); 131 132 if (stc == STCproperty || stc == STCnogc || stc == STCdisable || 133 stc == STCsafe || stc == STCtrusted || stc == STCsystem) 134 { 135 error("@%s attribute for module declaration is not supported", token.toChars()); 136 } 137 else 138 { 139 udas = UserAttributeDeclaration::concat(udas, exps); 140 } 141 if (stc) 142 nextToken(); 143 break; 144 } 145 default: 146 { 147 error("'module' expected instead of %s", token.toChars()); 148 nextToken(); 149 break; 150 } 151 } 152 } 153 } 154 155 if (udas) 156 { 157 Dsymbols *a = new Dsymbols(); 158 UserAttributeDeclaration *udad = new UserAttributeDeclaration(udas, a); 159 mod->userAttribDecl = udad; 160 } 161 162 // ModuleDeclation leads off 163 if (token.value == TOKmodule) 164 { 165 Loc loc = token.loc; 166 167 nextToken(); 168 if (token.value != TOKidentifier) 169 { 170 error("identifier expected following module"); 171 goto Lerr; 172 } 173 else 174 { 175 Identifiers *a = NULL; 176 Identifier *id; 177 178 id = token.ident; 179 while (nextToken() == TOKdot) 180 { 181 if (!a) 182 a = new Identifiers(); 183 a->push(id); 184 nextToken(); 185 if (token.value != TOKidentifier) 186 { 187 error("identifier expected following package"); 188 goto Lerr; 189 } 190 id = token.ident; 191 } 192 193 md = new ModuleDeclaration(loc, a, id); 194 md->isdeprecated = isdeprecated; 195 md->msg = msg; 196 197 if (token.value != TOKsemicolon) 198 error("';' expected following module declaration instead of %s", token.toChars()); 199 nextToken(); 200 addComment(mod, comment); 201 } 202 } 203 204 decldefs = parseDeclDefs(0); 205 if (token.value != TOKeof) 206 { 207 error(token.loc, "unrecognized declaration"); 208 goto Lerr; 209 } 210 return decldefs; 211 212Lerr: 213 while (token.value != TOKsemicolon && token.value != TOKeof) 214 nextToken(); 215 nextToken(); 216 return new Dsymbols(); 217} 218 219struct PrefixAttributes 220{ 221 StorageClass storageClass; 222 Expression *depmsg; 223 LINK link; 224 Prot protection; 225 bool setAlignment; 226 Expression *ealign; 227 Expressions *udas; 228 const utf8_t *comment; 229 230 PrefixAttributes() 231 : storageClass(STCundefined), 232 depmsg(NULL), 233 link(LINKdefault), 234 protection(PROTundefined), 235 setAlignment(false), 236 ealign(NULL), 237 udas(NULL), 238 comment(NULL) 239 { 240 } 241}; 242 243Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes *pAttrs) 244{ 245 Dsymbol *lastDecl = NULL; // used to link unittest to its previous declaration 246 if (!pLastDecl) 247 pLastDecl = &lastDecl; 248 249 LINK linksave = linkage; // save global state 250 251 //printf("Parser::parseDeclDefs()\n"); 252 Dsymbols *decldefs = new Dsymbols(); 253 do 254 { 255 // parse result 256 Dsymbol *s = NULL; 257 Dsymbols *a = NULL; 258 259 PrefixAttributes attrs; 260 if (!once || !pAttrs) 261 { 262 pAttrs = &attrs; 263 pAttrs->comment = token.blockComment; 264 } 265 PROTKIND prot; 266 StorageClass stc; 267 Condition *condition; 268 269 linkage = linksave; 270 271 switch (token.value) 272 { 273 case TOKenum: 274 { 275 /* Determine if this is a manifest constant declaration, 276 * or a conventional enum. 277 */ 278 Token *t = peek(&token); 279 if (t->value == TOKlcurly || t->value == TOKcolon) 280 s = parseEnum(); 281 else if (t->value != TOKidentifier) 282 goto Ldeclaration; 283 else 284 { 285 t = peek(t); 286 if (t->value == TOKlcurly || t->value == TOKcolon || 287 t->value == TOKsemicolon) 288 s = parseEnum(); 289 else 290 goto Ldeclaration; 291 } 292 break; 293 } 294 295 case TOKimport: 296 a = parseImport(); 297 // keep pLastDecl 298 break; 299 300 case TOKtemplate: 301 s = (Dsymbol *)parseTemplateDeclaration(); 302 break; 303 304 case TOKmixin: 305 { 306 Loc loc = token.loc; 307 switch (peekNext()) 308 { 309 case TOKlparen: 310 { 311 // mixin(string) 312 nextToken(); 313 check(TOKlparen, "mixin"); 314 Expression *e = parseAssignExp(); 315 check(TOKrparen); 316 check(TOKsemicolon); 317 s = new CompileDeclaration(loc, e); 318 break; 319 } 320 case TOKtemplate: 321 // mixin template 322 nextToken(); 323 s = (Dsymbol *)parseTemplateDeclaration(true); 324 break; 325 326 default: 327 s = parseMixin(); 328 break; 329 } 330 break; 331 } 332 333 case TOKwchar: case TOKdchar: 334 case TOKbool: case TOKchar: 335 case TOKint8: case TOKuns8: 336 case TOKint16: case TOKuns16: 337 case TOKint32: case TOKuns32: 338 case TOKint64: case TOKuns64: 339 case TOKint128: case TOKuns128: 340 case TOKfloat32: case TOKfloat64: case TOKfloat80: 341 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 342 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 343 case TOKvoid: 344 case TOKalias: 345 case TOKidentifier: 346 case TOKsuper: 347 case TOKtypeof: 348 case TOKdot: 349 case TOKvector: 350 case TOKstruct: 351 case TOKunion: 352 case TOKclass: 353 case TOKinterface: 354 case TOKtraits: 355 Ldeclaration: 356 a = parseDeclarations(false, pAttrs, pAttrs->comment); 357 if (a && a->dim) 358 *pLastDecl = (*a)[a->dim-1]; 359 break; 360 361 case TOKthis: 362 if (peekNext() == TOKdot) 363 goto Ldeclaration; 364 else 365 s = parseCtor(pAttrs); 366 break; 367 368 case TOKtilde: 369 s = parseDtor(pAttrs); 370 break; 371 372 case TOKinvariant: 373 { 374 Token *t = peek(&token); 375 if ((t->value == TOKlparen && peek(t)->value == TOKrparen) || 376 t->value == TOKlcurly) 377 { 378 // invariant {} 379 // invariant() {} 380 s = parseInvariant(pAttrs); 381 } 382 else 383 { 384 error("invariant body expected, not '%s'", token.toChars()); 385 goto Lerror; 386 } 387 break; 388 } 389 390 case TOKunittest: 391 if (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration) 392 { 393 s = parseUnitTest(pAttrs); 394 if (*pLastDecl) 395 (*pLastDecl)->ddocUnittest = (UnitTestDeclaration *)s; 396 } 397 else 398 { 399 // Skip over unittest block by counting { } 400 Loc loc = token.loc; 401 int braces = 0; 402 while (1) 403 { 404 nextToken(); 405 switch (token.value) 406 { 407 case TOKlcurly: 408 ++braces; 409 continue; 410 411 case TOKrcurly: 412 if (--braces) 413 continue; 414 nextToken(); 415 break; 416 417 case TOKeof: 418 /* { */ 419 error(loc, "closing } of unittest not found before end of file"); 420 goto Lerror; 421 422 default: 423 continue; 424 } 425 break; 426 } 427 // Workaround 14894. Add an empty unittest declaration to keep 428 // the number of symbols in this scope independent of -unittest. 429 s = new UnitTestDeclaration(loc, token.loc, STCundefined, NULL); 430 } 431 break; 432 433 case TOKnew: 434 s = parseNew(pAttrs); 435 break; 436 437 case TOKdelete: 438 s = parseDelete(pAttrs); 439 break; 440 441 case TOKcolon: 442 case TOKlcurly: 443 error("declaration expected, not '%s'",token.toChars()); 444 goto Lerror; 445 446 case TOKrcurly: 447 case TOKeof: 448 if (once) 449 error("declaration expected, not '%s'", token.toChars()); 450 return decldefs; 451 452 case TOKstatic: 453 { 454 TOK next = peekNext(); 455 if (next == TOKthis) 456 s = parseStaticCtor(pAttrs); 457 else if (next == TOKtilde) 458 s = parseStaticDtor(pAttrs); 459 else if (next == TOKassert) 460 s = parseStaticAssert(); 461 else if (next == TOKif) 462 { 463 condition = parseStaticIfCondition(); 464 Dsymbols *athen; 465 if (token.value == TOKcolon) 466 athen = parseBlock(pLastDecl); 467 else 468 { 469 Loc lookingForElseSave = lookingForElse; 470 lookingForElse = token.loc; 471 athen = parseBlock(pLastDecl); 472 lookingForElse = lookingForElseSave; 473 } 474 Dsymbols *aelse = NULL; 475 if (token.value == TOKelse) 476 { 477 Loc elseloc = token.loc; 478 nextToken(); 479 aelse = parseBlock(pLastDecl); 480 checkDanglingElse(elseloc); 481 } 482 s = new StaticIfDeclaration(condition, athen, aelse); 483 } 484 else if (next == TOKimport) 485 { 486 a = parseImport(); 487 // keep pLastDecl 488 } 489 else if (next == TOKforeach || next == TOKforeach_reverse) 490 { 491 s = parseForeachStaticDecl(token.loc, pLastDecl); 492 } 493 else 494 { 495 stc = STCstatic; 496 goto Lstc; 497 } 498 break; 499 } 500 501 case TOKconst: 502 if (peekNext() == TOKlparen) 503 goto Ldeclaration; 504 stc = STCconst; 505 goto Lstc; 506 507 case TOKimmutable: 508 if (peekNext() == TOKlparen) 509 goto Ldeclaration; 510 stc = STCimmutable; 511 goto Lstc; 512 513 case TOKshared: 514 { 515 TOK next = peekNext(); 516 if (next == TOKlparen) 517 goto Ldeclaration; 518 if (next == TOKstatic) 519 { 520 TOK next2 = peekNext2(); 521 if (next2 == TOKthis) 522 { 523 s = parseSharedStaticCtor(pAttrs); 524 break; 525 } 526 if (next2 == TOKtilde) 527 { 528 s = parseSharedStaticDtor(pAttrs); 529 break; 530 } 531 } 532 stc = STCshared; 533 goto Lstc; 534 } 535 536 case TOKwild: 537 if (peekNext() == TOKlparen) 538 goto Ldeclaration; 539 stc = STCwild; 540 goto Lstc; 541 542 case TOKfinal: stc = STCfinal; goto Lstc; 543 case TOKauto: stc = STCauto; goto Lstc; 544 case TOKscope: stc = STCscope; goto Lstc; 545 case TOKoverride: stc = STCoverride; goto Lstc; 546 case TOKabstract: stc = STCabstract; goto Lstc; 547 case TOKsynchronized: stc = STCsynchronized; goto Lstc; 548 case TOKnothrow: stc = STCnothrow; goto Lstc; 549 case TOKpure: stc = STCpure; goto Lstc; 550 case TOKref: stc = STCref; goto Lstc; 551 case TOKgshared: stc = STCgshared; goto Lstc; 552 //case TOKmanifest: stc = STCmanifest; goto Lstc; 553 case TOKat: 554 { 555 Expressions *exps = NULL; 556 stc = parseAttribute(&exps); 557 if (stc) 558 goto Lstc; // it's a predefined attribute 559 // no redundant/conflicting check for UDAs 560 pAttrs->udas = UserAttributeDeclaration::concat(pAttrs->udas, exps); 561 goto Lautodecl; 562 } 563 Lstc: 564 pAttrs->storageClass = appendStorageClass(pAttrs->storageClass, stc); 565 nextToken(); 566 567 Lautodecl: 568 Token *tk; 569 570 /* Look for auto initializers: 571 * storage_class identifier = initializer; 572 * storage_class identifier(...) = initializer; 573 */ 574 if (token.value == TOKidentifier && 575 skipParensIf(peek(&token), &tk) && 576 tk->value == TOKassign) 577 { 578 a = parseAutoDeclarations(pAttrs->storageClass, pAttrs->comment); 579 pAttrs->storageClass = STCundefined; 580 if (a && a->dim) 581 *pLastDecl = (*a)[a->dim-1]; 582 if (pAttrs->udas) 583 { 584 s = new UserAttributeDeclaration(pAttrs->udas, a); 585 pAttrs->udas = NULL; 586 } 587 break; 588 } 589 590 /* Look for return type inference for template functions. 591 */ 592 if (token.value == TOKidentifier && skipParens(peek(&token), &tk) && skipAttributes(tk, &tk) && 593 (tk->value == TOKlparen || tk->value == TOKlcurly || tk->value == TOKin || 594 tk->value == TOKout || tk->value == TOKdo || 595 (tk->value == TOKidentifier && tk->ident == Id::_body)) 596 ) 597 { 598 a = parseDeclarations(true, pAttrs, pAttrs->comment); 599 if (a && a->dim) 600 *pLastDecl = (*a)[a->dim-1]; 601 if (pAttrs->udas) 602 { 603 s = new UserAttributeDeclaration(pAttrs->udas, a); 604 pAttrs->udas = NULL; 605 } 606 break; 607 } 608 609 a = parseBlock(pLastDecl, pAttrs); 610 if (pAttrs->storageClass != STCundefined) 611 { 612 s = new StorageClassDeclaration(pAttrs->storageClass, a); 613 pAttrs->storageClass = STCundefined; 614 } 615 if (pAttrs->udas) 616 { 617 if (s) 618 { 619 a = new Dsymbols(); 620 a->push(s); 621 } 622 s = new UserAttributeDeclaration(pAttrs->udas, a); 623 pAttrs->udas = NULL; 624 } 625 break; 626 627 case TOKdeprecated: 628 { 629 if (peek(&token)->value != TOKlparen) 630 { 631 stc = STCdeprecated; 632 goto Lstc; 633 } 634 nextToken(); 635 check(TOKlparen); 636 Expression *e = parseAssignExp(); 637 check(TOKrparen); 638 if (pAttrs->depmsg) 639 { 640 error("conflicting storage class 'deprecated(%s)' and 'deprecated(%s)'", 641 pAttrs->depmsg->toChars(), e->toChars()); 642 } 643 pAttrs->depmsg = e; 644 a = parseBlock(pLastDecl, pAttrs); 645 if (pAttrs->depmsg) 646 { 647 s = new DeprecatedDeclaration(pAttrs->depmsg, a); 648 pAttrs->depmsg = NULL; 649 } 650 break; 651 } 652 653 case TOKlbracket: 654 { 655 if (peekNext() == TOKrbracket) 656 error("empty attribute list is not allowed"); 657 error("use @(attributes) instead of [attributes]"); 658 Expressions *exps = parseArguments(); 659 // no redundant/conflicting check for UDAs 660 661 pAttrs->udas = UserAttributeDeclaration::concat(pAttrs->udas, exps); 662 a = parseBlock(pLastDecl, pAttrs); 663 if (pAttrs->udas) 664 { 665 s = new UserAttributeDeclaration(pAttrs->udas, a); 666 pAttrs->udas = NULL; 667 } 668 break; 669 } 670 671 case TOKextern: 672 { 673 if (peek(&token)->value != TOKlparen) 674 { 675 stc = STCextern; 676 goto Lstc; 677 } 678 679 Loc linkLoc = token.loc; 680 Identifiers *idents = NULL; 681 CPPMANGLE cppmangle = CPPMANGLEdefault; 682 bool cppMangleOnly = false; 683 LINK link = parseLinkage(&idents, &cppmangle, &cppMangleOnly); 684 if (pAttrs->link != LINKdefault) 685 { 686 if (pAttrs->link != link) 687 { 688 error("conflicting linkage extern (%s) and extern (%s)", 689 linkageToChars(pAttrs->link), linkageToChars(link)); 690 } 691 else if (idents) 692 { 693 // Allow: 694 // extern(C++, foo) extern(C++, bar) void foo(); 695 // to be equivalent with: 696 // extern(C++, foo.bar) void foo(); 697 } 698 else 699 error("redundant linkage extern (%s)", linkageToChars(pAttrs->link)); 700 } 701 pAttrs->link = link; 702 this->linkage = link; 703 a = parseBlock(pLastDecl, pAttrs); 704 if (idents) 705 { 706 assert(link == LINKcpp); 707 assert(idents->dim); 708 for (size_t i = idents->dim; i;) 709 { 710 Identifier *id = (*idents)[--i]; 711 if (s) 712 { 713 a = new Dsymbols(); 714 a->push(s); 715 } 716 s = new Nspace(linkLoc, id, a, cppMangleOnly); 717 } 718 delete idents; 719 pAttrs->link = LINKdefault; 720 } 721 else if (pAttrs->link != LINKdefault) 722 { 723 s = new LinkDeclaration(pAttrs->link, a); 724 pAttrs->link = LINKdefault; 725 } 726 else if (cppmangle != CPPMANGLEdefault) 727 { 728 assert(link == LINKcpp); 729 s = new CPPMangleDeclaration(cppmangle, a); 730 } 731 break; 732 } 733 734 case TOKprivate: prot = PROTprivate; goto Lprot; 735 case TOKpackage: prot = PROTpackage; goto Lprot; 736 case TOKprotected: prot = PROTprotected; goto Lprot; 737 case TOKpublic: prot = PROTpublic; goto Lprot; 738 case TOKexport: prot = PROTexport; goto Lprot; 739 Lprot: 740 { 741 if (pAttrs->protection.kind != PROTundefined) 742 { 743 if (pAttrs->protection.kind != prot) 744 error("conflicting protection attribute '%s' and '%s'", 745 protectionToChars(pAttrs->protection.kind), protectionToChars(prot)); 746 else 747 error("redundant protection attribute '%s'", protectionToChars(prot)); 748 } 749 pAttrs->protection.kind = prot; 750 751 nextToken(); 752 753 // optional qualified package identifier to bind 754 // protection to 755 Identifiers *pkg_prot_idents = NULL; 756 if (pAttrs->protection.kind == PROTpackage && token.value == TOKlparen) 757 { 758 pkg_prot_idents = parseQualifiedIdentifier("protection package"); 759 760 if (pkg_prot_idents) 761 check(TOKrparen); 762 else 763 { 764 while (token.value != TOKsemicolon && token.value != TOKeof) 765 nextToken(); 766 nextToken(); 767 break; 768 } 769 } 770 771 Loc attrloc = token.loc; 772 a = parseBlock(pLastDecl, pAttrs); 773 if (pAttrs->protection.kind != PROTundefined) 774 { 775 if (pAttrs->protection.kind == PROTpackage && pkg_prot_idents) 776 s = new ProtDeclaration(attrloc, pkg_prot_idents, a); 777 else 778 s = new ProtDeclaration(attrloc, pAttrs->protection, a); 779 780 pAttrs->protection = Prot(PROTundefined); 781 } 782 break; 783 } 784 785 case TOKalign: 786 { 787 const Loc attrLoc = token.loc; 788 789 nextToken(); 790 791 Expression *e = NULL; // default 792 if (token.value == TOKlparen) 793 { 794 nextToken(); 795 e = parseAssignExp(); 796 check(TOKrparen); 797 } 798 799 if (pAttrs->setAlignment) 800 { 801 const char *s1 = ""; 802 OutBuffer buf1; 803 if (e) 804 { 805 buf1.printf("(%s)", e->toChars()); 806 s1 = buf1.peekString(); 807 } 808 error("redundant alignment attribute align%s", s1); 809 } 810 811 pAttrs->setAlignment = true; 812 pAttrs->ealign = e; 813 a = parseBlock(pLastDecl, pAttrs); 814 if (pAttrs->setAlignment) 815 { 816 s = new AlignDeclaration(attrLoc, pAttrs->ealign, a); 817 pAttrs->setAlignment = false; 818 pAttrs->ealign = NULL; 819 } 820 break; 821 } 822 823 case TOKpragma: 824 { 825 Expressions *args = NULL; 826 Loc loc = token.loc; 827 828 nextToken(); 829 check(TOKlparen); 830 if (token.value != TOKidentifier) 831 { 832 error("pragma(identifier) expected"); 833 goto Lerror; 834 } 835 Identifier *ident = token.ident; 836 nextToken(); 837 if (token.value == TOKcomma && peekNext() != TOKrparen) 838 args = parseArguments(); // pragma(identifier, args...) 839 else 840 check(TOKrparen); // pragma(identifier) 841 842 Dsymbols *a2 = NULL; 843 if (token.value == TOKsemicolon) 844 { 845 /* Bugzilla 2354: Accept single semicolon as an empty 846 * DeclarationBlock following attribute. 847 * 848 * Attribute DeclarationBlock 849 * Pragma DeclDef 850 * ; 851 */ 852 nextToken(); 853 } 854 else 855 a2 = parseBlock(pLastDecl); 856 s = new PragmaDeclaration(loc, ident, args, a2); 857 break; 858 } 859 860 case TOKdebug: 861 nextToken(); 862 if (token.value == TOKassign) 863 { 864 nextToken(); 865 if (token.value == TOKidentifier) 866 s = new DebugSymbol(token.loc, token.ident); 867 else if (token.value == TOKint32v || token.value == TOKint64v) 868 s = new DebugSymbol(token.loc, (unsigned)token.uns64value); 869 else 870 { 871 error("identifier or integer expected, not %s", token.toChars()); 872 s = NULL; 873 } 874 nextToken(); 875 if (token.value != TOKsemicolon) 876 error("semicolon expected"); 877 nextToken(); 878 break; 879 } 880 881 condition = parseDebugCondition(); 882 goto Lcondition; 883 884 case TOKversion: 885 nextToken(); 886 if (token.value == TOKassign) 887 { 888 nextToken(); 889 if (token.value == TOKidentifier) 890 s = new VersionSymbol(token.loc, token.ident); 891 else if (token.value == TOKint32v || token.value == TOKint64v) 892 s = new VersionSymbol(token.loc, (unsigned)token.uns64value); 893 else 894 { 895 error("identifier or integer expected, not %s", token.toChars()); 896 s = NULL; 897 } 898 nextToken(); 899 if (token.value != TOKsemicolon) 900 error("semicolon expected"); 901 nextToken(); 902 break; 903 } 904 condition = parseVersionCondition(); 905 goto Lcondition; 906 907 Lcondition: 908 { 909 Dsymbols *athen; 910 if (token.value == TOKcolon) 911 athen = parseBlock(pLastDecl); 912 else 913 { 914 Loc lookingForElseSave = lookingForElse; 915 lookingForElse = token.loc; 916 athen = parseBlock(pLastDecl); 917 lookingForElse = lookingForElseSave; 918 } 919 Dsymbols *aelse = NULL; 920 if (token.value == TOKelse) 921 { 922 Loc elseloc = token.loc; 923 nextToken(); 924 aelse = parseBlock(pLastDecl); 925 checkDanglingElse(elseloc); 926 } 927 s = new ConditionalDeclaration(condition, athen, aelse); 928 break; 929 } 930 931 case TOKsemicolon: // empty declaration 932 //error("empty declaration"); 933 nextToken(); 934 continue; 935 936 default: 937 error("declaration expected, not '%s'",token.toChars()); 938 Lerror: 939 while (token.value != TOKsemicolon && token.value != TOKeof) 940 nextToken(); 941 nextToken(); 942 s = NULL; 943 continue; 944 } 945 946 if (s) 947 { 948 if (!s->isAttribDeclaration()) 949 *pLastDecl = s; 950 decldefs->push(s); 951 addComment(s, pAttrs->comment); 952 } 953 else if (a && a->dim) 954 { 955 decldefs->append(a); 956 } 957 } while (!once); 958 959 linkage = linksave; 960 961 return decldefs; 962} 963 964/********************************************* 965 * Give error on redundant/conflicting storage class. 966 * 967 * TODO: remove deprecation in 2.068 and keep only error 968 */ 969 970StorageClass Parser::appendStorageClass(StorageClass storageClass, StorageClass stc, 971 bool deprec) 972{ 973 if ((storageClass & stc) || 974 (storageClass & STCin && stc & (STCconst | STCscope)) || 975 (stc & STCin && storageClass & (STCconst | STCscope))) 976 { 977 OutBuffer buf; 978 stcToBuffer(&buf, stc); 979 if (deprec) 980 deprecation("redundant attribute '%s'", buf.peekString()); 981 else 982 error("redundant attribute '%s'", buf.peekString()); 983 return storageClass | stc; 984 } 985 986 storageClass |= stc; 987 988 if (stc & (STCconst | STCimmutable | STCmanifest)) 989 { 990 StorageClass u = storageClass & (STCconst | STCimmutable | STCmanifest); 991 if (u & (u - 1)) 992 error("conflicting attribute '%s'", Token::toChars(token.value)); 993 } 994 if (stc & (STCgshared | STCshared | STCtls)) 995 { 996 StorageClass u = storageClass & (STCgshared | STCshared | STCtls); 997 if (u & (u - 1)) 998 error("conflicting attribute '%s'", Token::toChars(token.value)); 999 } 1000 if (stc & (STCsafe | STCsystem | STCtrusted)) 1001 { 1002 StorageClass u = storageClass & (STCsafe | STCsystem | STCtrusted); 1003 if (u & (u - 1)) 1004 error("conflicting attribute '@%s'", token.toChars()); 1005 } 1006 1007 return storageClass; 1008} 1009 1010/*********************************************** 1011 * Parse attribute, lexer is on '@'. 1012 * Input: 1013 * pudas array of UDAs to append to 1014 * Returns: 1015 * storage class if a predefined attribute; also scanner remains on identifier. 1016 * 0 if not a predefined attribute 1017 * *pudas set if user defined attribute, scanner is past UDA 1018 * *pudas NULL if not a user defined attribute 1019 */ 1020 1021StorageClass Parser::parseAttribute(Expressions **pudas) 1022{ 1023 nextToken(); 1024 Expressions *udas = NULL; 1025 StorageClass stc = 0; 1026 if (token.value == TOKidentifier) 1027 { 1028 if (token.ident == Id::property) 1029 stc = STCproperty; 1030 else if (token.ident == Id::nogc) 1031 stc = STCnogc; 1032 else if (token.ident == Id::safe) 1033 stc = STCsafe; 1034 else if (token.ident == Id::trusted) 1035 stc = STCtrusted; 1036 else if (token.ident == Id::system) 1037 stc = STCsystem; 1038 else if (token.ident == Id::disable) 1039 stc = STCdisable; 1040 else if (token.ident == Id::future) 1041 stc = STCfuture; 1042 else 1043 { 1044 // Allow identifier, template instantiation, or function call 1045 Expression *exp = parsePrimaryExp(); 1046 if (token.value == TOKlparen) 1047 { 1048 Loc loc = token.loc; 1049 exp = new CallExp(loc, exp, parseArguments()); 1050 } 1051 1052 udas = new Expressions(); 1053 udas->push(exp); 1054 } 1055 } 1056 else if (token.value == TOKlparen) 1057 { 1058 // @( ArgumentList ) 1059 // Concatenate with existing 1060 if (peekNext() == TOKrparen) 1061 error("empty attribute list is not allowed"); 1062 udas = parseArguments(); 1063 } 1064 else 1065 { 1066 error("@identifier or @(ArgumentList) expected, not @%s", token.toChars()); 1067 } 1068 1069 if (stc) 1070 { 1071 } 1072 else if (udas) 1073 { 1074 *pudas = UserAttributeDeclaration::concat(*pudas, udas); 1075 } 1076 else 1077 error("valid attributes are @property, @safe, @trusted, @system, @disable"); 1078 return stc; 1079} 1080 1081/*********************************************** 1082 * Parse const/immutable/shared/inout/nothrow/pure postfix 1083 */ 1084 1085StorageClass Parser::parsePostfix(StorageClass storageClass, Expressions **pudas) 1086{ 1087 while (1) 1088 { 1089 StorageClass stc; 1090 switch (token.value) 1091 { 1092 case TOKconst: stc = STCconst; break; 1093 case TOKimmutable: stc = STCimmutable; break; 1094 case TOKshared: stc = STCshared; break; 1095 case TOKwild: stc = STCwild; break; 1096 case TOKnothrow: stc = STCnothrow; break; 1097 case TOKpure: stc = STCpure; break; 1098 case TOKreturn: stc = STCreturn; break; 1099 case TOKscope: stc = STCscope; break; 1100 case TOKat: 1101 { 1102 Expressions *udas = NULL; 1103 stc = parseAttribute(&udas); 1104 if (udas) 1105 { 1106 if (pudas) 1107 *pudas = UserAttributeDeclaration::concat(*pudas, udas); 1108 else 1109 { 1110 // Disallow: 1111 // void function() @uda fp; 1112 // () @uda { return 1; } 1113 error("user defined attributes cannot appear as postfixes"); 1114 } 1115 continue; 1116 } 1117 break; 1118 } 1119 1120 default: 1121 return storageClass; 1122 } 1123 storageClass = appendStorageClass(storageClass, stc, true); 1124 nextToken(); 1125 } 1126} 1127 1128StorageClass Parser::parseTypeCtor() 1129{ 1130 StorageClass storageClass = STCundefined; 1131 1132 while (1) 1133 { 1134 if (peek(&token)->value == TOKlparen) 1135 return storageClass; 1136 1137 StorageClass stc; 1138 switch (token.value) 1139 { 1140 case TOKconst: stc = STCconst; break; 1141 case TOKimmutable: stc = STCimmutable; break; 1142 case TOKshared: stc = STCshared; break; 1143 case TOKwild: stc = STCwild; break; 1144 1145 default: 1146 return storageClass; 1147 } 1148 storageClass = appendStorageClass(storageClass, stc); 1149 nextToken(); 1150 } 1151} 1152 1153/******************************************** 1154 * Parse declarations after an align, protection, or extern decl. 1155 */ 1156 1157Dsymbols *Parser::parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs) 1158{ 1159 Dsymbols *a = NULL; 1160 1161 //printf("parseBlock()\n"); 1162 switch (token.value) 1163 { 1164 case TOKsemicolon: 1165 error("declaration expected following attribute, not ';'"); 1166 nextToken(); 1167 break; 1168 1169 case TOKeof: 1170 error("declaration expected following attribute, not EOF"); 1171 break; 1172 1173 case TOKlcurly: 1174 { 1175 Loc lookingForElseSave = lookingForElse; 1176 lookingForElse = Loc(); 1177 1178 nextToken(); 1179 a = parseDeclDefs(0, pLastDecl); 1180 if (token.value != TOKrcurly) 1181 { 1182 /* { */ 1183 error("matching '}' expected, not %s", token.toChars()); 1184 } 1185 else 1186 nextToken(); 1187 lookingForElse = lookingForElseSave; 1188 break; 1189 } 1190 1191 case TOKcolon: 1192 nextToken(); 1193 a = parseDeclDefs(0, pLastDecl); // grab declarations up to closing curly bracket 1194 break; 1195 1196 default: 1197 a = parseDeclDefs(1, pLastDecl, pAttrs); 1198 break; 1199 } 1200 return a; 1201} 1202 1203/********************************** 1204 * Parse a static assertion. 1205 * Current token is 'static'. 1206 */ 1207 1208StaticAssert *Parser::parseStaticAssert() 1209{ 1210 Loc loc = token.loc; 1211 Expression *exp; 1212 Expression *msg = NULL; 1213 1214 //printf("parseStaticAssert()\n"); 1215 nextToken(); 1216 nextToken(); 1217 check(TOKlparen); 1218 exp = parseAssignExp(); 1219 if (token.value == TOKcomma) 1220 { 1221 nextToken(); 1222 if (token.value != TOKrparen) 1223 { 1224 msg = parseAssignExp(); 1225 if (token.value == TOKcomma) 1226 nextToken(); 1227 } 1228 } 1229 check(TOKrparen); 1230 check(TOKsemicolon); 1231 return new StaticAssert(loc, exp, msg); 1232} 1233 1234/*********************************** 1235 * Parse typeof(expression). 1236 * Current token is on the 'typeof'. 1237 */ 1238 1239TypeQualified *Parser::parseTypeof() 1240{ 1241 TypeQualified *t; 1242 Loc loc = token.loc; 1243 1244 nextToken(); 1245 check(TOKlparen); 1246 if (token.value == TOKreturn) // typeof(return) 1247 { 1248 nextToken(); 1249 t = new TypeReturn(loc); 1250 } 1251 else 1252 { 1253 Expression *exp = parseExpression(); // typeof(expression) 1254 t = new TypeTypeof(loc, exp); 1255 } 1256 check(TOKrparen); 1257 return t; 1258} 1259 1260/*********************************** 1261 * Parse __vector(type). 1262 * Current token is on the '__vector'. 1263 */ 1264 1265Type *Parser::parseVector() 1266{ 1267 nextToken(); 1268 check(TOKlparen); 1269 Type *tb = parseType(); 1270 check(TOKrparen); 1271 return new TypeVector(tb); 1272} 1273 1274/*********************************** 1275 * Parse: 1276 * extern (linkage) 1277 * extern (C++, namespaces) 1278 * extern (C++, "namespace", "namespaces", ...) 1279 * The parser is on the 'extern' token. 1280 */ 1281 1282LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pcppMangleOnly) 1283{ 1284 Identifiers *idents = NULL; 1285 CPPMANGLE cppmangle = CPPMANGLEdefault; 1286 bool cppMangleOnly = false; 1287 LINK link = LINKdefault; 1288 nextToken(); 1289 assert(token.value == TOKlparen); 1290 nextToken(); 1291 if (token.value == TOKidentifier) 1292 { Identifier *id = token.ident; 1293 1294 nextToken(); 1295 if (id == Id::Windows) 1296 link = LINKwindows; 1297 else if (id == Id::Pascal) 1298 link = LINKpascal; 1299 else if (id == Id::D) 1300 link = LINKd; 1301 else if (id == Id::C) 1302 { 1303 link = LINKc; 1304 if (token.value == TOKplusplus) 1305 { 1306 link = LINKcpp; 1307 nextToken(); 1308 if (token.value == TOKcomma) // , namespaces or class or struct 1309 { 1310 nextToken(); 1311 if (token.value == TOKclass || token.value == TOKstruct) 1312 { 1313 cppmangle = token.value == TOKclass ? CPPMANGLEclass : CPPMANGLEstruct; 1314 nextToken(); 1315 } 1316 else if (token.value == TOKstring) // extern(C++, "namespace", "namespaces") 1317 { 1318 cppMangleOnly = true; 1319 idents = new Identifiers(); 1320 1321 while (1) 1322 { 1323 StringExp *stringExp = (StringExp *)parsePrimaryExp(); 1324 const char *name = stringExp->toPtr(); 1325 if (stringExp->len == 0) 1326 { 1327 error("invalid zero length C++ namespace"); 1328 idents = NULL; 1329 break; 1330 } 1331 else if (!Identifier::isValidIdentifier(name)) 1332 { 1333 error("expected valid identifer for C++ namespace but got `%s`", name); 1334 idents = NULL; 1335 break; 1336 } 1337 idents->push(Identifier::idPool(name)); 1338 if (token.value == TOKcomma) 1339 { 1340 nextToken(); 1341 if (token.value != TOKstring) 1342 { 1343 error("string expected following `,` for C++ namespace, not `%s`", token.toChars()); 1344 idents = NULL; 1345 break; 1346 } 1347 } 1348 else 1349 break; 1350 } 1351 } 1352 else 1353 { 1354 idents = new Identifiers(); 1355 while (1) 1356 { 1357 if (token.value == TOKidentifier) 1358 { 1359 Identifier *idn = token.ident; 1360 idents->push(idn); 1361 nextToken(); 1362 if (token.value == TOKdot) 1363 { 1364 nextToken(); 1365 continue; 1366 } 1367 } 1368 else 1369 { 1370 error("identifier expected for C++ namespace"); 1371 idents = NULL; // error occurred, invalidate list of elements. 1372 } 1373 break; 1374 } 1375 } 1376 } 1377 } 1378 } 1379 else if (id == Id::Objective) // Looking for tokens "Objective-C" 1380 { 1381 if (token.value == TOKmin) 1382 { 1383 nextToken(); 1384 if (token.ident == Id::C) 1385 { 1386 link = LINKobjc; 1387 nextToken(); 1388 } 1389 else 1390 goto LinvalidLinkage; 1391 } 1392 else 1393 goto LinvalidLinkage; 1394 } 1395 else if (id == Id::System) 1396 { 1397 link = LINKsystem; 1398 } 1399 else 1400 { 1401 LinvalidLinkage: 1402 error("valid linkage identifiers are D, C, C++, Objective-C, Pascal, Windows, System"); 1403 link = LINKd; 1404 } 1405 } 1406 else 1407 { 1408 link = LINKd; // default 1409 } 1410 check(TOKrparen); 1411 *pidents = idents; 1412 *pcppmangle = cppmangle; 1413 *pcppMangleOnly = cppMangleOnly; 1414 return link; 1415} 1416 1417/*********************************** 1418 * Parse ident1.ident2.ident3 1419 * 1420 * Params: 1421 * entity = what qualified identifier is expected to resolve into. 1422 * Used only for better error message 1423 * 1424 * Returns: 1425 * array of identifiers with actual qualified one stored last 1426 */ 1427Identifiers *Parser::parseQualifiedIdentifier(const char *entity) 1428{ 1429 Identifiers *qualified = NULL; 1430 1431 do 1432 { 1433 nextToken(); 1434 if (token.value != TOKidentifier) 1435 { 1436 error("%s expected as dot-separated identifiers, got '%s'", 1437 entity, token.toChars()); 1438 return NULL; 1439 } 1440 1441 Identifier *id = token.ident; 1442 if (!qualified) 1443 qualified = new Identifiers(); 1444 qualified->push(id); 1445 1446 nextToken(); 1447 } while (token.value == TOKdot); 1448 1449 return qualified; 1450} 1451 1452/************************************** 1453 * Parse a debug conditional 1454 */ 1455 1456Condition *Parser::parseDebugCondition() 1457{ 1458 Condition *c; 1459 1460 if (token.value == TOKlparen) 1461 { 1462 nextToken(); 1463 unsigned level = 1; 1464 Identifier *id = NULL; 1465 1466 if (token.value == TOKidentifier) 1467 id = token.ident; 1468 else if (token.value == TOKint32v || token.value == TOKint64v) 1469 level = (unsigned)token.uns64value; 1470 else 1471 error("identifier or integer expected, not %s", token.toChars()); 1472 nextToken(); 1473 check(TOKrparen); 1474 c = new DebugCondition(mod, level, id); 1475 } 1476 else 1477 c = new DebugCondition(mod, 1, NULL); 1478 return c; 1479 1480} 1481 1482/************************************** 1483 * Parse a version conditional 1484 */ 1485 1486Condition *Parser::parseVersionCondition() 1487{ 1488 Condition *c; 1489 unsigned level = 1; 1490 Identifier *id = NULL; 1491 1492 if (token.value == TOKlparen) 1493 { 1494 nextToken(); 1495 /* Allow: 1496 * version (unittest) 1497 * version (assert) 1498 * even though they are keywords 1499 */ 1500 if (token.value == TOKidentifier) 1501 id = token.ident; 1502 else if (token.value == TOKint32v || token.value == TOKint64v) 1503 level = (unsigned)token.uns64value; 1504 else if (token.value == TOKunittest) 1505 id = Identifier::idPool(Token::toChars(TOKunittest)); 1506 else if (token.value == TOKassert) 1507 id = Identifier::idPool(Token::toChars(TOKassert)); 1508 else 1509 error("identifier or integer expected, not %s", token.toChars()); 1510 nextToken(); 1511 check(TOKrparen); 1512 1513 } 1514 else 1515 error("(condition) expected following version"); 1516 c = new VersionCondition(mod, level, id); 1517 return c; 1518 1519} 1520 1521/*********************************************** 1522 * static if (expression) 1523 * body 1524 * else 1525 * body 1526 * Current token is 'static'. 1527 */ 1528 1529Condition *Parser::parseStaticIfCondition() 1530{ 1531 Expression *exp; 1532 Condition *condition; 1533 Loc loc = token.loc; 1534 1535 nextToken(); 1536 nextToken(); 1537 if (token.value == TOKlparen) 1538 { 1539 nextToken(); 1540 exp = parseAssignExp(); 1541 check(TOKrparen); 1542 } 1543 else 1544 { 1545 error("(expression) expected following static if"); 1546 exp = NULL; 1547 } 1548 condition = new StaticIfCondition(loc, exp); 1549 return condition; 1550} 1551 1552 1553/***************************************** 1554 * Parse a constructor definition: 1555 * this(parameters) { body } 1556 * or postblit: 1557 * this(this) { body } 1558 * or constructor template: 1559 * this(templateparameters)(parameters) { body } 1560 * Current token is 'this'. 1561 */ 1562 1563Dsymbol *Parser::parseCtor(PrefixAttributes *pAttrs) 1564{ 1565 Expressions *udas = NULL; 1566 Loc loc = token.loc; 1567 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1568 1569 nextToken(); 1570 if (token.value == TOKlparen && peekNext() == TOKthis && peekNext2() == TOKrparen) 1571 { 1572 // this(this) { ... } 1573 nextToken(); 1574 nextToken(); 1575 check(TOKrparen); 1576 1577 stc = parsePostfix(stc, &udas); 1578 if (stc & STCstatic) 1579 error(loc, "postblit cannot be static"); 1580 1581 PostBlitDeclaration *f = new PostBlitDeclaration(loc, Loc(), stc, Id::postblit); 1582 if (pAttrs) 1583 pAttrs->storageClass = STCundefined; 1584 Dsymbol *s = parseContracts(f); 1585 if (udas) 1586 { 1587 Dsymbols *a = new Dsymbols(); 1588 a->push(f); 1589 s = new UserAttributeDeclaration(udas, a); 1590 } 1591 return s; 1592 } 1593 1594 /* Look ahead to see if: 1595 * this(...)(...) 1596 * which is a constructor template 1597 */ 1598 TemplateParameters *tpl = NULL; 1599 if (token.value == TOKlparen && peekPastParen(&token)->value == TOKlparen) 1600 { 1601 tpl = parseTemplateParameterList(); 1602 } 1603 1604 /* Just a regular constructor 1605 */ 1606 int varargs; 1607 Parameters *parameters = parseParameters(&varargs); 1608 stc = parsePostfix(stc, &udas); 1609 if (varargs != 0 || Parameter::dim(parameters) != 0) 1610 { 1611 if (stc & STCstatic) 1612 error(loc, "constructor cannot be static"); 1613 } 1614 else if (StorageClass ss = stc & (STCshared | STCstatic)) // this() 1615 { 1616 if (ss == STCstatic) 1617 error(loc, "use 'static this()' to declare a static constructor"); 1618 else if (ss == (STCshared | STCstatic)) 1619 error(loc, "use 'shared static this()' to declare a shared static constructor"); 1620 } 1621 1622 Expression *constraint = tpl ? parseConstraint() : NULL; 1623 1624 Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto 1625 tf = tf->addSTC(stc); 1626 1627 CtorDeclaration *f = new CtorDeclaration(loc, Loc(), stc, tf); 1628 if (pAttrs) 1629 pAttrs->storageClass = STCundefined; 1630 Dsymbol *s = parseContracts(f); 1631 if (udas) 1632 { 1633 Dsymbols *a = new Dsymbols(); 1634 a->push(f); 1635 s = new UserAttributeDeclaration(udas, a); 1636 } 1637 1638 if (tpl) 1639 { 1640 // Wrap a template around it 1641 Dsymbols *decldefs = new Dsymbols(); 1642 decldefs->push(s); 1643 s = new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs); 1644 } 1645 1646 return s; 1647} 1648 1649/***************************************** 1650 * Parse a destructor definition: 1651 * ~this() { body } 1652 * Current token is '~'. 1653 */ 1654 1655Dsymbol *Parser::parseDtor(PrefixAttributes *pAttrs) 1656{ 1657 Expressions *udas = NULL; 1658 Loc loc = token.loc; 1659 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1660 1661 nextToken(); 1662 check(TOKthis); 1663 check(TOKlparen); 1664 check(TOKrparen); 1665 1666 stc = parsePostfix(stc, &udas); 1667 if (StorageClass ss = stc & (STCshared | STCstatic)) 1668 { 1669 if (ss == STCstatic) 1670 error(loc, "use 'static ~this()' to declare a static destructor"); 1671 else if (ss == (STCshared | STCstatic)) 1672 error(loc, "use 'shared static ~this()' to declare a shared static destructor"); 1673 } 1674 1675 DtorDeclaration *f = new DtorDeclaration(loc, Loc(), stc, Id::dtor); 1676 if (pAttrs) 1677 pAttrs->storageClass = STCundefined; 1678 Dsymbol *s = parseContracts(f); 1679 if (udas) 1680 { 1681 Dsymbols *a = new Dsymbols(); 1682 a->push(f); 1683 s = new UserAttributeDeclaration(udas, a); 1684 } 1685 return s; 1686} 1687 1688/***************************************** 1689 * Parse a static constructor definition: 1690 * static this() { body } 1691 * Current token is 'static'. 1692 */ 1693 1694Dsymbol *Parser::parseStaticCtor(PrefixAttributes *pAttrs) 1695{ 1696 //Expressions *udas = NULL; 1697 Loc loc = token.loc; 1698 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1699 1700 nextToken(); 1701 nextToken(); 1702 check(TOKlparen); 1703 check(TOKrparen); 1704 1705 stc = parsePostfix(stc & ~STC_TYPECTOR, NULL) | stc; 1706 if (stc & STCshared) 1707 error(loc, "use 'shared static this()' to declare a shared static constructor"); 1708 else if (stc & STCstatic) 1709 appendStorageClass(stc, STCstatic); // complaint for the redundancy 1710 else if (StorageClass modStc = stc & STC_TYPECTOR) 1711 { 1712 OutBuffer buf; 1713 stcToBuffer(&buf, modStc); 1714 error(loc, "static constructor cannot be %s", buf.peekString()); 1715 } 1716 stc &= ~(STCstatic | STC_TYPECTOR); 1717 1718 StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, Loc(), stc); 1719 if (pAttrs) 1720 pAttrs->storageClass = STCundefined; 1721 Dsymbol *s = parseContracts(f); 1722 return s; 1723} 1724 1725/***************************************** 1726 * Parse a static destructor definition: 1727 * static ~this() { body } 1728 * Current token is 'static'. 1729 */ 1730 1731Dsymbol *Parser::parseStaticDtor(PrefixAttributes *pAttrs) 1732{ 1733 Expressions *udas = NULL; 1734 Loc loc = token.loc; 1735 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1736 1737 nextToken(); 1738 nextToken(); 1739 check(TOKthis); 1740 check(TOKlparen); 1741 check(TOKrparen); 1742 1743 stc = parsePostfix(stc & ~STC_TYPECTOR, &udas) | stc; 1744 if (stc & STCshared) 1745 error(loc, "use 'shared static ~this()' to declare a shared static destructor"); 1746 else if (stc & STCstatic) 1747 appendStorageClass(stc, STCstatic); // complaint for the redundancy 1748 else if (StorageClass modStc = stc & STC_TYPECTOR) 1749 { 1750 OutBuffer buf; 1751 stcToBuffer(&buf, modStc); 1752 error(loc, "static destructor cannot be %s", buf.peekString()); 1753 } 1754 stc &= ~(STCstatic | STC_TYPECTOR); 1755 1756 StaticDtorDeclaration *f = new StaticDtorDeclaration(loc, Loc(), stc); 1757 if (pAttrs) 1758 pAttrs->storageClass = STCundefined; 1759 Dsymbol *s = parseContracts(f); 1760 if (udas) 1761 { 1762 Dsymbols *a = new Dsymbols(); 1763 a->push(f); 1764 s = new UserAttributeDeclaration(udas, a); 1765 } 1766 return s; 1767} 1768 1769/***************************************** 1770 * Parse a shared static constructor definition: 1771 * shared static this() { body } 1772 * Current token is 'shared'. 1773 */ 1774 1775Dsymbol *Parser::parseSharedStaticCtor(PrefixAttributes *pAttrs) 1776{ 1777 //Expressions *udas = NULL; 1778 Loc loc = token.loc; 1779 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1780 1781 nextToken(); 1782 nextToken(); 1783 nextToken(); 1784 check(TOKlparen); 1785 check(TOKrparen); 1786 1787 stc = parsePostfix(stc & ~STC_TYPECTOR, NULL) | stc; 1788 if (StorageClass ss = stc & (STCshared | STCstatic)) 1789 appendStorageClass(stc, ss); // complaint for the redundancy 1790 else if (StorageClass modStc = stc & STC_TYPECTOR) 1791 { 1792 OutBuffer buf; 1793 stcToBuffer(&buf, modStc); 1794 error(loc, "shared static constructor cannot be %s", buf.peekString()); 1795 } 1796 stc &= ~(STCstatic | STC_TYPECTOR); 1797 1798 SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, Loc(), stc); 1799 if (pAttrs) 1800 pAttrs->storageClass = STCundefined; 1801 Dsymbol *s = parseContracts(f); 1802 return s; 1803} 1804 1805/***************************************** 1806 * Parse a shared static destructor definition: 1807 * shared static ~this() { body } 1808 * Current token is 'shared'. 1809 */ 1810 1811Dsymbol *Parser::parseSharedStaticDtor(PrefixAttributes *pAttrs) 1812{ 1813 Expressions *udas = NULL; 1814 Loc loc = token.loc; 1815 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1816 1817 nextToken(); 1818 nextToken(); 1819 nextToken(); 1820 check(TOKthis); 1821 check(TOKlparen); 1822 check(TOKrparen); 1823 1824 stc = parsePostfix(stc & ~STC_TYPECTOR, &udas) | stc; 1825 if (StorageClass ss = stc & (STCshared | STCstatic)) 1826 appendStorageClass(stc, ss); // complaint for the redundancy 1827 else if (StorageClass modStc = stc & STC_TYPECTOR) 1828 { 1829 OutBuffer buf; 1830 stcToBuffer(&buf, modStc); 1831 error(loc, "shared static destructor cannot be %s", buf.peekString()); 1832 } 1833 stc &= ~(STCstatic | STC_TYPECTOR); 1834 1835 SharedStaticDtorDeclaration *f = new SharedStaticDtorDeclaration(loc, Loc(), stc); 1836 if (pAttrs) 1837 pAttrs->storageClass = STCundefined; 1838 Dsymbol *s = parseContracts(f); 1839 if (udas) 1840 { 1841 Dsymbols *a = new Dsymbols(); 1842 a->push(f); 1843 s = new UserAttributeDeclaration(udas, a); 1844 } 1845 return s; 1846} 1847 1848/***************************************** 1849 * Parse an invariant definition: 1850 * invariant() { body } 1851 * Current token is 'invariant'. 1852 */ 1853 1854Dsymbol *Parser::parseInvariant(PrefixAttributes *pAttrs) 1855{ 1856 Loc loc = token.loc; 1857 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1858 1859 nextToken(); 1860 if (token.value == TOKlparen) // optional () 1861 { 1862 nextToken(); 1863 check(TOKrparen); 1864 } 1865 1866 InvariantDeclaration *f = new InvariantDeclaration(loc, Loc(), stc); 1867 if (pAttrs) 1868 pAttrs->storageClass = STCundefined; 1869 f->fbody = parseStatement(PScurly); 1870 return f; 1871} 1872 1873/***************************************** 1874 * Parse a unittest definition: 1875 * unittest { body } 1876 * Current token is 'unittest'. 1877 */ 1878 1879Dsymbol *Parser::parseUnitTest(PrefixAttributes *pAttrs) 1880{ 1881 Loc loc = token.loc; 1882 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1883 1884 nextToken(); 1885 1886 const utf8_t *begPtr = token.ptr + 1; // skip '{' 1887 const utf8_t *endPtr = NULL; 1888 Statement *sbody = parseStatement(PScurly, &endPtr); 1889 1890 /** Extract unittest body as a string. Must be done eagerly since memory 1891 will be released by the lexer before doc gen. */ 1892 char *docline = NULL; 1893 if (global.params.doDocComments && endPtr > begPtr) 1894 { 1895 /* Remove trailing whitespaces */ 1896 for (const utf8_t *p = endPtr - 1; 1897 begPtr <= p && (*p == ' ' || *p == '\r' || *p == '\n' || *p == '\t'); --p) 1898 { 1899 endPtr = p; 1900 } 1901 1902 size_t len = endPtr - begPtr; 1903 if (len > 0) 1904 { 1905 docline = (char *)mem.xmalloc(len + 2); 1906 memcpy(docline, begPtr, len); 1907 docline[len ] = '\n'; // Terminate all lines by LF 1908 docline[len+1] = '\0'; 1909 } 1910 } 1911 1912 UnitTestDeclaration *f = new UnitTestDeclaration(loc, token.loc, stc, docline); 1913 if (pAttrs) 1914 pAttrs->storageClass = STCundefined; 1915 f->fbody = sbody; 1916 return f; 1917} 1918 1919/***************************************** 1920 * Parse a new definition: 1921 * new(parameters) { body } 1922 * Current token is 'new'. 1923 */ 1924 1925Dsymbol *Parser::parseNew(PrefixAttributes *pAttrs) 1926{ 1927 Loc loc = token.loc; 1928 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1929 1930 nextToken(); 1931 1932 int varargs; 1933 Parameters *parameters = parseParameters(&varargs); 1934 NewDeclaration *f = new NewDeclaration(loc, Loc(), stc, parameters, varargs); 1935 if (pAttrs) 1936 pAttrs->storageClass = STCundefined; 1937 Dsymbol *s = parseContracts(f); 1938 return s; 1939} 1940 1941/***************************************** 1942 * Parse a delete definition: 1943 * delete(parameters) { body } 1944 * Current token is 'delete'. 1945 */ 1946 1947Dsymbol *Parser::parseDelete(PrefixAttributes *pAttrs) 1948{ 1949 Loc loc = token.loc; 1950 StorageClass stc = pAttrs ? pAttrs->storageClass : STCundefined; 1951 1952 nextToken(); 1953 1954 int varargs; 1955 Parameters *parameters = parseParameters(&varargs); 1956 if (varargs) 1957 error("... not allowed in delete function parameter list"); 1958 DeleteDeclaration *f = new DeleteDeclaration(loc, Loc(), stc, parameters); 1959 if (pAttrs) 1960 pAttrs->storageClass = STCundefined; 1961 Dsymbol *s = parseContracts(f); 1962 return s; 1963} 1964 1965/********************************************** 1966 * Parse parameter list. 1967 */ 1968 1969Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) 1970{ 1971 Parameters *parameters = new Parameters(); 1972 int varargs = 0; 1973 int hasdefault = 0; 1974 1975 check(TOKlparen); 1976 while (1) 1977 { 1978 Identifier *ai = NULL; 1979 Type *at; 1980 StorageClass storageClass = 0; 1981 StorageClass stc; 1982 Expression *ae; 1983 1984 for (;1; nextToken()) 1985 { 1986 switch (token.value) 1987 { 1988 case TOKrparen: 1989 break; 1990 1991 case TOKdotdotdot: 1992 varargs = 1; 1993 nextToken(); 1994 break; 1995 1996 case TOKconst: 1997 if (peek(&token)->value == TOKlparen) 1998 goto Ldefault; 1999 stc = STCconst; 2000 goto L2; 2001 2002 case TOKimmutable: 2003 if (peek(&token)->value == TOKlparen) 2004 goto Ldefault; 2005 stc = STCimmutable; 2006 goto L2; 2007 2008 case TOKshared: 2009 if (peek(&token)->value == TOKlparen) 2010 goto Ldefault; 2011 stc = STCshared; 2012 goto L2; 2013 2014 case TOKwild: 2015 if (peek(&token)->value == TOKlparen) 2016 goto Ldefault; 2017 stc = STCwild; 2018 goto L2; 2019 2020 case TOKin: stc = STCin; goto L2; 2021 case TOKout: stc = STCout; goto L2; 2022 case TOKref: stc = STCref; goto L2; 2023 case TOKlazy: stc = STClazy; goto L2; 2024 case TOKscope: stc = STCscope; goto L2; 2025 case TOKfinal: stc = STCfinal; goto L2; 2026 case TOKauto: stc = STCauto; goto L2; 2027 case TOKreturn: stc = STCreturn; goto L2; 2028 L2: 2029 storageClass = appendStorageClass(storageClass, stc); 2030 continue; 2031 2032 default: 2033 Ldefault: 2034 { stc = storageClass & (STCin | STCout | STCref | STClazy); 2035 // if stc is not a power of 2 2036 if (stc & (stc - 1) && 2037 !(stc == (STCin | STCref))) 2038 error("incompatible parameter storage classes"); 2039 //if ((storageClass & STCscope) && (storageClass & (STCref | STCout))) 2040 //error("scope cannot be ref or out"); 2041 2042 Token *t; 2043 if (tpl && token.value == TOKidentifier && 2044 (t = peek(&token), (t->value == TOKcomma || 2045 t->value == TOKrparen || 2046 t->value == TOKdotdotdot))) 2047 { 2048 Identifier *id = Identifier::generateId("__T"); 2049 Loc loc = token.loc; 2050 at = new TypeIdentifier(loc, id); 2051 if (!*tpl) 2052 *tpl = new TemplateParameters(); 2053 TemplateParameter *tp = new TemplateTypeParameter(loc, id, NULL, NULL); 2054 (*tpl)->push(tp); 2055 2056 ai = token.ident; 2057 nextToken(); 2058 } 2059 else 2060 at = parseType(&ai); 2061 ae = NULL; 2062 if (token.value == TOKassign) // = defaultArg 2063 { nextToken(); 2064 ae = parseDefaultInitExp(); 2065 hasdefault = 1; 2066 } 2067 else 2068 { if (hasdefault) 2069 error("default argument expected for %s", 2070 ai ? ai->toChars() : at->toChars()); 2071 } 2072 if (token.value == TOKdotdotdot) 2073 { /* This is: 2074 * at ai ... 2075 */ 2076 2077 if (storageClass & (STCout | STCref)) 2078 error("variadic argument cannot be out or ref"); 2079 varargs = 2; 2080 parameters->push(new Parameter(storageClass, at, ai, ae)); 2081 nextToken(); 2082 break; 2083 } 2084 parameters->push(new Parameter(storageClass, at, ai, ae)); 2085 if (token.value == TOKcomma) 2086 { nextToken(); 2087 goto L1; 2088 } 2089 break; 2090 } 2091 } 2092 break; 2093 } 2094 break; 2095 2096 L1: ; 2097 } 2098 check(TOKrparen); 2099 *pvarargs = varargs; 2100 return parameters; 2101} 2102 2103 2104/************************************* 2105 */ 2106 2107EnumDeclaration *Parser::parseEnum() 2108{ 2109 EnumDeclaration *e; 2110 Identifier *id; 2111 Type *memtype; 2112 Loc loc = token.loc; 2113 2114 //printf("Parser::parseEnum()\n"); 2115 nextToken(); 2116 if (token.value == TOKidentifier) 2117 { 2118 id = token.ident; 2119 nextToken(); 2120 } 2121 else 2122 id = NULL; 2123 2124 if (token.value == TOKcolon) 2125 { 2126 nextToken(); 2127 2128 int alt = 0; 2129 Loc typeLoc = token.loc; 2130 memtype = parseBasicType(); 2131 memtype = parseDeclarator(memtype, &alt, NULL); 2132 checkCstyleTypeSyntax(typeLoc, memtype, alt, NULL); 2133 } 2134 else 2135 memtype = NULL; 2136 2137 e = new EnumDeclaration(loc, id, memtype); 2138 if (token.value == TOKsemicolon && id) 2139 nextToken(); 2140 else if (token.value == TOKlcurly) 2141 { 2142 //printf("enum definition\n"); 2143 e->members = new Dsymbols(); 2144 nextToken(); 2145 const utf8_t *comment = token.blockComment; 2146 while (token.value != TOKrcurly) 2147 { 2148 /* Can take the following forms: 2149 * 1. ident 2150 * 2. ident = value 2151 * 3. type ident = value 2152 */ 2153 2154 loc = token.loc; 2155 2156 Type *type = NULL; 2157 Identifier *ident = NULL; 2158 Token *tp = peek(&token); 2159 if (token.value == TOKidentifier && 2160 (tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly)) 2161 { 2162 ident = token.ident; 2163 type = NULL; 2164 nextToken(); 2165 } 2166 else 2167 { 2168 type = parseType(&ident, NULL); 2169 if (!ident) 2170 error("no identifier for declarator %s", type->toChars()); 2171 if (id || memtype) 2172 error("type only allowed if anonymous enum and no enum type"); 2173 } 2174 2175 Expression *value; 2176 if (token.value == TOKassign) 2177 { 2178 nextToken(); 2179 value = parseAssignExp(); 2180 } 2181 else 2182 { 2183 value = NULL; 2184 if (type) 2185 error("if type, there must be an initializer"); 2186 } 2187 2188 EnumMember *em = new EnumMember(loc, ident, value, type); 2189 e->members->push(em); 2190 2191 if (token.value == TOKrcurly) 2192 ; 2193 else 2194 { 2195 addComment(em, comment); 2196 comment = NULL; 2197 check(TOKcomma); 2198 } 2199 addComment(em, comment); 2200 comment = token.blockComment; 2201 2202 if (token.value == TOKeof) 2203 { 2204 error("premature end of file"); 2205 break; 2206 } 2207 } 2208 nextToken(); 2209 } 2210 else 2211 error("enum declaration is invalid"); 2212 2213 //printf("-parseEnum() %s\n", e->toChars()); 2214 return e; 2215} 2216 2217/******************************** 2218 * Parse struct, union, interface, class. 2219 */ 2220 2221Dsymbol *Parser::parseAggregate() 2222{ 2223 AggregateDeclaration *a = NULL; 2224 int anon = 0; 2225 Identifier *id; 2226 TemplateParameters *tpl = NULL; 2227 Expression *constraint = NULL; 2228 Loc loc = token.loc; 2229 TOK tok = token.value; 2230 2231 //printf("Parser::parseAggregate()\n"); 2232 nextToken(); 2233 if (token.value != TOKidentifier) 2234 { 2235 id = NULL; 2236 } 2237 else 2238 { 2239 id = token.ident; 2240 nextToken(); 2241 2242 if (token.value == TOKlparen) 2243 { 2244 // Class template declaration. 2245 // Gather template parameter list 2246 tpl = parseTemplateParameterList(); 2247 constraint = parseConstraint(); 2248 } 2249 } 2250 2251 switch (tok) 2252 { 2253 case TOKclass: 2254 case TOKinterface: 2255 { 2256 if (!id) 2257 error(loc, "anonymous classes not allowed"); 2258 2259 // Collect base class(es) 2260 BaseClasses *baseclasses = NULL; 2261 if (token.value == TOKcolon) 2262 { 2263 nextToken(); 2264 baseclasses = parseBaseClasses(); 2265 2266 if (tpl) 2267 { 2268 Expression *tempCons = parseConstraint(); 2269 if (tempCons) 2270 { 2271 if (constraint) 2272 error("members expected"); 2273 else 2274 constraint = tempCons; 2275 } 2276 } 2277 2278 if (token.value != TOKlcurly) 2279 error("members expected"); 2280 } 2281 2282 if (tok == TOKclass) 2283 { 2284 bool inObject = md && !md->packages && md->id == Id::object; 2285 a = new ClassDeclaration(loc, id, baseclasses, NULL, inObject); 2286 } 2287 else 2288 a = new InterfaceDeclaration(loc, id, baseclasses); 2289 break; 2290 } 2291 2292 case TOKstruct: 2293 if (id) 2294 { 2295 bool inObject = md && !md->packages && md->id == Id::object; 2296 a = new StructDeclaration(loc, id, inObject); 2297 } 2298 else 2299 anon = 1; 2300 break; 2301 2302 case TOKunion: 2303 if (id) 2304 a = new UnionDeclaration(loc, id); 2305 else 2306 anon = 2; 2307 break; 2308 2309 default: 2310 assert(0); 2311 break; 2312 } 2313 if (a && token.value == TOKsemicolon) 2314 { 2315 nextToken(); 2316 } 2317 else if (token.value == TOKlcurly) 2318 { 2319 const Loc lookingForElseSave = lookingForElse; 2320 lookingForElse = Loc(); 2321 //printf("aggregate definition\n"); 2322 nextToken(); 2323 Dsymbols *decl = parseDeclDefs(0); 2324 lookingForElse = lookingForElseSave; 2325 if (token.value != TOKrcurly) 2326 error("} expected following members in %s declaration at %s", 2327 Token::toChars(tok), loc.toChars()); 2328 nextToken(); 2329 if (anon) 2330 { 2331 /* Anonymous structs/unions are more like attributes. 2332 */ 2333 return new AnonDeclaration(loc, anon == 2, decl); 2334 } 2335 else 2336 a->members = decl; 2337 } 2338 else 2339 { 2340 error("{ } expected following %s declaration", Token::toChars(tok)); 2341 a = new StructDeclaration(loc, NULL, false); 2342 } 2343 2344 if (tpl) 2345 { 2346 // Wrap a template around the aggregate declaration 2347 Dsymbols *decldefs = new Dsymbols(); 2348 decldefs->push(a); 2349 TemplateDeclaration *tempdecl = 2350 new TemplateDeclaration(loc, id, tpl, constraint, decldefs); 2351 return tempdecl; 2352 } 2353 2354 return a; 2355} 2356 2357/******************************************* 2358 */ 2359 2360BaseClasses *Parser::parseBaseClasses() 2361{ 2362 BaseClasses *baseclasses = new BaseClasses(); 2363 2364 for (; 1; nextToken()) 2365 { 2366 bool prot = false; 2367 Prot protection = Prot(PROTpublic); 2368 switch (token.value) 2369 { 2370 case TOKprivate: 2371 prot = true; 2372 protection = Prot(PROTprivate); 2373 nextToken(); 2374 break; 2375 case TOKpackage: 2376 prot = true; 2377 protection = Prot(PROTpackage); 2378 nextToken(); 2379 break; 2380 case TOKprotected: 2381 prot = true; 2382 protection = Prot(PROTprotected); 2383 nextToken(); 2384 break; 2385 case TOKpublic: 2386 prot = true; 2387 protection = Prot(PROTpublic); 2388 nextToken(); 2389 break; 2390 default: break; 2391 } 2392 if (prot) 2393 error("use of base class protection is no longer supported"); 2394 BaseClass *b = new BaseClass(parseBasicType()); 2395 baseclasses->push(b); 2396 if (token.value != TOKcomma) 2397 break; 2398 } 2399 return baseclasses; 2400} 2401 2402/************************************** 2403 * Parse constraint. 2404 * Constraint is of the form: 2405 * if ( ConstraintExpression ) 2406 */ 2407 2408Expression *Parser::parseConstraint() 2409{ Expression *e = NULL; 2410 2411 if (token.value == TOKif) 2412 { 2413 nextToken(); // skip over 'if' 2414 check(TOKlparen); 2415 e = parseExpression(); 2416 check(TOKrparen); 2417 } 2418 return e; 2419} 2420 2421/************************************** 2422 * Parse a TemplateDeclaration. 2423 */ 2424 2425TemplateDeclaration *Parser::parseTemplateDeclaration(bool ismixin) 2426{ 2427 TemplateDeclaration *tempdecl; 2428 Identifier *id; 2429 TemplateParameters *tpl; 2430 Dsymbols *decldefs; 2431 Expression *constraint = NULL; 2432 Loc loc = token.loc; 2433 2434 nextToken(); 2435 if (token.value != TOKidentifier) 2436 { 2437 error("identifier expected following template"); 2438 goto Lerr; 2439 } 2440 id = token.ident; 2441 nextToken(); 2442 tpl = parseTemplateParameterList(); 2443 if (!tpl) 2444 goto Lerr; 2445 2446 constraint = parseConstraint(); 2447 2448 if (token.value != TOKlcurly) 2449 { 2450 error("members of template declaration expected"); 2451 goto Lerr; 2452 } 2453 else 2454 decldefs = parseBlock(NULL); 2455 2456 tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs, ismixin); 2457 return tempdecl; 2458 2459Lerr: 2460 return NULL; 2461} 2462 2463/****************************************** 2464 * Parse template parameter list. 2465 * Input: 2466 * flag 0: parsing "( list )" 2467 * 1: parsing non-empty "list )" 2468 */ 2469 2470TemplateParameters *Parser::parseTemplateParameterList(int flag) 2471{ 2472 TemplateParameters *tpl = new TemplateParameters(); 2473 2474 if (!flag && token.value != TOKlparen) 2475 { error("parenthesized TemplateParameterList expected following TemplateIdentifier"); 2476 goto Lerr; 2477 } 2478 nextToken(); 2479 2480 // Get array of TemplateParameters 2481 if (flag || token.value != TOKrparen) 2482 { 2483 int isvariadic = 0; 2484 while (token.value != TOKrparen) 2485 { 2486 TemplateParameter *tp; 2487 Loc loc; 2488 Identifier *tp_ident = NULL; 2489 Type *tp_spectype = NULL; 2490 Type *tp_valtype = NULL; 2491 Type *tp_defaulttype = NULL; 2492 Expression *tp_specvalue = NULL; 2493 Expression *tp_defaultvalue = NULL; 2494 Token *t; 2495 2496 // Get TemplateParameter 2497 2498 // First, look ahead to see if it is a TypeParameter or a ValueParameter 2499 t = peek(&token); 2500 if (token.value == TOKalias) 2501 { // AliasParameter 2502 nextToken(); 2503 loc = token.loc; // todo 2504 Type *spectype = NULL; 2505 if (isDeclaration(&token, 2, TOKreserved, NULL)) 2506 { 2507 spectype = parseType(&tp_ident); 2508 } 2509 else 2510 { 2511 if (token.value != TOKidentifier) 2512 { 2513 error("identifier expected for template alias parameter"); 2514 goto Lerr; 2515 } 2516 tp_ident = token.ident; 2517 nextToken(); 2518 } 2519 RootObject *spec = NULL; 2520 if (token.value == TOKcolon) // : Type 2521 { 2522 nextToken(); 2523 if (isDeclaration(&token, 0, TOKreserved, NULL)) 2524 spec = parseType(); 2525 else 2526 spec = parseCondExp(); 2527 } 2528 RootObject *def = NULL; 2529 if (token.value == TOKassign) // = Type 2530 { 2531 nextToken(); 2532 if (isDeclaration(&token, 0, TOKreserved, NULL)) 2533 def = parseType(); 2534 else 2535 def = parseCondExp(); 2536 } 2537 tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def); 2538 } 2539 else if (t->value == TOKcolon || t->value == TOKassign || 2540 t->value == TOKcomma || t->value == TOKrparen) 2541 { 2542 // TypeParameter 2543 if (token.value != TOKidentifier) 2544 { 2545 error("identifier expected for template type parameter"); 2546 goto Lerr; 2547 } 2548 loc = token.loc; 2549 tp_ident = token.ident; 2550 nextToken(); 2551 if (token.value == TOKcolon) // : Type 2552 { 2553 nextToken(); 2554 tp_spectype = parseType(); 2555 } 2556 if (token.value == TOKassign) // = Type 2557 { 2558 nextToken(); 2559 tp_defaulttype = parseType(); 2560 } 2561 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype); 2562 } 2563 else if (token.value == TOKidentifier && t->value == TOKdotdotdot) 2564 { 2565 // ident... 2566 if (isvariadic) 2567 error("variadic template parameter must be last"); 2568 isvariadic = 1; 2569 loc = token.loc; 2570 tp_ident = token.ident; 2571 nextToken(); 2572 nextToken(); 2573 tp = new TemplateTupleParameter(loc, tp_ident); 2574 } 2575 else if (token.value == TOKthis) 2576 { 2577 // ThisParameter 2578 nextToken(); 2579 if (token.value != TOKidentifier) 2580 { 2581 error("identifier expected for template this parameter"); 2582 goto Lerr; 2583 } 2584 loc = token.loc; 2585 tp_ident = token.ident; 2586 nextToken(); 2587 if (token.value == TOKcolon) // : Type 2588 { 2589 nextToken(); 2590 tp_spectype = parseType(); 2591 } 2592 if (token.value == TOKassign) // = Type 2593 { 2594 nextToken(); 2595 tp_defaulttype = parseType(); 2596 } 2597 tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype); 2598 } 2599 else 2600 { 2601 // ValueParameter 2602 loc = token.loc; // todo 2603 tp_valtype = parseType(&tp_ident); 2604 if (!tp_ident) 2605 { 2606 error("identifier expected for template value parameter"); 2607 tp_ident = Identifier::idPool("error"); 2608 } 2609 if (token.value == TOKcolon) // : CondExpression 2610 { 2611 nextToken(); 2612 tp_specvalue = parseCondExp(); 2613 } 2614 if (token.value == TOKassign) // = CondExpression 2615 { 2616 nextToken(); 2617 tp_defaultvalue = parseDefaultInitExp(); 2618 } 2619 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue); 2620 } 2621 tpl->push(tp); 2622 if (token.value != TOKcomma) 2623 break; 2624 nextToken(); 2625 } 2626 } 2627 check(TOKrparen); 2628Lerr: 2629 return tpl; 2630} 2631 2632/****************************************** 2633 * Parse template mixin. 2634 * mixin Foo; 2635 * mixin Foo!(args); 2636 * mixin a.b.c!(args).Foo!(args); 2637 * mixin Foo!(args) identifier; 2638 * mixin typeof(expr).identifier!(args); 2639 */ 2640 2641Dsymbol *Parser::parseMixin() 2642{ 2643 TemplateMixin *tm; 2644 Identifier *id; 2645 Objects *tiargs; 2646 2647 //printf("parseMixin()\n"); 2648 Loc locMixin = token.loc; 2649 nextToken(); // skip 'mixin' 2650 2651 Loc loc = token.loc; 2652 TypeQualified *tqual = NULL; 2653 if (token.value == TOKdot) 2654 { 2655 id = Id::empty; 2656 } 2657 else 2658 { 2659 if (token.value == TOKtypeof) 2660 { 2661 tqual = parseTypeof(); 2662 check(TOKdot); 2663 } 2664 if (token.value != TOKidentifier) 2665 { 2666 error("identifier expected, not %s", token.toChars()); 2667 id = Id::empty; 2668 } 2669 else 2670 id = token.ident; 2671 nextToken(); 2672 } 2673 2674 while (1) 2675 { 2676 tiargs = NULL; 2677 if (token.value == TOKnot) 2678 { 2679 tiargs = parseTemplateArguments(); 2680 } 2681 2682 if (tiargs && token.value == TOKdot) 2683 { 2684 TemplateInstance *tempinst = new TemplateInstance(loc, id); 2685 tempinst->tiargs = tiargs; 2686 if (!tqual) 2687 tqual = new TypeInstance(loc, tempinst); 2688 else 2689 tqual->addInst(tempinst); 2690 tiargs = NULL; 2691 } 2692 else 2693 { 2694 if (!tqual) 2695 tqual = new TypeIdentifier(loc, id); 2696 else 2697 tqual->addIdent(id); 2698 } 2699 2700 if (token.value != TOKdot) 2701 break; 2702 2703 nextToken(); 2704 if (token.value != TOKidentifier) 2705 { 2706 error("identifier expected following '.' instead of '%s'", token.toChars()); 2707 break; 2708 } 2709 loc = token.loc; 2710 id = token.ident; 2711 nextToken(); 2712 } 2713 2714 if (token.value == TOKidentifier) 2715 { 2716 id = token.ident; 2717 nextToken(); 2718 } 2719 else 2720 id = NULL; 2721 2722 tm = new TemplateMixin(locMixin, id, tqual, tiargs); 2723 if (token.value != TOKsemicolon) 2724 error("';' expected after mixin"); 2725 nextToken(); 2726 2727 return tm; 2728} 2729 2730/****************************************** 2731 * Parse template arguments. 2732 * Input: 2733 * current token is opening '!' 2734 * Output: 2735 * current token is one after closing ')' 2736 */ 2737 2738Objects *Parser::parseTemplateArguments() 2739{ 2740 Objects *tiargs; 2741 2742 nextToken(); 2743 if (token.value == TOKlparen) 2744 { 2745 // ident!(template_arguments) 2746 tiargs = parseTemplateArgumentList(); 2747 } 2748 else 2749 { 2750 // ident!template_argument 2751 tiargs = parseTemplateSingleArgument(); 2752 } 2753 if (token.value == TOKnot) 2754 { 2755 TOK tok = peekNext(); 2756 if (tok != TOKis && tok != TOKin) 2757 { 2758 error("multiple ! arguments are not allowed"); 2759 Lagain: 2760 nextToken(); 2761 if (token.value == TOKlparen) 2762 parseTemplateArgumentList(); 2763 else 2764 parseTemplateSingleArgument(); 2765 if (token.value == TOKnot && (tok = peekNext()) != TOKis && tok != TOKin) 2766 goto Lagain; 2767 } 2768 } 2769 return tiargs; 2770} 2771 2772/****************************************** 2773 * Parse template argument list. 2774 * Input: 2775 * current token is opening '(', 2776 * or ',' for __traits 2777 * Output: 2778 * current token is one after closing ')' 2779 */ 2780 2781Objects *Parser::parseTemplateArgumentList() 2782{ 2783 //printf("Parser::parseTemplateArgumentList()\n"); 2784 Objects *tiargs = new Objects(); 2785 TOK endtok = TOKrparen; 2786 assert(token.value == TOKlparen || token.value == TOKcomma); 2787 nextToken(); 2788 2789 // Get TemplateArgumentList 2790 while (token.value != endtok) 2791 { 2792 // See if it is an Expression or a Type 2793 if (isDeclaration(&token, 0, TOKreserved, NULL)) 2794 { // Template argument is a type 2795 Type *ta = parseType(); 2796 tiargs->push(ta); 2797 } 2798 else 2799 { // Template argument is an expression 2800 Expression *ea = parseAssignExp(); 2801 tiargs->push(ea); 2802 } 2803 if (token.value != TOKcomma) 2804 break; 2805 nextToken(); 2806 } 2807 check(endtok, "template argument list"); 2808 return tiargs; 2809} 2810 2811/***************************** 2812 * Parse single template argument, to support the syntax: 2813 * foo!arg 2814 * Input: 2815 * current token is the arg 2816 */ 2817 2818Objects *Parser::parseTemplateSingleArgument() 2819{ 2820 //printf("parseTemplateSingleArgument()\n"); 2821 Objects *tiargs = new Objects(); 2822 Type *ta; 2823 switch (token.value) 2824 { 2825 case TOKidentifier: 2826 ta = new TypeIdentifier(token.loc, token.ident); 2827 goto LabelX; 2828 2829 case TOKvector: 2830 ta = parseVector(); 2831 goto LabelX; 2832 2833 case TOKvoid: ta = Type::tvoid; goto LabelX; 2834 case TOKint8: ta = Type::tint8; goto LabelX; 2835 case TOKuns8: ta = Type::tuns8; goto LabelX; 2836 case TOKint16: ta = Type::tint16; goto LabelX; 2837 case TOKuns16: ta = Type::tuns16; goto LabelX; 2838 case TOKint32: ta = Type::tint32; goto LabelX; 2839 case TOKuns32: ta = Type::tuns32; goto LabelX; 2840 case TOKint64: ta = Type::tint64; goto LabelX; 2841 case TOKuns64: ta = Type::tuns64; goto LabelX; 2842 case TOKint128: ta = Type::tint128; goto LabelX; 2843 case TOKuns128: ta = Type::tuns128; goto LabelX; 2844 case TOKfloat32: ta = Type::tfloat32; goto LabelX; 2845 case TOKfloat64: ta = Type::tfloat64; goto LabelX; 2846 case TOKfloat80: ta = Type::tfloat80; goto LabelX; 2847 case TOKimaginary32: ta = Type::timaginary32; goto LabelX; 2848 case TOKimaginary64: ta = Type::timaginary64; goto LabelX; 2849 case TOKimaginary80: ta = Type::timaginary80; goto LabelX; 2850 case TOKcomplex32: ta = Type::tcomplex32; goto LabelX; 2851 case TOKcomplex64: ta = Type::tcomplex64; goto LabelX; 2852 case TOKcomplex80: ta = Type::tcomplex80; goto LabelX; 2853 case TOKbool: ta = Type::tbool; goto LabelX; 2854 case TOKchar: ta = Type::tchar; goto LabelX; 2855 case TOKwchar: ta = Type::twchar; goto LabelX; 2856 case TOKdchar: ta = Type::tdchar; goto LabelX; 2857 LabelX: 2858 tiargs->push(ta); 2859 nextToken(); 2860 break; 2861 2862 case TOKint32v: 2863 case TOKuns32v: 2864 case TOKint64v: 2865 case TOKuns64v: 2866 case TOKint128v: 2867 case TOKuns128v: 2868 case TOKfloat32v: 2869 case TOKfloat64v: 2870 case TOKfloat80v: 2871 case TOKimaginary32v: 2872 case TOKimaginary64v: 2873 case TOKimaginary80v: 2874 case TOKnull: 2875 case TOKtrue: 2876 case TOKfalse: 2877 case TOKcharv: 2878 case TOKwcharv: 2879 case TOKdcharv: 2880 case TOKstring: 2881 case TOKxstring: 2882 case TOKfile: 2883 case TOKfilefullpath: 2884 case TOKline: 2885 case TOKmodulestring: 2886 case TOKfuncstring: 2887 case TOKprettyfunc: 2888 case TOKthis: 2889 { // Template argument is an expression 2890 Expression *ea = parsePrimaryExp(); 2891 tiargs->push(ea); 2892 break; 2893 } 2894 2895 default: 2896 error("template argument expected following !"); 2897 break; 2898 } 2899 return tiargs; 2900} 2901 2902Dsymbols *Parser::parseImport() 2903{ 2904 Dsymbols *decldefs = new Dsymbols(); 2905 Identifier *aliasid = NULL; 2906 2907 int isstatic = token.value == TOKstatic; 2908 if (isstatic) 2909 nextToken(); 2910 2911 //printf("Parser::parseImport()\n"); 2912 do 2913 { 2914 L1: 2915 nextToken(); 2916 if (token.value != TOKidentifier) 2917 { 2918 error("identifier expected following import"); 2919 break; 2920 } 2921 2922 Loc loc = token.loc; 2923 Identifier *id = token.ident; 2924 Identifiers *a = NULL; 2925 nextToken(); 2926 if (!aliasid && token.value == TOKassign) 2927 { 2928 aliasid = id; 2929 goto L1; 2930 } 2931 while (token.value == TOKdot) 2932 { 2933 if (!a) 2934 a = new Identifiers(); 2935 a->push(id); 2936 nextToken(); 2937 if (token.value != TOKidentifier) 2938 { 2939 error("identifier expected following package"); 2940 break; 2941 } 2942 id = token.ident; 2943 nextToken(); 2944 } 2945 2946 Import *s = new Import(loc, a, id, aliasid, isstatic); 2947 decldefs->push(s); 2948 2949 /* Look for 2950 * : alias=name, alias=name; 2951 * syntax. 2952 */ 2953 if (token.value == TOKcolon) 2954 { 2955 do 2956 { 2957 nextToken(); 2958 if (token.value != TOKidentifier) 2959 { 2960 error("identifier expected following :"); 2961 break; 2962 } 2963 Identifier *alias = token.ident; 2964 Identifier *name; 2965 nextToken(); 2966 if (token.value == TOKassign) 2967 { 2968 nextToken(); 2969 if (token.value != TOKidentifier) 2970 { 2971 error("identifier expected following %s=", alias->toChars()); 2972 break; 2973 } 2974 name = token.ident; 2975 nextToken(); 2976 } 2977 else 2978 { 2979 name = alias; 2980 alias = NULL; 2981 } 2982 s->addAlias(name, alias); 2983 } while (token.value == TOKcomma); 2984 break; // no comma-separated imports of this form 2985 } 2986 2987 aliasid = NULL; 2988 } while (token.value == TOKcomma); 2989 2990 if (token.value == TOKsemicolon) 2991 nextToken(); 2992 else 2993 { 2994 error("';' expected"); 2995 nextToken(); 2996 } 2997 2998 return decldefs; 2999} 3000 3001Type *Parser::parseType(Identifier **pident, TemplateParameters **ptpl) 3002{ 3003 /* Take care of the storage class prefixes that 3004 * serve as type attributes: 3005 * const type 3006 * immutable type 3007 * shared type 3008 * inout type 3009 * inout const type 3010 * shared const type 3011 * shared inout type 3012 * shared inout const type 3013 */ 3014 StorageClass stc = 0; 3015 while (1) 3016 { 3017 switch (token.value) 3018 { 3019 case TOKconst: 3020 if (peekNext() == TOKlparen) 3021 break; // const as type constructor 3022 stc |= STCconst; // const as storage class 3023 nextToken(); 3024 continue; 3025 3026 case TOKimmutable: 3027 if (peekNext() == TOKlparen) 3028 break; 3029 stc |= STCimmutable; 3030 nextToken(); 3031 continue; 3032 3033 case TOKshared: 3034 if (peekNext() == TOKlparen) 3035 break; 3036 stc |= STCshared; 3037 nextToken(); 3038 continue; 3039 3040 case TOKwild: 3041 if (peekNext() == TOKlparen) 3042 break; 3043 stc |= STCwild; 3044 nextToken(); 3045 continue; 3046 3047 default: 3048 break; 3049 } 3050 break; 3051 } 3052 3053 Loc typeLoc = token.loc; 3054 3055 Type *t; 3056 t = parseBasicType(); 3057 3058 int alt = 0; 3059 t = parseDeclarator(t, &alt, pident, ptpl); 3060 checkCstyleTypeSyntax(typeLoc, t, alt, pident ? *pident : NULL); 3061 3062 t = t->addSTC(stc); 3063 return t; 3064} 3065 3066Type *Parser::parseBasicType(bool dontLookDotIdents) 3067{ 3068 Type *t; 3069 Loc loc; 3070 Identifier *id; 3071 3072 //printf("parseBasicType()\n"); 3073 switch (token.value) 3074 { 3075 case TOKvoid: t = Type::tvoid; goto LabelX; 3076 case TOKint8: t = Type::tint8; goto LabelX; 3077 case TOKuns8: t = Type::tuns8; goto LabelX; 3078 case TOKint16: t = Type::tint16; goto LabelX; 3079 case TOKuns16: t = Type::tuns16; goto LabelX; 3080 case TOKint32: t = Type::tint32; goto LabelX; 3081 case TOKuns32: t = Type::tuns32; goto LabelX; 3082 case TOKint64: 3083 t = Type::tint64; 3084 nextToken(); 3085 if (token.value == TOKint64) // if `long long` 3086 { 3087 error("use `long` for a 64 bit integer instead of `long long`"); 3088 nextToken(); 3089 } 3090 else if (token.value == TOKfloat64) // if `long double` 3091 { 3092 error("use `real` instead of `long double`"); 3093 t = Type::tfloat80; 3094 nextToken(); 3095 3096 } 3097 break; 3098 3099 case TOKuns64: t = Type::tuns64; goto LabelX; 3100 case TOKint128: t = Type::tint128; goto LabelX; 3101 case TOKuns128: t = Type::tuns128; goto LabelX; 3102 case TOKfloat32: t = Type::tfloat32; goto LabelX; 3103 case TOKfloat64: t = Type::tfloat64; goto LabelX; 3104 case TOKfloat80: t = Type::tfloat80; goto LabelX; 3105 case TOKimaginary32: t = Type::timaginary32; goto LabelX; 3106 case TOKimaginary64: t = Type::timaginary64; goto LabelX; 3107 case TOKimaginary80: t = Type::timaginary80; goto LabelX; 3108 case TOKcomplex32: t = Type::tcomplex32; goto LabelX; 3109 case TOKcomplex64: t = Type::tcomplex64; goto LabelX; 3110 case TOKcomplex80: t = Type::tcomplex80; goto LabelX; 3111 case TOKbool: t = Type::tbool; goto LabelX; 3112 case TOKchar: t = Type::tchar; goto LabelX; 3113 case TOKwchar: t = Type::twchar; goto LabelX; 3114 case TOKdchar: t = Type::tdchar; goto LabelX; 3115 LabelX: 3116 nextToken(); 3117 break; 3118 3119 case TOKthis: 3120 case TOKsuper: 3121 case TOKidentifier: 3122 loc = token.loc; 3123 id = token.ident; 3124 nextToken(); 3125 if (token.value == TOKnot) 3126 { 3127 // ident!(template_arguments) 3128 TemplateInstance *tempinst = new TemplateInstance(loc, id); 3129 tempinst->tiargs = parseTemplateArguments(); 3130 t = parseBasicTypeStartingAt(new TypeInstance(loc, tempinst), dontLookDotIdents); 3131 } 3132 else 3133 { 3134 t = parseBasicTypeStartingAt(new TypeIdentifier(loc, id), dontLookDotIdents); 3135 } 3136 break; 3137 3138 case TOKdot: 3139 // Leading . as in .foo 3140 t = parseBasicTypeStartingAt(new TypeIdentifier(token.loc, Id::empty), dontLookDotIdents); 3141 break; 3142 3143 case TOKtypeof: 3144 // typeof(expression) 3145 t = parseBasicTypeStartingAt(parseTypeof(), dontLookDotIdents); 3146 break; 3147 3148 case TOKvector: 3149 t = parseVector(); 3150 break; 3151 3152 case TOKtraits: 3153 if (TraitsExp *te = (TraitsExp *) parsePrimaryExp()) 3154 { 3155 if (te->ident && te->args) 3156 { 3157 t = new TypeTraits(token.loc, te); 3158 break; 3159 } 3160 } 3161 t = new TypeError(); 3162 break; 3163 3164 case TOKconst: 3165 // const(type) 3166 nextToken(); 3167 check(TOKlparen); 3168 t = parseType()->addSTC(STCconst); 3169 check(TOKrparen); 3170 break; 3171 3172 case TOKimmutable: 3173 // immutable(type) 3174 nextToken(); 3175 check(TOKlparen); 3176 t = parseType()->addSTC(STCimmutable); 3177 check(TOKrparen); 3178 break; 3179 3180 case TOKshared: 3181 // shared(type) 3182 nextToken(); 3183 check(TOKlparen); 3184 t = parseType()->addSTC(STCshared); 3185 check(TOKrparen); 3186 break; 3187 3188 case TOKwild: 3189 // wild(type) 3190 nextToken(); 3191 check(TOKlparen); 3192 t = parseType()->addSTC(STCwild); 3193 check(TOKrparen); 3194 break; 3195 3196 default: 3197 error("basic type expected, not %s", token.toChars()); 3198 t = Type::terror; 3199 break; 3200 } 3201 return t; 3202} 3203 3204Type *Parser::parseBasicTypeStartingAt(TypeQualified *tid, bool dontLookDotIdents) 3205{ 3206 Type *maybeArray = NULL; 3207 // See https://issues.dlang.org/show_bug.cgi?id=1215 3208 // A basic type can look like MyType (typical case), but also: 3209 // MyType.T -> A type 3210 // MyType[expr] -> Either a static array of MyType or a type (iif MyType is a Ttuple) 3211 // MyType[expr].T -> A type. 3212 // MyType[expr].T[expr] -> Either a static array of MyType[expr].T or a type 3213 // (iif MyType[expr].T is a Ttuple) 3214 while (1) 3215 { 3216 switch (token.value) 3217 { 3218 case TOKdot: 3219 { 3220 nextToken(); 3221 if (token.value != TOKidentifier) 3222 { 3223 error("identifier expected following '.' instead of '%s'", token.toChars()); 3224 break; 3225 } 3226 if (maybeArray) 3227 { 3228 // This is actually a TypeTuple index, not an {a/s}array. 3229 // We need to have a while loop to unwind all index taking: 3230 // T[e1][e2].U -> T, addIndex(e1), addIndex(e2) 3231 Objects dimStack; 3232 Type *t = maybeArray; 3233 while (true) 3234 { 3235 if (t->ty == Tsarray) 3236 { 3237 // The index expression is an Expression. 3238 TypeSArray *a = (TypeSArray *)t; 3239 dimStack.push(a->dim->syntaxCopy()); 3240 t = a->next->syntaxCopy(); 3241 } 3242 else if (t->ty == Taarray) 3243 { 3244 // The index expression is a Type. It will be interpreted as an expression at semantic time. 3245 TypeAArray *a = (TypeAArray *)t; 3246 dimStack.push(a->index->syntaxCopy()); 3247 t = a->next->syntaxCopy(); 3248 } 3249 else 3250 { 3251 break; 3252 } 3253 } 3254 assert(dimStack.dim > 0); 3255 // We're good. Replay indices in the reverse order. 3256 tid = (TypeQualified *)t; 3257 while (dimStack.dim) 3258 { 3259 tid->addIndex(dimStack.pop()); 3260 } 3261 maybeArray = NULL; 3262 } 3263 Loc loc = token.loc; 3264 Identifier *id = token.ident; 3265 nextToken(); 3266 if (token.value == TOKnot) 3267 { 3268 TemplateInstance *tempinst = new TemplateInstance(loc, id); 3269 tempinst->tiargs = parseTemplateArguments(); 3270 tid->addInst(tempinst); 3271 } 3272 else 3273 tid->addIdent(id); 3274 continue; 3275 } 3276 case TOKlbracket: 3277 { 3278 if (dontLookDotIdents) // workaround for Bugzilla 14911 3279 goto Lend; 3280 3281 nextToken(); 3282 Type *t = maybeArray ? maybeArray : (Type *)tid; 3283 if (token.value == TOKrbracket) 3284 { 3285 // It's a dynamic array, and we're done: 3286 // T[].U does not make sense. 3287 t = new TypeDArray(t); 3288 nextToken(); 3289 return t; 3290 } 3291 else if (isDeclaration(&token, 0, TOKrbracket, NULL)) 3292 { 3293 // This can be one of two things: 3294 // 1 - an associative array declaration, T[type] 3295 // 2 - an associative array declaration, T[expr] 3296 // These can only be disambiguated later. 3297 Type *index = parseType(); // [ type ] 3298 maybeArray = new TypeAArray(t, index); 3299 check(TOKrbracket); 3300 } 3301 else 3302 { 3303 // This can be one of three things: 3304 // 1 - an static array declaration, T[expr] 3305 // 2 - a slice, T[expr .. expr] 3306 // 3 - a template parameter pack index expression, T[expr].U 3307 // 1 and 3 can only be disambiguated later. 3308 //printf("it's type[expression]\n"); 3309 inBrackets++; 3310 Expression *e = parseAssignExp(); // [ expression ] 3311 if (token.value == TOKslice) 3312 { 3313 // It's a slice, and we're done. 3314 nextToken(); 3315 Expression *e2 = parseAssignExp(); // [ exp .. exp ] 3316 t = new TypeSlice(t, e, e2); 3317 inBrackets--; 3318 check(TOKrbracket); 3319 return t; 3320 } 3321 else 3322 { 3323 maybeArray = new TypeSArray(t, e); 3324 inBrackets--; 3325 check(TOKrbracket); 3326 continue; 3327 } 3328 } 3329 break; 3330 } 3331 default: 3332 goto Lend; 3333 } 3334 } 3335Lend: 3336 return maybeArray ? maybeArray : (Type *)tid; 3337} 3338 3339/****************************************** 3340 * Parse things that follow the initial type t. 3341 * t * 3342 * t [] 3343 * t [type] 3344 * t [expression] 3345 * t [expression .. expression] 3346 * t function 3347 * t delegate 3348 */ 3349 3350Type *Parser::parseBasicType2(Type *t) 3351{ 3352 //printf("parseBasicType2()\n"); 3353 while (1) 3354 { 3355 switch (token.value) 3356 { 3357 case TOKmul: 3358 t = new TypePointer(t); 3359 nextToken(); 3360 continue; 3361 3362 case TOKlbracket: 3363 // Handle []. Make sure things like 3364 // int[3][1] a; 3365 // is (array[1] of array[3] of int) 3366 nextToken(); 3367 if (token.value == TOKrbracket) 3368 { 3369 t = new TypeDArray(t); // [] 3370 nextToken(); 3371 } 3372 else if (isDeclaration(&token, 0, TOKrbracket, NULL)) 3373 { 3374 // It's an associative array declaration 3375 //printf("it's an associative array\n"); 3376 Type *index = parseType(); // [ type ] 3377 t = new TypeAArray(t, index); 3378 check(TOKrbracket); 3379 } 3380 else 3381 { 3382 //printf("it's type[expression]\n"); 3383 inBrackets++; 3384 Expression *e = parseAssignExp(); // [ expression ] 3385 if (token.value == TOKslice) 3386 { 3387 nextToken(); 3388 Expression *e2 = parseAssignExp(); // [ exp .. exp ] 3389 t = new TypeSlice(t, e, e2); 3390 } 3391 else 3392 { 3393 t = new TypeSArray(t,e); 3394 } 3395 inBrackets--; 3396 check(TOKrbracket); 3397 } 3398 continue; 3399 3400 case TOKdelegate: 3401 case TOKfunction: 3402 { 3403 // Handle delegate declaration: 3404 // t delegate(parameter list) nothrow pure 3405 // t function(parameter list) nothrow pure 3406 TOK save = token.value; 3407 nextToken(); 3408 3409 int varargs; 3410 Parameters *parameters = parseParameters(&varargs); 3411 3412 StorageClass stc = parsePostfix(STCundefined, NULL); 3413 TypeFunction *tf = new TypeFunction(parameters, t, varargs, linkage, stc); 3414 if (stc & (STCconst | STCimmutable | STCshared | STCwild | STCreturn)) 3415 { 3416 if (save == TOKfunction) 3417 error("const/immutable/shared/inout/return attributes are only valid for non-static member functions"); 3418 else 3419 tf = (TypeFunction *)tf->addSTC(stc); 3420 } 3421 3422 if (save == TOKdelegate) 3423 t = new TypeDelegate(tf); 3424 else 3425 t = new TypePointer(tf); // pointer to function 3426 continue; 3427 } 3428 3429 default: 3430 return t; 3431 } 3432 assert(0); 3433 } 3434 assert(0); 3435 return NULL; 3436} 3437 3438Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident, 3439 TemplateParameters **tpl, StorageClass storageClass, int *pdisable, Expressions **pudas) 3440{ 3441 //printf("parseDeclarator(tpl = %p)\n", tpl); 3442 t = parseBasicType2(t); 3443 3444 Type *ts; 3445 switch (token.value) 3446 { 3447 case TOKidentifier: 3448 if (pident) 3449 *pident = token.ident; 3450 else 3451 error("unexpected identifer '%s' in declarator", token.ident->toChars()); 3452 ts = t; 3453 nextToken(); 3454 break; 3455 3456 case TOKlparen: 3457 { 3458 // like: T (*fp)(); 3459 // like: T ((*fp))(); 3460 if (peekNext() == TOKmul || 3461 peekNext() == TOKlparen) 3462 { 3463 /* Parse things with parentheses around the identifier, like: 3464 * int (*ident[3])[] 3465 * although the D style would be: 3466 * int[]*[3] ident 3467 */ 3468 *palt |= 1; 3469 nextToken(); 3470 ts = parseDeclarator(t, palt, pident); 3471 check(TOKrparen); 3472 break; 3473 } 3474 ts = t; 3475 3476 Token *peekt = &token; 3477 /* Completely disallow C-style things like: 3478 * T (a); 3479 * Improve error messages for the common bug of a missing return type 3480 * by looking to see if (a) looks like a parameter list. 3481 */ 3482 if (isParameters(&peekt)) 3483 { 3484 error("function declaration without return type. (Note that constructors are always named 'this')"); 3485 } 3486 else 3487 error("unexpected ( in declarator"); 3488 break; 3489 } 3490 3491 default: 3492 ts = t; 3493 break; 3494 } 3495 3496 // parse DeclaratorSuffixes 3497 while (1) 3498 { 3499 switch (token.value) 3500 { 3501#if CARRAYDECL 3502 /* Support C style array syntax: 3503 * int ident[] 3504 * as opposed to D-style: 3505 * int[] ident 3506 */ 3507 case TOKlbracket: 3508 { 3509 // This is the old C-style post [] syntax. 3510 TypeNext *ta; 3511 nextToken(); 3512 if (token.value == TOKrbracket) 3513 { 3514 // It's a dynamic array 3515 ta = new TypeDArray(t); // [] 3516 nextToken(); 3517 *palt |= 2; 3518 } 3519 else if (isDeclaration(&token, 0, TOKrbracket, NULL)) 3520 { 3521 // It's an associative array 3522 //printf("it's an associative array\n"); 3523 Type *index = parseType(); // [ type ] 3524 check(TOKrbracket); 3525 ta = new TypeAArray(t, index); 3526 *palt |= 2; 3527 } 3528 else 3529 { 3530 //printf("It's a static array\n"); 3531 Expression *e = parseAssignExp(); // [ expression ] 3532 ta = new TypeSArray(t, e); 3533 check(TOKrbracket); 3534 *palt |= 2; 3535 } 3536 3537 /* Insert ta into 3538 * ts -> ... -> t 3539 * so that 3540 * ts -> ... -> ta -> t 3541 */ 3542 Type **pt; 3543 for (pt = &ts; *pt != t; pt = &((TypeNext *)*pt)->next) 3544 ; 3545 *pt = ta; 3546 continue; 3547 } 3548#endif 3549 case TOKlparen: 3550 { 3551 if (tpl) 3552 { 3553 Token *tk = peekPastParen(&token); 3554 if (tk->value == TOKlparen) 3555 { 3556 /* Look ahead to see if this is (...)(...), 3557 * i.e. a function template declaration 3558 */ 3559 //printf("function template declaration\n"); 3560 3561 // Gather template parameter list 3562 *tpl = parseTemplateParameterList(); 3563 } 3564 else if (tk->value == TOKassign) 3565 { 3566 /* or (...) =, 3567 * i.e. a variable template declaration 3568 */ 3569 //printf("variable template declaration\n"); 3570 *tpl = parseTemplateParameterList(); 3571 break; 3572 } 3573 } 3574 3575 int varargs; 3576 Parameters *parameters = parseParameters(&varargs); 3577 3578 /* Parse const/immutable/shared/inout/nothrow/pure/return postfix 3579 */ 3580 StorageClass stc = parsePostfix(storageClass, pudas); 3581 // merge prefix storage classes 3582 Type *tf = new TypeFunction(parameters, t, varargs, linkage, stc); 3583 tf = tf->addSTC(stc); 3584 if (pdisable) 3585 *pdisable = stc & STCdisable ? 1 : 0; 3586 3587 /* Insert tf into 3588 * ts -> ... -> t 3589 * so that 3590 * ts -> ... -> tf -> t 3591 */ 3592 Type **pt; 3593 for (pt = &ts; *pt != t; pt = &((TypeNext *)*pt)->next) 3594 ; 3595 *pt = tf; 3596 break; 3597 } 3598 default: break; 3599 } 3600 break; 3601 } 3602 3603 return ts; 3604} 3605 3606void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link, 3607 bool &setAlignment, Expression *&ealign, Expressions *&udas) 3608{ 3609 StorageClass stc; 3610 bool sawLinkage = false; // seen a linkage declaration 3611 3612 while (1) 3613 { 3614 switch (token.value) 3615 { 3616 case TOKconst: 3617 if (peek(&token)->value == TOKlparen) 3618 break; // const as type constructor 3619 stc = STCconst; // const as storage class 3620 goto L1; 3621 3622 case TOKimmutable: 3623 if (peek(&token)->value == TOKlparen) 3624 break; 3625 stc = STCimmutable; 3626 goto L1; 3627 3628 case TOKshared: 3629 if (peek(&token)->value == TOKlparen) 3630 break; 3631 stc = STCshared; 3632 goto L1; 3633 3634 case TOKwild: 3635 if (peek(&token)->value == TOKlparen) 3636 break; 3637 stc = STCwild; 3638 goto L1; 3639 3640 case TOKstatic: stc = STCstatic; goto L1; 3641 case TOKfinal: stc = STCfinal; goto L1; 3642 case TOKauto: stc = STCauto; goto L1; 3643 case TOKscope: stc = STCscope; goto L1; 3644 case TOKoverride: stc = STCoverride; goto L1; 3645 case TOKabstract: stc = STCabstract; goto L1; 3646 case TOKsynchronized: stc = STCsynchronized; goto L1; 3647 case TOKdeprecated: stc = STCdeprecated; goto L1; 3648 case TOKnothrow: stc = STCnothrow; goto L1; 3649 case TOKpure: stc = STCpure; goto L1; 3650 case TOKref: stc = STCref; goto L1; 3651 case TOKgshared: stc = STCgshared; goto L1; 3652 case TOKenum: stc = STCmanifest; goto L1; 3653 case TOKat: 3654 { 3655 stc = parseAttribute(&udas); 3656 if (stc) 3657 goto L1; 3658 continue; 3659 } 3660 L1: 3661 storage_class = appendStorageClass(storage_class, stc); 3662 nextToken(); 3663 continue; 3664 3665 case TOKextern: 3666 { 3667 if (peek(&token)->value != TOKlparen) 3668 { 3669 stc = STCextern; 3670 goto L1; 3671 } 3672 3673 if (sawLinkage) 3674 error("redundant linkage declaration"); 3675 sawLinkage = true; 3676 Identifiers *idents = NULL; 3677 CPPMANGLE cppmangle = CPPMANGLEdefault; 3678 bool cppMangleOnly = false; 3679 link = parseLinkage(&idents, &cppmangle, &cppMangleOnly); 3680 if (idents) 3681 { 3682 error("C++ name spaces not allowed here"); 3683 delete idents; 3684 } 3685 if (cppmangle != CPPMANGLEdefault) 3686 { 3687 error("C++ mangle declaration not allowed here"); 3688 } 3689 continue; 3690 } 3691 3692 case TOKalign: 3693 { 3694 nextToken(); 3695 setAlignment = true; 3696 if (token.value == TOKlparen) 3697 { 3698 nextToken(); 3699 ealign = parseExpression(); 3700 check(TOKrparen); 3701 } 3702 continue; 3703 } 3704 default: 3705 break; 3706 } 3707 break; 3708 } 3709} 3710 3711/********************************** 3712 * Parse Declarations. 3713 * These can be: 3714 * 1. declarations at global/class level 3715 * 2. declarations at statement level 3716 * Return array of Declaration *'s. 3717 */ 3718 3719Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, const utf8_t *comment) 3720{ 3721 StorageClass storage_class = STCundefined; 3722 Type *ts; 3723 Type *t; 3724 Type *tfirst; 3725 Identifier *ident; 3726 TOK tok = TOKreserved; 3727 LINK link = linkage; 3728 bool setAlignment = false; 3729 Expression *ealign = NULL; 3730 Loc loc = token.loc; 3731 Expressions *udas = NULL; 3732 Token *tk; 3733 3734 //printf("parseDeclarations() %s\n", token.toChars()); 3735 if (!comment) 3736 comment = token.blockComment; 3737 3738 if (autodecl) 3739 { 3740 ts = NULL; // infer type 3741 goto L2; 3742 } 3743 3744 if (token.value == TOKalias) 3745 { 3746 tok = token.value; 3747 nextToken(); 3748 3749 /* Look for: 3750 * alias identifier this; 3751 */ 3752 if (token.value == TOKidentifier && peekNext() == TOKthis) 3753 { 3754 AliasThis *s = new AliasThis(loc, token.ident); 3755 nextToken(); 3756 check(TOKthis); 3757 check(TOKsemicolon); 3758 Dsymbols *a = new Dsymbols(); 3759 a->push(s); 3760 addComment(s, comment); 3761 return a; 3762 } 3763 /* Look for: 3764 * alias identifier = type; 3765 * alias identifier(...) = type; 3766 */ 3767 if (token.value == TOKidentifier && 3768 skipParensIf(peek(&token), &tk) && 3769 tk->value == TOKassign) 3770 { 3771 Dsymbols *a = new Dsymbols(); 3772 while (1) 3773 { 3774 ident = token.ident; 3775 nextToken(); 3776 TemplateParameters *tpl = NULL; 3777 if (token.value == TOKlparen) 3778 tpl = parseTemplateParameterList(); 3779 check(TOKassign); 3780 3781 Declaration *v; 3782 if (token.value == TOKfunction || 3783 token.value == TOKdelegate || 3784 (token.value == TOKlparen && 3785 skipAttributes(peekPastParen(&token), &tk) && 3786 (tk->value == TOKgoesto || tk->value == TOKlcurly)) || 3787 token.value == TOKlcurly || 3788 (token.value == TOKidentifier && peekNext() == TOKgoesto)) 3789 { 3790 // function (parameters) { statements... } 3791 // delegate (parameters) { statements... } 3792 // (parameters) { statements... } 3793 // (parameters) => expression 3794 // { statements... } 3795 // identifier => expression 3796 3797 Dsymbol *s = parseFunctionLiteral(); 3798 v = new AliasDeclaration(loc, ident, s); 3799 } 3800 else 3801 { 3802 // StorageClasses type 3803 3804 storage_class = STCundefined; 3805 link = linkage; 3806 setAlignment = false; 3807 ealign = NULL; 3808 udas = NULL; 3809 parseStorageClasses(storage_class, link, setAlignment, ealign, udas); 3810 3811 if (udas) 3812 error("user defined attributes not allowed for %s declarations", Token::toChars(tok)); 3813 3814 t = parseType(); 3815 v = new AliasDeclaration(loc, ident, t); 3816 } 3817 v->storage_class = storage_class; 3818 3819 Dsymbol *s = v; 3820 if (tpl) 3821 { 3822 Dsymbols *a2 = new Dsymbols(); 3823 a2->push(s); 3824 TemplateDeclaration *tempdecl = 3825 new TemplateDeclaration(loc, ident, tpl, NULL, a2); 3826 s = tempdecl; 3827 } 3828 if (setAlignment) 3829 { 3830 Dsymbols *ax = new Dsymbols(); 3831 ax->push(s); 3832 s = new AlignDeclaration(v->loc, ealign, ax); 3833 } 3834 if (link != linkage) 3835 { 3836 Dsymbols *a2 = new Dsymbols(); 3837 a2->push(s); 3838 s = new LinkDeclaration(link, a2); 3839 } 3840 a->push(s); 3841 3842 switch (token.value) 3843 { 3844 case TOKsemicolon: 3845 nextToken(); 3846 addComment(s, comment); 3847 break; 3848 case TOKcomma: 3849 nextToken(); 3850 addComment(s, comment); 3851 if (token.value != TOKidentifier) 3852 { 3853 error("identifier expected following comma, not %s", token.toChars()); 3854 break; 3855 } 3856 if (peekNext() != TOKassign && peekNext() != TOKlparen) 3857 { 3858 error("= expected following identifier"); 3859 nextToken(); 3860 break; 3861 } 3862 continue; 3863 default: 3864 error("semicolon expected to close %s declaration", Token::toChars(tok)); 3865 break; 3866 } 3867 break; 3868 } 3869 return a; 3870 } 3871 3872 // alias StorageClasses type ident; 3873 } 3874 3875 parseStorageClasses(storage_class, link, setAlignment, ealign, udas); 3876 3877 if (token.value == TOKstruct || 3878 token.value == TOKunion || 3879 token.value == TOKclass || 3880 token.value == TOKinterface) 3881 { 3882 Dsymbol *s = parseAggregate(); 3883 Dsymbols *a = new Dsymbols(); 3884 a->push(s); 3885 3886 if (storage_class) 3887 { 3888 s = new StorageClassDeclaration(storage_class, a); 3889 a = new Dsymbols(); 3890 a->push(s); 3891 } 3892 if (setAlignment) 3893 { 3894 s = new AlignDeclaration(s->loc, ealign, a); 3895 a = new Dsymbols(); 3896 a->push(s); 3897 } 3898 if (link != linkage) 3899 { 3900 s = new LinkDeclaration(link, a); 3901 a = new Dsymbols(); 3902 a->push(s); 3903 } 3904 if (udas) 3905 { 3906 s = new UserAttributeDeclaration(udas, a); 3907 a = new Dsymbols(); 3908 a->push(s); 3909 } 3910 3911 addComment(s, comment); 3912 return a; 3913 } 3914 3915 /* Look for auto initializers: 3916 * storage_class identifier = initializer; 3917 * storage_class identifier(...) = initializer; 3918 */ 3919 if ((storage_class || udas) && 3920 token.value == TOKidentifier && 3921 skipParensIf(peek(&token), &tk) && 3922 tk->value == TOKassign) 3923 { 3924 Dsymbols *a = parseAutoDeclarations(storage_class, comment); 3925 if (udas) 3926 { 3927 Dsymbol *s = new UserAttributeDeclaration(udas, a); 3928 a = new Dsymbols(); 3929 a->push(s); 3930 } 3931 return a; 3932 } 3933 3934 /* Look for return type inference for template functions. 3935 */ 3936 if ((storage_class || udas) && token.value == TOKidentifier && skipParens(peek(&token), &tk) && 3937 skipAttributes(tk, &tk) && 3938 (tk->value == TOKlparen || tk->value == TOKlcurly || tk->value == TOKin || tk->value == TOKout || 3939 tk->value == TOKdo || (tk->value == TOKidentifier && tk->ident == Id::_body))) 3940 { 3941 ts = NULL; 3942 } 3943 else 3944 { 3945 ts = parseBasicType(); 3946 ts = parseBasicType2(ts); 3947 } 3948 3949L2: 3950 tfirst = NULL; 3951 Dsymbols *a = new Dsymbols(); 3952 3953 if (pAttrs) 3954 { 3955 storage_class |= pAttrs->storageClass; 3956 //pAttrs->storageClass = STCundefined; 3957 } 3958 3959 while (1) 3960 { 3961 TemplateParameters *tpl = NULL; 3962 int disable; 3963 int alt = 0; 3964 3965 loc = token.loc; 3966 ident = NULL; 3967 t = parseDeclarator(ts, &alt, &ident, &tpl, storage_class, &disable, &udas); 3968 assert(t); 3969 if (!tfirst) 3970 tfirst = t; 3971 else if (t != tfirst) 3972 error("multiple declarations must have the same type, not %s and %s", 3973 tfirst->toChars(), t->toChars()); 3974 bool isThis = (t->ty == Tident && ((TypeIdentifier *)t)->ident == Id::This && token.value == TOKassign); 3975 if (ident) 3976 checkCstyleTypeSyntax(loc, t, alt, ident); 3977 else if (!isThis) 3978 error("no identifier for declarator %s", t->toChars()); 3979 3980 if (tok == TOKalias) 3981 { 3982 Declaration *v; 3983 Initializer *init = NULL; 3984 3985 /* Aliases can no longer have multiple declarators, storage classes, 3986 * linkages, or auto declarations. 3987 * These never made any sense, anyway. 3988 * The code below needs to be fixed to reject them. 3989 * The grammar has already been fixed to preclude them. 3990 */ 3991 3992 if (udas) 3993 error("user defined attributes not allowed for %s declarations", Token::toChars(tok)); 3994 3995 if (token.value == TOKassign) 3996 { 3997 nextToken(); 3998 init = parseInitializer(); 3999 } 4000 if (init) 4001 { 4002 if (isThis) 4003 error("cannot use syntax 'alias this = %s', use 'alias %s this' instead", 4004 init->toChars(), init->toChars()); 4005 else 4006 error("alias cannot have initializer"); 4007 } 4008 v = new AliasDeclaration(loc, ident, t); 4009 4010 v->storage_class = storage_class; 4011 if (pAttrs) 4012 { 4013 /* AliasDeclaration distinguish @safe, @system, @trusted atttributes 4014 * on prefix and postfix. 4015 * @safe alias void function() FP1; 4016 * alias @safe void function() FP2; // FP2 is not @safe 4017 * alias void function() @safe FP3; 4018 */ 4019 pAttrs->storageClass &= (STCsafe | STCsystem | STCtrusted); 4020 } 4021 Dsymbol *s = v; 4022 4023 if (link != linkage) 4024 { 4025 Dsymbols *ax = new Dsymbols(); 4026 ax->push(v); 4027 s = new LinkDeclaration(link, ax); 4028 } 4029 a->push(s); 4030 switch (token.value) 4031 { 4032 case TOKsemicolon: 4033 nextToken(); 4034 addComment(s, comment); 4035 break; 4036 4037 case TOKcomma: 4038 nextToken(); 4039 addComment(s, comment); 4040 continue; 4041 4042 default: 4043 error("semicolon expected to close %s declaration", Token::toChars(tok)); 4044 break; 4045 } 4046 } 4047 else if (t->ty == Tfunction) 4048 { 4049 Expression *constraint = NULL; 4050 4051 //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t->toChars(), storage_class); 4052 FuncDeclaration *f = 4053 new FuncDeclaration(loc, Loc(), ident, storage_class | (disable ? STCdisable : 0), t); 4054 if (pAttrs) 4055 pAttrs->storageClass = STCundefined; 4056 if (tpl) 4057 constraint = parseConstraint(); 4058 Dsymbol *s = parseContracts(f); 4059 Identifier *tplIdent = s->ident; 4060 if (link != linkage) 4061 { 4062 Dsymbols *ax = new Dsymbols(); 4063 ax->push(s); 4064 s = new LinkDeclaration(link, ax); 4065 } 4066 if (udas) 4067 { 4068 Dsymbols *ax = new Dsymbols(); 4069 ax->push(s); 4070 s = new UserAttributeDeclaration(udas, ax); 4071 } 4072 4073 /* A template parameter list means it's a function template 4074 */ 4075 if (tpl) 4076 { 4077 // Wrap a template around the function declaration 4078 Dsymbols *decldefs = new Dsymbols(); 4079 decldefs->push(s); 4080 TemplateDeclaration *tempdecl = 4081 new TemplateDeclaration(loc, tplIdent, tpl, constraint, decldefs); 4082 s = tempdecl; 4083 4084 if (storage_class & STCstatic) 4085 { 4086 assert(f->storage_class & STCstatic); 4087 f->storage_class &= ~STCstatic; 4088 4089 Dsymbols *ax = new Dsymbols(); 4090 ax->push(s); 4091 s = new StorageClassDeclaration(STCstatic, ax); 4092 } 4093 } 4094 a->push(s); 4095 addComment(s, comment); 4096 } 4097 else if (ident) 4098 { 4099 Initializer *init = NULL; 4100 if (token.value == TOKassign) 4101 { 4102 nextToken(); 4103 init = parseInitializer(); 4104 } 4105 4106 VarDeclaration *v = new VarDeclaration(loc, t, ident, init); 4107 v->storage_class = storage_class; 4108 if (pAttrs) 4109 pAttrs->storageClass = STCundefined; 4110 4111 Dsymbol *s = v; 4112 4113 if (tpl && init) 4114 { 4115 Dsymbols *a2 = new Dsymbols(); 4116 a2->push(s); 4117 TemplateDeclaration *tempdecl = 4118 new TemplateDeclaration(loc, ident, tpl, NULL, a2, 0); 4119 s = tempdecl; 4120 } 4121 if (link != linkage) 4122 { 4123 Dsymbols *ax = new Dsymbols(); 4124 ax->push(s); 4125 s = new LinkDeclaration(link, ax); 4126 } 4127 if (udas) 4128 { 4129 Dsymbols *ax = new Dsymbols(); 4130 ax->push(s); 4131 s = new UserAttributeDeclaration(udas, ax); 4132 } 4133 a->push(s); 4134 switch (token.value) 4135 { 4136 case TOKsemicolon: 4137 nextToken(); 4138 addComment(s, comment); 4139 break; 4140 4141 case TOKcomma: 4142 nextToken(); 4143 addComment(s, comment); 4144 continue; 4145 4146 default: 4147 error("semicolon expected, not '%s'", token.toChars()); 4148 break; 4149 } 4150 } 4151 break; 4152 } 4153 return a; 4154} 4155 4156Dsymbol *Parser::parseFunctionLiteral() 4157{ 4158 Loc loc = token.loc; 4159 4160 TemplateParameters *tpl = NULL; 4161 Parameters *parameters = NULL; 4162 int varargs = 0; 4163 Type *tret = NULL; 4164 StorageClass stc = 0; 4165 TOK save = TOKreserved; 4166 4167 switch (token.value) 4168 { 4169 case TOKfunction: 4170 case TOKdelegate: 4171 save = token.value; 4172 nextToken(); 4173 if (token.value != TOKlparen && token.value != TOKlcurly) 4174 { 4175 // function type (parameters) { statements... } 4176 // delegate type (parameters) { statements... } 4177 tret = parseBasicType(); 4178 tret = parseBasicType2(tret); // function return type 4179 } 4180 4181 if (token.value == TOKlparen) 4182 { 4183 // function (parameters) { statements... } 4184 // delegate (parameters) { statements... } 4185 } 4186 else 4187 { 4188 // function { statements... } 4189 // delegate { statements... } 4190 break; 4191 } 4192 /* fall through */ 4193 4194 case TOKlparen: 4195 { 4196 // (parameters) => expression 4197 // (parameters) { statements... } 4198 parameters = parseParameters(&varargs, &tpl); 4199 stc = parsePostfix(STCundefined, NULL); 4200 if (StorageClass modStc = stc & STC_TYPECTOR) 4201 { 4202 if (save == TOKfunction) 4203 { 4204 OutBuffer buf; 4205 stcToBuffer(&buf, modStc); 4206 error("function literal cannot be %s", buf.peekString()); 4207 } 4208 else 4209 save = TOKdelegate; 4210 } 4211 break; 4212 } 4213 case TOKlcurly: 4214 // { statements... } 4215 break; 4216 4217 case TOKidentifier: 4218 { 4219 // identifier => expression 4220 parameters = new Parameters(); 4221 Identifier *id = Identifier::generateId("__T"); 4222 Type *t = new TypeIdentifier(loc, id); 4223 parameters->push(new Parameter(0, t, token.ident, NULL)); 4224 4225 tpl = new TemplateParameters(); 4226 TemplateParameter *tp = new TemplateTypeParameter(loc, id, NULL, NULL); 4227 tpl->push(tp); 4228 4229 nextToken(); 4230 break; 4231 } 4232 default: 4233 assert(0); 4234 } 4235 4236 if (!parameters) 4237 parameters = new Parameters(); 4238 TypeFunction *tf = new TypeFunction(parameters, tret, varargs, linkage, stc); 4239 tf = (TypeFunction *)tf->addSTC(stc); 4240 FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, save, NULL); 4241 4242 if (token.value == TOKgoesto) 4243 { 4244 check(TOKgoesto); 4245 Loc returnloc = token.loc; 4246 Expression *ae = parseAssignExp(); 4247 fd->fbody = new ReturnStatement(returnloc, ae); 4248 fd->endloc = token.loc; 4249 } 4250 else 4251 { 4252 parseContracts(fd); 4253 } 4254 4255 if (tpl) 4256 { 4257 // Wrap a template around function fd 4258 Dsymbols *decldefs = new Dsymbols(); 4259 decldefs->push(fd); 4260 return new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, false, true); 4261 } 4262 else 4263 return fd; 4264} 4265 4266/***************************************** 4267 * Parse auto declarations of the form: 4268 * storageClass ident = init, ident = init, ... ; 4269 * and return the array of them. 4270 * Starts with token on the first ident. 4271 * Ends with scanner past closing ';' 4272 */ 4273 4274Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment) 4275{ 4276 //printf("parseAutoDeclarations\n"); 4277 Token *tk; 4278 Dsymbols *a = new Dsymbols; 4279 4280 while (1) 4281 { 4282 Loc loc = token.loc; 4283 Identifier *ident = token.ident; 4284 nextToken(); // skip over ident 4285 4286 TemplateParameters *tpl = NULL; 4287 if (token.value == TOKlparen) 4288 tpl = parseTemplateParameterList(); 4289 4290 check(TOKassign); // skip over '=' 4291 Initializer *init = parseInitializer(); 4292 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init); 4293 v->storage_class = storageClass; 4294 4295 Dsymbol *s = v; 4296 if (tpl) 4297 { 4298 Dsymbols *a2 = new Dsymbols(); 4299 a2->push(v); 4300 TemplateDeclaration *tempdecl = 4301 new TemplateDeclaration(loc, ident, tpl, NULL, a2, 0); 4302 s = tempdecl; 4303 } 4304 a->push(s); 4305 switch (token.value) 4306 { 4307 case TOKsemicolon: 4308 nextToken(); 4309 addComment(s, comment); 4310 break; 4311 4312 case TOKcomma: 4313 nextToken(); 4314 if (!(token.value == TOKidentifier && 4315 skipParensIf(peek(&token), &tk) && 4316 tk->value == TOKassign)) 4317 { 4318 error("identifier expected following comma"); 4319 break; 4320 } 4321 addComment(s, comment); 4322 continue; 4323 4324 default: 4325 error("semicolon expected following auto declaration, not '%s'", token.toChars()); 4326 break; 4327 } 4328 break; 4329 } 4330 return a; 4331} 4332 4333/***************************************** 4334 * Parse contracts following function declaration. 4335 */ 4336 4337FuncDeclaration *Parser::parseContracts(FuncDeclaration *f) 4338{ 4339 LINK linksave = linkage; 4340 4341 bool literal = f->isFuncLiteralDeclaration() != NULL; 4342 4343 // The following is irrelevant, as it is overridden by sc->linkage in 4344 // TypeFunction::semantic 4345 linkage = LINKd; // nested functions have D linkage 4346L1: 4347 switch (token.value) 4348 { 4349 case TOKlcurly: 4350 if (f->frequire || f->fensure) 4351 error("missing body { ... } after in or out"); 4352 f->fbody = parseStatement(PSsemi); 4353 f->endloc = endloc; 4354 break; 4355 4356 case TOKidentifier: 4357 if (token.ident != Id::_body) 4358 goto Ldefault; 4359 /* fall through */ 4360 4361 case TOKdo: 4362 nextToken(); 4363 f->fbody = parseStatement(PScurly); 4364 f->endloc = endloc; 4365 break; 4366 4367 case TOKin: 4368 nextToken(); 4369 if (f->frequire) 4370 error("redundant 'in' statement"); 4371 f->frequire = parseStatement(PScurly | PSscope); 4372 goto L1; 4373 4374 case TOKout: 4375 // parse: out (identifier) { statement } 4376 nextToken(); 4377 if (token.value != TOKlcurly) 4378 { 4379 check(TOKlparen); 4380 if (token.value != TOKidentifier) 4381 error("(identifier) following 'out' expected, not %s", token.toChars()); 4382 f->outId = token.ident; 4383 nextToken(); 4384 check(TOKrparen); 4385 } 4386 if (f->fensure) 4387 error("redundant 'out' statement"); 4388 f->fensure = parseStatement(PScurly | PSscope); 4389 goto L1; 4390 4391 case TOKsemicolon: 4392 if (!literal) 4393 { 4394 // Bugzilla 15799: Semicolon becomes a part of function declaration 4395 // only when neither of contracts exists. 4396 if (!f->frequire && !f->fensure) 4397 nextToken(); 4398 break; 4399 } 4400 /* fall through */ 4401 4402 default: 4403 Ldefault: 4404 if (literal) 4405 { 4406 const char *sbody = (f->frequire || f->fensure) ? "body " : ""; 4407 error("missing %s{ ... } for function literal", sbody); 4408 } 4409 else if (!f->frequire && !f->fensure) // allow these even with no body 4410 { 4411 error("semicolon expected following function declaration"); 4412 } 4413 break; 4414 } 4415 if (literal && !f->fbody) 4416 { 4417 // Set empty function body for error recovery 4418 f->fbody = new CompoundStatement(Loc(), (Statement *)NULL); 4419 } 4420 4421 linkage = linksave; 4422 4423 return f; 4424} 4425 4426/***************************************** 4427 * Parse initializer for variable declaration. 4428 */ 4429 4430Initializer *Parser::parseInitializer() 4431{ 4432 StructInitializer *is; 4433 ArrayInitializer *ia; 4434 ExpInitializer *ie; 4435 Expression *e; 4436 Identifier *id; 4437 Initializer *value; 4438 int comma; 4439 Loc loc = token.loc; 4440 Token *t; 4441 int braces; 4442 int brackets; 4443 4444 switch (token.value) 4445 { 4446 case TOKlcurly: 4447 /* Scan ahead to see if it is a struct initializer or 4448 * a function literal. 4449 * If it contains a ';', it is a function literal. 4450 * Treat { } as a struct initializer. 4451 */ 4452 braces = 1; 4453 for (t = peek(&token); 1; t = peek(t)) 4454 { 4455 switch (t->value) 4456 { 4457 case TOKsemicolon: 4458 case TOKreturn: 4459 goto Lexpression; 4460 4461 case TOKlcurly: 4462 braces++; 4463 continue; 4464 4465 case TOKrcurly: 4466 if (--braces == 0) 4467 break; 4468 continue; 4469 4470 case TOKeof: 4471 break; 4472 4473 default: 4474 continue; 4475 } 4476 break; 4477 } 4478 4479 is = new StructInitializer(loc); 4480 nextToken(); 4481 comma = 2; 4482 while (1) 4483 { 4484 switch (token.value) 4485 { 4486 case TOKidentifier: 4487 if (comma == 1) 4488 error("comma expected separating field initializers"); 4489 t = peek(&token); 4490 if (t->value == TOKcolon) 4491 { 4492 id = token.ident; 4493 nextToken(); 4494 nextToken(); // skip over ':' 4495 } 4496 else 4497 { id = NULL; 4498 } 4499 value = parseInitializer(); 4500 is->addInit(id, value); 4501 comma = 1; 4502 continue; 4503 4504 case TOKcomma: 4505 if (comma == 2) 4506 error("expression expected, not ','"); 4507 nextToken(); 4508 comma = 2; 4509 continue; 4510 4511 case TOKrcurly: // allow trailing comma's 4512 nextToken(); 4513 break; 4514 4515 case TOKeof: 4516 error("found EOF instead of initializer"); 4517 break; 4518 4519 default: 4520 if (comma == 1) 4521 error("comma expected separating field initializers"); 4522 value = parseInitializer(); 4523 is->addInit(NULL, value); 4524 comma = 1; 4525 continue; 4526 //error("found '%s' instead of field initializer", token.toChars()); 4527 //break; 4528 } 4529 break; 4530 } 4531 return is; 4532 4533 case TOKlbracket: 4534 /* Scan ahead to see if it is an array initializer or 4535 * an expression. 4536 * If it ends with a ';' ',' or '}', it is an array initializer. 4537 */ 4538 brackets = 1; 4539 for (t = peek(&token); 1; t = peek(t)) 4540 { 4541 switch (t->value) 4542 { 4543 case TOKlbracket: 4544 brackets++; 4545 continue; 4546 4547 case TOKrbracket: 4548 if (--brackets == 0) 4549 { t = peek(t); 4550 if (t->value != TOKsemicolon && 4551 t->value != TOKcomma && 4552 t->value != TOKrbracket && 4553 t->value != TOKrcurly) 4554 goto Lexpression; 4555 break; 4556 } 4557 continue; 4558 4559 case TOKeof: 4560 break; 4561 4562 default: 4563 continue; 4564 } 4565 break; 4566 } 4567 4568 ia = new ArrayInitializer(loc); 4569 nextToken(); 4570 comma = 2; 4571 while (1) 4572 { 4573 switch (token.value) 4574 { 4575 default: 4576 if (comma == 1) 4577 { error("comma expected separating array initializers, not %s", token.toChars()); 4578 nextToken(); 4579 break; 4580 } 4581 e = parseAssignExp(); 4582 if (!e) 4583 break; 4584 if (token.value == TOKcolon) 4585 { 4586 nextToken(); 4587 value = parseInitializer(); 4588 } 4589 else 4590 { value = new ExpInitializer(e->loc, e); 4591 e = NULL; 4592 } 4593 ia->addInit(e, value); 4594 comma = 1; 4595 continue; 4596 4597 case TOKlcurly: 4598 case TOKlbracket: 4599 if (comma == 1) 4600 error("comma expected separating array initializers, not %s", token.toChars()); 4601 value = parseInitializer(); 4602 if (token.value == TOKcolon) 4603 { 4604 nextToken(); 4605 e = initializerToExpression(value); 4606 value = parseInitializer(); 4607 } 4608 else 4609 e = NULL; 4610 ia->addInit(e, value); 4611 comma = 1; 4612 continue; 4613 4614 case TOKcomma: 4615 if (comma == 2) 4616 error("expression expected, not ','"); 4617 nextToken(); 4618 comma = 2; 4619 continue; 4620 4621 case TOKrbracket: // allow trailing comma's 4622 nextToken(); 4623 break; 4624 4625 case TOKeof: 4626 error("found '%s' instead of array initializer", token.toChars()); 4627 break; 4628 } 4629 break; 4630 } 4631 return ia; 4632 4633 case TOKvoid: 4634 t = peek(&token); 4635 if (t->value == TOKsemicolon || t->value == TOKcomma) 4636 { 4637 nextToken(); 4638 return new VoidInitializer(loc); 4639 } 4640 goto Lexpression; 4641 4642 default: 4643 Lexpression: 4644 e = parseAssignExp(); 4645 ie = new ExpInitializer(loc, e); 4646 return ie; 4647 } 4648} 4649 4650/***************************************** 4651 * Parses default argument initializer expression that is an assign expression, 4652 * with special handling for __FILE__, __FILE_FULL_PATH__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__. 4653 */ 4654 4655Expression *Parser::parseDefaultInitExp() 4656{ 4657 if (token.value == TOKfile || 4658 token.value == TOKfilefullpath || 4659 token.value == TOKline || 4660 token.value == TOKmodulestring || 4661 token.value == TOKfuncstring || 4662 token.value == TOKprettyfunc) 4663 { 4664 Token *t = peek(&token); 4665 if (t->value == TOKcomma || t->value == TOKrparen) 4666 { 4667 Expression *e = NULL; 4668 if (token.value == TOKfile) 4669 e = new FileInitExp(token.loc, TOKfile); 4670 else if (token.value == TOKfilefullpath) 4671 e = new FileInitExp(token.loc, TOKfilefullpath); 4672 else if (token.value == TOKline) 4673 e = new LineInitExp(token.loc); 4674 else if (token.value == TOKmodulestring) 4675 e = new ModuleInitExp(token.loc); 4676 else if (token.value == TOKfuncstring) 4677 e = new FuncInitExp(token.loc); 4678 else if (token.value == TOKprettyfunc) 4679 e = new PrettyFuncInitExp(token.loc); 4680 else 4681 assert(0); 4682 nextToken(); 4683 return e; 4684 } 4685 } 4686 4687 Expression *e = parseAssignExp(); 4688 return e; 4689} 4690 4691/***************************************** 4692 */ 4693 4694void Parser::checkDanglingElse(Loc elseloc) 4695{ 4696 if (token.value != TOKelse && 4697 token.value != TOKcatch && 4698 token.value != TOKfinally && 4699 lookingForElse.linnum != 0) 4700 { 4701 warning(elseloc, "else is dangling, add { } after condition at %s", lookingForElse.toChars()); 4702 } 4703} 4704 4705void Parser::checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident) 4706{ 4707 if (!alt) 4708 return; 4709 4710 const char *sp = !ident ? "" : " "; 4711 const char *s = !ident ? "" : ident->toChars(); 4712 if (alt & 1) // contains C-style function pointer syntax 4713 error(loc, "instead of C-style syntax, use D-style '%s%s%s'", t->toChars(), sp, s); 4714 else 4715 ::warning(loc, "instead of C-style syntax, use D-style syntax '%s%s%s'", t->toChars(), sp, s); 4716 4717} 4718 4719/***************************************** 4720 * Parses `foreach` statements, `static foreach` statements and 4721 * `static foreach` declarations. The template parameter 4722 * `isStatic` is true, iff a `static foreach` should be parsed. 4723 * If `isStatic` is true, `isDecl` can be true to indicate that a 4724 * `static foreach` declaration should be parsed. 4725 */ 4726Statement *Parser::parseForeach(Loc loc, bool *isRange, bool isDecl) 4727{ 4728 TOK op = token.value; 4729 4730 nextToken(); 4731 check(TOKlparen); 4732 4733 Parameters *parameters = new Parameters(); 4734 4735 while (1) 4736 { 4737 Identifier *ai = NULL; 4738 Type *at; 4739 4740 StorageClass storageClass = 0; 4741 StorageClass stc = 0; 4742 Lagain: 4743 if (stc) 4744 { 4745 storageClass = appendStorageClass(storageClass, stc); 4746 nextToken(); 4747 } 4748 switch (token.value) 4749 { 4750 case TOKref: 4751 stc = STCref; 4752 goto Lagain; 4753 4754 case TOKenum: 4755 stc = STCmanifest; 4756 goto Lagain; 4757 4758 case TOKalias: 4759 storageClass = appendStorageClass(storageClass, STCalias); 4760 nextToken(); 4761 break; 4762 4763 case TOKconst: 4764 if (peekNext() != TOKlparen) 4765 { 4766 stc = STCconst; 4767 goto Lagain; 4768 } 4769 break; 4770 4771 case TOKimmutable: 4772 if (peekNext() != TOKlparen) 4773 { 4774 stc = STCimmutable; 4775 goto Lagain; 4776 } 4777 break; 4778 4779 case TOKshared: 4780 if (peekNext() != TOKlparen) 4781 { 4782 stc = STCshared; 4783 goto Lagain; 4784 } 4785 break; 4786 4787 case TOKwild: 4788 if (peekNext() != TOKlparen) 4789 { 4790 stc = STCwild; 4791 goto Lagain; 4792 } 4793 break; 4794 4795 default: 4796 break; 4797 } 4798 if (token.value == TOKidentifier) 4799 { 4800 Token *t = peek(&token); 4801 if (t->value == TOKcomma || t->value == TOKsemicolon) 4802 { ai = token.ident; 4803 at = NULL; // infer argument type 4804 nextToken(); 4805 goto Larg; 4806 } 4807 } 4808 at = parseType(&ai); 4809 if (!ai) 4810 error("no identifier for declarator %s", at->toChars()); 4811 Larg: 4812 Parameter *p = new Parameter(storageClass, at, ai, NULL); 4813 parameters->push(p); 4814 if (token.value == TOKcomma) 4815 { nextToken(); 4816 continue; 4817 } 4818 break; 4819 } 4820 check(TOKsemicolon); 4821 4822 Expression *aggr = parseExpression(); 4823 if (token.value == TOKslice && parameters->dim == 1) 4824 { 4825 Parameter *p = (*parameters)[0]; 4826 delete parameters; 4827 nextToken(); 4828 Expression *upr = parseExpression(); 4829 check(TOKrparen); 4830 Loc endloc; 4831 Statement *body = (!isDecl) ? parseStatement(0, NULL, &endloc) : NULL; 4832 if (isRange) 4833 *isRange = true; 4834 return new ForeachRangeStatement(loc, op, p, aggr, upr, body, endloc); 4835 } 4836 else 4837 { 4838 check(TOKrparen); 4839 Loc endloc; 4840 Statement *body = (!isDecl) ? parseStatement(0, NULL, &endloc) : NULL; 4841 if (isRange) 4842 *isRange = false; 4843 return new ForeachStatement(loc, op, parameters, aggr, body, endloc); 4844 } 4845} 4846 4847Dsymbol *Parser::parseForeachStaticDecl(Loc loc, Dsymbol **pLastDecl) 4848{ 4849 nextToken(); 4850 4851 bool isRange = false; 4852 Statement *s = parseForeach(loc, &isRange, true); 4853 4854 return new StaticForeachDeclaration( 4855 new StaticForeach(loc, isRange ? NULL : (ForeachStatement *)s, 4856 isRange ? (ForeachRangeStatement *)s : NULL), 4857 parseBlock(pLastDecl) 4858 ); 4859} 4860 4861Statement *Parser::parseForeachStatic(Loc loc) 4862{ 4863 nextToken(); 4864 4865 bool isRange = false; 4866 Statement *s = parseForeach(loc, &isRange, false); 4867 4868 return new StaticForeachStatement(loc, 4869 new StaticForeach(loc, isRange ? NULL : (ForeachStatement *)s, 4870 isRange ? (ForeachRangeStatement *)s : NULL) 4871 ); 4872} 4873 4874/***************************************** 4875 * Input: 4876 * flags PSxxxx 4877 * Output: 4878 * pEndloc if { ... statements ... }, store location of closing brace, otherwise loc of first token of next statement 4879 */ 4880 4881Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc) 4882{ 4883 Statement *s = NULL; 4884 Condition *cond; 4885 Statement *ifbody; 4886 Statement *elsebody; 4887 bool isfinal; 4888 Loc loc = token.loc; 4889 4890 //printf("parseStatement()\n"); 4891 4892 if (flags & PScurly && token.value != TOKlcurly) 4893 error("statement expected to be { }, not %s", token.toChars()); 4894 4895 switch (token.value) 4896 { 4897 case TOKidentifier: 4898 { /* A leading identifier can be a declaration, label, or expression. 4899 * The easiest case to check first is label: 4900 */ 4901 Token *t = peek(&token); 4902 if (t->value == TOKcolon) 4903 { 4904 Token *nt = peek(t); 4905 if (nt->value == TOKcolon) 4906 { 4907 // skip ident:: 4908 nextToken(); 4909 nextToken(); 4910 nextToken(); 4911 error("use `.` for member lookup, not `::`"); 4912 break; 4913 } 4914 // It's a label 4915 Identifier *ident = token.ident; 4916 nextToken(); 4917 nextToken(); 4918 if (token.value == TOKrcurly) 4919 s = NULL; 4920 else if (token.value == TOKlcurly) 4921 s = parseStatement(PScurly | PSscope); 4922 else 4923 s = parseStatement(PSsemi_ok); 4924 s = new LabelStatement(loc, ident, s); 4925 break; 4926 } 4927 } 4928 /* fall through */ 4929 case TOKdot: 4930 case TOKtypeof: 4931 case TOKvector: 4932 case TOKtraits: 4933 /* Bugzilla 15163: If tokens can be handled as 4934 * old C-style declaration or D expression, prefer the latter. 4935 */ 4936 if (isDeclaration(&token, 3, TOKreserved, NULL)) 4937 goto Ldeclaration; 4938 else 4939 goto Lexp; 4940 break; 4941 4942 case TOKassert: 4943 case TOKthis: 4944 case TOKsuper: 4945 case TOKint32v: 4946 case TOKuns32v: 4947 case TOKint64v: 4948 case TOKuns64v: 4949 case TOKint128v: 4950 case TOKuns128v: 4951 case TOKfloat32v: 4952 case TOKfloat64v: 4953 case TOKfloat80v: 4954 case TOKimaginary32v: 4955 case TOKimaginary64v: 4956 case TOKimaginary80v: 4957 case TOKcharv: 4958 case TOKwcharv: 4959 case TOKdcharv: 4960 case TOKnull: 4961 case TOKtrue: 4962 case TOKfalse: 4963 case TOKstring: 4964 case TOKxstring: 4965 case TOKlparen: 4966 case TOKcast: 4967 case TOKmul: 4968 case TOKmin: 4969 case TOKadd: 4970 case TOKtilde: 4971 case TOKnot: 4972 case TOKplusplus: 4973 case TOKminusminus: 4974 case TOKnew: 4975 case TOKdelete: 4976 case TOKdelegate: 4977 case TOKfunction: 4978 case TOKtypeid: 4979 case TOKis: 4980 case TOKlbracket: 4981 case TOKfile: 4982 case TOKfilefullpath: 4983 case TOKline: 4984 case TOKmodulestring: 4985 case TOKfuncstring: 4986 case TOKprettyfunc: 4987 Lexp: 4988 { 4989 Expression *exp = parseExpression(); 4990 check(TOKsemicolon, "statement"); 4991 s = new ExpStatement(loc, exp); 4992 break; 4993 } 4994 4995 case TOKstatic: 4996 { // Look ahead to see if it's static assert() or static if() 4997 4998 Token *t = peek(&token); 4999 if (t->value == TOKassert) 5000 { 5001 s = new StaticAssertStatement(parseStaticAssert()); 5002 break; 5003 } 5004 if (t->value == TOKif) 5005 { 5006 cond = parseStaticIfCondition(); 5007 goto Lcondition; 5008 } 5009 else if (t->value == TOKforeach || t->value == TOKforeach_reverse) 5010 { 5011 s = parseForeachStatic(loc); 5012 if (flags & PSscope) 5013 s = new ScopeStatement(loc, s, token.loc); 5014 break; 5015 } 5016 if (t->value == TOKimport) 5017 { 5018 Dsymbols *imports = parseImport(); 5019 s = new ImportStatement(loc, imports); 5020 if (flags & PSscope) 5021 s = new ScopeStatement(loc, s, token.loc); 5022 break; 5023 } 5024 goto Ldeclaration; 5025 } 5026 5027 case TOKfinal: 5028 if (peekNext() == TOKswitch) 5029 { 5030 nextToken(); 5031 isfinal = true; 5032 goto Lswitch; 5033 } 5034 goto Ldeclaration; 5035 5036 case TOKwchar: case TOKdchar: 5037 case TOKbool: case TOKchar: 5038 case TOKint8: case TOKuns8: 5039 case TOKint16: case TOKuns16: 5040 case TOKint32: case TOKuns32: 5041 case TOKint64: case TOKuns64: 5042 case TOKint128: case TOKuns128: 5043 case TOKfloat32: case TOKfloat64: case TOKfloat80: 5044 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 5045 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 5046 case TOKvoid: 5047 // bug 7773: int.max is always a part of expression 5048 if (peekNext() == TOKdot) 5049 goto Lexp; 5050 if (peekNext() == TOKlparen) 5051 goto Lexp; 5052 /* fall through */ 5053 5054 case TOKalias: 5055 case TOKconst: 5056 case TOKauto: 5057 case TOKabstract: 5058 case TOKextern: 5059 case TOKalign: 5060 case TOKimmutable: 5061 case TOKshared: 5062 case TOKwild: 5063 case TOKdeprecated: 5064 case TOKnothrow: 5065 case TOKpure: 5066 case TOKref: 5067 case TOKgshared: 5068 case TOKat: 5069 case TOKstruct: 5070 case TOKunion: 5071 case TOKclass: 5072 case TOKinterface: 5073 Ldeclaration: 5074 { 5075 Dsymbols *a = parseDeclarations(false, NULL, NULL); 5076 if (a->dim > 1) 5077 { 5078 Statements *as = new Statements(); 5079 as->reserve(a->dim); 5080 for (size_t i = 0; i < a->dim; i++) 5081 { 5082 Dsymbol *d = (*a)[i]; 5083 s = new ExpStatement(loc, d); 5084 as->push(s); 5085 } 5086 s = new CompoundDeclarationStatement(loc, as); 5087 } 5088 else if (a->dim == 1) 5089 { 5090 Dsymbol *d = (*a)[0]; 5091 s = new ExpStatement(loc, d); 5092 } 5093 else 5094 s = new ExpStatement(loc, (Expression *)NULL); 5095 if (flags & PSscope) 5096 s = new ScopeStatement(loc, s, token.loc); 5097 break; 5098 } 5099 5100 case TOKenum: 5101 { /* Determine if this is a manifest constant declaration, 5102 * or a conventional enum. 5103 */ 5104 Dsymbol *d; 5105 Token *t = peek(&token); 5106 if (t->value == TOKlcurly || t->value == TOKcolon) 5107 d = parseEnum(); 5108 else if (t->value != TOKidentifier) 5109 goto Ldeclaration; 5110 else 5111 { 5112 t = peek(t); 5113 if (t->value == TOKlcurly || t->value == TOKcolon || 5114 t->value == TOKsemicolon) 5115 d = parseEnum(); 5116 else 5117 goto Ldeclaration; 5118 } 5119 s = new ExpStatement(loc, d); 5120 if (flags & PSscope) 5121 s = new ScopeStatement(loc, s, token.loc); 5122 break; 5123 } 5124 5125 case TOKmixin: 5126 { Token *t = peek(&token); 5127 if (t->value == TOKlparen) 5128 { // mixin(string) 5129 Expression *e = parseAssignExp(); 5130 check(TOKsemicolon); 5131 if (e->op == TOKmixin) 5132 { 5133 CompileExp *cpe = (CompileExp *)e; 5134 s = new CompileStatement(loc, cpe->e1); 5135 } 5136 else 5137 { 5138 s = new ExpStatement(loc, e); 5139 } 5140 break; 5141 } 5142 Dsymbol *d = parseMixin(); 5143 s = new ExpStatement(loc, d); 5144 if (flags & PSscope) 5145 s = new ScopeStatement(loc, s, token.loc); 5146 break; 5147 } 5148 5149 case TOKlcurly: 5150 { 5151 Loc lookingForElseSave = lookingForElse; 5152 lookingForElse = Loc(); 5153 5154 nextToken(); 5155 //if (token.value == TOKsemicolon) 5156 //error("use '{ }' for an empty statement, not a ';'"); 5157 Statements *statements = new Statements(); 5158 while (token.value != TOKrcurly && token.value != TOKeof) 5159 { 5160 statements->push(parseStatement(PSsemi | PScurlyscope)); 5161 } 5162 if (endPtr) *endPtr = token.ptr; 5163 endloc = token.loc; 5164 if (pEndloc) 5165 { 5166 *pEndloc = token.loc; 5167 pEndloc = NULL; // don't set it again 5168 } 5169 s = new CompoundStatement(loc, statements); 5170 if (flags & (PSscope | PScurlyscope)) 5171 s = new ScopeStatement(loc, s, token.loc); 5172 check(TOKrcurly, "compound statement"); 5173 lookingForElse = lookingForElseSave; 5174 break; 5175 } 5176 5177 case TOKwhile: 5178 { 5179 nextToken(); 5180 check(TOKlparen); 5181 Expression *condition = parseExpression(); 5182 check(TOKrparen); 5183 Loc endloc; 5184 Statement *body = parseStatement(PSscope, NULL, &endloc); 5185 s = new WhileStatement(loc, condition, body, endloc); 5186 break; 5187 } 5188 5189 case TOKsemicolon: 5190 if (!(flags & PSsemi_ok)) 5191 { 5192 if (flags & PSsemi) 5193 deprecation("use '{ }' for an empty statement, not a ';'"); 5194 else 5195 error("use '{ }' for an empty statement, not a ';'"); 5196 } 5197 nextToken(); 5198 s = new ExpStatement(loc, (Expression *)NULL); 5199 break; 5200 5201 case TOKdo: 5202 { Statement *body; 5203 Expression *condition; 5204 5205 nextToken(); 5206 Loc lookingForElseSave = lookingForElse; 5207 lookingForElse = Loc(); 5208 body = parseStatement(PSscope); 5209 lookingForElse = lookingForElseSave; 5210 check(TOKwhile); 5211 check(TOKlparen); 5212 condition = parseExpression(); 5213 check(TOKrparen); 5214 if (token.value == TOKsemicolon) 5215 nextToken(); 5216 else 5217 error("terminating ';' required after do-while statement"); 5218 s = new DoStatement(loc, body, condition, token.loc); 5219 break; 5220 } 5221 5222 case TOKfor: 5223 { 5224 Statement *init; 5225 Expression *condition; 5226 Expression *increment; 5227 5228 nextToken(); 5229 check(TOKlparen); 5230 if (token.value == TOKsemicolon) 5231 { init = NULL; 5232 nextToken(); 5233 } 5234 else 5235 { 5236 Loc lookingForElseSave = lookingForElse; 5237 lookingForElse = Loc(); 5238 init = parseStatement(0); 5239 lookingForElse = lookingForElseSave; 5240 } 5241 if (token.value == TOKsemicolon) 5242 { 5243 condition = NULL; 5244 nextToken(); 5245 } 5246 else 5247 { 5248 condition = parseExpression(); 5249 check(TOKsemicolon, "for condition"); 5250 } 5251 if (token.value == TOKrparen) 5252 { increment = NULL; 5253 nextToken(); 5254 } 5255 else 5256 { increment = parseExpression(); 5257 check(TOKrparen); 5258 } 5259 Loc endloc; 5260 Statement *body = parseStatement(PSscope, NULL, &endloc); 5261 s = new ForStatement(loc, init, condition, increment, body, endloc); 5262 break; 5263 } 5264 5265 case TOKforeach: 5266 case TOKforeach_reverse: 5267 { 5268 s = parseForeach(loc, NULL, false); 5269 break; 5270 } 5271 5272 case TOKif: 5273 { 5274 Parameter *param = NULL; 5275 Expression *condition; 5276 5277 nextToken(); 5278 check(TOKlparen); 5279 5280 StorageClass storageClass = 0; 5281 StorageClass stc = 0; 5282 LagainStc: 5283 if (stc) 5284 { 5285 storageClass = appendStorageClass(storageClass, stc); 5286 nextToken(); 5287 } 5288 switch (token.value) 5289 { 5290 case TOKref: 5291 stc = STCref; 5292 goto LagainStc; 5293 case TOKauto: 5294 stc = STCauto; 5295 goto LagainStc; 5296 case TOKconst: 5297 if (peekNext() != TOKlparen) 5298 { 5299 stc = STCconst; 5300 goto LagainStc; 5301 } 5302 break; 5303 case TOKimmutable: 5304 if (peekNext() != TOKlparen) 5305 { 5306 stc = STCimmutable; 5307 goto LagainStc; 5308 } 5309 break; 5310 case TOKshared: 5311 if (peekNext() != TOKlparen) 5312 { 5313 stc = STCshared; 5314 goto LagainStc; 5315 } 5316 break; 5317 case TOKwild: 5318 if (peekNext() != TOKlparen) 5319 { 5320 stc = STCwild; 5321 goto LagainStc; 5322 } 5323 break; 5324 default: 5325 break; 5326 } 5327 5328 if (storageClass != 0 && 5329 token.value == TOKidentifier && 5330 peek(&token)->value == TOKassign) 5331 { 5332 Identifier *ai = token.ident; 5333 Type *at = NULL; // infer parameter type 5334 nextToken(); 5335 check(TOKassign); 5336 param = new Parameter(storageClass, at, ai, NULL); 5337 } 5338 else if (isDeclaration(&token, 2, TOKassign, NULL)) 5339 { 5340 Identifier *ai; 5341 Type *at = parseType(&ai); 5342 check(TOKassign); 5343 param = new Parameter(storageClass, at, ai, NULL); 5344 } 5345 5346 condition = parseExpression(); 5347 check(TOKrparen); 5348 { 5349 Loc lookingForElseSave = lookingForElse; 5350 lookingForElse = loc; 5351 ifbody = parseStatement(PSscope); 5352 lookingForElse = lookingForElseSave; 5353 } 5354 if (token.value == TOKelse) 5355 { 5356 Loc elseloc = token.loc; 5357 nextToken(); 5358 elsebody = parseStatement(PSscope); 5359 checkDanglingElse(elseloc); 5360 } 5361 else 5362 elsebody = NULL; 5363 if (condition && ifbody) 5364 s = new IfStatement(loc, param, condition, ifbody, elsebody, token.loc); 5365 else 5366 s = NULL; // don't propagate parsing errors 5367 break; 5368 } 5369 5370 case TOKscope: 5371 if (peek(&token)->value != TOKlparen) 5372 goto Ldeclaration; // scope used as storage class 5373 nextToken(); 5374 check(TOKlparen); 5375 if (token.value != TOKidentifier) 5376 { error("scope identifier expected"); 5377 goto Lerror; 5378 } 5379 else 5380 { TOK t = TOKon_scope_exit; 5381 Identifier *id = token.ident; 5382 5383 if (id == Id::exit) 5384 t = TOKon_scope_exit; 5385 else if (id == Id::failure) 5386 t = TOKon_scope_failure; 5387 else if (id == Id::success) 5388 t = TOKon_scope_success; 5389 else 5390 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars()); 5391 nextToken(); 5392 check(TOKrparen); 5393 Statement *st = parseStatement(PSscope); 5394 s = new OnScopeStatement(loc, t, st); 5395 break; 5396 } 5397 5398 case TOKdebug: 5399 nextToken(); 5400 if (token.value == TOKassign) 5401 { 5402 error("debug conditions can only be declared at module scope"); 5403 nextToken(); 5404 nextToken(); 5405 goto Lerror; 5406 } 5407 cond = parseDebugCondition(); 5408 goto Lcondition; 5409 5410 case TOKversion: 5411 nextToken(); 5412 if (token.value == TOKassign) 5413 { 5414 error("version conditions can only be declared at module scope"); 5415 nextToken(); 5416 nextToken(); 5417 goto Lerror; 5418 } 5419 cond = parseVersionCondition(); 5420 goto Lcondition; 5421 5422 Lcondition: 5423 { 5424 Loc lookingForElseSave = lookingForElse; 5425 lookingForElse = loc; 5426 ifbody = parseStatement(0); 5427 lookingForElse = lookingForElseSave; 5428 } 5429 elsebody = NULL; 5430 if (token.value == TOKelse) 5431 { 5432 Loc elseloc = token.loc; 5433 nextToken(); 5434 elsebody = parseStatement(0); 5435 checkDanglingElse(elseloc); 5436 } 5437 s = new ConditionalStatement(loc, cond, ifbody, elsebody); 5438 if (flags & PSscope) 5439 s = new ScopeStatement(loc, s, token.loc); 5440 break; 5441 5442 case TOKpragma: 5443 { Identifier *ident; 5444 Expressions *args = NULL; 5445 Statement *body; 5446 5447 nextToken(); 5448 check(TOKlparen); 5449 if (token.value != TOKidentifier) 5450 { error("pragma(identifier expected"); 5451 goto Lerror; 5452 } 5453 ident = token.ident; 5454 nextToken(); 5455 if (token.value == TOKcomma && peekNext() != TOKrparen) 5456 args = parseArguments(); // pragma(identifier, args...); 5457 else 5458 check(TOKrparen); // pragma(identifier); 5459 if (token.value == TOKsemicolon) 5460 { nextToken(); 5461 body = NULL; 5462 } 5463 else 5464 body = parseStatement(PSsemi); 5465 s = new PragmaStatement(loc, ident, args, body); 5466 break; 5467 } 5468 5469 case TOKswitch: 5470 isfinal = false; 5471 goto Lswitch; 5472 5473 Lswitch: 5474 { 5475 nextToken(); 5476 check(TOKlparen); 5477 Expression *condition = parseExpression(); 5478 check(TOKrparen); 5479 Statement *body = parseStatement(PSscope); 5480 s = new SwitchStatement(loc, condition, body, isfinal); 5481 break; 5482 } 5483 5484 case TOKcase: 5485 { Expression *exp; 5486 Expressions cases; // array of Expression's 5487 Expression *last = NULL; 5488 5489 while (1) 5490 { 5491 nextToken(); 5492 exp = parseAssignExp(); 5493 cases.push(exp); 5494 if (token.value != TOKcomma) 5495 break; 5496 } 5497 check(TOKcolon); 5498 5499 /* case exp: .. case last: 5500 */ 5501 if (token.value == TOKslice) 5502 { 5503 if (cases.dim > 1) 5504 error("only one case allowed for start of case range"); 5505 nextToken(); 5506 check(TOKcase); 5507 last = parseAssignExp(); 5508 check(TOKcolon); 5509 } 5510 5511 if (flags & PScurlyscope) 5512 { 5513 Statements *statements = new Statements(); 5514 while (token.value != TOKcase && 5515 token.value != TOKdefault && 5516 token.value != TOKeof && 5517 token.value != TOKrcurly) 5518 { 5519 statements->push(parseStatement(PSsemi | PScurlyscope)); 5520 } 5521 s = new CompoundStatement(loc, statements); 5522 } 5523 else 5524 s = parseStatement(PSsemi | PScurlyscope); 5525 s = new ScopeStatement(loc, s, token.loc); 5526 5527 if (last) 5528 { 5529 s = new CaseRangeStatement(loc, exp, last, s); 5530 } 5531 else 5532 { 5533 // Keep cases in order by building the case statements backwards 5534 for (size_t i = cases.dim; i; i--) 5535 { 5536 exp = cases[i - 1]; 5537 s = new CaseStatement(loc, exp, s); 5538 } 5539 } 5540 break; 5541 } 5542 5543 case TOKdefault: 5544 { 5545 nextToken(); 5546 check(TOKcolon); 5547 5548 if (flags & PScurlyscope) 5549 { 5550 Statements *statements = new Statements(); 5551 while (token.value != TOKcase && 5552 token.value != TOKdefault && 5553 token.value != TOKeof && 5554 token.value != TOKrcurly) 5555 { 5556 statements->push(parseStatement(PSsemi | PScurlyscope)); 5557 } 5558 s = new CompoundStatement(loc, statements); 5559 } 5560 else 5561 s = parseStatement(PSsemi | PScurlyscope); 5562 s = new ScopeStatement(loc, s, token.loc); 5563 s = new DefaultStatement(loc, s); 5564 break; 5565 } 5566 5567 case TOKreturn: 5568 { Expression *exp; 5569 5570 nextToken(); 5571 if (token.value == TOKsemicolon) 5572 exp = NULL; 5573 else 5574 exp = parseExpression(); 5575 check(TOKsemicolon, "return statement"); 5576 s = new ReturnStatement(loc, exp); 5577 break; 5578 } 5579 5580 case TOKbreak: 5581 { Identifier *ident; 5582 5583 nextToken(); 5584 if (token.value == TOKidentifier) 5585 { ident = token.ident; 5586 nextToken(); 5587 } 5588 else 5589 ident = NULL; 5590 check(TOKsemicolon, "break statement"); 5591 s = new BreakStatement(loc, ident); 5592 break; 5593 } 5594 5595 case TOKcontinue: 5596 { Identifier *ident; 5597 5598 nextToken(); 5599 if (token.value == TOKidentifier) 5600 { ident = token.ident; 5601 nextToken(); 5602 } 5603 else 5604 ident = NULL; 5605 check(TOKsemicolon, "continue statement"); 5606 s = new ContinueStatement(loc, ident); 5607 break; 5608 } 5609 5610 case TOKgoto: 5611 { Identifier *ident; 5612 5613 nextToken(); 5614 if (token.value == TOKdefault) 5615 { 5616 nextToken(); 5617 s = new GotoDefaultStatement(loc); 5618 } 5619 else if (token.value == TOKcase) 5620 { 5621 Expression *exp = NULL; 5622 5623 nextToken(); 5624 if (token.value != TOKsemicolon) 5625 exp = parseExpression(); 5626 s = new GotoCaseStatement(loc, exp); 5627 } 5628 else 5629 { 5630 if (token.value != TOKidentifier) 5631 { 5632 error("identifier expected following goto"); 5633 ident = NULL; 5634 } 5635 else 5636 { 5637 ident = token.ident; 5638 nextToken(); 5639 } 5640 s = new GotoStatement(loc, ident); 5641 } 5642 check(TOKsemicolon, "goto statement"); 5643 break; 5644 } 5645 5646 case TOKsynchronized: 5647 { Expression *exp; 5648 Statement *body; 5649 5650 Token *t = peek(&token); 5651 if (skipAttributes(t, &t) && t->value == TOKclass) 5652 goto Ldeclaration; 5653 5654 nextToken(); 5655 if (token.value == TOKlparen) 5656 { 5657 nextToken(); 5658 exp = parseExpression(); 5659 check(TOKrparen); 5660 } 5661 else 5662 exp = NULL; 5663 body = parseStatement(PSscope); 5664 s = new SynchronizedStatement(loc, exp, body); 5665 break; 5666 } 5667 5668 case TOKwith: 5669 { Expression *exp; 5670 Statement *body; 5671 5672 nextToken(); 5673 check(TOKlparen); 5674 exp = parseExpression(); 5675 check(TOKrparen); 5676 body = parseStatement(PSscope); 5677 s = new WithStatement(loc, exp, body, token.loc); 5678 break; 5679 } 5680 5681 case TOKtry: 5682 { Statement *body; 5683 Catches *catches = NULL; 5684 Statement *finalbody = NULL; 5685 5686 nextToken(); 5687 Loc lookingForElseSave = lookingForElse; 5688 lookingForElse = Loc(); 5689 body = parseStatement(PSscope); 5690 lookingForElse = lookingForElseSave; 5691 while (token.value == TOKcatch) 5692 { 5693 Statement *handler; 5694 Catch *c; 5695 Type *t; 5696 Identifier *id; 5697 Loc catchloc = token.loc; 5698 5699 nextToken(); 5700 if (token.value == TOKlcurly || token.value != TOKlparen) 5701 { 5702 t = NULL; 5703 id = NULL; 5704 } 5705 else 5706 { 5707 check(TOKlparen); 5708 id = NULL; 5709 t = parseType(&id); 5710 check(TOKrparen); 5711 } 5712 handler = parseStatement(0); 5713 c = new Catch(catchloc, t, id, handler); 5714 if (!catches) 5715 catches = new Catches(); 5716 catches->push(c); 5717 } 5718 5719 if (token.value == TOKfinally) 5720 { 5721 nextToken(); 5722 finalbody = parseStatement(PSscope); 5723 } 5724 5725 s = body; 5726 if (!catches && !finalbody) 5727 error("catch or finally expected following try"); 5728 else 5729 { if (catches) 5730 s = new TryCatchStatement(loc, body, catches); 5731 if (finalbody) 5732 s = new TryFinallyStatement(loc, s, finalbody); 5733 } 5734 break; 5735 } 5736 5737 case TOKthrow: 5738 { Expression *exp; 5739 5740 nextToken(); 5741 exp = parseExpression(); 5742 check(TOKsemicolon, "throw statement"); 5743 s = new ThrowStatement(loc, exp); 5744 break; 5745 } 5746 5747 case TOKasm: 5748 { 5749 // Parse the asm block into a sequence of AsmStatements, 5750 // each AsmStatement is one instruction. 5751 // Separate out labels. 5752 // Defer parsing of AsmStatements until semantic processing. 5753 5754 Loc labelloc; 5755 5756 nextToken(); 5757 StorageClass stc = parsePostfix(STCundefined, NULL); 5758 if (stc & (STCconst | STCimmutable | STCshared | STCwild)) 5759 error("const/immutable/shared/inout attributes are not allowed on asm blocks"); 5760 5761 check(TOKlcurly); 5762 Token *toklist = NULL; 5763 Token **ptoklist = &toklist; 5764 Identifier *label = NULL; 5765 Statements *statements = new Statements(); 5766 size_t nestlevel = 0; 5767 while (1) 5768 { 5769 switch (token.value) 5770 { 5771 case TOKidentifier: 5772 if (!toklist) 5773 { 5774 // Look ahead to see if it is a label 5775 Token *t = peek(&token); 5776 if (t->value == TOKcolon) 5777 { // It's a label 5778 label = token.ident; 5779 labelloc = token.loc; 5780 nextToken(); 5781 nextToken(); 5782 continue; 5783 } 5784 } 5785 goto Ldefault; 5786 5787 case TOKlcurly: 5788 ++nestlevel; 5789 goto Ldefault; 5790 5791 case TOKrcurly: 5792 if (nestlevel > 0) 5793 { 5794 --nestlevel; 5795 goto Ldefault; 5796 } 5797 5798 if (toklist || label) 5799 { 5800 error("asm statements must end in ';'"); 5801 } 5802 break; 5803 5804 case TOKsemicolon: 5805 if (nestlevel != 0) 5806 error("mismatched number of curly brackets"); 5807 5808 s = NULL; 5809 if (toklist || label) 5810 { 5811 // Create AsmStatement from list of tokens we've saved 5812 s = new AsmStatement(token.loc, toklist); 5813 toklist = NULL; 5814 ptoklist = &toklist; 5815 if (label) 5816 { s = new LabelStatement(labelloc, label, s); 5817 label = NULL; 5818 } 5819 statements->push(s); 5820 } 5821 nextToken(); 5822 continue; 5823 5824 case TOKeof: 5825 /* { */ 5826 error("matching '}' expected, not end of file"); 5827 goto Lerror; 5828 /* fall through */ 5829 5830 default: 5831 Ldefault: 5832 *ptoklist = Token::alloc(); 5833 memcpy(*ptoklist, &token, sizeof(Token)); 5834 ptoklist = &(*ptoklist)->next; 5835 *ptoklist = NULL; 5836 5837 nextToken(); 5838 continue; 5839 } 5840 break; 5841 } 5842 s = new CompoundAsmStatement(loc, statements, stc); 5843 nextToken(); 5844 break; 5845 } 5846 5847 case TOKimport: 5848 { 5849 Dsymbols *imports = parseImport(); 5850 s = new ImportStatement(loc, imports); 5851 if (flags & PSscope) 5852 s = new ScopeStatement(loc, s, token.loc); 5853 break; 5854 } 5855 5856 case TOKtemplate: 5857 { 5858 Dsymbol *d = parseTemplateDeclaration(); 5859 s = new ExpStatement(loc, d); 5860 break; 5861 } 5862 5863 default: 5864 error("found '%s' instead of statement", token.toChars()); 5865 goto Lerror; 5866 5867 Lerror: 5868 while (token.value != TOKrcurly && 5869 token.value != TOKsemicolon && 5870 token.value != TOKeof) 5871 nextToken(); 5872 if (token.value == TOKsemicolon) 5873 nextToken(); 5874 s = NULL; 5875 break; 5876 } 5877 if (pEndloc) 5878 *pEndloc = token.loc; 5879 return s; 5880} 5881 5882void Parser::check(TOK value) 5883{ 5884 check(token.loc, value); 5885} 5886 5887void Parser::check(Loc loc, TOK value) 5888{ 5889 if (token.value != value) 5890 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value)); 5891 nextToken(); 5892} 5893 5894void Parser::check(TOK value, const char *string) 5895{ 5896 if (token.value != value) 5897 error("found '%s' when expecting '%s' following %s", 5898 token.toChars(), Token::toChars(value), string); 5899 nextToken(); 5900} 5901 5902void Parser::checkParens(TOK value, Expression *e) 5903{ 5904 if (precedence[e->op] == PREC_rel && !e->parens) 5905 error(e->loc, "%s must be parenthesized when next to operator %s", e->toChars(), Token::toChars(value)); 5906} 5907 5908/************************************ 5909 * Determine if the scanner is sitting on the start of a declaration. 5910 * Input: 5911 * needId 0 no identifier 5912 * 1 identifier optional 5913 * 2 must have identifier 5914 * 3 must have identifier, but don't recognize old C-style syntax. 5915 * Output: 5916 * if *pt is not NULL, it is set to the ending token, which would be endtok 5917 */ 5918 5919bool Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt) 5920{ 5921 //printf("isDeclaration(needId = %d)\n", needId); 5922 int haveId = 0; 5923 int haveTpl = 0; 5924 5925 while (1) 5926 { 5927 if ((t->value == TOKconst || 5928 t->value == TOKimmutable || 5929 t->value == TOKwild || 5930 t->value == TOKshared) && 5931 peek(t)->value != TOKlparen) 5932 { 5933 /* const type 5934 * immutable type 5935 * shared type 5936 * wild type 5937 */ 5938 t = peek(t); 5939 continue; 5940 } 5941 break; 5942 } 5943 5944 if (!isBasicType(&t)) 5945 { 5946 goto Lisnot; 5947 } 5948 if (!isDeclarator(&t, &haveId, &haveTpl, endtok, needId != 3)) 5949 goto Lisnot; 5950 if (needId == 1 || (needId == 0 && !haveId) || ((needId == 2 || needId == 3) && haveId)) 5951 { 5952 if (pt) 5953 *pt = t; 5954 goto Lis; 5955 } 5956 else 5957 goto Lisnot; 5958 5959Lis: 5960 //printf("\tis declaration, t = %s\n", t->toChars()); 5961 return true; 5962 5963Lisnot: 5964 //printf("\tis not declaration\n"); 5965 return false; 5966} 5967 5968bool Parser::isBasicType(Token **pt) 5969{ 5970 // This code parallels parseBasicType() 5971 Token *t = *pt; 5972 5973 switch (t->value) 5974 { 5975 case TOKwchar: case TOKdchar: 5976 case TOKbool: case TOKchar: 5977 case TOKint8: case TOKuns8: 5978 case TOKint16: case TOKuns16: 5979 case TOKint32: case TOKuns32: 5980 case TOKint64: case TOKuns64: 5981 case TOKint128: case TOKuns128: 5982 case TOKfloat32: case TOKfloat64: case TOKfloat80: 5983 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 5984 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 5985 case TOKvoid: 5986 t = peek(t); 5987 break; 5988 5989 case TOKidentifier: 5990 L5: 5991 t = peek(t); 5992 if (t->value == TOKnot) 5993 { 5994 goto L4; 5995 } 5996 goto L3; 5997 while (1) 5998 { 5999 L2: 6000 t = peek(t); 6001 L3: 6002 if (t->value == TOKdot) 6003 { 6004 Ldot: 6005 t = peek(t); 6006 if (t->value != TOKidentifier) 6007 goto Lfalse; 6008 t = peek(t); 6009 if (t->value != TOKnot) 6010 goto L3; 6011 L4: 6012 /* Seen a ! 6013 * Look for: 6014 * !( args ), !identifier, etc. 6015 */ 6016 t = peek(t); 6017 switch (t->value) 6018 { 6019 case TOKidentifier: 6020 goto L5; 6021 case TOKlparen: 6022 if (!skipParens(t, &t)) 6023 goto Lfalse; 6024 goto L3; 6025 case TOKwchar: case TOKdchar: 6026 case TOKbool: case TOKchar: 6027 case TOKint8: case TOKuns8: 6028 case TOKint16: case TOKuns16: 6029 case TOKint32: case TOKuns32: 6030 case TOKint64: case TOKuns64: 6031 case TOKint128: case TOKuns128: 6032 case TOKfloat32: case TOKfloat64: case TOKfloat80: 6033 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 6034 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 6035 case TOKvoid: 6036 case TOKint32v: 6037 case TOKuns32v: 6038 case TOKint64v: 6039 case TOKuns64v: 6040 case TOKint128v: 6041 case TOKuns128v: 6042 case TOKfloat32v: 6043 case TOKfloat64v: 6044 case TOKfloat80v: 6045 case TOKimaginary32v: 6046 case TOKimaginary64v: 6047 case TOKimaginary80v: 6048 case TOKnull: 6049 case TOKtrue: 6050 case TOKfalse: 6051 case TOKcharv: 6052 case TOKwcharv: 6053 case TOKdcharv: 6054 case TOKstring: 6055 case TOKxstring: 6056 case TOKfile: 6057 case TOKfilefullpath: 6058 case TOKline: 6059 case TOKmodulestring: 6060 case TOKfuncstring: 6061 case TOKprettyfunc: 6062 goto L2; 6063 default: 6064 goto Lfalse; 6065 } 6066 } 6067 else 6068 break; 6069 } 6070 break; 6071 6072 case TOKdot: 6073 goto Ldot; 6074 6075 case TOKtypeof: 6076 case TOKvector: 6077 /* typeof(exp).identifier... 6078 */ 6079 t = peek(t); 6080 if (!skipParens(t, &t)) 6081 goto Lfalse; 6082 goto L3; 6083 6084 case TOKtraits: 6085 { 6086 // __traits(getMember 6087 t = peek(t); 6088 if (t->value != TOKlparen) 6089 goto Lfalse; 6090 Token *lp = t; 6091 t = peek(t); 6092 if (t->value != TOKidentifier || t->ident != Id::getMember) 6093 goto Lfalse; 6094 if (!skipParens(lp, &lp)) 6095 goto Lfalse; 6096 // we are in a lookup for decl VS statement 6097 // so we expect a declarator following __trait if it's a type. 6098 // other usages wont be ambiguous (alias, template instance, type qual, etc.) 6099 if (lp->value != TOKidentifier) 6100 goto Lfalse; 6101 6102 break; 6103 } 6104 6105 case TOKconst: 6106 case TOKimmutable: 6107 case TOKshared: 6108 case TOKwild: 6109 // const(type) or immutable(type) or shared(type) or wild(type) 6110 t = peek(t); 6111 if (t->value != TOKlparen) 6112 goto Lfalse; 6113 t = peek(t); 6114 if (!isDeclaration(t, 0, TOKrparen, &t)) 6115 { 6116 goto Lfalse; 6117 } 6118 t = peek(t); 6119 break; 6120 6121 default: 6122 goto Lfalse; 6123 } 6124 *pt = t; 6125 //printf("is\n"); 6126 return true; 6127 6128Lfalse: 6129 //printf("is not\n"); 6130 return false; 6131} 6132 6133bool Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, bool allowAltSyntax) 6134{ // This code parallels parseDeclarator() 6135 Token *t = *pt; 6136 int parens; 6137 6138 //printf("Parser::isDeclarator() %s\n", t->toChars()); 6139 if (t->value == TOKassign) 6140 return false; 6141 6142 while (1) 6143 { 6144 parens = false; 6145 switch (t->value) 6146 { 6147 case TOKmul: 6148 //case TOKand: 6149 t = peek(t); 6150 continue; 6151 6152 case TOKlbracket: 6153 t = peek(t); 6154 if (t->value == TOKrbracket) 6155 { 6156 t = peek(t); 6157 } 6158 else if (isDeclaration(t, 0, TOKrbracket, &t)) 6159 { 6160 // It's an associative array declaration 6161 t = peek(t); 6162 6163 // ...[type].ident 6164 if (t->value == TOKdot && peek(t)->value == TOKidentifier) 6165 { 6166 t = peek(t); 6167 t = peek(t); 6168 } 6169 } 6170 else 6171 { 6172 // [ expression ] 6173 // [ expression .. expression ] 6174 if (!isExpression(&t)) 6175 return false; 6176 if (t->value == TOKslice) 6177 { 6178 t = peek(t); 6179 if (!isExpression(&t)) 6180 return false; 6181 if (t->value != TOKrbracket) 6182 return false; 6183 t = peek(t); 6184 } 6185 else 6186 { 6187 if (t->value != TOKrbracket) 6188 return false; 6189 t = peek(t); 6190 6191 // ...[index].ident 6192 if (t->value == TOKdot && peek(t)->value == TOKidentifier) 6193 { 6194 t = peek(t); 6195 t = peek(t); 6196 } 6197 } 6198 } 6199 continue; 6200 6201 case TOKidentifier: 6202 if (*haveId) 6203 return false; 6204 *haveId = true; 6205 t = peek(t); 6206 break; 6207 6208 case TOKlparen: 6209 if (!allowAltSyntax) 6210 return false; // Do not recognize C-style declarations. 6211 6212 t = peek(t); 6213 6214 if (t->value == TOKrparen) 6215 return false; // () is not a declarator 6216 6217 /* Regard ( identifier ) as not a declarator 6218 * BUG: what about ( *identifier ) in 6219 * f(*p)(x); 6220 * where f is a class instance with overloaded () ? 6221 * Should we just disallow C-style function pointer declarations? 6222 */ 6223 if (t->value == TOKidentifier) 6224 { Token *t2 = peek(t); 6225 if (t2->value == TOKrparen) 6226 return false; 6227 } 6228 6229 6230 if (!isDeclarator(&t, haveId, NULL, TOKrparen)) 6231 return false; 6232 t = peek(t); 6233 parens = true; 6234 break; 6235 6236 case TOKdelegate: 6237 case TOKfunction: 6238 t = peek(t); 6239 if (!isParameters(&t)) 6240 return false; 6241 skipAttributes(t, &t); 6242 continue; 6243 default: break; 6244 } 6245 break; 6246 } 6247 6248 while (1) 6249 { 6250 switch (t->value) 6251 { 6252#if CARRAYDECL 6253 case TOKlbracket: 6254 parens = false; 6255 t = peek(t); 6256 if (t->value == TOKrbracket) 6257 { 6258 t = peek(t); 6259 } 6260 else if (isDeclaration(t, 0, TOKrbracket, &t)) 6261 { // It's an associative array declaration 6262 t = peek(t); 6263 } 6264 else 6265 { 6266 // [ expression ] 6267 if (!isExpression(&t)) 6268 return false; 6269 if (t->value != TOKrbracket) 6270 return false; 6271 t = peek(t); 6272 } 6273 continue; 6274#endif 6275 6276 case TOKlparen: 6277 parens = false; 6278 if (Token *tk = peekPastParen(t)) 6279 { 6280 if (tk->value == TOKlparen) 6281 { 6282 if (!haveTpl) return false; 6283 *haveTpl = 1; 6284 t = tk; 6285 } 6286 else if (tk->value == TOKassign) 6287 { 6288 if (!haveTpl) return false; 6289 *haveTpl = 1; 6290 *pt = tk; 6291 return true; 6292 } 6293 } 6294 if (!isParameters(&t)) 6295 return false; 6296 while (1) 6297 { 6298 switch (t->value) 6299 { 6300 case TOKconst: 6301 case TOKimmutable: 6302 case TOKshared: 6303 case TOKwild: 6304 case TOKpure: 6305 case TOKnothrow: 6306 case TOKreturn: 6307 case TOKscope: 6308 t = peek(t); 6309 continue; 6310 case TOKat: 6311 t = peek(t); // skip '@' 6312 t = peek(t); // skip identifier 6313 continue; 6314 default: 6315 break; 6316 } 6317 break; 6318 } 6319 continue; 6320 6321 case TOKidentifier: 6322 if (t->ident != Id::_body) 6323 goto Ldefault; 6324 /* fall through */ 6325 6326 // Valid tokens that follow a declaration 6327 case TOKrparen: 6328 case TOKrbracket: 6329 case TOKassign: 6330 case TOKcomma: 6331 case TOKdotdotdot: 6332 case TOKsemicolon: 6333 case TOKlcurly: 6334 case TOKin: 6335 case TOKout: 6336 case TOKdo: 6337 // The !parens is to disallow unnecessary parentheses 6338 if (!parens && (endtok == TOKreserved || endtok == t->value)) 6339 { *pt = t; 6340 return true; 6341 } 6342 return false; 6343 6344 case TOKif: 6345 return haveTpl ? true : false; 6346 6347 default: 6348 Ldefault: 6349 return false; 6350 } 6351 } 6352 assert(0); 6353} 6354 6355 6356bool Parser::isParameters(Token **pt) 6357{ // This code parallels parseParameters() 6358 Token *t = *pt; 6359 6360 //printf("isParameters()\n"); 6361 if (t->value != TOKlparen) 6362 return false; 6363 6364 t = peek(t); 6365 for (;1; t = peek(t)) 6366 { 6367 L1: 6368 switch (t->value) 6369 { 6370 case TOKrparen: 6371 break; 6372 6373 case TOKdotdotdot: 6374 t = peek(t); 6375 break; 6376 6377 case TOKin: 6378 case TOKout: 6379 case TOKref: 6380 case TOKlazy: 6381 case TOKscope: 6382 case TOKfinal: 6383 case TOKauto: 6384 case TOKreturn: 6385 continue; 6386 6387 case TOKconst: 6388 case TOKimmutable: 6389 case TOKshared: 6390 case TOKwild: 6391 t = peek(t); 6392 if (t->value == TOKlparen) 6393 { 6394 t = peek(t); 6395 if (!isDeclaration(t, 0, TOKrparen, &t)) 6396 return false; 6397 t = peek(t); // skip past closing ')' 6398 goto L2; 6399 } 6400 goto L1; 6401 6402 default: 6403 { if (!isBasicType(&t)) 6404 return false; 6405 L2: 6406 int tmp = false; 6407 if (t->value != TOKdotdotdot && 6408 !isDeclarator(&t, &tmp, NULL, TOKreserved)) 6409 return false; 6410 if (t->value == TOKassign) 6411 { t = peek(t); 6412 if (!isExpression(&t)) 6413 return false; 6414 } 6415 if (t->value == TOKdotdotdot) 6416 { 6417 t = peek(t); 6418 break; 6419 } 6420 } 6421 if (t->value == TOKcomma) 6422 { 6423 continue; 6424 } 6425 break; 6426 } 6427 break; 6428 } 6429 if (t->value != TOKrparen) 6430 return false; 6431 t = peek(t); 6432 *pt = t; 6433 return true; 6434} 6435 6436bool Parser::isExpression(Token **pt) 6437{ 6438 // This is supposed to determine if something is an expression. 6439 // What it actually does is scan until a closing right bracket 6440 // is found. 6441 6442 Token *t = *pt; 6443 int brnest = 0; 6444 int panest = 0; 6445 int curlynest = 0; 6446 6447 for (;; t = peek(t)) 6448 { 6449 switch (t->value) 6450 { 6451 case TOKlbracket: 6452 brnest++; 6453 continue; 6454 6455 case TOKrbracket: 6456 if (--brnest >= 0) 6457 continue; 6458 break; 6459 6460 case TOKlparen: 6461 panest++; 6462 continue; 6463 6464 case TOKcomma: 6465 if (brnest || panest) 6466 continue; 6467 break; 6468 6469 case TOKrparen: 6470 if (--panest >= 0) 6471 continue; 6472 break; 6473 6474 case TOKlcurly: 6475 curlynest++; 6476 continue; 6477 6478 case TOKrcurly: 6479 if (--curlynest >= 0) 6480 continue; 6481 return false; 6482 6483 case TOKslice: 6484 if (brnest) 6485 continue; 6486 break; 6487 6488 case TOKsemicolon: 6489 if (curlynest) 6490 continue; 6491 return false; 6492 6493 case TOKeof: 6494 return false; 6495 6496 default: 6497 continue; 6498 } 6499 break; 6500 } 6501 6502 *pt = t; 6503 return true; 6504} 6505 6506/******************************************* 6507 * Skip parens, brackets. 6508 * Input: 6509 * t is on opening ( 6510 * Output: 6511 * *pt is set to closing token, which is ')' on success 6512 * Returns: 6513 * true successful 6514 * false some parsing error 6515 */ 6516 6517bool Parser::skipParens(Token *t, Token **pt) 6518{ 6519 if (t->value != TOKlparen) 6520 return false; 6521 6522 int parens = 0; 6523 6524 while (1) 6525 { 6526 switch (t->value) 6527 { 6528 case TOKlparen: 6529 parens++; 6530 break; 6531 6532 case TOKrparen: 6533 parens--; 6534 if (parens < 0) 6535 goto Lfalse; 6536 if (parens == 0) 6537 goto Ldone; 6538 break; 6539 6540 case TOKeof: 6541 goto Lfalse; 6542 6543 default: 6544 break; 6545 } 6546 t = peek(t); 6547 } 6548 6549 Ldone: 6550 if (pt) 6551 *pt = peek(t); // skip found rparen 6552 return true; 6553 6554 Lfalse: 6555 return false; 6556} 6557 6558bool Parser::skipParensIf(Token *t, Token **pt) 6559{ 6560 if (t->value != TOKlparen) 6561 { 6562 if (pt) 6563 *pt = t; 6564 return true; 6565 } 6566 return skipParens(t, pt); 6567} 6568 6569/******************************************* 6570 * Skip attributes. 6571 * Input: 6572 * t is on a candidate attribute 6573 * Output: 6574 * *pt is set to first non-attribute token on success 6575 * Returns: 6576 * true successful 6577 * false some parsing error 6578 */ 6579 6580bool Parser::skipAttributes(Token *t, Token **pt) 6581{ 6582 while (1) 6583 { 6584 switch (t->value) 6585 { 6586 case TOKconst: 6587 case TOKimmutable: 6588 case TOKshared: 6589 case TOKwild: 6590 case TOKfinal: 6591 case TOKauto: 6592 case TOKscope: 6593 case TOKoverride: 6594 case TOKabstract: 6595 case TOKsynchronized: 6596 break; 6597 case TOKdeprecated: 6598 if (peek(t)->value == TOKlparen) 6599 { 6600 t = peek(t); 6601 if (!skipParens(t, &t)) 6602 goto Lerror; 6603 // t is on the next of closing parenthesis 6604 continue; 6605 } 6606 break; 6607 case TOKnothrow: 6608 case TOKpure: 6609 case TOKref: 6610 case TOKgshared: 6611 case TOKreturn: 6612 //case TOKmanifest: 6613 break; 6614 case TOKat: 6615 t = peek(t); 6616 if (t->value == TOKidentifier) 6617 { 6618 /* @identifier 6619 * @identifier!arg 6620 * @identifier!(arglist) 6621 * any of the above followed by (arglist) 6622 * @predefined_attribute 6623 */ 6624 if (t->ident == Id::property || 6625 t->ident == Id::nogc || 6626 t->ident == Id::safe || 6627 t->ident == Id::trusted || 6628 t->ident == Id::system || 6629 t->ident == Id::disable) 6630 break; 6631 t = peek(t); 6632 if (t->value == TOKnot) 6633 { 6634 t = peek(t); 6635 if (t->value == TOKlparen) 6636 { 6637 // @identifier!(arglist) 6638 if (!skipParens(t, &t)) 6639 goto Lerror; 6640 // t is on the next of closing parenthesis 6641 } 6642 else 6643 { 6644 // @identifier!arg 6645 // Do low rent skipTemplateArgument 6646 if (t->value == TOKvector) 6647 { 6648 // identifier!__vector(type) 6649 t = peek(t); 6650 if (!skipParens(t, &t)) 6651 goto Lerror; 6652 } 6653 else 6654 t = peek(t); 6655 } 6656 } 6657 if (t->value == TOKlparen) 6658 { 6659 if (!skipParens(t, &t)) 6660 goto Lerror; 6661 // t is on the next of closing parenthesis 6662 continue; 6663 } 6664 continue; 6665 } 6666 if (t->value == TOKlparen) 6667 { 6668 // @( ArgumentList ) 6669 if (!skipParens(t, &t)) 6670 goto Lerror; 6671 // t is on the next of closing parenthesis 6672 continue; 6673 } 6674 goto Lerror; 6675 default: 6676 goto Ldone; 6677 } 6678 t = peek(t); 6679 } 6680 6681 Ldone: 6682 if (pt) 6683 *pt = t; 6684 return true; 6685 6686 Lerror: 6687 return false; 6688} 6689 6690/********************************* Expression Parser ***************************/ 6691 6692Expression *Parser::parsePrimaryExp() 6693{ 6694 Expression *e; 6695 Type *t; 6696 Identifier *id; 6697 Loc loc = token.loc; 6698 6699 //printf("parsePrimaryExp(): loc = %d\n", loc.linnum); 6700 switch (token.value) 6701 { 6702 case TOKidentifier: 6703 { 6704 Token *t1 = peek(&token); 6705 Token *t2 = peek(t1); 6706 if (t1->value == TOKmin && t2->value == TOKgt) 6707 { 6708 // skip ident. 6709 nextToken(); 6710 nextToken(); 6711 nextToken(); 6712 error("use `.` for member lookup, not `->`"); 6713 goto Lerr; 6714 } 6715 6716 if (peekNext() == TOKgoesto) 6717 goto case_delegate; 6718 6719 id = token.ident; 6720 nextToken(); 6721 TOK save; 6722 if (token.value == TOKnot && (save = peekNext()) != TOKis && save != TOKin) 6723 { 6724 // identifier!(template-argument-list) 6725 TemplateInstance *tempinst; 6726 tempinst = new TemplateInstance(loc, id); 6727 tempinst->tiargs = parseTemplateArguments(); 6728 e = new ScopeExp(loc, tempinst); 6729 } 6730 else 6731 e = new IdentifierExp(loc, id); 6732 break; 6733 } 6734 6735 case TOKdollar: 6736 if (!inBrackets) 6737 error("'$' is valid only inside [] of index or slice"); 6738 e = new DollarExp(loc); 6739 nextToken(); 6740 break; 6741 6742 case TOKdot: 6743 // Signal global scope '.' operator with "" identifier 6744 e = new IdentifierExp(loc, Id::empty); 6745 break; 6746 6747 case TOKthis: 6748 e = new ThisExp(loc); 6749 nextToken(); 6750 break; 6751 6752 case TOKsuper: 6753 e = new SuperExp(loc); 6754 nextToken(); 6755 break; 6756 6757 case TOKint32v: 6758 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32); 6759 nextToken(); 6760 break; 6761 6762 case TOKuns32v: 6763 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32); 6764 nextToken(); 6765 break; 6766 6767 case TOKint64v: 6768 e = new IntegerExp(loc, token.int64value, Type::tint64); 6769 nextToken(); 6770 break; 6771 6772 case TOKuns64v: 6773 e = new IntegerExp(loc, token.uns64value, Type::tuns64); 6774 nextToken(); 6775 break; 6776 6777 case TOKfloat32v: 6778 e = new RealExp(loc, token.floatvalue, Type::tfloat32); 6779 nextToken(); 6780 break; 6781 6782 case TOKfloat64v: 6783 e = new RealExp(loc, token.floatvalue, Type::tfloat64); 6784 nextToken(); 6785 break; 6786 6787 case TOKfloat80v: 6788 e = new RealExp(loc, token.floatvalue, Type::tfloat80); 6789 nextToken(); 6790 break; 6791 6792 case TOKimaginary32v: 6793 e = new RealExp(loc, token.floatvalue, Type::timaginary32); 6794 nextToken(); 6795 break; 6796 6797 case TOKimaginary64v: 6798 e = new RealExp(loc, token.floatvalue, Type::timaginary64); 6799 nextToken(); 6800 break; 6801 6802 case TOKimaginary80v: 6803 e = new RealExp(loc, token.floatvalue, Type::timaginary80); 6804 nextToken(); 6805 break; 6806 6807 case TOKnull: 6808 e = new NullExp(loc); 6809 nextToken(); 6810 break; 6811 6812 case TOKfile: 6813 { 6814 const char *s = loc.filename ? loc.filename : mod->ident->toChars(); 6815 e = new StringExp(loc, const_cast<char *>(s), strlen(s), 0); 6816 nextToken(); 6817 break; 6818 } 6819 6820 case TOKfilefullpath: 6821 { 6822 const char *srcfile = mod->srcfile->name->toChars(); 6823 const char *s; 6824 if (loc.filename && !FileName::equals(loc.filename, srcfile)) 6825 s = loc.filename; 6826 else 6827 s = FileName::combine(mod->srcfilePath, srcfile); 6828 e = new StringExp(loc, const_cast<char *>(s), strlen(s), 0); 6829 nextToken(); 6830 break; 6831 } 6832 6833 case TOKline: 6834 e = new IntegerExp(loc, loc.linnum, Type::tint32); 6835 nextToken(); 6836 break; 6837 6838 case TOKmodulestring: 6839 { 6840 const char *s = md ? md->toChars() : mod->toChars(); 6841 e = new StringExp(loc, const_cast<char *>(s), strlen(s), 0); 6842 nextToken(); 6843 break; 6844 } 6845 6846 case TOKfuncstring: 6847 e = new FuncInitExp(loc); 6848 nextToken(); 6849 break; 6850 6851 case TOKprettyfunc: 6852 e = new PrettyFuncInitExp(loc); 6853 nextToken(); 6854 break; 6855 6856 case TOKtrue: 6857 e = new IntegerExp(loc, 1, Type::tbool); 6858 nextToken(); 6859 break; 6860 6861 case TOKfalse: 6862 e = new IntegerExp(loc, 0, Type::tbool); 6863 nextToken(); 6864 break; 6865 6866 case TOKcharv: 6867 e = new IntegerExp(loc, (d_uns8)token.uns64value, Type::tchar); 6868 nextToken(); 6869 break; 6870 6871 case TOKwcharv: 6872 e = new IntegerExp(loc, (d_uns16)token.uns64value, Type::twchar); 6873 nextToken(); 6874 break; 6875 6876 case TOKdcharv: 6877 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar); 6878 nextToken(); 6879 break; 6880 6881 case TOKstring: 6882 case TOKxstring: 6883 { 6884 // cat adjacent strings 6885 utf8_t *s = token.ustring; 6886 size_t len = token.len; 6887 unsigned char postfix = token.postfix; 6888 while (1) 6889 { 6890 const Token prev = token; 6891 nextToken(); 6892 if (token.value == TOKstring || 6893 token.value == TOKxstring) 6894 { 6895 if (token.postfix) 6896 { if (token.postfix != postfix) 6897 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix); 6898 postfix = token.postfix; 6899 } 6900 6901 deprecation("Implicit string concatenation is deprecated, use %s ~ %s instead", 6902 prev.toChars(), token.toChars()); 6903 6904 size_t len1 = len; 6905 size_t len2 = token.len; 6906 len = len1 + len2; 6907 utf8_t *s2 = (utf8_t *)mem.xmalloc((len + 1) * sizeof(utf8_t)); 6908 memcpy(s2, s, len1 * sizeof(utf8_t)); 6909 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(utf8_t)); 6910 s = s2; 6911 } 6912 else 6913 break; 6914 } 6915 e = new StringExp(loc, s, len, postfix); 6916 break; 6917 } 6918 6919 case TOKvoid: t = Type::tvoid; goto LabelX; 6920 case TOKint8: t = Type::tint8; goto LabelX; 6921 case TOKuns8: t = Type::tuns8; goto LabelX; 6922 case TOKint16: t = Type::tint16; goto LabelX; 6923 case TOKuns16: t = Type::tuns16; goto LabelX; 6924 case TOKint32: t = Type::tint32; goto LabelX; 6925 case TOKuns32: t = Type::tuns32; goto LabelX; 6926 case TOKint64: t = Type::tint64; goto LabelX; 6927 case TOKuns64: t = Type::tuns64; goto LabelX; 6928 case TOKint128: t = Type::tint128; goto LabelX; 6929 case TOKuns128: t = Type::tuns128; goto LabelX; 6930 case TOKfloat32: t = Type::tfloat32; goto LabelX; 6931 case TOKfloat64: t = Type::tfloat64; goto LabelX; 6932 case TOKfloat80: t = Type::tfloat80; goto LabelX; 6933 case TOKimaginary32: t = Type::timaginary32; goto LabelX; 6934 case TOKimaginary64: t = Type::timaginary64; goto LabelX; 6935 case TOKimaginary80: t = Type::timaginary80; goto LabelX; 6936 case TOKcomplex32: t = Type::tcomplex32; goto LabelX; 6937 case TOKcomplex64: t = Type::tcomplex64; goto LabelX; 6938 case TOKcomplex80: t = Type::tcomplex80; goto LabelX; 6939 case TOKbool: t = Type::tbool; goto LabelX; 6940 case TOKchar: t = Type::tchar; goto LabelX; 6941 case TOKwchar: t = Type::twchar; goto LabelX; 6942 case TOKdchar: t = Type::tdchar; goto LabelX; 6943 LabelX: 6944 nextToken(); 6945 if (token.value == TOKlparen) 6946 { 6947 e = new TypeExp(loc, t); 6948 e = new CallExp(loc, e, parseArguments()); 6949 break; 6950 } 6951 check(TOKdot, t->toChars()); 6952 if (token.value != TOKidentifier) 6953 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars()); 6954 goto Lerr; 6955 } 6956 e = typeDotIdExp(loc, t, token.ident); 6957 nextToken(); 6958 break; 6959 6960 case TOKtypeof: 6961 { 6962 t = parseTypeof(); 6963 e = new TypeExp(loc, t); 6964 break; 6965 } 6966 6967 case TOKvector: 6968 { 6969 t = parseVector(); 6970 e = new TypeExp(loc, t); 6971 break; 6972 } 6973 6974 case TOKtypeid: 6975 { 6976 nextToken(); 6977 check(TOKlparen, "typeid"); 6978 RootObject *o; 6979 if (isDeclaration(&token, 0, TOKreserved, NULL)) 6980 { // argument is a type 6981 o = parseType(); 6982 } 6983 else 6984 { // argument is an expression 6985 o = parseAssignExp(); 6986 } 6987 check(TOKrparen); 6988 e = new TypeidExp(loc, o); 6989 break; 6990 } 6991 6992 case TOKtraits: 6993 { /* __traits(identifier, args...) 6994 */ 6995 Identifier *ident; 6996 Objects *args = NULL; 6997 6998 nextToken(); 6999 check(TOKlparen); 7000 if (token.value != TOKidentifier) 7001 { error("__traits(identifier, args...) expected"); 7002 goto Lerr; 7003 } 7004 ident = token.ident; 7005 nextToken(); 7006 if (token.value == TOKcomma) 7007 args = parseTemplateArgumentList(); // __traits(identifier, args...) 7008 else 7009 check(TOKrparen); // __traits(identifier) 7010 7011 e = new TraitsExp(loc, ident, args); 7012 break; 7013 } 7014 7015 case TOKis: 7016 { 7017 Type *targ; 7018 Identifier *ident = NULL; 7019 Type *tspec = NULL; 7020 TOK tok = TOKreserved; 7021 TOK tok2 = TOKreserved; 7022 TemplateParameters *tpl = NULL; 7023 7024 nextToken(); 7025 if (token.value == TOKlparen) 7026 { 7027 nextToken(); 7028 targ = parseType(&ident); 7029 if (token.value == TOKcolon || token.value == TOKequal) 7030 { 7031 tok = token.value; 7032 nextToken(); 7033 if (tok == TOKequal && 7034 (token.value == TOKstruct || 7035 token.value == TOKunion || 7036 token.value == TOKclass || 7037 token.value == TOKsuper || 7038 token.value == TOKenum || 7039 token.value == TOKinterface || 7040 token.value == TOKargTypes || 7041 token.value == TOKparameters || 7042 (token.value == TOKconst && peek(&token)->value == TOKrparen) || 7043 (token.value == TOKimmutable && peek(&token)->value == TOKrparen) || 7044 (token.value == TOKshared && peek(&token)->value == TOKrparen) || 7045 (token.value == TOKwild && peek(&token)->value == TOKrparen) || 7046 token.value == TOKfunction || 7047 token.value == TOKdelegate || 7048 token.value == TOKreturn || 7049 (token.value == TOKvector && peek(&token)->value == TOKrparen))) 7050 { 7051 tok2 = token.value; 7052 nextToken(); 7053 } 7054 else 7055 { 7056 tspec = parseType(); 7057 } 7058 } 7059 if (tspec) 7060 { 7061 if (token.value == TOKcomma) 7062 tpl = parseTemplateParameterList(1); 7063 else 7064 { 7065 tpl = new TemplateParameters(); 7066 check(TOKrparen); 7067 } 7068 } 7069 else 7070 check(TOKrparen); 7071 } 7072 else 7073 { 7074 error("(type identifier : specialization) expected following is"); 7075 goto Lerr; 7076 } 7077 e = new IsExp(loc, targ, ident, tok, tspec, tok2, tpl); 7078 break; 7079 } 7080 7081 case TOKassert: 7082 { Expression *msg = NULL; 7083 7084 nextToken(); 7085 check(TOKlparen, "assert"); 7086 e = parseAssignExp(); 7087 if (token.value == TOKcomma) 7088 { 7089 nextToken(); 7090 if (token.value != TOKrparen) 7091 { 7092 msg = parseAssignExp(); 7093 if (token.value == TOKcomma) 7094 nextToken(); 7095 } 7096 } 7097 check(TOKrparen); 7098 e = new AssertExp(loc, e, msg); 7099 break; 7100 } 7101 7102 case TOKmixin: 7103 { 7104 nextToken(); 7105 check(TOKlparen, "mixin"); 7106 e = parseAssignExp(); 7107 check(TOKrparen); 7108 e = new CompileExp(loc, e); 7109 break; 7110 } 7111 7112 case TOKimport: 7113 { 7114 nextToken(); 7115 check(TOKlparen, "import"); 7116 e = parseAssignExp(); 7117 check(TOKrparen); 7118 e = new ImportExp(loc, e); 7119 break; 7120 } 7121 7122 case TOKnew: 7123 e = parseNewExp(NULL); 7124 break; 7125 7126 case TOKlparen: 7127 { 7128 Token *tk = peekPastParen(&token); 7129 if (skipAttributes(tk, &tk) && 7130 (tk->value == TOKgoesto || tk->value == TOKlcurly)) 7131 { 7132 // (arguments) => expression 7133 // (arguments) { statements... } 7134 goto case_delegate; 7135 } 7136 7137 // ( expression ) 7138 nextToken(); 7139 e = parseExpression(); 7140 e->parens = 1; 7141 check(loc, TOKrparen); 7142 break; 7143 } 7144 7145 case TOKlbracket: 7146 { /* Parse array literals and associative array literals: 7147 * [ value, value, value ... ] 7148 * [ key:value, key:value, key:value ... ] 7149 */ 7150 Expressions *values = new Expressions(); 7151 Expressions *keys = NULL; 7152 7153 nextToken(); 7154 while (token.value != TOKrbracket && token.value != TOKeof) 7155 { 7156 e = parseAssignExp(); 7157 if (token.value == TOKcolon && (keys || values->dim == 0)) 7158 { nextToken(); 7159 if (!keys) 7160 keys = new Expressions(); 7161 keys->push(e); 7162 e = parseAssignExp(); 7163 } 7164 else if (keys) 7165 { error("'key:value' expected for associative array literal"); 7166 delete keys; 7167 keys = NULL; 7168 } 7169 values->push(e); 7170 if (token.value == TOKrbracket) 7171 break; 7172 check(TOKcomma); 7173 } 7174 check(loc, TOKrbracket); 7175 7176 if (keys) 7177 e = new AssocArrayLiteralExp(loc, keys, values); 7178 else 7179 e = new ArrayLiteralExp(loc, NULL, values); 7180 break; 7181 } 7182 7183 case TOKlcurly: 7184 case TOKfunction: 7185 case TOKdelegate: 7186 case_delegate: 7187 { 7188 Dsymbol *s = parseFunctionLiteral(); 7189 e = new FuncExp(loc, s); 7190 break; 7191 } 7192 7193 default: 7194 error("expression expected, not '%s'", token.toChars()); 7195 Lerr: 7196 // Anything for e, as long as it's not NULL 7197 e = new IntegerExp(loc, 0, Type::tint32); 7198 nextToken(); 7199 break; 7200 } 7201 return e; 7202} 7203 7204Expression *Parser::parsePostExp(Expression *e) 7205{ 7206 Loc loc; 7207 7208 while (1) 7209 { 7210 loc = token.loc; 7211 switch (token.value) 7212 { 7213 case TOKdot: 7214 nextToken(); 7215 if (token.value == TOKidentifier) 7216 { Identifier *id = token.ident; 7217 7218 nextToken(); 7219 if (token.value == TOKnot && peekNext() != TOKis && peekNext() != TOKin) 7220 { 7221 Objects *tiargs = parseTemplateArguments(); 7222 e = new DotTemplateInstanceExp(loc, e, id, tiargs); 7223 } 7224 else 7225 e = new DotIdExp(loc, e, id); 7226 continue; 7227 } 7228 else if (token.value == TOKnew) 7229 { 7230 e = parseNewExp(e); 7231 continue; 7232 } 7233 else 7234 error("identifier expected following '.', not '%s'", token.toChars()); 7235 break; 7236 7237 case TOKplusplus: 7238 e = new PostExp(TOKplusplus, loc, e); 7239 break; 7240 7241 case TOKminusminus: 7242 e = new PostExp(TOKminusminus, loc, e); 7243 break; 7244 7245 case TOKlparen: 7246 e = new CallExp(loc, e, parseArguments()); 7247 continue; 7248 7249 case TOKlbracket: 7250 { // array dereferences: 7251 // array[index] 7252 // array[] 7253 // array[lwr .. upr] 7254 Expression *index; 7255 Expression *upr; 7256 Expressions *arguments = new Expressions(); 7257 7258 inBrackets++; 7259 nextToken(); 7260 while (token.value != TOKrbracket && token.value != TOKeof) 7261 { 7262 index = parseAssignExp(); 7263 if (token.value == TOKslice) 7264 { 7265 // array[..., lwr..upr, ...] 7266 nextToken(); 7267 upr = parseAssignExp(); 7268 arguments->push(new IntervalExp(loc, index, upr)); 7269 } 7270 else 7271 arguments->push(index); 7272 if (token.value == TOKrbracket) 7273 break; 7274 check(TOKcomma); 7275 } 7276 check(TOKrbracket); 7277 inBrackets--; 7278 e = new ArrayExp(loc, e, arguments); 7279 continue; 7280 } 7281 7282 default: 7283 return e; 7284 } 7285 nextToken(); 7286 } 7287} 7288 7289Expression *Parser::parseUnaryExp() 7290{ 7291 Expression *e; 7292 Loc loc = token.loc; 7293 7294 switch (token.value) 7295 { 7296 case TOKand: 7297 nextToken(); 7298 e = parseUnaryExp(); 7299 e = new AddrExp(loc, e); 7300 break; 7301 7302 case TOKplusplus: 7303 nextToken(); 7304 e = parseUnaryExp(); 7305 //e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); 7306 e = new PreExp(TOKpreplusplus, loc, e); 7307 break; 7308 7309 case TOKminusminus: 7310 nextToken(); 7311 e = parseUnaryExp(); 7312 //e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); 7313 e = new PreExp(TOKpreminusminus, loc, e); 7314 break; 7315 7316 case TOKmul: 7317 nextToken(); 7318 e = parseUnaryExp(); 7319 e = new PtrExp(loc, e); 7320 break; 7321 7322 case TOKmin: 7323 nextToken(); 7324 e = parseUnaryExp(); 7325 e = new NegExp(loc, e); 7326 break; 7327 7328 case TOKadd: 7329 nextToken(); 7330 e = parseUnaryExp(); 7331 e = new UAddExp(loc, e); 7332 break; 7333 7334 case TOKnot: 7335 nextToken(); 7336 e = parseUnaryExp(); 7337 e = new NotExp(loc, e); 7338 break; 7339 7340 case TOKtilde: 7341 nextToken(); 7342 e = parseUnaryExp(); 7343 e = new ComExp(loc, e); 7344 break; 7345 7346 case TOKdelete: 7347 nextToken(); 7348 e = parseUnaryExp(); 7349 e = new DeleteExp(loc, e, false); 7350 break; 7351 7352 case TOKcast: // cast(type) expression 7353 { 7354 nextToken(); 7355 check(TOKlparen); 7356 /* Look for cast(), cast(const), cast(immutable), 7357 * cast(shared), cast(shared const), cast(wild), cast(shared wild) 7358 */ 7359 unsigned char m = 0; 7360 while (1) 7361 { 7362 switch (token.value) 7363 { 7364 case TOKconst: 7365 if (peekNext() == TOKlparen) 7366 break; // const as type constructor 7367 m |= MODconst; // const as storage class 7368 nextToken(); 7369 continue; 7370 7371 case TOKimmutable: 7372 if (peekNext() == TOKlparen) 7373 break; 7374 m |= MODimmutable; 7375 nextToken(); 7376 continue; 7377 7378 case TOKshared: 7379 if (peekNext() == TOKlparen) 7380 break; 7381 m |= MODshared; 7382 nextToken(); 7383 continue; 7384 7385 case TOKwild: 7386 if (peekNext() == TOKlparen) 7387 break; 7388 m |= MODwild; 7389 nextToken(); 7390 continue; 7391 7392 default: 7393 break; 7394 } 7395 break; 7396 } 7397 if (token.value == TOKrparen) 7398 { 7399 nextToken(); 7400 e = parseUnaryExp(); 7401 e = new CastExp(loc, e, m); 7402 } 7403 else 7404 { 7405 Type *t = parseType(); // cast( type ) 7406 t = t->addMod(m); // cast( const type ) 7407 check(TOKrparen); 7408 e = parseUnaryExp(); 7409 e = new CastExp(loc, e, t); 7410 } 7411 break; 7412 } 7413 7414 case TOKwild: 7415 case TOKshared: 7416 case TOKconst: 7417 case TOKimmutable: // immutable(type)(arguments) / immutable(type).init 7418 { 7419 StorageClass stc = parseTypeCtor(); 7420 Type *t = parseBasicType(); 7421 t = t->addSTC(stc); 7422 e = new TypeExp(loc, t); 7423 if (stc == 0 && token.value == TOKdot) 7424 { 7425 nextToken(); 7426 if (token.value != TOKidentifier) 7427 { 7428 error("identifier expected following (type)."); 7429 return NULL; 7430 } 7431 e = typeDotIdExp(loc, t, token.ident); 7432 nextToken(); 7433 e = parsePostExp(e); 7434 break; 7435 } 7436 else if (token.value != TOKlparen) 7437 { 7438 error("(arguments) expected following %s", t->toChars()); 7439 return e; 7440 } 7441 e = new CallExp(loc, e, parseArguments()); 7442 break; 7443 } 7444 7445 7446 case TOKlparen: 7447 { Token *tk; 7448 7449 tk = peek(&token); 7450#if CCASTSYNTAX 7451 // If cast 7452 if (isDeclaration(tk, 0, TOKrparen, &tk)) 7453 { 7454 tk = peek(tk); // skip over right parenthesis 7455 switch (tk->value) 7456 { 7457 case TOKnot: 7458 tk = peek(tk); 7459 if (tk->value == TOKis || tk->value == TOKin) // !is or !in 7460 break; 7461 /* fall through */ 7462 7463 case TOKdot: 7464 case TOKplusplus: 7465 case TOKminusminus: 7466 case TOKdelete: 7467 case TOKnew: 7468 case TOKlparen: 7469 case TOKidentifier: 7470 case TOKthis: 7471 case TOKsuper: 7472 case TOKint32v: 7473 case TOKuns32v: 7474 case TOKint64v: 7475 case TOKuns64v: 7476 case TOKint128v: 7477 case TOKuns128v: 7478 case TOKfloat32v: 7479 case TOKfloat64v: 7480 case TOKfloat80v: 7481 case TOKimaginary32v: 7482 case TOKimaginary64v: 7483 case TOKimaginary80v: 7484 case TOKnull: 7485 case TOKtrue: 7486 case TOKfalse: 7487 case TOKcharv: 7488 case TOKwcharv: 7489 case TOKdcharv: 7490 case TOKstring: 7491 case TOKfunction: 7492 case TOKdelegate: 7493 case TOKtypeof: 7494 case TOKtraits: 7495 case TOKvector: 7496 case TOKfile: 7497 case TOKfilefullpath: 7498 case TOKline: 7499 case TOKmodulestring: 7500 case TOKfuncstring: 7501 case TOKprettyfunc: 7502 case TOKwchar: case TOKdchar: 7503 case TOKbool: case TOKchar: 7504 case TOKint8: case TOKuns8: 7505 case TOKint16: case TOKuns16: 7506 case TOKint32: case TOKuns32: 7507 case TOKint64: case TOKuns64: 7508 case TOKint128: case TOKuns128: 7509 case TOKfloat32: case TOKfloat64: case TOKfloat80: 7510 case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: 7511 case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: 7512 case TOKvoid: 7513 { // (type) una_exp 7514 Type *t; 7515 7516 nextToken(); 7517 t = parseType(); 7518 check(TOKrparen); 7519 7520 // if .identifier 7521 // or .identifier!( ... ) 7522 if (token.value == TOKdot) 7523 { 7524 if (peekNext() != TOKidentifier && peekNext() != TOKnew) 7525 { 7526 error("identifier or new keyword expected following (...)."); 7527 return NULL; 7528 } 7529 e = new TypeExp(loc, t); 7530 e->parens = 1; 7531 e = parsePostExp(e); 7532 } 7533 else 7534 { 7535 e = parseUnaryExp(); 7536 e = new CastExp(loc, e, t); 7537 error("C style cast illegal, use %s", e->toChars()); 7538 } 7539 return e; 7540 } 7541 default: 7542 break; 7543 } 7544 } 7545#endif 7546 e = parsePrimaryExp(); 7547 e = parsePostExp(e); 7548 break; 7549 } 7550 default: 7551 e = parsePrimaryExp(); 7552 e = parsePostExp(e); 7553 break; 7554 } 7555 assert(e); 7556 7557 // ^^ is right associative and has higher precedence than the unary operators 7558 while (token.value == TOKpow) 7559 { 7560 nextToken(); 7561 Expression *e2 = parseUnaryExp(); 7562 e = new PowExp(loc, e, e2); 7563 } 7564 7565 return e; 7566} 7567 7568Expression *Parser::parseMulExp() 7569{ 7570 Expression *e; 7571 Expression *e2; 7572 Loc loc = token.loc; 7573 7574 e = parseUnaryExp(); 7575 while (1) 7576 { 7577 switch (token.value) 7578 { 7579 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; 7580 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; 7581 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; 7582 7583 default: 7584 break; 7585 } 7586 break; 7587 } 7588 return e; 7589} 7590 7591Expression *Parser::parseAddExp() 7592{ 7593 Expression *e; 7594 Expression *e2; 7595 Loc loc = token.loc; 7596 7597 e = parseMulExp(); 7598 while (1) 7599 { 7600 switch (token.value) 7601 { 7602 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue; 7603 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue; 7604 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue; 7605 7606 default: 7607 break; 7608 } 7609 break; 7610 } 7611 return e; 7612} 7613 7614Expression *Parser::parseShiftExp() 7615{ 7616 Expression *e; 7617 Expression *e2; 7618 Loc loc = token.loc; 7619 7620 e = parseAddExp(); 7621 while (1) 7622 { 7623 switch (token.value) 7624 { 7625 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue; 7626 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue; 7627 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue; 7628 7629 default: 7630 break; 7631 } 7632 break; 7633 } 7634 return e; 7635} 7636 7637Expression *Parser::parseCmpExp() 7638{ 7639 Expression *e; 7640 Expression *e2; 7641 Token *t; 7642 Loc loc = token.loc; 7643 7644 e = parseShiftExp(); 7645 TOK op = token.value; 7646 7647 switch (op) 7648 { 7649 case TOKequal: 7650 case TOKnotequal: 7651 nextToken(); 7652 e2 = parseShiftExp(); 7653 e = new EqualExp(op, loc, e, e2); 7654 break; 7655 7656 case TOKis: 7657 op = TOKidentity; 7658 goto L1; 7659 7660 case TOKnot: 7661 // Attempt to identify '!is' 7662 t = peek(&token); 7663 if (t->value == TOKin) 7664 { 7665 nextToken(); 7666 nextToken(); 7667 e2 = parseShiftExp(); 7668 e = new InExp(loc, e, e2); 7669 e = new NotExp(loc, e); 7670 break; 7671 } 7672 if (t->value != TOKis) 7673 break; 7674 nextToken(); 7675 op = TOKnotidentity; 7676 goto L1; 7677 7678 L1: 7679 nextToken(); 7680 e2 = parseShiftExp(); 7681 e = new IdentityExp(op, loc, e, e2); 7682 break; 7683 7684 case TOKlt: 7685 case TOKle: 7686 case TOKgt: 7687 case TOKge: 7688 case TOKunord: 7689 case TOKlg: 7690 case TOKleg: 7691 case TOKule: 7692 case TOKul: 7693 case TOKuge: 7694 case TOKug: 7695 case TOKue: 7696 nextToken(); 7697 e2 = parseShiftExp(); 7698 e = new CmpExp(op, loc, e, e2); 7699 break; 7700 7701 case TOKin: 7702 nextToken(); 7703 e2 = parseShiftExp(); 7704 e = new InExp(loc, e, e2); 7705 break; 7706 7707 default: 7708 break; 7709 } 7710 return e; 7711} 7712 7713Expression *Parser::parseAndExp() 7714{ 7715 Loc loc = token.loc; 7716 7717 Expression *e = parseCmpExp(); 7718 while (token.value == TOKand) 7719 { 7720 checkParens(TOKand, e); 7721 nextToken(); 7722 Expression *e2 = parseCmpExp(); 7723 checkParens(TOKand, e2); 7724 e = new AndExp(loc,e,e2); 7725 loc = token.loc; 7726 } 7727 return e; 7728} 7729 7730Expression *Parser::parseXorExp() 7731{ 7732 Loc loc = token.loc; 7733 7734 Expression *e = parseAndExp(); 7735 while (token.value == TOKxor) 7736 { 7737 checkParens(TOKxor, e); 7738 nextToken(); 7739 Expression *e2 = parseAndExp(); 7740 checkParens(TOKxor, e2); 7741 e = new XorExp(loc, e, e2); 7742 } 7743 return e; 7744} 7745 7746Expression *Parser::parseOrExp() 7747{ 7748 Loc loc = token.loc; 7749 7750 Expression *e = parseXorExp(); 7751 while (token.value == TOKor) 7752 { 7753 checkParens(TOKor, e); 7754 nextToken(); 7755 Expression *e2 = parseXorExp(); 7756 checkParens(TOKor, e2); 7757 e = new OrExp(loc, e, e2); 7758 } 7759 return e; 7760} 7761 7762Expression *Parser::parseAndAndExp() 7763{ 7764 Expression *e; 7765 Expression *e2; 7766 Loc loc = token.loc; 7767 7768 e = parseOrExp(); 7769 while (token.value == TOKandand) 7770 { 7771 nextToken(); 7772 e2 = parseOrExp(); 7773 e = new AndAndExp(loc, e, e2); 7774 } 7775 return e; 7776} 7777 7778Expression *Parser::parseOrOrExp() 7779{ 7780 Expression *e; 7781 Expression *e2; 7782 Loc loc = token.loc; 7783 7784 e = parseAndAndExp(); 7785 while (token.value == TOKoror) 7786 { 7787 nextToken(); 7788 e2 = parseAndAndExp(); 7789 e = new OrOrExp(loc, e, e2); 7790 } 7791 return e; 7792} 7793 7794Expression *Parser::parseCondExp() 7795{ 7796 Expression *e; 7797 Expression *e1; 7798 Expression *e2; 7799 Loc loc = token.loc; 7800 7801 e = parseOrOrExp(); 7802 if (token.value == TOKquestion) 7803 { 7804 nextToken(); 7805 e1 = parseExpression(); 7806 check(TOKcolon); 7807 e2 = parseCondExp(); 7808 e = new CondExp(loc, e, e1, e2); 7809 } 7810 return e; 7811} 7812 7813Expression *Parser::parseAssignExp() 7814{ 7815 Expression *e; 7816 Expression *e2; 7817 Loc loc; 7818 7819 e = parseCondExp(); 7820 while (1) 7821 { 7822 loc = token.loc; 7823 switch (token.value) 7824 { 7825 case TOKassign: nextToken(); e2 = parseAssignExp(); e = new AssignExp(loc,e,e2); continue; 7826 case TOKaddass: nextToken(); e2 = parseAssignExp(); e = new AddAssignExp(loc,e,e2); continue; 7827 case TOKminass: nextToken(); e2 = parseAssignExp(); e = new MinAssignExp(loc,e,e2); continue; 7828 case TOKmulass: nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue; 7829 case TOKdivass: nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue; 7830 case TOKmodass: nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue; 7831 case TOKpowass: nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue; 7832 case TOKandass: nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue; 7833 case TOKorass: nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue; 7834 case TOKxorass: nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue; 7835 case TOKshlass: nextToken(); e2 = parseAssignExp(); e = new ShlAssignExp(loc,e,e2); continue; 7836 case TOKshrass: nextToken(); e2 = parseAssignExp(); e = new ShrAssignExp(loc,e,e2); continue; 7837 case TOKushrass: nextToken(); e2 = parseAssignExp(); e = new UshrAssignExp(loc,e,e2); continue; 7838 case TOKcatass: nextToken(); e2 = parseAssignExp(); e = new CatAssignExp(loc,e,e2); continue; 7839 default: 7840 break; 7841 } 7842 break; 7843 } 7844 return e; 7845} 7846 7847Expression *Parser::parseExpression() 7848{ 7849 Expression *e; 7850 Expression *e2; 7851 Loc loc = token.loc; 7852 7853 //printf("Parser::parseExpression() loc = %d\n", loc.linnum); 7854 e = parseAssignExp(); 7855 while (token.value == TOKcomma) 7856 { 7857 nextToken(); 7858 e2 = parseAssignExp(); 7859 e = new CommaExp(loc, e, e2, false); 7860 loc = token.loc; 7861 } 7862 return e; 7863} 7864 7865 7866/************************* 7867 * Collect argument list. 7868 * Assume current token is ',', '(' or '['. 7869 */ 7870 7871Expressions *Parser::parseArguments() 7872{ // function call 7873 Expressions *arguments; 7874 Expression *arg; 7875 TOK endtok; 7876 7877 arguments = new Expressions(); 7878 if (token.value == TOKlbracket) 7879 endtok = TOKrbracket; 7880 else 7881 endtok = TOKrparen; 7882 7883 { 7884 nextToken(); 7885 while (token.value != endtok && token.value != TOKeof) 7886 { 7887 arg = parseAssignExp(); 7888 arguments->push(arg); 7889 if (token.value == endtok) 7890 break; 7891 check(TOKcomma); 7892 } 7893 check(endtok); 7894 } 7895 return arguments; 7896} 7897 7898/******************************************* 7899 */ 7900 7901Expression *Parser::parseNewExp(Expression *thisexp) 7902{ 7903 Type *t; 7904 Expressions *newargs; 7905 Expressions *arguments = NULL; 7906 Loc loc = token.loc; 7907 7908 nextToken(); 7909 newargs = NULL; 7910 if (token.value == TOKlparen) 7911 { 7912 newargs = parseArguments(); 7913 } 7914 7915 // An anonymous nested class starts with "class" 7916 if (token.value == TOKclass) 7917 { 7918 nextToken(); 7919 if (token.value == TOKlparen) 7920 arguments = parseArguments(); 7921 7922 BaseClasses *baseclasses = NULL; 7923 if (token.value != TOKlcurly) 7924 baseclasses = parseBaseClasses(); 7925 7926 Identifier *id = NULL; 7927 Dsymbols *members = NULL; 7928 7929 if (token.value != TOKlcurly) 7930 { 7931 error("{ members } expected for anonymous class"); 7932 } 7933 else 7934 { 7935 nextToken(); 7936 members = parseDeclDefs(0); 7937 if (token.value != TOKrcurly) 7938 error("class member expected"); 7939 nextToken(); 7940 } 7941 7942 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses, members, false); 7943 Expression *e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments); 7944 7945 return e; 7946 } 7947 7948 StorageClass stc = parseTypeCtor(); 7949 t = parseBasicType(true); 7950 t = parseBasicType2(t); 7951 t = t->addSTC(stc); 7952 if (t->ty == Taarray) 7953 { 7954 TypeAArray *taa = (TypeAArray *)t; 7955 Type *index = taa->index; 7956 7957 Expression *edim = typeToExpression(index); 7958 if (!edim) 7959 { 7960 error("need size of rightmost array, not type %s", index->toChars()); 7961 return new NullExp(loc); 7962 } 7963 t = new TypeSArray(taa->next, edim); 7964 } 7965 else if (t->ty == Tsarray) 7966 { 7967 } 7968 else if (token.value == TOKlparen) 7969 { 7970 arguments = parseArguments(); 7971 } 7972 Expression *e = new NewExp(loc, thisexp, newargs, t, arguments); 7973 return e; 7974} 7975 7976/********************************************** 7977 */ 7978 7979void Parser::addComment(Dsymbol *s, const utf8_t *blockComment) 7980{ 7981 s->addComment(combineComments(blockComment, token.lineComment)); 7982 token.lineComment = NULL; 7983} 7984 7985 7986/********************************** 7987 * Set operator precedence for each operator. 7988 */ 7989 7990PREC precedence[TOKMAX]; 7991 7992struct PrecedenceInitializer 7993{ 7994 PrecedenceInitializer(); 7995}; 7996 7997static PrecedenceInitializer precedenceinitializer; 7998 7999PrecedenceInitializer::PrecedenceInitializer() 8000{ 8001 for (size_t i = 0; i < TOKMAX; i++) 8002 precedence[i] = PREC_zero; 8003 8004 precedence[TOKtype] = PREC_expr; 8005 precedence[TOKerror] = PREC_expr; 8006 8007 precedence[TOKtypeof] = PREC_primary; 8008 precedence[TOKmixin] = PREC_primary; 8009 precedence[TOKimport] = PREC_primary; 8010 8011 precedence[TOKdotvar] = PREC_primary; 8012 precedence[TOKscope] = PREC_primary; 8013 precedence[TOKidentifier] = PREC_primary; 8014 precedence[TOKthis] = PREC_primary; 8015 precedence[TOKsuper] = PREC_primary; 8016 precedence[TOKint64] = PREC_primary; 8017 precedence[TOKfloat64] = PREC_primary; 8018 precedence[TOKcomplex80] = PREC_primary; 8019 precedence[TOKnull] = PREC_primary; 8020 precedence[TOKstring] = PREC_primary; 8021 precedence[TOKarrayliteral] = PREC_primary; 8022 precedence[TOKassocarrayliteral] = PREC_primary; 8023 precedence[TOKclassreference] = PREC_primary; 8024 precedence[TOKfile] = PREC_primary; 8025 precedence[TOKfilefullpath] = PREC_primary; 8026 precedence[TOKline] = PREC_primary; 8027 precedence[TOKmodulestring] = PREC_primary; 8028 precedence[TOKfuncstring] = PREC_primary; 8029 precedence[TOKprettyfunc] = PREC_primary; 8030 precedence[TOKtypeid] = PREC_primary; 8031 precedence[TOKis] = PREC_primary; 8032 precedence[TOKassert] = PREC_primary; 8033 precedence[TOKhalt] = PREC_primary; 8034 precedence[TOKtemplate] = PREC_primary; 8035 precedence[TOKdsymbol] = PREC_primary; 8036 precedence[TOKfunction] = PREC_primary; 8037 precedence[TOKvar] = PREC_primary; 8038 precedence[TOKsymoff] = PREC_primary; 8039 precedence[TOKstructliteral] = PREC_primary; 8040 precedence[TOKarraylength] = PREC_primary; 8041 precedence[TOKdelegateptr] = PREC_primary; 8042 precedence[TOKdelegatefuncptr] = PREC_primary; 8043 precedence[TOKremove] = PREC_primary; 8044 precedence[TOKtuple] = PREC_primary; 8045 precedence[TOKtraits] = PREC_primary; 8046 precedence[TOKdefault] = PREC_primary; 8047 precedence[TOKoverloadset] = PREC_primary; 8048 precedence[TOKvoid] = PREC_primary; 8049 precedence[TOKvectorarray] = PREC_primary; 8050 8051 // post 8052 precedence[TOKdotti] = PREC_primary; 8053 precedence[TOKdotid] = PREC_primary; 8054 precedence[TOKdottd] = PREC_primary; 8055 precedence[TOKdot] = PREC_primary; 8056 precedence[TOKdottype] = PREC_primary; 8057// precedence[TOKarrow] = PREC_primary; 8058 precedence[TOKplusplus] = PREC_primary; 8059 precedence[TOKminusminus] = PREC_primary; 8060 precedence[TOKpreplusplus] = PREC_primary; 8061 precedence[TOKpreminusminus] = PREC_primary; 8062 precedence[TOKcall] = PREC_primary; 8063 precedence[TOKslice] = PREC_primary; 8064 precedence[TOKarray] = PREC_primary; 8065 precedence[TOKindex] = PREC_primary; 8066 8067 precedence[TOKdelegate] = PREC_unary; 8068 precedence[TOKaddress] = PREC_unary; 8069 precedence[TOKstar] = PREC_unary; 8070 precedence[TOKneg] = PREC_unary; 8071 precedence[TOKuadd] = PREC_unary; 8072 precedence[TOKnot] = PREC_unary; 8073 precedence[TOKtilde] = PREC_unary; 8074 precedence[TOKdelete] = PREC_unary; 8075 precedence[TOKnew] = PREC_unary; 8076 precedence[TOKnewanonclass] = PREC_unary; 8077 precedence[TOKcast] = PREC_unary; 8078 8079 precedence[TOKvector] = PREC_unary; 8080 precedence[TOKpow] = PREC_pow; 8081 8082 precedence[TOKmul] = PREC_mul; 8083 precedence[TOKdiv] = PREC_mul; 8084 precedence[TOKmod] = PREC_mul; 8085 8086 precedence[TOKadd] = PREC_add; 8087 precedence[TOKmin] = PREC_add; 8088 precedence[TOKcat] = PREC_add; 8089 8090 precedence[TOKshl] = PREC_shift; 8091 precedence[TOKshr] = PREC_shift; 8092 precedence[TOKushr] = PREC_shift; 8093 8094 precedence[TOKlt] = PREC_rel; 8095 precedence[TOKle] = PREC_rel; 8096 precedence[TOKgt] = PREC_rel; 8097 precedence[TOKge] = PREC_rel; 8098 precedence[TOKunord] = PREC_rel; 8099 precedence[TOKlg] = PREC_rel; 8100 precedence[TOKleg] = PREC_rel; 8101 precedence[TOKule] = PREC_rel; 8102 precedence[TOKul] = PREC_rel; 8103 precedence[TOKuge] = PREC_rel; 8104 precedence[TOKug] = PREC_rel; 8105 precedence[TOKue] = PREC_rel; 8106 precedence[TOKin] = PREC_rel; 8107 8108 /* Note that we changed precedence, so that < and != have the same 8109 * precedence. This change is in the parser, too. 8110 */ 8111 precedence[TOKequal] = PREC_rel; 8112 precedence[TOKnotequal] = PREC_rel; 8113 precedence[TOKidentity] = PREC_rel; 8114 precedence[TOKnotidentity] = PREC_rel; 8115 8116 precedence[TOKand] = PREC_and; 8117 8118 precedence[TOKxor] = PREC_xor; 8119 8120 precedence[TOKor] = PREC_or; 8121 8122 precedence[TOKandand] = PREC_andand; 8123 8124 precedence[TOKoror] = PREC_oror; 8125 8126 precedence[TOKquestion] = PREC_cond; 8127 8128 precedence[TOKassign] = PREC_assign; 8129 precedence[TOKconstruct] = PREC_assign; 8130 precedence[TOKblit] = PREC_assign; 8131 precedence[TOKaddass] = PREC_assign; 8132 precedence[TOKminass] = PREC_assign; 8133 precedence[TOKcatass] = PREC_assign; 8134 precedence[TOKmulass] = PREC_assign; 8135 precedence[TOKdivass] = PREC_assign; 8136 precedence[TOKmodass] = PREC_assign; 8137 precedence[TOKpowass] = PREC_assign; 8138 precedence[TOKshlass] = PREC_assign; 8139 precedence[TOKshrass] = PREC_assign; 8140 precedence[TOKushrass] = PREC_assign; 8141 precedence[TOKandass] = PREC_assign; 8142 precedence[TOKorass] = PREC_assign; 8143 precedence[TOKxorass] = PREC_assign; 8144 8145 precedence[TOKcomma] = PREC_expr; 8146 precedence[TOKdeclaration] = PREC_expr; 8147 8148 precedence[TOKinterval] = PREC_assign; 8149} 8150