1: 
   2: // Compiler implementation of the D programming language
   3: // Copyright (c) 1999-2011 by Digital Mars
   4: // All Rights Reserved
   5: // written by Walter Bright
   6: // http://www.digitalmars.com
   7: // License for redistribution is by either the Artistic License
   8: // in artistic.txt, or the GNU General Public License in gnu.txt.
   9: // See the included readme.txt for details.
  10: 
  11: // This is the D parser
  12: 
  13: #include <stdio.h>
  14: static char __file__[] = __FILE__;      /* for tassert.h                */
  15: #include        "tassert.h"
  16: 
  17: #include "rmem.h"
  18: #include "lexer.h"
  19: #include "parse.h"
  20: #include "init.h"
  21: #include "attrib.h"
  22: #include "cond.h"
  23: #include "mtype.h"
  24: #include "template.h"
  25: #include "staticassert.h"
  26: #include "expression.h"
  27: #include "statement.h"
  28: #include "module.h"
  29: #include "dsymbol.h"
  30: #include "import.h"
  31: #include "declaration.h"
  32: #include "aggregate.h"
  33: #include "enum.h"
  34: #include "id.h"
  35: #include "version.h"
  36: #include "aliasthis.h"
  37: 
  38: // How multiple declarations are parsed.
  39: // If 1, treat as C.
  40: // If 0, treat:
  41: //      int *p, i;
  42: // as:
  43: //      int* p;
  44: //      int* i;
  45: #define CDECLSYNTAX     0
  46: 
  47: // Support C cast syntax:
  48: //      (type)(expression)
  49: #define CCASTSYNTAX     1
  50: 
  51: // Support postfix C array declarations, such as
  52: //      int a[3][4];
  53: #define CARRAYDECL      1
  54: 
  55: // Support D1 inout
  56: #define D1INOUT         0
  57: 
  58: Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
  59:     : Lexer(module, base, 0, length, doDocComment, 0)
  60: {
  61:     //printf("Parser::Parser()\n");
  62:     md = NULL;
  63:     linkage = LINKd;
  64:     endloc = 0;
  65:     inBrackets = 0;
  66:     //nextToken();              // start up the scanner
  67: }
  68: 
  69: Dsymbols *Parser::parseModule()
  70: {
  71:     Dsymbols *decldefs;
  72: 
  73:     // ModuleDeclation leads off
  74:     if (token.value == TOKmodule)
  75:     {
  76:         unsigned char *comment = token.blockComment;
  77:         bool safe = FALSE;
  78: 
  79:         nextToken();
  80: #if 0 && DMDV2
  81:         if (token.value == TOKlparen)
  82:         {
  83:             nextToken();
  84:             if (token.value != TOKidentifier)
  85:             {   error("module (system) identifier expected");
  86:                 goto Lerr;
  87:             }
  88:             Identifier *id = token.ident;
  89: 
  90:             if (id == Id::system)
  91:                 safe = TRUE;
  92:             else
  93:                 error("(safe) expected, not %s", id->toChars());
  94:             nextToken();
  95:             check(TOKrparen);
  96:         }
  97: #endif
  98: 
  99:         if (token.value != TOKidentifier)
 100:         {   error("Identifier expected following module");
 101:             goto Lerr;
 102:         }
 103:         else
 104:         {
 105:             Identifiers *a = NULL;
 106:             Identifier *id;
 107: 
 108:             id = token.ident;
 109:             while (nextToken() == TOKdot)
 110:             {
 111:                 if (!a)
 112:                     a = new Identifiers();
 113:                 a->push(id);
 114:                 nextToken();
 115:                 if (token.value != TOKidentifier)
 116:                 {   error("Identifier expected following package");
 117:                     goto Lerr;
 118:                 }
 119:                 id = token.ident;
 120:             }
 121: 
 122:             md = new ModuleDeclaration(a, id, safe);
 123: 
 124:             if (token.value != TOKsemicolon)
 125:                 error("';' expected following module declaration instead of %s", token.toChars());
 126:             nextToken();
 127:             addComment(mod, comment);
 128:         }
 129:     }
 130: 
 131:     decldefs = parseDeclDefs(0);
 132:     if (token.value != TOKeof)
 133:     {   error("unrecognized declaration");
 134:         goto Lerr;
 135:     }
 136:     return decldefs;
 137: 
 138: Lerr:
 139:     while (token.value != TOKsemicolon && token.value != TOKeof)
 140:         nextToken();
 141:     nextToken();
 142:     return new Dsymbols();
 143: }
 144: 
 145: Dsymbols *Parser::parseDeclDefs(int once)
 146: {   Dsymbol *s;
 147:     Dsymbols *decldefs;
 148:     Dsymbols *a;
 149:     Dsymbols *aelse;
 150:     enum PROT prot;
 151:     StorageClass stc;
 152:     StorageClass storageClass;
 153:     Condition *condition;
 154:     unsigned char *comment;
 155: 
 156:     //printf("Parser::parseDeclDefs()\n");
 157:     decldefs = new Dsymbols();
 158:     do
 159:     {
 160:         comment = token.blockComment;
 161:         storageClass = STCundefined;
 162:         switch (token.value)
 163:         {
 164:             case TOKenum:
 165:             {   /* Determine if this is a manifest constant declaration,
 166:                  * or a conventional enum.
 167:                  */
 168:                 Token *t = peek(&token);
 169:                 if (t->value == TOKlcurly || t->value == TOKcolon)
 170:                     s = parseEnum();
 171:                 else if (t->value != TOKidentifier)
 172:                     goto Ldeclaration;
 173:                 else
 174:                 {
 175:                     t = peek(t);
 176:                     if (t->value == TOKlcurly || t->value == TOKcolon ||
 177:                         t->value == TOKsemicolon)
 178:                         s = parseEnum();
 179:                     else
 180:                         goto Ldeclaration;
 181:                 }
 182:                 break;
 183:             }
 184: 
 185:             case TOKstruct:
 186:             case TOKunion:
 187:             case TOKclass:
 188:             case TOKinterface:
 189:                 s = parseAggregate();
 190:                 break;
 191: 
 192:             case TOKimport:
 193:                 s = parseImport(decldefs, 0);
 194:                 break;
 195: 
 196:             case TOKtemplate:
 197:                 s = (Dsymbol *)parseTemplateDeclaration(0);
 198:                 break;
 199: 
 200:             case TOKmixin:
 201:             {   Loc loc = this->loc;
 202:                 switch (peekNext())
 203:                 {
 204:                     case TOKlparen:
 205:                     {   // mixin(string)
 206:                         nextToken();
 207:                         check(TOKlparen, "mixin");
 208:                         Expression *e = parseAssignExp();
 209:                         check(TOKrparen);
 210:                         check(TOKsemicolon);
 211:                         s = new CompileDeclaration(loc, e);
 212:                         break;
 213:                     }
 214:                     case TOKtemplate:
 215:                         // mixin template
 216:                         nextToken();
 217:                         s = (Dsymbol *)parseTemplateDeclaration(1);
 218:                         break;
 219: 
 220:                     default:
 221:                         s = parseMixin();
 222:                         break;
 223:                 }
 224:                 break;
 225:             }
 226: 
 227:             case BASIC_TYPES:
 228:             case TOKalias:
 229:             case TOKtypedef:
 230:             case TOKidentifier:
 231:             case TOKtypeof:
 232:             case TOKdot:
 233:             Ldeclaration:
 234:                 a = parseDeclarations(STCundefined, NULL);
 235:                 decldefs->append(a);
 236:                 continue;
 237: 
 238:             case TOKthis:
 239:                 s = parseCtor();
 240:                 break;
 241: 
 242: #if 0 // dead end, use this(this){} instead
 243:             case TOKassign:
 244:                 s = parsePostBlit();
 245:                 break;
 246: #endif
 247:             case TOKtilde:
 248:                 s = parseDtor();
 249:                 break;
 250: 
 251:             case TOKinvariant:
 252:             {   Token *t;
 253:                 t = peek(&token);
 254:                 if (t->value == TOKlparen)
 255:                 {
 256:                     if (peek(t)->value == TOKrparen)
 257:                         // invariant() forms start of class invariant
 258:                         s = parseInvariant();
 259:                     else
 260:                         // invariant(type)
 261:                         goto Ldeclaration;
 262:                 }
 263:                 else
 264:                 {
 265:                     stc = STCimmutable;
 266:                     goto Lstc;
 267:                 }
 268:                 break;
 269:             }
 270: 
 271:             case TOKunittest:
 272:                 s = parseUnitTest();
 273:                 break;
 274: 
 275:             case TOKnew:
 276:                 s = parseNew();
 277:                 break;
 278: 
 279:             case TOKdelete:
 280:                 s = parseDelete();
 281:                 break;
 282: 
 283:             case TOKeof:
 284:             case TOKrcurly:
 285:                 return decldefs;
 286: 
 287:             case TOKstatic:
 288:                 nextToken();
 289:                 if (token.value == TOKthis)
 290:                     s = parseStaticCtor();
 291:                 else if (token.value == TOKtilde)
 292:                     s = parseStaticDtor();
 293:                 else if (token.value == TOKassert)
 294:                     s = parseStaticAssert();
 295:                 else if (token.value == TOKif)
 296:                 {   condition = parseStaticIfCondition();
 297:                     a = parseBlock();
 298:                     aelse = NULL;
 299:                     if (token.value == TOKelse)
 300:                     {   nextToken();
 301:                         aelse = parseBlock();
 302:                     }
 303:                     s = new StaticIfDeclaration(condition, a, aelse);
 304:                     break;
 305:                 }
 306:                 else if (token.value == TOKimport)
 307:                 {
 308:                     s = parseImport(decldefs, 1);
 309:                 }
 310:                 else
 311:                 {   stc = STCstatic;
 312:                     goto Lstc2;
 313:                 }
 314:                 break;
 315: 
 316:             case TOKconst:
 317:                 if (peekNext() == TOKlparen)
 318:                     goto Ldeclaration;
 319:                 stc = STCconst;
 320:                 goto Lstc;
 321: 
 322:             case TOKimmutable:
 323:                 if (peekNext() == TOKlparen)
 324:                     goto Ldeclaration;
 325:                 stc = STCimmutable;
 326:                 goto Lstc;
 327: 
 328:             case TOKshared:
 329:             {   TOK next = peekNext();
 330:                 if (next == TOKlparen)
 331:                     goto Ldeclaration;
 332:                 if (next == TOKstatic)
 333:                 {   TOK next2 = peekNext2();
 334:                     if (next2 == TOKthis)
 335:                     {   s = parseSharedStaticCtor();
 336:                         break;
 337:                     }
 338:                     if (next2 == TOKtilde)
 339:                     {   s = parseSharedStaticDtor();
 340:                         break;
 341:                     }
 342:                 }
 343:                 stc = STCshared;
 344:                 goto Lstc;
 345:             }
 346: 
 347:             case TOKwild:
 348:                 if (peekNext() == TOKlparen)
 349:                     goto Ldeclaration;
 350:                 stc = STCwild;
 351:                 goto Lstc;
 352: 
 353:             case TOKfinal:        stc = STCfinal;        goto Lstc;
 354:             case TOKauto:         stc = STCauto;         goto Lstc;
 355:             case TOKscope:        stc = STCscope;        goto Lstc;
 356:             case TOKoverride:     stc = STCoverride;     goto Lstc;
 357:             case TOKabstract:     stc = STCabstract;     goto Lstc;
 358:             case TOKsynchronized: stc = STCsynchronized; goto Lstc;
 359:             case TOKdeprecated:   stc = STCdeprecated;   goto Lstc;
 360: #if DMDV2
 361:             case TOKnothrow:      stc = STCnothrow;      goto Lstc;
 362:             case TOKpure:         stc = STCpure;         goto Lstc;
 363:             case TOKref:          stc = STCref;          goto Lstc;
 364:             case TOKtls:          stc = STCtls;          goto Lstc;
 365:             case TOKgshared:      stc = STCgshared;      goto Lstc;
 366:             //case TOKmanifest:   stc = STCmanifest;     goto Lstc;
 367:             case TOKat:           stc = parseAttribute(); goto Lstc;
 368: #endif
 369: 
 370:             Lstc:
 371:                 if (storageClass & stc)
 372:                     error("redundant storage class %s", Token::toChars(token.value));
 373:                 composeStorageClass(storageClass | stc);
 374:                 nextToken();
 375:             Lstc2:
 376:                 storageClass |= stc;
 377:                 switch (token.value)
 378:                 {
 379:                     case TOKconst:
 380:                     case TOKinvariant:
 381:                     case TOKimmutable:
 382:                     case TOKshared:
 383:                     case TOKwild:
 384:                         // If followed by a (, it is not a storage class
 385:                         if (peek(&token)->value == TOKlparen)
 386:                             break;
 387:                         if (token.value == TOKconst)
 388:                             stc = STCconst;
 389:                         else if (token.value == TOKshared)
 390:                             stc = STCshared;
 391:                         else if (token.value == TOKwild)
 392:                             stc = STCwild;
 393:                         else
 394:                             stc = STCimmutable;
 395:                         goto Lstc;
 396:                     case TOKfinal:        stc = STCfinal;        goto Lstc;
 397:                     case TOKauto:         stc = STCauto;         goto Lstc;
 398:                     case TOKscope:        stc = STCscope;        goto Lstc;
 399:                     case TOKoverride:     stc = STCoverride;     goto Lstc;
 400:                     case TOKabstract:     stc = STCabstract;     goto Lstc;
 401:                     case TOKsynchronized: stc = STCsynchronized; goto Lstc;
 402:                     case TOKdeprecated:   stc = STCdeprecated;   goto Lstc;
 403:                     case TOKnothrow:      stc = STCnothrow;      goto Lstc;
 404:                     case TOKpure:         stc = STCpure;         goto Lstc;
 405:                     case TOKref:          stc = STCref;          goto Lstc;
 406:                     case TOKtls:          stc = STCtls;          goto Lstc;
 407:                     case TOKgshared:      stc = STCgshared;      goto Lstc;
 408:                     //case TOKmanifest:   stc = STCmanifest;     goto Lstc;
 409:                     case TOKat:           stc = parseAttribute(); goto Lstc;
 410:                     default:
 411:                         break;
 412:                 }
 413: 
 414:                 /* Look for auto initializers:
 415:                  *      storage_class identifier = initializer;
 416:                  */
 417:                 if (token.value == TOKidentifier &&
 418:                     peek(&token)->value == TOKassign)
 419:                 {
 420:                     a = parseAutoDeclarations(storageClass, comment);
 421:                     decldefs->append(a);
 422:                     continue;
 423:                 }
 424: 
 425:                 /* Look for return type inference for template functions.
 426:                  */
 427:                 Token *tk;
 428:                 if (token.value == TOKidentifier &&
 429:                     (tk = peek(&token))->value == TOKlparen &&
 430:                     skipParens(tk, &tk) &&
 431:                     ((tk = peek(tk)), 1) &&
 432:                     skipAttributes(tk, &tk) &&
 433:                     (tk->value == TOKlparen ||
 434:                      tk->value == TOKlcurly)
 435:                    )
 436:                 {
 437:                     a = parseDeclarations(storageClass, comment);
 438:                     decldefs->append(a);
 439:                     continue;
 440:                 }
 441:                 a = parseBlock();
 442:                 s = new StorageClassDeclaration(storageClass, a);
 443:                 break;
 444: 
 445:             case TOKextern:
 446:                 if (peek(&token)->value != TOKlparen)
 447:                 {   stc = STCextern;
 448:                     goto Lstc;
 449:                 }
 450:             {
 451:                 enum LINK linksave = linkage;
 452:                 linkage = parseLinkage();
 453:                 a = parseBlock();
 454:                 s = new LinkDeclaration(linkage, a);
 455:                 linkage = linksave;
 456:                 break;
 457:             }
 458:             case TOKprivate:    prot = PROTprivate;     goto Lprot;
 459:             case TOKpackage:    prot = PROTpackage;     goto Lprot;
 460:             case TOKprotected:  prot = PROTprotected;   goto Lprot;
 461:             case TOKpublic:     prot = PROTpublic;      goto Lprot;
 462:             case TOKexport:     prot = PROTexport;      goto Lprot;
 463: 
 464:             Lprot:
 465:                 nextToken();
 466:                 switch (token.value)
 467:                 {
 468:                     case TOKprivate:
 469:                     case TOKpackage:
 470:                     case TOKprotected:
 471:                     case TOKpublic:
 472:                     case TOKexport:
 473:                         error("redundant protection attribute");
 474:                         break;
 475:                 }
 476:                 a = parseBlock();
 477:                 s = new ProtDeclaration(prot, a);
 478:                 break;
 479: 
 480:             case TOKalign:
 481:             {   unsigned n;
 482: 
 483:                 s = NULL;
 484:                 nextToken();
 485:                 if (token.value == TOKlparen)
 486:                 {
 487:                     nextToken();
 488:                     if (token.value == TOKint32v && token.uns64value > 0)
 489:                         n = (unsigned)token.uns64value;
 490:                     else
 491:                     {   error("positive integer expected, not %s", token.toChars());
 492:                         n = 1;
 493:                     }
 494:                     nextToken();
 495:                     check(TOKrparen);
 496:                 }
 497:                 else
 498:                     n = global.structalign;             // default
 499: 
 500:                 a = parseBlock();
 501:                 s = new AlignDeclaration(n, a);
 502:                 break;
 503:             }
 504: 
 505:             case TOKpragma:
 506:             {   Identifier *ident;
 507:                 Expressions *args = NULL;
 508: 
 509:                 nextToken();
 510:                 check(TOKlparen);
 511:                 if (token.value != TOKidentifier)
 512:                 {   error("pragma(identifier expected");
 513:                     goto Lerror;
 514:                 }
 515:                 ident = token.ident;
 516:                 nextToken();
 517:                 if (token.value == TOKcomma && peekNext() != TOKrparen)
 518:                     args = parseArguments();    // pragma(identifier, args...)
 519:                 else
 520:                     check(TOKrparen);           // pragma(identifier)
 521: 
 522:                 if (token.value == TOKsemicolon)
 523:                     a = NULL;
 524:                 else
 525:                     a = parseBlock();
 526:                 s = new PragmaDeclaration(loc, ident, args, a);
 527:                 break;
 528:             }
 529: 
 530:             case TOKdebug:
 531:                 nextToken();
 532:                 if (token.value == TOKassign)
 533:                 {
 534:                     nextToken();
 535:                     if (token.value == TOKidentifier)
 536:                         s = new DebugSymbol(loc, token.ident);
 537:                     else if (token.value == TOKint32v)
 538:                         s = new DebugSymbol(loc, (unsigned)token.uns64value);
 539:                     else
 540:                     {   error("identifier or integer expected, not %s", token.toChars());
 541:                         s = NULL;
 542:                     }
 543:                     nextToken();
 544:                     if (token.value != TOKsemicolon)
 545:                         error("semicolon expected");
 546:                     nextToken();
 547:                     break;
 548:                 }
 549: 
 550:                 condition = parseDebugCondition();
 551:                 goto Lcondition;
 552: 
 553:             case TOKversion:
 554:                 nextToken();
 555:                 if (token.value == TOKassign)
 556:                 {
 557:                     nextToken();
 558:                     if (token.value == TOKidentifier)
 559:                         s = new VersionSymbol(loc, token.ident);
 560:                     else if (token.value == TOKint32v)
 561:                         s = new VersionSymbol(loc, (unsigned)token.uns64value);
 562:                     else
 563:                     {   error("identifier or integer expected, not %s", token.toChars());
 564:                         s = NULL;
 565:                     }
 566:                     nextToken();
 567:                     if (token.value != TOKsemicolon)
 568:                         error("semicolon expected");
 569:                     nextToken();
 570:                     break;
 571:                 }
 572:                 condition = parseVersionCondition();
 573:                 goto Lcondition;
 574: 
 575:             Lcondition:
 576:                 a = parseBlock();
 577:                 aelse = NULL;
 578:                 if (token.value == TOKelse)
 579:                 {   nextToken();
 580:                     aelse = parseBlock();
 581:                 }
 582:                 s = new ConditionalDeclaration(condition, a, aelse);
 583:                 break;
 584: 
 585:             case TOKsemicolon:          // empty declaration
 586:                 //error("empty declaration");
 587:                 nextToken();
 588:                 continue;
 589: 
 590:             default:
 591:                 error("Declaration expected, not '%s'",token.toChars());
 592:             Lerror:
 593:                 while (token.value != TOKsemicolon && token.value != TOKeof)
 594:                     nextToken();
 595:                 nextToken();
 596:                 s = NULL;
 597:                 continue;
 598:         }
 599:         if (s)
 600:         {   decldefs->push(s);
 601:             addComment(s, comment);
 602:         }
 603:     } while (!once);
 604:     return decldefs;
 605: }
 606: 
 607: /*********************************************
 608:  * Give error on conflicting storage classes.
 609:  */
 610: 
 611: #if DMDV2
 612: void Parser::composeStorageClass(StorageClass stc)
 613: {
 614:     StorageClass u = stc;
 615:     u &= STCconst | STCimmutable | STCmanifest;
 616:     if (u & (u - 1))
 617:         error("conflicting storage class %s", Token::toChars(token.value));
 618:     u = stc;
 619:     u &= STCgshared | STCshared | STCtls;
 620:     if (u & (u - 1))
 621:         error("conflicting storage class %s", Token::toChars(token.value));
 622:     u = stc;
 623:     u &= STCsafe | STCsystem | STCtrusted;
 624:     if (u & (u - 1))
 625:         error("conflicting attribute @%s", token.toChars());
 626: }
 627: #endif
 628: 
 629: /***********************************************
 630:  * Parse storage class, lexer is on '@'
 631:  */
 632: 
 633: #if DMDV2
 634: StorageClass Parser::parseAttribute()
 635: {
 636:     nextToken();
 637:     StorageClass stc = 0;
 638:     if (token.value != TOKidentifier)
 639:     {
 640:         error("identifier expected after @, not %s", token.toChars());
 641:     }
 642:     else if (token.ident == Id::property)
 643:         stc = STCproperty;
 644:     else if (token.ident == Id::safe)
 645:         stc = STCsafe;
 646:     else if (token.ident == Id::trusted)
 647:         stc = STCtrusted;
 648:     else if (token.ident == Id::system)
 649:         stc = STCsystem;
 650:     else if (token.ident == Id::disable)
 651:         stc = STCdisable;
 652:     else
 653:         error("valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @%s", token.toChars());
 654:     return stc;
 655: }
 656: #endif
 657: 
 658: /***********************************************
 659:  * Parse const/immutable/shared/inout/nothrow/pure postfix
 660:  */
 661: 
 662: StorageClass Parser::parsePostfix()
 663: {
 664:     StorageClass stc = 0;
 665: 
 666:     while (1)
 667:     {
 668:         switch (token.value)
 669:         {
 670:             case TOKconst:              stc |= STCconst;                break;
 671:             case TOKinvariant:
 672:                 if (!global.params.useDeprecated)
 673:                     error("use of 'invariant' rather than 'immutable' is deprecated");
 674:             case TOKimmutable:          stc |= STCimmutable;            break;
 675:             case TOKshared:             stc |= STCshared;               break;
 676:             case TOKwild:               stc |= STCwild;                 break;
 677:             case TOKnothrow:            stc |= STCnothrow;              break;
 678:             case TOKpure:               stc |= STCpure;                 break;
 679:             case TOKat:                 stc |= parseAttribute();        break;
 680: 
 681:             default:
 682:                 composeStorageClass(stc);
 683:                 return stc;
 684:         }
 685:         nextToken();
 686:     }
 687: }
 688: 
 689: /********************************************
 690:  * Parse declarations after an align, protection, or extern decl.
 691:  */
 692: 
 693: Dsymbols *Parser::parseBlock()
 694: {
 695:     Dsymbols *a = NULL;
 696:     Dsymbol *s;
warning C4101: 's' : unreferenced local variable
697: 698: //printf("parseBlock()\n"); 699: switch (token.value) 700: { 701: case TOKsemicolon: 702: error("declaration expected following attribute, not ';'"); 703: nextToken(); 704: break; 705: 706: case TOKeof: 707: error("declaration expected following attribute, not EOF"); 708: break; 709: 710: case TOKlcurly: 711: nextToken(); 712: a = parseDeclDefs(0); 713: if (token.value != TOKrcurly) 714: { /* { */ 715: error("matching '}' expected, not %s", token.toChars()); 716: } 717: else 718: nextToken(); 719: break; 720: 721: case TOKcolon: 722: nextToken(); 723: #if 0 724: a = NULL; 725: #else 726: a = parseDeclDefs(0); // grab declarations up to closing curly bracket 727: #endif 728: break; 729: 730: default: 731: a = parseDeclDefs(1); 732: break; 733: } 734: return a; 735: } 736: 737: /********************************** 738: * Parse a static assertion. 739: */ 740: 741: StaticAssert *Parser::parseStaticAssert() 742: { 743: Loc loc = this->loc; 744: Expression *exp; 745: Expression *msg = NULL; 746: 747: //printf("parseStaticAssert()\n"); 748: nextToken(); 749: check(TOKlparen); 750: exp = parseAssignExp(); 751: if (token.value == TOKcomma) 752: { nextToken(); 753: msg = parseAssignExp(); 754: } 755: check(TOKrparen); 756: check(TOKsemicolon); 757: return new StaticAssert(loc, exp, msg); 758: } 759: 760: /*********************************** 761: * Parse typeof(expression). 762: * Current token is on the 'typeof'. 763: */ 764: 765: #if DMDV2 766: TypeQualified *Parser::parseTypeof() 767: { TypeQualified *t; 768: Loc loc = this->loc; 769: 770: nextToken(); 771: check(TOKlparen); 772: if (token.value == TOKreturn) // typeof(return) 773: { 774: nextToken(); 775: t = new TypeReturn(loc); 776: } 777: else 778: { Expression *exp = parseExpression(); // typeof(expression) 779: t = new TypeTypeof(loc, exp); 780: } 781: check(TOKrparen); 782: return t; 783: } 784: #endif 785: 786: /*********************************** 787: * Parse extern (linkage) 788: * The parser is on the 'extern' token. 789: */ 790: 791: enum LINK Parser::parseLinkage() 792: { 793: enum LINK link = LINKdefault; 794: nextToken(); 795: assert(token.value == TOKlparen); 796: nextToken(); 797: if (token.value == TOKidentifier) 798: { Identifier *id = token.ident; 799: 800: nextToken(); 801: if (id == Id::Windows) 802: link = LINKwindows; 803: else if (id == Id::Pascal) 804: link = LINKpascal; 805: else if (id == Id::D) 806: link = LINKd; 807: else if (id == Id::C) 808: { 809: link = LINKc; 810: if (token.value == TOKplusplus) 811: { link = LINKcpp; 812: nextToken(); 813: } 814: } 815: else if (id == Id::System) 816: { 817: #if _WIN32 818: link = LINKwindows; 819: #else 820: link = LINKc; 821: #endif 822: } 823: else 824: { 825: error("valid linkage identifiers are D, C, C++, Pascal, Windows, System"); 826: link = LINKd; 827: } 828: } 829: else 830: { 831: link = LINKd; // default 832: } 833: check(TOKrparen); 834: return link; 835: } 836: 837: /************************************** 838: * Parse a debug conditional 839: */ 840: 841: Condition *Parser::parseDebugCondition() 842: { 843: Condition *c; 844: 845: if (token.value == TOKlparen) 846: { 847: nextToken(); 848: unsigned level = 1; 849: Identifier *id = NULL; 850: 851: if (token.value == TOKidentifier) 852: id = token.ident; 853: else if (token.value == TOKint32v) 854: level = (unsigned)token.uns64value; 855: else 856: error("identifier or integer expected, not %s", token.toChars()); 857: nextToken(); 858: check(TOKrparen); 859: c = new DebugCondition(mod, level, id); 860: } 861: else 862: c = new DebugCondition(mod, 1, NULL); 863: return c; 864: 865: } 866: 867: /************************************** 868: * Parse a version conditional 869: */ 870: 871: Condition *Parser::parseVersionCondition() 872: { 873: Condition *c; 874: unsigned level = 1; 875: Identifier *id = NULL; 876: 877: if (token.value == TOKlparen) 878: { 879: nextToken(); 880: if (token.value == TOKidentifier) 881: id = token.ident; 882: else if (token.value == TOKint32v) 883: level = (unsigned)token.uns64value; 884: #if DMDV2 885: /* Allow: 886: * version (unittest) 887: * even though unittest is a keyword 888: */ 889: else if (token.value == TOKunittest) 890: id = Lexer::idPool(Token::toChars(TOKunittest)); 891: #endif 892: else 893: error("identifier or integer expected, not %s", token.toChars()); 894: nextToken(); 895: check(TOKrparen); 896: 897: } 898: else 899: error("(condition) expected following version"); 900: c = new VersionCondition(mod, level, id); 901: return c; 902: 903: } 904: 905: /*********************************************** 906: * static if (expression) 907: * body 908: * else 909: * body 910: */ 911: 912: Condition *Parser::parseStaticIfCondition() 913: { Expression *exp; 914: Condition *condition; 915: Dsymbols *aif;
warning C4101: 'aif' : unreferenced local variable
916: Dsymbols *aelse;
warning C4101: 'aelse' : unreferenced local variable
917: Loc loc = this->loc; 918: 919: nextToken(); 920: if (token.value == TOKlparen) 921: { 922: nextToken(); 923: exp = parseAssignExp(); 924: check(TOKrparen); 925: } 926: else 927: { error("(expression) expected following static if"); 928: exp = NULL; 929: } 930: condition = new StaticIfCondition(loc, exp); 931: return condition; 932: } 933: 934: 935: /***************************************** 936: * Parse a constructor definition: 937: * this(parameters) { body } 938: * or postblit: 939: * this(this) { body } 940: * or constructor template: 941: * this(templateparameters)(parameters) { body } 942: * Current token is 'this'. 943: */ 944: 945: Dsymbol *Parser::parseCtor() 946: { 947: Loc loc = this->loc; 948: 949: nextToken(); 950: if (token.value == TOKlparen && peek(&token)->value == TOKthis) 951: { // this(this) { ... } 952: nextToken(); 953: nextToken(); 954: check(TOKrparen); 955: PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0); 956: parseContracts(f); 957: return f; 958: } 959: 960: /* Look ahead to see if: 961: * this(...)(...) 962: * which is a constructor template 963: */ 964: TemplateParameters *tpl = NULL; 965: if (token.value == TOKlparen && peekPastParen(&token)->value == TOKlparen) 966: { tpl = parseTemplateParameterList(); 967: 968: int varargs; 969: Parameters *parameters = parseParameters(&varargs); 970: StorageClass stc = parsePostfix(); 971: 972: Expression *constraint = tpl ? parseConstraint() : NULL; 973: 974: Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto 975: CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf); 976: parseContracts(f); 977: 978: // Wrap a template around it 979: Dsymbols *decldefs = new Dsymbols(); 980: decldefs->push(f); 981: TemplateDeclaration *tempdecl = 982: new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs, 0); 983: return tempdecl; 984: } 985: 986: /* Just a regular constructor 987: */ 988: int varargs; 989: Parameters *parameters = parseParameters(&varargs); 990: StorageClass stc = parsePostfix(); 991: Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto 992: CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf); 993: parseContracts(f); 994: return f; 995: } 996: 997: /***************************************** 998: * Parse a postblit definition: 999: * =this() { body } 1000: * Current token is '='. 1001: */ 1002: 1003: PostBlitDeclaration *Parser::parsePostBlit() 1004: { 1005: Loc loc = this->loc; 1006: 1007: nextToken(); 1008: check(TOKthis); 1009: check(TOKlparen); 1010: check(TOKrparen); 1011: 1012: PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0); 1013: parseContracts(f); 1014: return f; 1015: } 1016: 1017: /***************************************** 1018: * Parse a destructor definition: 1019: * ~this() { body } 1020: * Current token is '~'. 1021: */ 1022: 1023: DtorDeclaration *Parser::parseDtor() 1024: { 1025: DtorDeclaration *f; 1026: Loc loc = this->loc; 1027: 1028: nextToken(); 1029: check(TOKthis); 1030: check(TOKlparen); 1031: check(TOKrparen); 1032: 1033: f = new DtorDeclaration(loc, 0); 1034: parseContracts(f); 1035: return f; 1036: } 1037: 1038: /***************************************** 1039: * Parse a static constructor definition: 1040: * static this() { body } 1041: * Current token is 'this'. 1042: */ 1043: 1044: StaticCtorDeclaration *Parser::parseStaticCtor() 1045: { 1046: Loc loc = this->loc; 1047: 1048: nextToken(); 1049: check(TOKlparen); 1050: check(TOKrparen); 1051: 1052: StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, 0); 1053: parseContracts(f); 1054: return f; 1055: } 1056: 1057: /***************************************** 1058: * Parse a shared static constructor definition: 1059: * shared static this() { body } 1060: * Current token is 'shared'. 1061: */ 1062: 1063: SharedStaticCtorDeclaration *Parser::parseSharedStaticCtor() 1064: { 1065: Loc loc = this->loc; 1066: 1067: nextToken(); 1068: nextToken(); 1069: nextToken(); 1070: check(TOKlparen); 1071: check(TOKrparen); 1072: 1073: SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, 0); 1074: parseContracts(f); 1075: return f; 1076: } 1077: 1078: /***************************************** 1079: * Parse a static destructor definition: 1080: * static ~this() { body } 1081: * Current token is '~'. 1082: */ 1083: 1084: StaticDtorDeclaration *Parser::parseStaticDtor() 1085: { 1086: Loc loc = this->loc; 1087: 1088: nextToken(); 1089: check(TOKthis); 1090: check(TOKlparen); 1091: check(TOKrparen); 1092: 1093: StaticDtorDeclaration *f = new StaticDtorDeclaration(loc, 0); 1094: parseContracts(f); 1095: return f; 1096: } 1097: 1098: /***************************************** 1099: * Parse a shared static destructor definition: 1100: * shared static ~this() { body } 1101: * Current token is 'shared'. 1102: */ 1103: 1104: SharedStaticDtorDeclaration *Parser::parseSharedStaticDtor() 1105: { 1106: Loc loc = this->loc; 1107: 1108: nextToken(); 1109: nextToken(); 1110: nextToken(); 1111: check(TOKthis); 1112: check(TOKlparen); 1113: check(TOKrparen); 1114: 1115: SharedStaticDtorDeclaration *f = new SharedStaticDtorDeclaration(loc, 0); 1116: parseContracts(f); 1117: return f; 1118: } 1119: 1120: /***************************************** 1121: * Parse an invariant definition: 1122: * invariant() { body } 1123: * Current token is 'invariant'. 1124: */ 1125: 1126: InvariantDeclaration *Parser::parseInvariant() 1127: { 1128: InvariantDeclaration *f; 1129: Loc loc = this->loc; 1130: 1131: nextToken(); 1132: if (token.value == TOKlparen) // optional () 1133: { 1134: nextToken(); 1135: check(TOKrparen); 1136: } 1137: 1138: f = new InvariantDeclaration(loc, 0); 1139: f->fbody = parseStatement(PScurly); 1140: return f; 1141: } 1142: 1143: /***************************************** 1144: * Parse a unittest definition: 1145: * unittest { body } 1146: * Current token is 'unittest'. 1147: */ 1148: 1149: UnitTestDeclaration *Parser::parseUnitTest() 1150: { 1151: UnitTestDeclaration *f; 1152: Statement *body; 1153: Loc loc = this->loc; 1154: 1155: nextToken(); 1156: 1157: body = parseStatement(PScurly); 1158: 1159: f = new UnitTestDeclaration(loc, this->loc); 1160: f->fbody = body; 1161: return f; 1162: } 1163: 1164: /***************************************** 1165: * Parse a new definition: 1166: * new(arguments) { body } 1167: * Current token is 'new'. 1168: */ 1169: 1170: NewDeclaration *Parser::parseNew() 1171: { 1172: NewDeclaration *f; 1173: Parameters *arguments; 1174: int varargs; 1175: Loc loc = this->loc; 1176: 1177: nextToken(); 1178: arguments = parseParameters(&varargs); 1179: f = new NewDeclaration(loc, 0, arguments, varargs); 1180: parseContracts(f); 1181: return f; 1182: } 1183: 1184: /***************************************** 1185: * Parse a delete definition: 1186: * delete(arguments) { body } 1187: * Current token is 'delete'. 1188: */ 1189: 1190: DeleteDeclaration *Parser::parseDelete() 1191: { 1192: DeleteDeclaration *f; 1193: Parameters *arguments; 1194: int varargs; 1195: Loc loc = this->loc; 1196: 1197: nextToken(); 1198: arguments = parseParameters(&varargs); 1199: if (varargs) 1200: error("... not allowed in delete function parameter list"); 1201: f = new DeleteDeclaration(loc, 0, arguments); 1202: parseContracts(f); 1203: return f; 1204: } 1205: 1206: /********************************************** 1207: * Parse parameter list. 1208: */ 1209: 1210: Parameters *Parser::parseParameters(int *pvarargs) 1211: { 1212: Parameters *arguments = new Parameters();
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 1212, 1213, 1214, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1226, 1228, 1238, 1239, 1240, 1310, 1311, 1312, 1313, 1315, 1317, 1319, 1322, 1323, 1324, 1330, 1334, 1347, 1348
1213: int varargs = 0; 1214: int hasdefault = 0; 1215: 1216: check(TOKlparen); 1217: while (1) 1218: { Type *tb;
warning C4101: 'tb' : unreferenced local variable
1219: Identifier *ai = NULL; 1220: Type *at; 1221: Parameter *a; 1222: StorageClass storageClass = 0; 1223: StorageClass stc; 1224: Expression *ae; 1225: 1226: for (;1; nextToken()) 1227: { 1228: switch (token.value) 1229: { 1230: case TOKrparen: 1231: break; 1232: 1233: case TOKdotdotdot: 1234: varargs = 1; 1235: nextToken(); 1236: break; 1237: 1238: case TOKconst: 1239: if (peek(&token)->value == TOKlparen) 1240: goto Ldefault; 1241: stc = STCconst; 1242: goto L2; 1243: 1244: case TOKinvariant: 1245: case TOKimmutable: 1246: if (peek(&token)->value == TOKlparen) 1247: goto Ldefault; 1248: stc = STCimmutable; 1249: goto L2; 1250: 1251: case TOKshared: 1252: if (peek(&token)->value == TOKlparen) 1253: goto Ldefault; 1254: stc = STCshared; 1255: goto L2; 1256: 1257: case TOKwild: 1258: if (peek(&token)->value == TOKlparen) 1259: goto Ldefault; 1260: stc = STCwild; 1261: goto L2; 1262: 1263: case TOKin: stc = STCin; goto L2; 1264: case TOKout: stc = STCout; goto L2; 1265: #if D1INOUT 1266: case TOKinout: 1267: #endif 1268: case TOKref: stc = STCref; goto L2; 1269: case TOKlazy: stc = STClazy; goto L2; 1270: case TOKscope: stc = STCscope; goto L2; 1271: case TOKfinal: stc = STCfinal; goto L2; 1272: case TOKauto: stc = STCauto; goto L2; 1273: L2: 1274: if (storageClass & stc || 1275: (storageClass & STCin && stc & (STCconst | STCscope)) || 1276: (stc & STCin && storageClass & (STCconst | STCscope)) 1277: ) 1278: error("redundant storage class %s", Token::toChars(token.value)); 1279: storageClass |= stc; 1280: composeStorageClass(storageClass); 1281: continue; 1282: 1283: #if 0 1284: case TOKstatic: stc = STCstatic; goto L2; 1285: case TOKauto: storageClass = STCauto; goto L4; 1286: case TOKalias: storageClass = STCalias; goto L4; 1287: L4: 1288: nextToken(); 1289: if (token.value == TOKidentifier) 1290: { ai = token.ident; 1291: nextToken(); 1292: } 1293: else 1294: ai = NULL; 1295: at = NULL; // no type 1296: ae = NULL; // no default argument 1297: if (token.value == TOKassign) // = defaultArg 1298: { nextToken(); 1299: ae = parseDefaultInitExp(); 1300: hasdefault = 1; 1301: } 1302: else 1303: { if (hasdefault) 1304: error("default argument expected for alias %s", 1305: ai ? ai->toChars() : ""); 1306: } 1307: goto L3; 1308: #endif 1309: 1310: default: 1311: Ldefault: 1312: stc = storageClass & (STCin | STCout | STCref | STClazy); 1313: if (stc & (stc - 1)) // if stc is not a power of 2 1314: error("incompatible parameter storage classes"); 1315: if ((storageClass & (STCconst | STCout)) == (STCconst | STCout)) 1316: error("out cannot be const"); 1317: if ((storageClass & (STCimmutable | STCout)) == (STCimmutable | STCout)) 1318: error("out cannot be immutable"); 1319: if ((storageClass & STCscope) && 1320: (storageClass & (STCref | STCout))) 1321: error("scope cannot be ref or out"); 1322: at = parseType(&ai); 1323: ae = NULL; 1324: if (token.value == TOKassign) // = defaultArg 1325: { nextToken(); 1326: ae = parseDefaultInitExp(); 1327: hasdefault = 1; 1328: } 1329: else 1330: { if (hasdefault) 1331: error("default argument expected for %s", 1332: ai ? ai->toChars() : at->toChars()); 1333: } 1334: if (token.value == TOKdotdotdot) 1335: { /* This is: 1336: * at ai ... 1337: */ 1338: 1339: if (storageClass & (STCout | STCref)) 1340: error("variadic argument cannot be out or ref"); 1341: varargs = 2; 1342: a = new Parameter(storageClass, at, ai, ae); 1343: arguments->push(a); 1344: nextToken(); 1345: break; 1346: } 1347: L3:
warning C4102: 'L3' : unreferenced label
1348: a = new Parameter(storageClass, at, ai, ae); 1349: arguments->push(a); 1350: if (token.value == TOKcomma) 1351: { nextToken(); 1352: goto L1; 1353: } 1354: break; 1355: } 1356: break; 1357: } 1358: break; 1359: 1360: L1: ; 1361: } 1362: check(TOKrparen); 1363: *pvarargs = varargs; 1364: return arguments; 1365: } 1366: 1367: 1368: /************************************* 1369: */ 1370: 1371: EnumDeclaration *Parser::parseEnum() 1372: { EnumDeclaration *e; 1373: Identifier *id; 1374: Type *memtype; 1375: Loc loc = this->loc; 1376: 1377: //printf("Parser::parseEnum()\n"); 1378: nextToken(); 1379: if (token.value == TOKidentifier) 1380: { id = token.ident; 1381: nextToken(); 1382: } 1383: else 1384: id = NULL; 1385: 1386: if (token.value == TOKcolon) 1387: { 1388: nextToken(); 1389: memtype = parseBasicType(); 1390: memtype = parseDeclarator(memtype, NULL, NULL); 1391: } 1392: else 1393: memtype = NULL; 1394: 1395: e = new EnumDeclaration(loc, id, memtype); 1396: if (token.value == TOKsemicolon && id) 1397: nextToken(); 1398: else if (token.value == TOKlcurly) 1399: { 1400: //printf("enum definition\n"); 1401: e->members = new Dsymbols(); 1402: nextToken(); 1403: unsigned char *comment = token.blockComment; 1404: while (token.value != TOKrcurly) 1405: { 1406: /* Can take the following forms: 1407: * 1. ident 1408: * 2. ident = value 1409: * 3. type ident = value 1410: */ 1411: 1412: loc = this->loc; 1413: 1414: Type *type = NULL; 1415: Identifier *ident; 1416: Token *tp = peek(&token); 1417: if (token.value == TOKidentifier && 1418: (tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly)) 1419: { 1420: ident = token.ident; 1421: type = NULL; 1422: nextToken(); 1423: } 1424: else 1425: { 1426: type = parseType(&ident, NULL); 1427: if (id || memtype) 1428: error("type only allowed if anonymous enum and no enum type"); 1429: } 1430: 1431: Expression *value; 1432: if (token.value == TOKassign) 1433: { 1434: nextToken(); 1435: value = parseAssignExp(); 1436: } 1437: else 1438: { value = NULL; 1439: if (type) 1440: error("if type, there must be an initializer"); 1441: } 1442: 1443: EnumMember *em = new EnumMember(loc, ident, value, type); 1444: e->members->push(em); 1445: 1446: if (token.value == TOKrcurly) 1447: ; 1448: else 1449: { addComment(em, comment); 1450: comment = NULL; 1451: check(TOKcomma); 1452: } 1453: addComment(em, comment); 1454: comment = token.blockComment; 1455: } 1456: nextToken(); 1457: } 1458: else 1459: error("enum declaration is invalid"); 1460: 1461: //printf("-parseEnum() %s\n", e->toChars()); 1462: return e; 1463: } 1464: 1465: /******************************** 1466: * Parse struct, union, interface, class. 1467: */ 1468: 1469: Dsymbol *Parser::parseAggregate() 1470: { AggregateDeclaration *a = NULL; 1471: int anon = 0; 1472: enum TOK tok; 1473: Identifier *id; 1474: TemplateParameters *tpl = NULL; 1475: Expression *constraint = NULL; 1476: 1477: //printf("Parser::parseAggregate()\n"); 1478: tok = token.value; 1479: nextToken(); 1480: if (token.value != TOKidentifier) 1481: { id = NULL; 1482: } 1483: else 1484: { id = token.ident; 1485: nextToken(); 1486: 1487: if (token.value == TOKlparen) 1488: { // Class template declaration. 1489: 1490: // Gather template parameter list 1491: tpl = parseTemplateParameterList(); 1492: constraint = parseConstraint(); 1493: } 1494: } 1495: 1496: Loc loc = this->loc; 1497: switch (tok) 1498: { case TOKclass: 1499: case TOKinterface: 1500: { 1501: if (!id) 1502: error("anonymous classes not allowed"); 1503: 1504: // Collect base class(es) 1505: BaseClasses *baseclasses = NULL; 1506: if (token.value == TOKcolon) 1507: { 1508: nextToken(); 1509: baseclasses = parseBaseClasses(); 1510: 1511: if (token.value != TOKlcurly) 1512: error("members expected"); 1513: } 1514: 1515: if (tok == TOKclass) 1516: a = new ClassDeclaration(loc, id, baseclasses); 1517: else 1518: a = new InterfaceDeclaration(loc, id, baseclasses); 1519: break; 1520: } 1521: 1522: case TOKstruct: 1523: if (id) 1524: a = new StructDeclaration(loc, id); 1525: else 1526: anon = 1; 1527: break; 1528: 1529: case TOKunion: 1530: if (id) 1531: a = new UnionDeclaration(loc, id); 1532: else 1533: anon = 2; 1534: break; 1535: 1536: default: 1537: assert(0); 1538: break; 1539: } 1540: if (a && token.value == TOKsemicolon) 1541: { nextToken(); 1542: } 1543: else if (token.value == TOKlcurly) 1544: { 1545: //printf("aggregate definition\n"); 1546: nextToken(); 1547: Dsymbols *decl = parseDeclDefs(0); 1548: if (token.value != TOKrcurly) 1549: error("} expected following member declarations in aggregate"); 1550: nextToken(); 1551: if (anon) 1552: { 1553: /* Anonymous structs/unions are more like attributes. 1554: */ 1555: return new AnonDeclaration(loc, anon - 1, decl); 1556: } 1557: else 1558: a->members = decl; 1559: } 1560: else 1561: { 1562: error("{ } expected following aggregate declaration"); 1563: a = new StructDeclaration(loc, NULL); 1564: } 1565: 1566: if (tpl) 1567: { // Wrap a template around the aggregate declaration 1568: 1569: Dsymbols *decldefs = new Dsymbols(); 1570: decldefs->push(a); 1571: TemplateDeclaration *tempdecl = 1572: new TemplateDeclaration(loc, id, tpl, constraint, decldefs, 0); 1573: return tempdecl; 1574: } 1575: 1576: return a; 1577: } 1578: 1579: /******************************************* 1580: */ 1581: 1582: BaseClasses *Parser::parseBaseClasses() 1583: { 1584: BaseClasses *baseclasses = new BaseClasses(); 1585: 1586: for (; 1; nextToken()) 1587: { 1588: enum PROT protection = PROTpublic; 1589: switch (token.value) 1590: { 1591: case TOKprivate: 1592: protection = PROTprivate; 1593: nextToken(); 1594: break; 1595: case TOKpackage: 1596: protection = PROTpackage; 1597: nextToken(); 1598: break; 1599: case TOKprotected: 1600: protection = PROTprotected; 1601: nextToken(); 1602: break; 1603: case TOKpublic: 1604: protection = PROTpublic; 1605: nextToken(); 1606: break; 1607: } 1608: if (token.value == TOKidentifier) 1609: { 1610: BaseClass *b = new BaseClass(parseBasicType(), protection); 1611: baseclasses->push(b); 1612: if (token.value != TOKcomma) 1613: break; 1614: } 1615: else 1616: { 1617: error("base classes expected instead of %s", token.toChars()); 1618: return NULL; 1619: } 1620: } 1621: return baseclasses; 1622: } 1623: 1624: /************************************** 1625: * Parse constraint. 1626: * Constraint is of the form: 1627: * if ( ConstraintExpression ) 1628: */ 1629: 1630: #if DMDV2 1631: Expression *Parser::parseConstraint() 1632: { Expression *e = NULL; 1633: 1634: if (token.value == TOKif) 1635: { 1636: nextToken(); // skip over 'if' 1637: check(TOKlparen); 1638: e = parseExpression(); 1639: check(TOKrparen); 1640: } 1641: return e; 1642: } 1643: #endif 1644: 1645: /************************************** 1646: * Parse a TemplateDeclaration. 1647: */ 1648: 1649: TemplateDeclaration *Parser::parseTemplateDeclaration(int ismixin) 1650: { 1651: TemplateDeclaration *tempdecl; 1652: Identifier *id; 1653: TemplateParameters *tpl; 1654: Dsymbols *decldefs; 1655: Expression *constraint = NULL; 1656: Loc loc = this->loc; 1657: 1658: nextToken(); 1659: if (token.value != TOKidentifier) 1660: { error("TemplateIdentifier expected following template"); 1661: goto Lerr; 1662: } 1663: id = token.ident; 1664: nextToken(); 1665: tpl = parseTemplateParameterList(); 1666: if (!tpl) 1667: goto Lerr; 1668: 1669: constraint = parseConstraint(); 1670: 1671: if (token.value != TOKlcurly) 1672: { error("members of template declaration expected"); 1673: goto Lerr; 1674: } 1675: else 1676: { 1677: nextToken(); 1678: decldefs = parseDeclDefs(0); 1679: if (token.value != TOKrcurly) 1680: { error("template member expected"); 1681: goto Lerr; 1682: } 1683: nextToken(); 1684: } 1685: 1686: tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs, ismixin); 1687: return tempdecl; 1688: 1689: Lerr: 1690: return NULL; 1691: } 1692: 1693: /****************************************** 1694: * Parse template parameter list. 1695: * Input: 1696: * flag 0: parsing "( list )" 1697: * 1: parsing non-empty "list )" 1698: */ 1699: 1700: TemplateParameters *Parser::parseTemplateParameterList(int flag) 1701: { 1702: TemplateParameters *tpl = new TemplateParameters();
warning C6211: Leaking memory 'tpl' due to an exception. Consider using a local catch block to clean up memory: Lines: 1702, 1704, 1708, 1711, 1712, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1727, 1728, 1766, 1786, 1797, 1821, 1822, 1824, 1825
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 1702, 1704, 1708, 1711, 1712, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1727, 1728, 1766, 1786, 1797, 1821, 1822, 1827, 1832, 1837
1703: 1704: if (!flag && token.value != TOKlparen) 1705: { error("parenthesized TemplateParameterList expected following TemplateIdentifier"); 1706: goto Lerr; 1707: } 1708: nextToken(); 1709: 1710: // Get array of TemplateParameters 1711: if (flag || token.value != TOKrparen) 1712: { int isvariadic = 0; 1713: 1714: while (token.value != TOKrparen) 1715: { TemplateParameter *tp; 1716: Identifier *tp_ident = NULL; 1717: Type *tp_spectype = NULL; 1718: Type *tp_valtype = NULL; 1719: Type *tp_defaulttype = NULL; 1720: Expression *tp_specvalue = NULL; 1721: Expression *tp_defaultvalue = NULL; 1722: Token *t; 1723: 1724: // Get TemplateParameter 1725: 1726: // First, look ahead to see if it is a TypeParameter or a ValueParameter 1727: t = peek(&token); 1728: if (token.value == TOKalias) 1729: { // AliasParameter 1730: nextToken(); 1731: Type *spectype = NULL; 1732: if (isDeclaration(&token, 2, TOKreserved, NULL)) 1733: { 1734: spectype = parseType(&tp_ident); 1735: } 1736: else 1737: { 1738: if (token.value != TOKidentifier) 1739: { error("identifier expected for template alias parameter"); 1740: goto Lerr; 1741: } 1742: tp_ident = token.ident; 1743: nextToken(); 1744: } 1745: Object *spec = NULL; 1746: if (token.value == TOKcolon) // : Type 1747: { 1748: nextToken(); 1749: if (isDeclaration(&token, 0, TOKreserved, NULL)) 1750: spec = parseType(); 1751: else 1752: spec = parseCondExp(); 1753: } 1754: Object *def = NULL; 1755: if (token.value == TOKassign) // = Type 1756: { 1757: nextToken(); 1758: if (isDeclaration(&token, 0, TOKreserved, NULL)) 1759: def = parseType(); 1760: else 1761: def = parseCondExp(); 1762: } 1763: tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def); 1764: } 1765: else if (t->value == TOKcolon || t->value == TOKassign || 1766: t->value == TOKcomma || t->value == TOKrparen) 1767: { // TypeParameter 1768: if (token.value != TOKidentifier) 1769: { error("identifier expected for template type parameter"); 1770: goto Lerr; 1771: } 1772: tp_ident = token.ident; 1773: nextToken(); 1774: if (token.value == TOKcolon) // : Type 1775: { 1776: nextToken(); 1777: tp_spectype = parseType(); 1778: } 1779: if (token.value == TOKassign) // = Type 1780: { 1781: nextToken(); 1782: tp_defaulttype = parseType(); 1783: } 1784: tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype); 1785: } 1786: else if (token.value == TOKidentifier && t->value == TOKdotdotdot) 1787: { // ident... 1788: if (isvariadic) 1789: error("variadic template parameter must be last"); 1790: isvariadic = 1; 1791: tp_ident = token.ident; 1792: nextToken(); 1793: nextToken(); 1794: tp = new TemplateTupleParameter(loc, tp_ident); 1795: } 1796: #if DMDV2 1797: else if (token.value == TOKthis) 1798: { // ThisParameter 1799: nextToken(); 1800: if (token.value != TOKidentifier) 1801: { error("identifier expected for template this parameter"); 1802: goto Lerr; 1803: } 1804: tp_ident = token.ident; 1805: nextToken(); 1806: if (token.value == TOKcolon) // : Type 1807: { 1808: nextToken(); 1809: tp_spectype = parseType(); 1810: } 1811: if (token.value == TOKassign) // = Type 1812: { 1813: nextToken(); 1814: tp_defaulttype = parseType(); 1815: } 1816: tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype); 1817: } 1818: #endif 1819: else 1820: { // ValueParameter 1821: tp_valtype = parseType(&tp_ident); 1822: if (!tp_ident) 1823: { 1824: error("identifier expected for template value parameter"); 1825: tp_ident = new Identifier("error", TOKidentifier); 1826: } 1827: if (token.value == TOKcolon) // : CondExpression 1828: { 1829: nextToken(); 1830: tp_specvalue = parseCondExp(); 1831: } 1832: if (token.value == TOKassign) // = CondExpression 1833: { 1834: nextToken(); 1835: tp_defaultvalue = parseDefaultInitExp(); 1836: } 1837: tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue); 1838: } 1839: tpl->push(tp); 1840: if (token.value != TOKcomma) 1841: break; 1842: nextToken(); 1843: } 1844: } 1845: check(TOKrparen); 1846: Lerr: 1847: return tpl; 1848: } 1849: 1850: /****************************************** 1851: * Parse template mixin. 1852: * mixin Foo; 1853: * mixin Foo!(args); 1854: * mixin a.b.c!(args).Foo!(args); 1855: * mixin Foo!(args) identifier; 1856: * mixin typeof(expr).identifier!(args); 1857: */ 1858: 1859: Dsymbol *Parser::parseMixin() 1860: { 1861: TemplateMixin *tm; 1862: Identifier *id; 1863: Type *tqual; 1864: Objects *tiargs; 1865: Identifiers *idents; 1866: 1867: //printf("parseMixin()\n"); 1868: nextToken(); 1869: tqual = NULL; 1870: if (token.value == TOKdot) 1871: { 1872: id = Id::empty; 1873: } 1874: else 1875: { 1876: if (token.value == TOKtypeof) 1877: { 1878: tqual = parseTypeof(); 1879: check(TOKdot); 1880: } 1881: if (token.value != TOKidentifier) 1882: { 1883: error("identifier expected, not %s", token.toChars()); 1884: id = Id::empty; 1885: } 1886: else 1887: id = token.ident; 1888: nextToken(); 1889: } 1890: 1891: idents = new Identifiers(); 1892: while (1) 1893: { 1894: tiargs = NULL; 1895: if (token.value == TOKnot) 1896: { 1897: nextToken(); 1898: if (token.value == TOKlparen) 1899: tiargs = parseTemplateArgumentList(); 1900: else 1901: tiargs = parseTemplateArgument(); 1902: } 1903: 1904: if (token.value != TOKdot) 1905: break; 1906: 1907: if (tiargs) 1908: { TemplateInstance *tempinst = new TemplateInstance(loc, id); 1909: tempinst->tiargs = tiargs; 1910: id = (Identifier *)tempinst; 1911: tiargs = NULL; 1912: } 1913: idents->push(id); 1914: 1915: nextToken(); 1916: if (token.value != TOKidentifier) 1917: { error("identifier expected following '.' instead of '%s'", token.toChars()); 1918: break; 1919: } 1920: id = token.ident; 1921: nextToken(); 1922: } 1923: idents->push(id); 1924: 1925: if (token.value == TOKidentifier) 1926: { 1927: id = token.ident; 1928: nextToken(); 1929: } 1930: else 1931: id = NULL; 1932: 1933: tm = new TemplateMixin(loc, id, tqual, idents, tiargs); 1934: if (token.value != TOKsemicolon) 1935: error("';' expected after mixin"); 1936: nextToken(); 1937: 1938: return tm; 1939: } 1940: 1941: /****************************************** 1942: * Parse template argument list. 1943: * Input: 1944: * current token is opening '(' 1945: * Output: 1946: * current token is one after closing ')' 1947: */ 1948: 1949: Objects *Parser::parseTemplateArgumentList() 1950: { 1951: //printf("Parser::parseTemplateArgumentList()\n"); 1952: if (token.value != TOKlparen && token.value != TOKlcurly) 1953: { error("!(TemplateArgumentList) expected following TemplateIdentifier"); 1954: return new Objects(); 1955: } 1956: return parseTemplateArgumentList2(); 1957: } 1958: 1959: Objects *Parser::parseTemplateArgumentList2() 1960: { 1961: //printf("Parser::parseTemplateArgumentList2()\n"); 1962: Objects *tiargs = new Objects(); 1963: enum TOK endtok = TOKrparen; 1964: nextToken(); 1965: 1966: // Get TemplateArgumentList 1967: while (token.value != endtok) 1968: { 1969: // See if it is an Expression or a Type 1970: if (isDeclaration(&token, 0, TOKreserved, NULL)) 1971: { // Template argument is a type 1972: Type *ta = parseType(); 1973: tiargs->push(ta); 1974: } 1975: else 1976: { // Template argument is an expression 1977: Expression *ea = parseAssignExp(); 1978: 1979: if (ea->op == TOKfunction) 1980: { FuncLiteralDeclaration *fd = ((FuncExp *)ea)->fd; 1981: if (fd->type->ty == Tfunction) 1982: { 1983: TypeFunction *tf = (TypeFunction *)fd->type; 1984: /* If there are parameters that consist of only an identifier, 1985: * rather than assuming the identifier is a type, as we would 1986: * for regular function declarations, assume the identifier 1987: * is the parameter name, and we're building a template with 1988: * a deduced type. 1989: */ 1990: TemplateParameters *tpl = NULL; 1991: for (int i = 0; i < tf->parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1992: { Parameter *param = tf->parameters->tdata()[i]; 1993: if (param->ident == NULL && 1994: param->type && 1995: param->type->ty == Tident && 1996: ((TypeIdentifier *)param->type)->idents.dim == 0 1997: ) 1998: { 1999: /* Switch parameter type to parameter identifier, 2000: * parameterize with template type parameter _T 2001: */ 2002: TypeIdentifier *pt = (TypeIdentifier *)param->type; 2003: param->ident = pt->ident; 2004: Identifier *id = Lexer::uniqueId("__T"); 2005: param->type = new TypeIdentifier(pt->loc, id); 2006: TemplateParameter *tp = new TemplateTypeParameter(fd->loc, id, NULL, NULL); 2007: if (!tpl) 2008: tpl = new TemplateParameters(); 2009: tpl->push(tp); 2010: } 2011: } 2012: 2013: if (tpl) 2014: { // Wrap a template around function fd 2015: Dsymbols *decldefs = new Dsymbols(); 2016: decldefs->push(fd); 2017: TemplateDeclaration *tempdecl = 2018: new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, 0); 2019: tempdecl->literal = 1; // it's a template 'literal' 2020: tiargs->push(tempdecl); 2021: goto L1; 2022: } 2023: } 2024: } 2025: 2026: tiargs->push(ea); 2027: } 2028: L1: 2029: if (token.value != TOKcomma) 2030: break; 2031: nextToken(); 2032: } 2033: check(endtok, "template argument list"); 2034: return tiargs; 2035: } 2036: 2037: /***************************** 2038: * Parse single template argument, to support the syntax: 2039: * foo!arg 2040: * Input: 2041: * current token is the arg 2042: */ 2043: 2044: Objects *Parser::parseTemplateArgument() 2045: { 2046: //printf("parseTemplateArgument()\n"); 2047: Objects *tiargs = new Objects();
warning C6211: Leaking memory 'tiargs' due to an exception. Consider using a local catch block to clean up memory: Lines: 2047, 2048, 2049, 2051, 2052
2048: Type *ta; 2049: switch (token.value) 2050: { 2051: case TOKidentifier: 2052: ta = new TypeIdentifier(loc, token.ident); 2053: goto LabelX; 2054: 2055: case BASIC_TYPES_X(ta): 2056: tiargs->push(ta); 2057: nextToken(); 2058: break; 2059: 2060: case TOKint32v: 2061: case TOKuns32v: 2062: case TOKint64v: 2063: case TOKuns64v: 2064: case TOKfloat32v: 2065: case TOKfloat64v: 2066: case TOKfloat80v: 2067: case TOKimaginary32v: 2068: case TOKimaginary64v: 2069: case TOKimaginary80v: 2070: case TOKnull: 2071: case TOKtrue: 2072: case TOKfalse: 2073: case TOKcharv: 2074: case TOKwcharv: 2075: case TOKdcharv: 2076: case TOKstring: 2077: case TOKfile: 2078: case TOKline: 2079: case TOKthis: 2080: { // Template argument is an expression 2081: Expression *ea = parsePrimaryExp(); 2082: tiargs->push(ea); 2083: break; 2084: } 2085: 2086: default: 2087: error("template argument expected following !"); 2088: break; 2089: } 2090: if (token.value == TOKnot) 2091: error("multiple ! arguments are not allowed"); 2092: return tiargs; 2093: } 2094: 2095: Import *Parser::parseImport(Dsymbols *decldefs, int isstatic) 2096: { Import *s; 2097: Identifier *id; 2098: Identifier *aliasid = NULL; 2099: Identifiers *a; 2100: Loc loc; 2101: 2102: //printf("Parser::parseImport()\n"); 2103: do 2104: { 2105: L1: 2106: nextToken(); 2107: if (token.value != TOKidentifier) 2108: { error("Identifier expected following import"); 2109: break; 2110: } 2111: 2112: loc = this->loc; 2113: a = NULL; 2114: id = token.ident; 2115: nextToken(); 2116: if (!aliasid && token.value == TOKassign) 2117: { 2118: aliasid = id; 2119: goto L1; 2120: } 2121: while (token.value == TOKdot) 2122: { 2123: if (!a) 2124: a = new Identifiers(); 2125: a->push(id); 2126: nextToken(); 2127: if (token.value != TOKidentifier) 2128: { error("identifier expected following package"); 2129: break; 2130: } 2131: id = token.ident; 2132: nextToken(); 2133: } 2134: 2135: s = new Import(loc, a, id, aliasid, isstatic); 2136: decldefs->push(s); 2137: 2138: /* Look for 2139: * : alias=name, alias=name; 2140: * syntax. 2141: */ 2142: if (token.value == TOKcolon) 2143: { 2144: do 2145: { Identifier *name; 2146: 2147: nextToken(); 2148: if (token.value != TOKidentifier) 2149: { error("Identifier expected following :"); 2150: break; 2151: } 2152: Identifier *alias = token.ident; 2153: nextToken(); 2154: if (token.value == TOKassign) 2155: { 2156: nextToken(); 2157: if (token.value != TOKidentifier) 2158: { error("Identifier expected following %s=", alias->toChars()); 2159: break; 2160: } 2161: name = token.ident; 2162: nextToken(); 2163: } 2164: else 2165: { name = alias; 2166: alias = NULL; 2167: } 2168: s->addAlias(name, alias); 2169: } while (token.value == TOKcomma); 2170: break; // no comma-separated imports of this form 2171: } 2172: 2173: aliasid = NULL; 2174: } while (token.value == TOKcomma); 2175: 2176: if (token.value == TOKsemicolon) 2177: nextToken(); 2178: else 2179: { 2180: error("';' expected"); 2181: nextToken(); 2182: } 2183: 2184: return NULL; 2185: } 2186: 2187: #if DMDV2 2188: Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) 2189: { Type *t; 2190: 2191: /* Take care of the storage class prefixes that 2192: * serve as type attributes: 2193: * const shared, shared const, const, invariant, shared 2194: */ 2195: if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen || 2196: token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen) 2197: { 2198: nextToken(); 2199: nextToken(); 2200: /* shared const type 2201: */ 2202: t = parseType(pident, tpl); 2203: t = t->makeSharedConst(); 2204: return t; 2205: } 2206: else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() != TOKlparen || 2207: token.value == TOKshared && peekNext() == TOKwild && peekNext2() != TOKlparen) 2208: { 2209: nextToken(); 2210: nextToken(); 2211: /* shared wild type 2212: */ 2213: t = parseType(pident, tpl); 2214: t = t->makeSharedWild(); 2215: return t; 2216: } 2217: else if (token.value == TOKconst && peekNext() != TOKlparen) 2218: { 2219: nextToken(); 2220: /* const type 2221: */ 2222: t = parseType(pident, tpl); 2223: t = t->makeConst(); 2224: return t; 2225: } 2226: else if ((token.value == TOKinvariant || token.value == TOKimmutable) && 2227: peekNext() != TOKlparen) 2228: { 2229: nextToken(); 2230: /* invariant type 2231: */ 2232: t = parseType(pident, tpl); 2233: t = t->makeInvariant(); 2234: return t; 2235: } 2236: else if (token.value == TOKshared && peekNext() != TOKlparen) 2237: { 2238: nextToken(); 2239: /* shared type 2240: */ 2241: t = parseType(pident, tpl); 2242: t = t->makeShared(); 2243: return t; 2244: } 2245: else if (token.value == TOKwild && peekNext() != TOKlparen) 2246: { 2247: nextToken(); 2248: /* wild type 2249: */ 2250: t = parseType(pident, tpl); 2251: t = t->makeWild(); 2252: return t; 2253: } 2254: else 2255: t = parseBasicType(); 2256: t = parseDeclarator(t, pident, tpl); 2257: return t; 2258: } 2259: #endif 2260: 2261: Type *Parser::parseBasicType() 2262: { Type *t; 2263: Identifier *id; 2264: TypeQualified *tid; 2265: 2266: //printf("parseBasicType()\n"); 2267: switch (token.value) 2268: { 2269: case BASIC_TYPES_X(t): 2270: nextToken(); 2271: break; 2272: 2273: case TOKidentifier: 2274: id = token.ident; 2275: nextToken(); 2276: if (token.value == TOKnot) 2277: { // ident!(template_arguments) 2278: TemplateInstance *tempinst = new TemplateInstance(loc, id); 2279: nextToken(); 2280: if (token.value == TOKlparen) 2281: // ident!(template_arguments) 2282: tempinst->tiargs = parseTemplateArgumentList(); 2283: else 2284: // ident!template_argument 2285: tempinst->tiargs = parseTemplateArgument(); 2286: tid = new TypeInstance(loc, tempinst); 2287: goto Lident2; 2288: } 2289: Lident: 2290: tid = new TypeIdentifier(loc, id); 2291: Lident2: 2292: while (token.value == TOKdot) 2293: { nextToken(); 2294: if (token.value != TOKidentifier) 2295: { error("identifier expected following '.' instead of '%s'", token.toChars()); 2296: break; 2297: } 2298: id = token.ident; 2299: nextToken(); 2300: if (token.value == TOKnot) 2301: { 2302: TemplateInstance *tempinst = new TemplateInstance(loc, id); 2303: nextToken(); 2304: if (token.value == TOKlparen) 2305: // ident!(template_arguments) 2306: tempinst->tiargs = parseTemplateArgumentList(); 2307: else 2308: // ident!template_argument 2309: tempinst->tiargs = parseTemplateArgument(); 2310: tid->addIdent((Identifier *)tempinst); 2311: } 2312: else 2313: tid->addIdent(id); 2314: } 2315: t = tid; 2316: break; 2317: 2318: case TOKdot: 2319: // Leading . as in .foo 2320: id = Id::empty; 2321: goto Lident; 2322: 2323: case TOKtypeof: 2324: // typeof(expression) 2325: tid = parseTypeof(); 2326: goto Lident2; 2327: 2328: case TOKconst: 2329: // const(type) 2330: nextToken(); 2331: check(TOKlparen); 2332: t = parseType(); 2333: check(TOKrparen); 2334: if (t->isShared()) 2335: t = t->makeSharedConst(); 2336: else 2337: t = t->makeConst(); 2338: break; 2339: 2340: case TOKinvariant: 2341: if (!global.params.useDeprecated) 2342: error("use of 'invariant' rather than 'immutable' is deprecated"); 2343: case TOKimmutable: 2344: // invariant(type) 2345: nextToken(); 2346: check(TOKlparen); 2347: t = parseType(); 2348: check(TOKrparen); 2349: t = t->makeInvariant(); 2350: break; 2351: 2352: case TOKshared: 2353: // shared(type) 2354: nextToken(); 2355: check(TOKlparen); 2356: t = parseType(); 2357: check(TOKrparen); 2358: if (t->isConst()) 2359: t = t->makeSharedConst(); 2360: else if (t->isWild()) 2361: t = t->makeSharedWild(); 2362: else 2363: t = t->makeShared(); 2364: break; 2365: 2366: case TOKwild: 2367: // wild(type) 2368: nextToken(); 2369: check(TOKlparen); 2370: t = parseType(); 2371: check(TOKrparen); 2372: if (t->isShared()) 2373: t = t->makeSharedWild(); 2374: else 2375: t = t->makeWild(); 2376: break; 2377: 2378: default: 2379: error("basic type expected, not %s", token.toChars()); 2380: t = Type::tint32; 2381: break; 2382: } 2383: return t; 2384: } 2385: 2386: /****************************************** 2387: * Parse things that follow the initial type t. 2388: * t * 2389: * t [] 2390: * t [type] 2391: * t [expression] 2392: * t [expression .. expression] 2393: * t function 2394: * t delegate 2395: */ 2396: 2397: Type *Parser::parseBasicType2(Type *t) 2398: { 2399: //printf("parseBasicType2()\n"); 2400: while (1) 2401: { 2402: switch (token.value) 2403: { 2404: case TOKmul: 2405: t = new TypePointer(t); 2406: nextToken(); 2407: continue; 2408: 2409: case TOKlbracket: 2410: // Handle []. Make sure things like 2411: // int[3][1] a; 2412: // is (array[1] of array[3] of int) 2413: nextToken(); 2414: if (token.value == TOKrbracket) 2415: { 2416: t = new TypeDArray(t); // [] 2417: nextToken(); 2418: } 2419: else if (isDeclaration(&token, 0, TOKrbracket, NULL)) 2420: { // It's an associative array declaration 2421: 2422: //printf("it's an associative array\n"); 2423: Type *index = parseType(); // [ type ] 2424: t = new TypeAArray(t, index); 2425: check(TOKrbracket); 2426: } 2427: else 2428: { 2429: //printf("it's type[expression]\n"); 2430: inBrackets++; 2431: Expression *e = parseAssignExp(); // [ expression ] 2432: if (token.value == TOKslice) 2433: { 2434: nextToken(); 2435: Expression *e2 = parseAssignExp(); // [ exp .. exp ] 2436: t = new TypeSlice(t, e, e2); 2437: } 2438: else 2439: t = new TypeSArray(t,e); 2440: inBrackets--; 2441: check(TOKrbracket); 2442: } 2443: continue; 2444: 2445: case TOKdelegate: 2446: case TOKfunction: 2447: { // Handle delegate declaration: 2448: // t delegate(parameter list) nothrow pure 2449: // t function(parameter list) nothrow pure 2450: Parameters *arguments; 2451: int varargs; 2452: enum TOK save = token.value; 2453: 2454: nextToken(); 2455: arguments = parseParameters(&varargs); 2456: 2457: StorageClass stc = parsePostfix(); 2458: if (stc & (STCconst | STCimmutable | STCshared | STCwild)) 2459: error("const/immutable/shared/inout attributes are only valid for non-static member functions"); 2460: 2461: TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage, stc); 2462: 2463: if (save == TOKdelegate) 2464: t = new TypeDelegate(tf); 2465: else 2466: t = new TypePointer(tf); // pointer to function 2467: continue; 2468: } 2469: 2470: default: 2471: return t; 2472: } 2473: assert(0); 2474: } 2475: assert(0); 2476: return NULL; 2477: } 2478: 2479: Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl, StorageClass storage_class) 2480: { Type *ts; 2481: 2482: //printf("parseDeclarator(tpl = %p)\n", tpl); 2483: t = parseBasicType2(t); 2484: 2485: switch (token.value) 2486: { 2487: 2488: case TOKidentifier: 2489: if (pident) 2490: *pident = token.ident; 2491: else 2492: error("unexpected identifer '%s' in declarator", token.ident->toChars()); 2493: ts = t; 2494: nextToken(); 2495: break; 2496: 2497: case TOKlparen: 2498: if (peekNext() == TOKmul || // like: T (*fp)(); 2499: peekNext() == TOKlparen // like: T ((*fp))(); 2500: /* || peekNext() == TOKlbracket*/) // like: T ([] a) 2501: { 2502: /* Parse things with parentheses around the identifier, like: 2503: * int (*ident[3])[] 2504: * although the D style would be: 2505: * int[]*[3] ident 2506: */ 2507: if (!global.params.useDeprecated) 2508: { 2509: error("C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers"); 2510: } 2511: nextToken(); 2512: ts = parseDeclarator(t, pident); 2513: check(TOKrparen); 2514: break; 2515: } 2516: ts = t; 2517: { 2518: Token *peekt = &token; 2519: /* Completely disallow C-style things like: 2520: * T (a); 2521: * Improve error messages for the common bug of a missing return type 2522: * by looking to see if (a) looks like a parameter list. 2523: */ 2524: if (isParameters(&peekt)) { 2525: error("function declaration without return type. " 2526: "(Note that constructors are always named 'this')"); 2527: } 2528: else 2529: error("unexpected ( in declarator"); 2530: } 2531: break; 2532: 2533: default: 2534: ts = t; 2535: break; 2536: } 2537: 2538: // parse DeclaratorSuffixes 2539: while (1) 2540: { 2541: switch (token.value) 2542: { 2543: #if CARRAYDECL 2544: /* Support C style array syntax: 2545: * int ident[] 2546: * as opposed to D-style: 2547: * int[] ident 2548: */ 2549: case TOKlbracket: 2550: { // This is the old C-style post [] syntax. 2551: TypeNext *ta; 2552: nextToken(); 2553: if (token.value == TOKrbracket) 2554: { // It's a dynamic array 2555: ta = new TypeDArray(t); // [] 2556: nextToken(); 2557: } 2558: else if (isDeclaration(&token, 0, TOKrbracket, NULL)) 2559: { // It's an associative array 2560: 2561: //printf("it's an associative array\n"); 2562: Type *index = parseType(); // [ type ] 2563: check(TOKrbracket); 2564: ta = new TypeAArray(t, index); 2565: } 2566: else 2567: { 2568: //printf("It's a static array\n"); 2569: Expression *e = parseAssignExp(); // [ expression ] 2570: ta = new TypeSArray(t, e); 2571: check(TOKrbracket); 2572: } 2573: 2574: /* Insert ta into 2575: * ts -> ... -> t 2576: * so that 2577: * ts -> ... -> ta -> t 2578: */ 2579: Type **pt; 2580: for (pt = &ts; *pt != t; pt = &((TypeNext*)*pt)->next) 2581: ; 2582: *pt = ta; 2583: continue; 2584: } 2585: #endif 2586: case TOKlparen: 2587: { 2588: if (tpl) 2589: { 2590: /* Look ahead to see if this is (...)(...), 2591: * i.e. a function template declaration 2592: */ 2593: if (peekPastParen(&token)->value == TOKlparen) 2594: { 2595: //printf("function template declaration\n"); 2596: 2597: // Gather template parameter list 2598: *tpl = parseTemplateParameterList(); 2599: } 2600: } 2601: 2602: int varargs; 2603: Parameters *arguments = parseParameters(&varargs); 2604: 2605: /* Parse const/immutable/shared/inout/nothrow/pure postfix 2606: */ 2607: StorageClass stc = parsePostfix(); 2608: stc |= storage_class; // merge prefix storage classes 2609: Type *tf = new TypeFunction(arguments, t, varargs, linkage, stc); 2610: 2611: if (stc & STCconst) 2612: { if (tf->isShared()) 2613: tf = tf->makeSharedConst(); 2614: else 2615: tf = tf->makeConst(); 2616: } 2617: if (stc & STCimmutable) 2618: tf = tf->makeInvariant(); 2619: if (stc & STCshared) 2620: { if (tf->isConst()) 2621: tf = tf->makeSharedConst(); 2622: else 2623: tf = tf->makeShared(); 2624: } 2625: if (stc & STCwild) 2626: { if (tf->isShared()) 2627: tf = tf->makeSharedWild(); 2628: else 2629: tf = tf->makeWild(); 2630: } 2631: 2632: /* Insert tf into 2633: * ts -> ... -> t 2634: * so that 2635: * ts -> ... -> tf -> t 2636: */ 2637: Type **pt; 2638: for (pt = &ts; *pt != t; pt = &((TypeNext*)*pt)->next) 2639: ; 2640: *pt = tf; 2641: break; 2642: } 2643: } 2644: break; 2645: } 2646: 2647: return ts; 2648: } 2649: 2650: /********************************** 2651: * Parse Declarations. 2652: * These can be: 2653: * 1. declarations at global/class level 2654: * 2. declarations at statement level 2655: * Return array of Declaration *'s. 2656: */ 2657: 2658: Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *comment) 2659: { 2660: StorageClass stc; 2661: Type *ts; 2662: Type *t; 2663: Type *tfirst; 2664: Identifier *ident; 2665: Dsymbols *a; 2666: enum TOK tok = TOKreserved; 2667: enum LINK link = linkage; 2668: 2669: //printf("parseDeclarations() %s\n", token.toChars()); 2670: if (!comment) 2671: comment = token.blockComment; 2672: 2673: if (storage_class) 2674: { ts = NULL; // infer type 2675: goto L2; 2676: } 2677: 2678: switch (token.value) 2679: { 2680: case TOKalias: 2681: /* Look for: 2682: * alias identifier this; 2683: */ 2684: tok = token.value; 2685: nextToken(); 2686: if (token.value == TOKidentifier && peek(&token)->value == TOKthis) 2687: { 2688: AliasThis *s = new AliasThis(this->loc, token.ident); 2689: nextToken(); 2690: check(TOKthis); 2691: check(TOKsemicolon); 2692: a = new Dsymbols(); 2693: a->push(s); 2694: addComment(s, comment); 2695: return a; 2696: } 2697: break; 2698: case TOKtypedef: 2699: tok = token.value; 2700: nextToken(); 2701: break; 2702: } 2703: 2704: storage_class = STCundefined; 2705: while (1) 2706: { 2707: switch (token.value) 2708: { 2709: case TOKconst: 2710: if (peek(&token)->value == TOKlparen) 2711: break; // const as type constructor 2712: stc = STCconst; // const as storage class 2713: goto L1; 2714: 2715: case TOKinvariant: 2716: case TOKimmutable: 2717: if (peek(&token)->value == TOKlparen) 2718: break; 2719: stc = STCimmutable; 2720: goto L1; 2721: 2722: case TOKshared: 2723: if (peek(&token)->value == TOKlparen) 2724: break; 2725: stc = STCshared; 2726: goto L1; 2727: 2728: case TOKwild: 2729: if (peek(&token)->value == TOKlparen) 2730: break; 2731: stc = STCwild; 2732: goto L1; 2733: 2734: case TOKstatic: stc = STCstatic; goto L1; 2735: case TOKfinal: stc = STCfinal; goto L1; 2736: case TOKauto: stc = STCauto; goto L1; 2737: case TOKscope: stc = STCscope; goto L1; 2738: case TOKoverride: stc = STCoverride; goto L1; 2739: case TOKabstract: stc = STCabstract; goto L1; 2740: case TOKsynchronized: stc = STCsynchronized; goto L1; 2741: case TOKdeprecated: stc = STCdeprecated; goto L1; 2742: #if DMDV2 2743: case TOKnothrow: stc = STCnothrow; goto L1; 2744: case TOKpure: stc = STCpure; goto L1; 2745: case TOKref: stc = STCref; goto L1; 2746: case TOKtls: stc = STCtls; goto L1; 2747: case TOKgshared: stc = STCgshared; goto L1; 2748: case TOKenum: stc = STCmanifest; goto L1; 2749: case TOKat: stc = parseAttribute(); goto L1; 2750: #endif 2751: L1: 2752: if (storage_class & stc) 2753: error("redundant storage class '%s'", token.toChars()); 2754: storage_class = storage_class | stc; 2755: composeStorageClass(storage_class); 2756: nextToken(); 2757: continue; 2758: 2759: case TOKextern: 2760: if (peek(&token)->value != TOKlparen) 2761: { stc = STCextern; 2762: goto L1; 2763: } 2764: 2765: link = parseLinkage(); 2766: continue; 2767: 2768: default: 2769: break; 2770: } 2771: break; 2772: } 2773: 2774: /* Look for auto initializers: 2775: * storage_class identifier = initializer; 2776: */ 2777: if (storage_class && 2778: token.value == TOKidentifier && 2779: peek(&token)->value == TOKassign) 2780: { 2781: return parseAutoDeclarations(storage_class, comment); 2782: } 2783: 2784: if (token.value == TOKclass) 2785: { 2786: AggregateDeclaration *s = (AggregateDeclaration *)parseAggregate(); 2787: s->storage_class |= storage_class; 2788: Dsymbols *a = new Dsymbols();
warning C6246: Local declaration of 'a' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2665' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 2665
2789: a->push(s); 2790: addComment(s, comment); 2791: return a; 2792: } 2793: 2794: /* Look for return type inference for template functions. 2795: */ 2796: { 2797: Token *tk; 2798: if (storage_class && 2799: token.value == TOKidentifier && 2800: (tk = peek(&token))->value == TOKlparen && 2801: skipParens(tk, &tk) && 2802: peek(tk)->value == TOKlparen) 2803: { 2804: ts = NULL; 2805: } 2806: else 2807: { 2808: ts = parseBasicType(); 2809: ts = parseBasicType2(ts); 2810: } 2811: } 2812: 2813: L2: 2814: tfirst = NULL; 2815: a = new Dsymbols();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2670, 2671, 2673, 2674, 2675, 2813, 2814, 2815, 2817, 2819, 2820, 2822, 2823, 2824, 2825, 2826, 2830, 2831, 2833, 2875, 2923, 2924, 2930
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2670, 2671, 2673, 2674, 2675, 2813, 2814, 2815, 2817, 2819, 2820, 2822, 2823, 2824, 2825, 2826, 2830, 2831, 2833, 2875, 2923, 2924, 2926, 2927, 2930
2816: 2817: while (1) 2818: { 2819: Loc loc = this->loc; 2820: TemplateParameters *tpl = NULL; 2821: 2822: ident = NULL; 2823: t = parseDeclarator(ts, &ident, &tpl, storage_class); 2824: assert(t); 2825: if (!tfirst) 2826: tfirst = t; 2827: else if (t != tfirst) 2828: error("multiple declarations must have the same type, not %s and %s", 2829: tfirst->toChars(), t->toChars()); 2830: if (!ident) 2831: error("no identifier for declarator %s", t->toChars()); 2832: 2833: if (tok == TOKtypedef || tok == TOKalias) 2834: { Declaration *v; 2835: Initializer *init = NULL; 2836: 2837: if (token.value == TOKassign) 2838: { 2839: nextToken(); 2840: init = parseInitializer(); 2841: } 2842: if (tok == TOKtypedef) 2843: v = new TypedefDeclaration(loc, ident, t, init); 2844: else 2845: { if (init) 2846: error("alias cannot have initializer"); 2847: v = new AliasDeclaration(loc, ident, t); 2848: } 2849: v->storage_class = storage_class; 2850: if (link == linkage) 2851: a->push(v); 2852: else 2853: { 2854: Dsymbols *ax = new Dsymbols(); 2855: ax->push(v); 2856: Dsymbol *s = new LinkDeclaration(link, ax); 2857: a->push(s); 2858: } 2859: switch (token.value) 2860: { case TOKsemicolon: 2861: nextToken(); 2862: addComment(v, comment); 2863: break; 2864: 2865: case TOKcomma: 2866: nextToken(); 2867: addComment(v, comment); 2868: continue; 2869: 2870: default: 2871: error("semicolon expected to close %s declaration", Token::toChars(tok)); 2872: break; 2873: } 2874: } 2875: else if (t->ty == Tfunction) 2876: { 2877: TypeFunction *tf = (TypeFunction *)t; 2878: Expression *constraint = NULL; 2879: #if 0 2880: if (Parameter::isTPL(tf->parameters)) 2881: { 2882: if (!tpl) 2883: tpl = new TemplateParameters(); 2884: } 2885: #endif 2886: 2887: //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t->toChars(), storage_class); 2888: 2889: FuncDeclaration *f = 2890: new FuncDeclaration(loc, 0, ident, storage_class, t); 2891: addComment(f, comment); 2892: if (tpl) 2893: constraint = parseConstraint(); 2894: parseContracts(f); 2895: addComment(f, NULL); 2896: Dsymbol *s; 2897: if (link == linkage) 2898: { 2899: s = f; 2900: } 2901: else 2902: { 2903: Dsymbols *ax = new Dsymbols(); 2904: ax->push(f); 2905: s = new LinkDeclaration(link, ax); 2906: } 2907: /* A template parameter list means it's a function template 2908: */ 2909: if (tpl) 2910: { 2911: // Wrap a template around the function declaration 2912: Dsymbols *decldefs = new Dsymbols(); 2913: decldefs->push(s); 2914: TemplateDeclaration *tempdecl = 2915: new TemplateDeclaration(loc, s->ident, tpl, constraint, decldefs, 0); 2916: s = tempdecl; 2917: } 2918: addComment(s, comment); 2919: a->push(s); 2920: } 2921: else 2922: { 2923: Initializer *init = NULL; 2924: if (token.value == TOKassign) 2925: { 2926: nextToken(); 2927: init = parseInitializer(); 2928: } 2929: 2930: VarDeclaration *v = new VarDeclaration(loc, t, ident, init); 2931: v->storage_class = storage_class; 2932: if (link == linkage) 2933: a->push(v); 2934: else 2935: { 2936: Dsymbols *ax = new Dsymbols(); 2937: ax->push(v); 2938: Dsymbol *s = new LinkDeclaration(link, ax); 2939: a->push(s); 2940: } 2941: switch (token.value) 2942: { case TOKsemicolon: 2943: nextToken(); 2944: addComment(v, comment); 2945: break; 2946: 2947: case TOKcomma: 2948: nextToken(); 2949: addComment(v, comment); 2950: continue; 2951: 2952: default: 2953: error("semicolon expected, not '%s'", token.toChars()); 2954: break; 2955: } 2956: } 2957: break; 2958: } 2959: return a; 2960: } 2961: 2962: /***************************************** 2963: * Parse auto declarations of the form: 2964: * storageClass ident = init, ident = init, ... ; 2965: * and return the array of them. 2966: * Starts with token on the first ident. 2967: * Ends with scanner past closing ';' 2968: */ 2969: 2970: #if DMDV2 2971: Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, unsigned char *comment) 2972: { 2973: Dsymbols *a = new Dsymbols;
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 2973, 2975, 2977, 2978, 2979, 2980, 2981, 2982
2974: 2975: while (1) 2976: { 2977: Identifier *ident = token.ident; 2978: nextToken(); // skip over ident 2979: assert(token.value == TOKassign); 2980: nextToken(); // skip over '=' 2981: Initializer *init = parseInitializer(); 2982: VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init); 2983: v->storage_class = storageClass; 2984: a->push(v); 2985: if (token.value == TOKsemicolon) 2986: { 2987: nextToken(); 2988: addComment(v, comment); 2989: } 2990: else if (token.value == TOKcomma) 2991: { 2992: nextToken(); 2993: if (token.value == TOKidentifier && 2994: peek(&token)->value == TOKassign) 2995: { 2996: addComment(v, comment); 2997: continue; 2998: } 2999: else 3000: error("Identifier expected following comma"); 3001: } 3002: else 3003: error("semicolon expected following auto declaration, not '%s'", token.toChars()); 3004: break; 3005: } 3006: return a; 3007: } 3008: #endif 3009: 3010: /***************************************** 3011: * Parse contracts following function declaration. 3012: */ 3013: 3014: void Parser::parseContracts(FuncDeclaration *f) 3015: { 3016: enum LINK linksave = linkage; 3017: 3018: // The following is irrelevant, as it is overridden by sc->linkage in 3019: // TypeFunction::semantic 3020: linkage = LINKd; // nested functions have D linkage 3021: L1: 3022: switch (token.value) 3023: { 3024: case TOKlcurly: 3025: if (f->frequire || f->fensure) 3026: error("missing body { ... } after in or out"); 3027: f->fbody = parseStatement(PSsemi); 3028: f->endloc = endloc; 3029: break; 3030: 3031: case TOKbody: 3032: nextToken(); 3033: f->fbody = parseStatement(PScurly); 3034: f->endloc = endloc; 3035: break; 3036: 3037: case TOKsemicolon: 3038: if (f->frequire || f->fensure) 3039: error("missing body { ... } after in or out"); 3040: nextToken(); 3041: break; 3042: 3043: #if 0 // Do we want this for function declarations, so we can do: 3044: // int x, y, foo(), z; 3045: case TOKcomma: 3046: nextToken(); 3047: continue; 3048: #endif 3049: 3050: #if 0 // Dumped feature 3051: case TOKthrow: 3052: if (!f->fthrows) 3053: f->fthrows = new Types(); 3054: nextToken(); 3055: check(TOKlparen); 3056: while (1) 3057: { 3058: Type *tb = parseBasicType(); 3059: f->fthrows->push(tb); 3060: if (token.value == TOKcomma) 3061: { nextToken(); 3062: continue; 3063: } 3064: break; 3065: } 3066: check(TOKrparen); 3067: goto L1; 3068: #endif 3069: 3070: case TOKin: 3071: nextToken(); 3072: if (f->frequire) 3073: error("redundant 'in' statement"); 3074: f->frequire = parseStatement(PScurly | PSscope); 3075: goto L1; 3076: 3077: case TOKout: 3078: // parse: out (identifier) { statement } 3079: nextToken(); 3080: if (token.value != TOKlcurly) 3081: { 3082: check(TOKlparen); 3083: if (token.value != TOKidentifier) 3084: error("(identifier) following 'out' expected, not %s", token.toChars()); 3085: f->outId = token.ident; 3086: nextToken(); 3087: check(TOKrparen); 3088: } 3089: if (f->fensure) 3090: error("redundant 'out' statement"); 3091: f->fensure = parseStatement(PScurly | PSscope); 3092: goto L1; 3093: 3094: default: 3095: if (!f->frequire && !f->fensure) // allow these even with no body 3096: error("semicolon expected following function declaration"); 3097: break; 3098: } 3099: linkage = linksave; 3100: } 3101: 3102: /***************************************** 3103: * Parse initializer for variable declaration. 3104: */ 3105: 3106: Initializer *Parser::parseInitializer() 3107: { 3108: StructInitializer *is; 3109: ArrayInitializer *ia; 3110: ExpInitializer *ie; 3111: Expression *e; 3112: Identifier *id; 3113: Initializer *value; 3114: int comma; 3115: Loc loc = this->loc; 3116: Token *t; 3117: int braces; 3118: int brackets; 3119: 3120: switch (token.value) 3121: { 3122: case TOKlcurly: 3123: /* Scan ahead to see if it is a struct initializer or 3124: * a function literal. 3125: * If it contains a ';', it is a function literal. 3126: * Treat { } as a struct initializer. 3127: */ 3128: braces = 1; 3129: for (t = peek(&token); 1; t = peek(t)) 3130: { 3131: switch (t->value) 3132: { 3133: case TOKsemicolon: 3134: case TOKreturn: 3135: goto Lexpression; 3136: 3137: case TOKlcurly: 3138: braces++; 3139: continue; 3140: 3141: case TOKrcurly: 3142: if (--braces == 0) 3143: break; 3144: continue; 3145: 3146: case TOKeof: 3147: break; 3148: 3149: default: 3150: continue; 3151: } 3152: break; 3153: } 3154: 3155: is = new StructInitializer(loc); 3156: nextToken(); 3157: comma = 0; 3158: while (1) 3159: { 3160: switch (token.value) 3161: { 3162: case TOKidentifier: 3163: if (comma == 1) 3164: error("comma expected separating field initializers"); 3165: t = peek(&token); 3166: if (t->value == TOKcolon) 3167: { 3168: id = token.ident; 3169: nextToken(); 3170: nextToken(); // skip over ':' 3171: } 3172: else 3173: { id = NULL; 3174: } 3175: value = parseInitializer(); 3176: is->addInit(id, value); 3177: comma = 1; 3178: continue; 3179: 3180: case TOKcomma: 3181: nextToken(); 3182: comma = 2; 3183: continue; 3184: 3185: case TOKrcurly: // allow trailing comma's 3186: nextToken(); 3187: break; 3188: 3189: case TOKeof: 3190: error("found EOF instead of initializer"); 3191: break; 3192: 3193: default: 3194: if (comma == 1) 3195: error("comma expected separating field initializers"); 3196: value = parseInitializer(); 3197: is->addInit(NULL, value); 3198: comma = 1; 3199: continue; 3200: //error("found '%s' instead of field initializer", token.toChars()); 3201: //break; 3202: } 3203: break; 3204: } 3205: return is; 3206: 3207: case TOKlbracket: 3208: /* Scan ahead to see if it is an array initializer or 3209: * an expression. 3210: * If it ends with a ';' ',' or '}', it is an array initializer. 3211: */ 3212: brackets = 1; 3213: for (t = peek(&token); 1; t = peek(t)) 3214: { 3215: switch (t->value) 3216: { 3217: case TOKlbracket: 3218: brackets++; 3219: continue; 3220: 3221: case TOKrbracket: 3222: if (--brackets == 0) 3223: { t = peek(t); 3224: if (t->value != TOKsemicolon && 3225: t->value != TOKcomma && 3226: t->value != TOKrbracket && 3227: t->value != TOKrcurly) 3228: goto Lexpression; 3229: break; 3230: } 3231: continue; 3232: 3233: case TOKeof: 3234: break; 3235: 3236: default: 3237: continue; 3238: } 3239: break; 3240: } 3241: 3242: ia = new ArrayInitializer(loc); 3243: nextToken(); 3244: comma = 0; 3245: while (1) 3246: { 3247: switch (token.value) 3248: { 3249: default: 3250: if (comma == 1) 3251: { error("comma expected separating array initializers, not %s", token.toChars()); 3252: nextToken(); 3253: break; 3254: } 3255: e = parseAssignExp(); 3256: if (!e) 3257: break; 3258: if (token.value == TOKcolon) 3259: { 3260: nextToken(); 3261: value = parseInitializer(); 3262: } 3263: else 3264: { value = new ExpInitializer(e->loc, e); 3265: e = NULL; 3266: } 3267: ia->addInit(e, value); 3268: comma = 1; 3269: continue; 3270: 3271: case TOKlcurly: 3272: case TOKlbracket: 3273: if (comma == 1) 3274: error("comma expected separating array initializers, not %s", token.toChars()); 3275: value = parseInitializer(); 3276: ia->addInit(NULL, value); 3277: comma = 1; 3278: continue; 3279: 3280: case TOKcomma: 3281: nextToken(); 3282: comma = 2; 3283: continue; 3284: 3285: case TOKrbracket: // allow trailing comma's 3286: nextToken(); 3287: break; 3288: 3289: case TOKeof: 3290: error("found '%s' instead of array initializer", token.toChars()); 3291: break; 3292: } 3293: break; 3294: } 3295: return ia; 3296: 3297: case TOKvoid: 3298: t = peek(&token); 3299: if (t->value == TOKsemicolon || t->value == TOKcomma) 3300: { 3301: nextToken(); 3302: return new VoidInitializer(loc); 3303: } 3304: goto Lexpression; 3305: 3306: default: 3307: Lexpression: 3308: e = parseAssignExp(); 3309: ie = new ExpInitializer(loc, e); 3310: return ie; 3311: } 3312: } 3313: 3314: /***************************************** 3315: * Parses default argument initializer expression that is an assign expression, 3316: * with special handling for __FILE__ and __LINE__. 3317: */ 3318: 3319: #if DMDV2 3320: Expression *Parser::parseDefaultInitExp() 3321: { 3322: if (token.value == TOKfile || 3323: token.value == TOKline) 3324: { 3325: Token *t = peek(&token); 3326: if (t->value == TOKcomma || t->value == TOKrparen) 3327: { Expression *e; 3328: 3329: if (token.value == TOKfile) 3330: e = new FileInitExp(loc); 3331: else 3332: e = new LineInitExp(loc); 3333: nextToken(); 3334: return e; 3335: } 3336: } 3337: 3338: Expression *e = parseAssignExp(); 3339: return e; 3340: } 3341: #endif 3342: 3343: /***************************************** 3344: * Input: 3345: * flags PSxxxx 3346: */ 3347: 3348: Statement *Parser::parseStatement(int flags) 3349: { Statement *s; 3350: Token *t; 3351: Condition *condition; 3352: Statement *ifbody; 3353: Statement *elsebody; 3354: bool isfinal; 3355: Loc loc = this->loc; 3356: 3357: //printf("parseStatement()\n"); 3358: 3359: if (flags & PScurly && token.value != TOKlcurly) 3360: error("statement expected to be { }, not %s", token.toChars()); 3361: 3362: switch (token.value) 3363: { 3364: case TOKidentifier: 3365: /* A leading identifier can be a declaration, label, or expression. 3366: * The easiest case to check first is label: 3367: */ 3368: t = peek(&token); 3369: if (t->value == TOKcolon) 3370: { // It's a label 3371: 3372: Identifier *ident = token.ident; 3373: nextToken(); 3374: nextToken(); 3375: s = parseStatement(PSsemi); 3376: s = new LabelStatement(loc, ident, s); 3377: break; 3378: } 3379: // fallthrough to TOKdot 3380: case TOKdot: 3381: case TOKtypeof: 3382: if (isDeclaration(&token, 2, TOKreserved, NULL)) 3383: goto Ldeclaration; 3384: else 3385: goto Lexp; 3386: break; 3387: 3388: case TOKassert: 3389: case TOKthis: 3390: case TOKsuper: 3391: case TOKint32v: 3392: case TOKuns32v: 3393: case TOKint64v: 3394: case TOKuns64v: 3395: case TOKfloat32v: 3396: case TOKfloat64v: 3397: case TOKfloat80v: 3398: case TOKimaginary32v: 3399: case TOKimaginary64v: 3400: case TOKimaginary80v: 3401: case TOKcharv: 3402: case TOKwcharv: 3403: case TOKdcharv: 3404: case TOKnull: 3405: case TOKtrue: 3406: case TOKfalse: 3407: case TOKstring: 3408: case TOKlparen: 3409: case TOKcast: 3410: case TOKmul: 3411: case TOKmin: 3412: case TOKadd: 3413: case TOKtilde: 3414: case TOKnot: 3415: case TOKplusplus: 3416: case TOKminusminus: 3417: case TOKnew: 3418: case TOKdelete: 3419: case TOKdelegate: 3420: case TOKfunction: 3421: case TOKtypeid: 3422: case TOKis: 3423: case TOKlbracket: 3424: #if DMDV2 3425: case TOKtraits: 3426: case TOKfile: 3427: case TOKline: 3428: #endif 3429: Lexp: 3430: { 3431: Expression *exp = parseExpression(); 3432: check(TOKsemicolon, "statement"); 3433: s = new ExpStatement(loc, exp); 3434: break; 3435: } 3436: 3437: case TOKstatic: 3438: { // Look ahead to see if it's static assert() or static if() 3439: 3440: Token *t = peek(&token);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3441: if (t->value == TOKassert) 3442: { 3443: nextToken(); 3444: s = new StaticAssertStatement(parseStaticAssert()); 3445: break; 3446: } 3447: if (t->value == TOKif) 3448: { 3449: nextToken(); 3450: condition = parseStaticIfCondition(); 3451: goto Lcondition; 3452: } 3453: if (t->value == TOKstruct || t->value == TOKunion || t->value == TOKclass) 3454: { 3455: nextToken(); 3456: Dsymbols *a = parseBlock(); 3457: Dsymbol *d = new StorageClassDeclaration(STCstatic, a); 3458: s = new ExpStatement(loc, d); 3459: if (flags & PSscope) 3460: s = new ScopeStatement(loc, s); 3461: break; 3462: } 3463: if (t->value == TOKimport) 3464: { nextToken(); 3465: Dsymbols *imports = new Dsymbols(); 3466: parseImport(imports, 1); // static import ... 3467: s = new ImportStatement(loc, imports); 3468: break; 3469: } 3470: goto Ldeclaration; 3471: } 3472: 3473: case TOKfinal: 3474: if (peekNext() == TOKswitch) 3475: { 3476: nextToken(); 3477: isfinal = TRUE; 3478: goto Lswitch; 3479: } 3480: goto Ldeclaration; 3481: 3482: case BASIC_TYPES: 3483: case TOKtypedef: 3484: case TOKalias: 3485: case TOKconst: 3486: case TOKauto: 3487: case TOKextern: 3488: case TOKinvariant: 3489: #if DMDV2 3490: case TOKimmutable: 3491: case TOKshared: 3492: case TOKwild: 3493: case TOKnothrow: 3494: case TOKpure: 3495: case TOKref: 3496: case TOKtls: 3497: case TOKgshared: 3498: case TOKat: 3499: #endif 3500: // case TOKtypeof: 3501: Ldeclaration: 3502: { Dsymbols *a; 3503: 3504: a = parseDeclarations(STCundefined, NULL); 3505: if (a->dim > 1) 3506: { 3507: Statements *as = new Statements();
warning C6211: Leaking memory 'as' due to an exception. Consider using a local catch block to clean up memory: Lines: 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3359, 3362, 3364, 3368, 3369, 3380, 3381, 3382, 3383, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3501, 3502, 3504, 3505, 3507, 3508, 3509, 3511, 3512
3508: as->reserve(a->dim); 3509: for (int i = 0; i < a->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
3510: { 3511: Dsymbol *d = a->tdata()[i]; 3512: s = new ExpStatement(loc, d); 3513: as->push(s); 3514: } 3515: s = new CompoundDeclarationStatement(loc, as); 3516: } 3517: else if (a->dim == 1) 3518: { 3519: Dsymbol *d = a->tdata()[0]; 3520: s = new ExpStatement(loc, d); 3521: } 3522: else 3523: assert(0); 3524: if (flags & PSscope) 3525: s = new ScopeStatement(loc, s); 3526: break; 3527: } 3528: 3529: case TOKstruct: 3530: case TOKunion: 3531: case TOKclass: 3532: case TOKinterface: 3533: { Dsymbol *d; 3534: 3535: d = parseAggregate(); 3536: s = new ExpStatement(loc, d); 3537: break; 3538: } 3539: 3540: case TOKenum: 3541: { /* Determine if this is a manifest constant declaration, 3542: * or a conventional enum. 3543: */ 3544: Dsymbol *d; 3545: Token *t = peek(&token);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3546: if (t->value == TOKlcurly || t->value == TOKcolon) 3547: d = parseEnum(); 3548: else if (t->value != TOKidentifier) 3549: goto Ldeclaration; 3550: else 3551: { 3552: t = peek(t); 3553: if (t->value == TOKlcurly || t->value == TOKcolon || 3554: t->value == TOKsemicolon) 3555: d = parseEnum(); 3556: else 3557: goto Ldeclaration; 3558: } 3559: s = new ExpStatement(loc, d); 3560: break; 3561: } 3562: 3563: case TOKmixin: 3564: { t = peek(&token); 3565: if (t->value == TOKlparen) 3566: { // mixin(string) 3567: Expression *e = parseAssignExp(); 3568: check(TOKsemicolon); 3569: if (e->op == TOKmixin) 3570: { 3571: CompileExp *cpe = (CompileExp *)e; 3572: s = new CompileStatement(loc, cpe->e1); 3573: } 3574: else 3575: { 3576: s = new ExpStatement(loc, e); 3577: } 3578: break; 3579: } 3580: Dsymbol *d = parseMixin(); 3581: s = new ExpStatement(loc, d); 3582: break; 3583: } 3584: 3585: case TOKlcurly: 3586: { 3587: nextToken(); 3588: //if (token.value == TOKsemicolon) 3589: //error("use '{ }' for an empty statement, not a ';'"); 3590: Statements *statements = new Statements(); 3591: while (token.value != TOKrcurly && token.value != TOKeof) 3592: { 3593: statements->push(parseStatement(PSsemi | PScurlyscope)); 3594: } 3595: endloc = this->loc; 3596: s = new CompoundStatement(loc, statements); 3597: if (flags & (PSscope | PScurlyscope)) 3598: s = new ScopeStatement(loc, s); 3599: check(TOKrcurly, "compound statement"); 3600: break; 3601: } 3602: 3603: case TOKwhile: 3604: { Expression *condition;
warning C6246: Local declaration of 'condition' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3351' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3351
3605: Statement *body; 3606: 3607: nextToken(); 3608: check(TOKlparen); 3609: condition = parseExpression(); 3610: check(TOKrparen); 3611: body = parseStatement(PSscope); 3612: s = new WhileStatement(loc, condition, body); 3613: break; 3614: } 3615: 3616: case TOKsemicolon: 3617: if (!(flags & PSsemi)) 3618: error("use '{ }' for an empty statement, not a ';'"); 3619: nextToken(); 3620: s = new ExpStatement(loc, (Expression *)NULL); 3621: break; 3622: 3623: case TOKdo: 3624: { Statement *body; 3625: Expression *condition;
warning C6246: Local declaration of 'condition' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3351' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3351
3626: 3627: nextToken(); 3628: body = parseStatement(PSscope); 3629: check(TOKwhile); 3630: check(TOKlparen); 3631: condition = parseExpression(); 3632: check(TOKrparen); 3633: s = new DoStatement(loc, body, condition); 3634: break; 3635: } 3636: 3637: case TOKfor: 3638: { 3639: Statement *init; 3640: Expression *condition;
warning C6246: Local declaration of 'condition' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3351' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3351
3641: Expression *increment; 3642: Statement *body; 3643: 3644: nextToken(); 3645: check(TOKlparen); 3646: if (token.value == TOKsemicolon) 3647: { init = NULL; 3648: nextToken(); 3649: } 3650: else 3651: { init = parseStatement(0); 3652: } 3653: if (token.value == TOKsemicolon) 3654: { 3655: condition = NULL; 3656: nextToken(); 3657: } 3658: else 3659: { 3660: condition = parseExpression(); 3661: check(TOKsemicolon, "for condition"); 3662: } 3663: if (token.value == TOKrparen) 3664: { increment = NULL; 3665: nextToken(); 3666: } 3667: else 3668: { increment = parseExpression(); 3669: check(TOKrparen); 3670: } 3671: body = parseStatement(PSscope); 3672: s = new ForStatement(loc, init, condition, increment, body); 3673: if (init) 3674: s = new ScopeStatement(loc, s); 3675: break; 3676: } 3677: 3678: case TOKforeach: 3679: case TOKforeach_reverse: 3680: { 3681: enum TOK op = token.value; 3682: 3683: nextToken(); 3684: check(TOKlparen); 3685: 3686: Parameters *arguments = new Parameters(); 3687: 3688: while (1) 3689: { 3690: Identifier *ai = NULL; 3691: Type *at; 3692: 3693: StorageClass storageClass = 0; 3694: if (token.value == TOKref 3695: #if D1INOUT 3696: || token.value == TOKinout 3697: #endif 3698: ) 3699: { storageClass = STCref; 3700: nextToken(); 3701: } 3702: if (token.value == TOKidentifier) 3703: { 3704: Token *t = peek(&token);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3705: if (t->value == TOKcomma || t->value == TOKsemicolon) 3706: { ai = token.ident; 3707: at = NULL; // infer argument type 3708: nextToken(); 3709: goto Larg; 3710: } 3711: } 3712: at = parseType(&ai); 3713: if (!ai) 3714: error("no identifier for declarator %s", at->toChars()); 3715: Larg: 3716: Parameter *a = new Parameter(storageClass, at, ai, NULL); 3717: arguments->push(a); 3718: if (token.value == TOKcomma) 3719: { nextToken(); 3720: continue; 3721: } 3722: break; 3723: } 3724: check(TOKsemicolon); 3725: 3726: Expression *aggr = parseExpression(); 3727: if (token.value == TOKslice && arguments->dim == 1) 3728: { 3729: Parameter *a = arguments->tdata()[0]; 3730: delete arguments; 3731: nextToken(); 3732: Expression *upr = parseExpression(); 3733: check(TOKrparen); 3734: Statement *body = parseStatement(0); 3735: s = new ForeachRangeStatement(loc, op, a, aggr, upr, body); 3736: } 3737: else 3738: { 3739: check(TOKrparen); 3740: Statement *body = parseStatement(0); 3741: s = new ForeachStatement(loc, op, arguments, aggr, body); 3742: } 3743: break; 3744: } 3745: 3746: case TOKif: 3747: { Parameter *arg = NULL; 3748: Expression *condition;
warning C6246: Local declaration of 'condition' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3351' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3351
3749: Statement *ifbody;
warning C6246: Local declaration of 'ifbody' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3352' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3352
3750: Statement *elsebody;
warning C6246: Local declaration of 'elsebody' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3353' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3353
3751: 3752: nextToken(); 3753: check(TOKlparen); 3754: 3755: if (token.value == TOKauto) 3756: { 3757: nextToken(); 3758: if (token.value == TOKidentifier) 3759: { 3760: Token *t = peek(&token);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3761: if (t->value == TOKassign) 3762: { 3763: arg = new Parameter(0, NULL, token.ident, NULL); 3764: nextToken(); 3765: nextToken(); 3766: } 3767: else 3768: { error("= expected following auto identifier"); 3769: goto Lerror; 3770: } 3771: } 3772: else 3773: { error("identifier expected following auto"); 3774: goto Lerror; 3775: } 3776: } 3777: else if (isDeclaration(&token, 2, TOKassign, NULL)) 3778: { 3779: Type *at; 3780: Identifier *ai; 3781: 3782: at = parseType(&ai); 3783: check(TOKassign); 3784: arg = new Parameter(0, at, ai, NULL); 3785: } 3786: 3787: // Check for " ident;" 3788: else if (token.value == TOKidentifier) 3789: { 3790: Token *t = peek(&token);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3791: if (t->value == TOKcomma || t->value == TOKsemicolon) 3792: { 3793: arg = new Parameter(0, NULL, token.ident, NULL); 3794: nextToken(); 3795: nextToken(); 3796: if (1 || !global.params.useDeprecated) 3797: error("if (v; e) is deprecated, use if (auto v = e)"); 3798: } 3799: } 3800: 3801: condition = parseExpression(); 3802: check(TOKrparen); 3803: ifbody = parseStatement(PSscope); 3804: if (token.value == TOKelse) 3805: { 3806: nextToken(); 3807: elsebody = parseStatement(PSscope); 3808: } 3809: else 3810: elsebody = NULL; 3811: if (condition && ifbody) 3812: s = new IfStatement(loc, arg, condition, ifbody, elsebody); 3813: else 3814: s = NULL; // don't propagate parsing errors 3815: break; 3816: } 3817: 3818: case TOKscope: 3819: if (peek(&token)->value != TOKlparen) 3820: goto Ldeclaration; // scope used as storage class 3821: nextToken(); 3822: check(TOKlparen); 3823: if (token.value != TOKidentifier) 3824: { error("scope identifier expected"); 3825: goto Lerror; 3826: } 3827: else 3828: { TOK t = TOKon_scope_exit;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
3829: Identifier *id = token.ident; 3830: 3831: if (id == Id::exit) 3832: t = TOKon_scope_exit; 3833: else if (id == Id::failure) 3834: t = TOKon_scope_failure; 3835: else if (id == Id::success) 3836: t = TOKon_scope_success; 3837: else 3838: error("valid scope identifiers are exit, failure, or success, not %s", id->toChars()); 3839: nextToken(); 3840: check(TOKrparen); 3841: Statement *st = parseStatement(PScurlyscope); 3842: s = new OnScopeStatement(loc, t, st); 3843: break; 3844: } 3845: 3846: case TOKdebug: 3847: nextToken(); 3848: condition = parseDebugCondition(); 3849: goto Lcondition; 3850: 3851: case TOKversion: 3852: nextToken(); 3853: condition = parseVersionCondition(); 3854: goto Lcondition; 3855: 3856: Lcondition: 3857: ifbody = parseStatement(0 /*PSsemi*/); 3858: elsebody = NULL; 3859: if (token.value == TOKelse) 3860: { 3861: nextToken(); 3862: elsebody = parseStatement(0 /*PSsemi*/); 3863: } 3864: s = new ConditionalStatement(loc, condition, ifbody, elsebody); 3865: break; 3866: 3867: case TOKpragma: 3868: { Identifier *ident; 3869: Expressions *args = NULL; 3870: Statement *body; 3871: 3872: nextToken(); 3873: check(TOKlparen); 3874: if (token.value != TOKidentifier) 3875: { error("pragma(identifier expected"); 3876: goto Lerror; 3877: } 3878: ident = token.ident; 3879: nextToken(); 3880: if (token.value == TOKcomma && peekNext() != TOKrparen) 3881: args = parseArguments(); // pragma(identifier, args...); 3882: else 3883: check(TOKrparen); // pragma(identifier); 3884: if (token.value == TOKsemicolon) 3885: { nextToken(); 3886: body = NULL; 3887: } 3888: else 3889: body = parseStatement(PSsemi); 3890: s = new PragmaStatement(loc, ident, args, body); 3891: break; 3892: } 3893: 3894: case TOKswitch: 3895: isfinal = FALSE; 3896: goto Lswitch; 3897: 3898: Lswitch: 3899: { 3900: nextToken(); 3901: check(TOKlparen); 3902: Expression *condition = parseExpression();
warning C6246: Local declaration of 'condition' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3351' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3351
3903: check(TOKrparen); 3904: Statement *body = parseStatement(PSscope); 3905: s = new SwitchStatement(loc, condition, body, isfinal); 3906: break; 3907: } 3908: 3909: case TOKcase: 3910: { Expression *exp; 3911: Statements *statements; 3912: Expressions cases; // array of Expression's 3913: Expression *last = NULL; 3914: 3915: while (1) 3916: { 3917: nextToken(); 3918: exp = parseAssignExp(); 3919: cases.push(exp); 3920: if (token.value != TOKcomma) 3921: break; 3922: } 3923: check(TOKcolon); 3924: 3925: #if DMDV2 3926: /* case exp: .. case last: 3927: */ 3928: if (token.value == TOKslice) 3929: { 3930: if (cases.dim > 1) 3931: error("only one case allowed for start of case range"); 3932: nextToken(); 3933: check(TOKcase); 3934: last = parseAssignExp(); 3935: check(TOKcolon); 3936: } 3937: #endif 3938: 3939: statements = new Statements(); 3940: while (token.value != TOKcase && 3941: token.value != TOKdefault && 3942: token.value != TOKeof && 3943: token.value != TOKrcurly) 3944: { 3945: statements->push(parseStatement(PSsemi | PScurlyscope)); 3946: } 3947: s = new CompoundStatement(loc, statements); 3948: s = new ScopeStatement(loc, s); 3949: 3950: #if DMDV2 3951: if (last) 3952: { 3953: s = new CaseRangeStatement(loc, exp, last, s); 3954: } 3955: else 3956: #endif 3957: { 3958: // Keep cases in order by building the case statements backwards 3959: for (int i = cases.dim; i; i--) 3960: { 3961: exp = cases.tdata()[i - 1]; 3962: s = new CaseStatement(loc, exp, s); 3963: } 3964: } 3965: break; 3966: } 3967: 3968: case TOKdefault: 3969: { 3970: Statements *statements; 3971: 3972: nextToken(); 3973: check(TOKcolon); 3974: 3975: statements = new Statements(); 3976: while (token.value != TOKcase && 3977: token.value != TOKdefault && 3978: token.value != TOKeof && 3979: token.value != TOKrcurly) 3980: { 3981: statements->push(parseStatement(PSsemi | PScurlyscope)); 3982: } 3983: s = new CompoundStatement(loc, statements); 3984: s = new ScopeStatement(loc, s); 3985: s = new DefaultStatement(loc, s); 3986: break; 3987: } 3988: 3989: case TOKreturn: 3990: { Expression *exp; 3991: 3992: nextToken(); 3993: if (token.value == TOKsemicolon) 3994: exp = NULL; 3995: else 3996: exp = parseExpression(); 3997: check(TOKsemicolon, "return statement"); 3998: s = new ReturnStatement(loc, exp); 3999: break; 4000: } 4001: 4002: case TOKbreak: 4003: { Identifier *ident; 4004: 4005: nextToken(); 4006: if (token.value == TOKidentifier) 4007: { ident = token.ident; 4008: nextToken(); 4009: } 4010: else 4011: ident = NULL; 4012: check(TOKsemicolon, "break statement"); 4013: s = new BreakStatement(loc, ident); 4014: break; 4015: } 4016: 4017: case TOKcontinue: 4018: { Identifier *ident; 4019: 4020: nextToken(); 4021: if (token.value == TOKidentifier) 4022: { ident = token.ident; 4023: nextToken(); 4024: } 4025: else 4026: ident = NULL; 4027: check(TOKsemicolon, "continue statement"); 4028: s = new ContinueStatement(loc, ident); 4029: break; 4030: } 4031: 4032: case TOKgoto: 4033: { Identifier *ident; 4034: 4035: nextToken(); 4036: if (token.value == TOKdefault) 4037: { 4038: nextToken(); 4039: s = new GotoDefaultStatement(loc); 4040: } 4041: else if (token.value == TOKcase) 4042: { 4043: Expression *exp = NULL; 4044: 4045: nextToken(); 4046: if (token.value != TOKsemicolon) 4047: exp = parseExpression(); 4048: s = new GotoCaseStatement(loc, exp); 4049: } 4050: else 4051: { 4052: if (token.value != TOKidentifier) 4053: { error("Identifier expected following goto"); 4054: ident = NULL; 4055: } 4056: else 4057: { ident = token.ident; 4058: nextToken(); 4059: } 4060: s = new GotoStatement(loc, ident); 4061: } 4062: check(TOKsemicolon, "goto statement"); 4063: break; 4064: } 4065: 4066: case TOKsynchronized: 4067: { Expression *exp; 4068: Statement *body; 4069: 4070: nextToken(); 4071: if (token.value == TOKlparen) 4072: { 4073: nextToken(); 4074: exp = parseExpression(); 4075: check(TOKrparen); 4076: } 4077: else 4078: exp = NULL; 4079: body = parseStatement(PSscope); 4080: s = new SynchronizedStatement(loc, exp, body); 4081: break; 4082: } 4083: 4084: case TOKwith: 4085: { Expression *exp; 4086: Statement *body; 4087: 4088: nextToken(); 4089: check(TOKlparen); 4090: exp = parseExpression(); 4091: check(TOKrparen); 4092: body = parseStatement(PSscope); 4093: s = new WithStatement(loc, exp, body); 4094: break; 4095: } 4096: 4097: case TOKtry: 4098: { Statement *body; 4099: Catches *catches = NULL; 4100: Statement *finalbody = NULL; 4101: 4102: nextToken(); 4103: body = parseStatement(PSscope); 4104: while (token.value == TOKcatch) 4105: { 4106: Statement *handler; 4107: Catch *c; 4108: Type *t;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3350' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3350
4109: Identifier *id; 4110: Loc loc = this->loc;
warning C6246: Local declaration of 'loc' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3355' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 3355
4111: 4112: nextToken(); 4113: if (token.value == TOKlcurly) 4114: { 4115: t = NULL; 4116: id = NULL; 4117: } 4118: else 4119: { 4120: check(TOKlparen); 4121: id = NULL; 4122: t = parseType(&id); 4123: check(TOKrparen); 4124: } 4125: handler = parseStatement(0); 4126: c = new Catch(loc, t, id, handler); 4127: if (!catches) 4128: catches = new Catches(); 4129: catches->push(c); 4130: } 4131: 4132: if (token.value == TOKfinally) 4133: { nextToken(); 4134: finalbody = parseStatement(0); 4135: } 4136: 4137: s = body; 4138: if (!catches && !finalbody) 4139: error("catch or finally expected following try"); 4140: else 4141: { if (catches) 4142: s = new TryCatchStatement(loc, body, catches); 4143: if (finalbody) 4144: s = new TryFinallyStatement(loc, s, finalbody); 4145: } 4146: break; 4147: } 4148: 4149: case TOKthrow: 4150: { Expression *exp; 4151: 4152: nextToken(); 4153: exp = parseExpression(); 4154: check(TOKsemicolon, "throw statement"); 4155: s = new ThrowStatement(loc, exp); 4156: break; 4157: } 4158: 4159: case TOKvolatile: 4160: nextToken(); 4161: s = parseStatement(PSsemi | PScurlyscope); 4162: #if DMDV2 4163: if (!global.params.useDeprecated) 4164: error("volatile statements deprecated; used synchronized statements instead"); 4165: #endif 4166: s = new VolatileStatement(loc, s); 4167: break; 4168: 4169: case TOKasm: 4170: { Statements *statements; 4171: Identifier *label; 4172: Loc labelloc; 4173: Token *toklist; 4174: Token **ptoklist; 4175: 4176: // Parse the asm block into a sequence of AsmStatements, 4177: // each AsmStatement is one instruction. 4178: // Separate out labels. 4179: // Defer parsing of AsmStatements until semantic processing. 4180: 4181: nextToken(); 4182: check(TOKlcurly); 4183: toklist = NULL; 4184: ptoklist = &toklist; 4185: label = NULL; 4186: statements = new Statements(); 4187: while (1) 4188: { 4189: switch (token.value) 4190: { 4191: case TOKidentifier: 4192: if (!toklist) 4193: { 4194: // Look ahead to see if it is a label 4195: t = peek(&token); 4196: if (t->value == TOKcolon) 4197: { // It's a label 4198: label = token.ident; 4199: labelloc = this->loc; 4200: nextToken(); 4201: nextToken(); 4202: continue; 4203: } 4204: } 4205: goto Ldefault; 4206: 4207: case TOKrcurly: 4208: if (toklist || label) 4209: { 4210: error("asm statements must end in ';'"); 4211: } 4212: break; 4213: 4214: case TOKsemicolon: 4215: s = NULL; 4216: if (toklist || label) 4217: { // Create AsmStatement from list of tokens we've saved 4218: s = new AsmStatement(this->loc, toklist); 4219: toklist = NULL; 4220: ptoklist = &toklist; 4221: if (label) 4222: { s = new LabelStatement(labelloc, label, s); 4223: label = NULL; 4224: } 4225: statements->push(s); 4226: } 4227: nextToken(); 4228: continue; 4229: 4230: case TOKeof: 4231: /* { */ 4232: error("matching '}' expected, not end of file"); 4233: break; 4234: 4235: default: 4236: Ldefault: 4237: *ptoklist = new Token(); 4238: memcpy(*ptoklist, &token, sizeof(Token)); 4239: ptoklist = &(*ptoklist)->next; 4240: *ptoklist = NULL; 4241: 4242: nextToken(); 4243: continue; 4244: } 4245: break; 4246: } 4247: s = new CompoundStatement(loc, statements); 4248: nextToken(); 4249: break; 4250: } 4251: 4252: case TOKimport: 4253: { Dsymbols *imports = new Dsymbols(); 4254: parseImport(imports, 0); 4255: s = new ImportStatement(loc, imports); 4256: break; 4257: } 4258: 4259: default: 4260: error("found '%s' instead of statement", token.toChars()); 4261: goto Lerror; 4262: 4263: Lerror: 4264: while (token.value != TOKrcurly && 4265: token.value != TOKsemicolon && 4266: token.value != TOKeof) 4267: nextToken(); 4268: if (token.value == TOKsemicolon) 4269: nextToken(); 4270: s = NULL; 4271: break; 4272: } 4273: 4274: return s; 4275: } 4276: 4277: void Parser::check(enum TOK value) 4278: { 4279: check(loc, value); 4280: } 4281: 4282: void Parser::check(Loc loc, enum TOK value) 4283: { 4284: if (token.value != value) 4285: error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value)); 4286: nextToken(); 4287: } 4288: 4289: void Parser::check(enum TOK value, const char *string) 4290: { 4291: if (token.value != value) 4292: error("found '%s' when expecting '%s' following %s", 4293: token.toChars(), Token::toChars(value), string); 4294: nextToken(); 4295: } 4296: 4297: void Parser::checkParens(enum TOK value, Expression *e) 4298: { 4299: if (precedence[e->op] == PREC_rel && !e->parens) 4300: error(loc, "%s must be parenthesized when next to operator %s", e->toChars(), Token::toChars(value)); 4301: } 4302: 4303: /************************************ 4304: * Determine if the scanner is sitting on the start of a declaration. 4305: * Input: 4306: * needId 0 no identifier 4307: * 1 identifier optional 4308: * 2 must have identifier 4309: * Output: 4310: * if *pt is not NULL, it is set to the ending token, which would be endtok 4311: */ 4312: 4313: int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) 4314: { 4315: //printf("isDeclaration(needId = %d)\n", needId); 4316: int haveId = 0; 4317: 4318: #if DMDV2 4319: if ((t->value == TOKconst || 4320: t->value == TOKinvariant || 4321: t->value == TOKimmutable || 4322: t->value == TOKwild || 4323: t->value == TOKshared) && 4324: peek(t)->value != TOKlparen) 4325: { /* const type 4326: * immutable type 4327: * shared type 4328: * wild type 4329: */ 4330: t = peek(t); 4331: } 4332: #endif 4333: 4334: if (!isBasicType(&t)) 4335: { 4336: goto Lisnot; 4337: } 4338: if (!isDeclarator(&t, &haveId, endtok)) 4339: goto Lisnot; 4340: if ( needId == 1 || 4341: (needId == 0 && !haveId) || 4342: (needId == 2 && haveId)) 4343: { if (pt) 4344: *pt = t; 4345: goto Lis; 4346: } 4347: else 4348: goto Lisnot; 4349: 4350: Lis: 4351: //printf("\tis declaration, t = %s\n", t->toChars()); 4352: return TRUE; 4353: 4354: Lisnot: 4355: //printf("\tis not declaration\n"); 4356: return FALSE; 4357: } 4358: 4359: int Parser::isBasicType(Token **pt) 4360: { 4361: // This code parallels parseBasicType() 4362: Token *t = *pt; 4363: Token *t2;
warning C4101: 't2' : unreferenced local variable
4364: int parens;
warning C4101: 'parens' : unreferenced local variable
4365: int haveId = 0; 4366: 4367: switch (t->value) 4368: { 4369: case BASIC_TYPES: 4370: t = peek(t); 4371: break; 4372: 4373: case TOKidentifier: 4374: L5: 4375: t = peek(t); 4376: if (t->value == TOKnot) 4377: { 4378: goto L4; 4379: } 4380: goto L3; 4381: while (1) 4382: { 4383: L2: 4384: t = peek(t); 4385: L3: 4386: if (t->value == TOKdot) 4387: { 4388: Ldot: 4389: t = peek(t); 4390: if (t->value != TOKidentifier) 4391: goto Lfalse; 4392: t = peek(t); 4393: if (t->value != TOKnot) 4394: goto L3; 4395: L4: 4396: /* Seen a ! 4397: * Look for: 4398: * !( args ), !identifier, etc. 4399: */ 4400: t = peek(t); 4401: switch (t->value) 4402: { case TOKidentifier: 4403: goto L5; 4404: case TOKlparen: 4405: if (!skipParens(t, &t)) 4406: goto Lfalse; 4407: break; 4408: case BASIC_TYPES: 4409: case TOKint32v: 4410: case TOKuns32v: 4411: case TOKint64v: 4412: case TOKuns64v: 4413: case TOKfloat32v: 4414: case TOKfloat64v: 4415: case TOKfloat80v: 4416: case TOKimaginary32v: 4417: case TOKimaginary64v: 4418: case TOKimaginary80v: 4419: case TOKnull: 4420: case TOKtrue: 4421: case TOKfalse: 4422: case TOKcharv: 4423: case TOKwcharv: 4424: case TOKdcharv: 4425: case TOKstring: 4426: case TOKfile: 4427: case TOKline: 4428: goto L2; 4429: default: 4430: goto Lfalse; 4431: } 4432: } 4433: else 4434: break; 4435: } 4436: break; 4437: 4438: case TOKdot: 4439: goto Ldot; 4440: 4441: case TOKtypeof: 4442: /* typeof(exp).identifier... 4443: */ 4444: t = peek(t); 4445: if (t->value != TOKlparen) 4446: goto Lfalse; 4447: if (!skipParens(t, &t)) 4448: goto Lfalse; 4449: goto L2; 4450: 4451: case TOKconst: 4452: case TOKinvariant: 4453: case TOKimmutable: 4454: case TOKshared: 4455: case TOKwild: 4456: // const(type) or immutable(type) or shared(type) or wild(type) 4457: t = peek(t); 4458: if (t->value != TOKlparen) 4459: goto Lfalse; 4460: t = peek(t); 4461: if (!isDeclaration(t, 0, TOKrparen, &t)) 4462: { 4463: goto Lfalse; 4464: } 4465: t = peek(t); 4466: break; 4467: 4468: default: 4469: goto Lfalse; 4470: } 4471: *pt = t; 4472: //printf("is\n"); 4473: return TRUE; 4474: 4475: Lfalse: 4476: //printf("is not\n"); 4477: return FALSE; 4478: } 4479: 4480: int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) 4481: { // This code parallels parseDeclarator() 4482: Token *t = *pt; 4483: int parens; 4484: 4485: //printf("Parser::isDeclarator()\n"); 4486: //t->print(); 4487: if (t->value == TOKassign) 4488: return FALSE; 4489: 4490: while (1) 4491: { 4492: parens = FALSE; 4493: switch (t->value) 4494: { 4495: case TOKmul: 4496: //case TOKand: 4497: t = peek(t); 4498: continue; 4499: 4500: case TOKlbracket: 4501: t = peek(t); 4502: if (t->value == TOKrbracket) 4503: { 4504: t = peek(t); 4505: } 4506: else if (isDeclaration(t, 0, TOKrbracket, &t)) 4507: { // It's an associative array declaration 4508: t = peek(t); 4509: } 4510: else 4511: { 4512: // [ expression ] 4513: // [ expression .. expression ] 4514: if (!isExpression(&t)) 4515: return FALSE; 4516: if (t->value == TOKslice) 4517: { t = peek(t); 4518: if (!isExpression(&t)) 4519: return FALSE; 4520: } 4521: if (t->value != TOKrbracket) 4522: return FALSE; 4523: t = peek(t); 4524: } 4525: continue; 4526: 4527: case TOKidentifier: 4528: if (*haveId) 4529: return FALSE; 4530: *haveId = TRUE; 4531: t = peek(t); 4532: break; 4533: 4534: case TOKlparen: 4535: t = peek(t); 4536: 4537: if (t->value == TOKrparen) 4538: return FALSE; // () is not a declarator 4539: 4540: /* Regard ( identifier ) as not a declarator 4541: * BUG: what about ( *identifier ) in 4542: * f(*p)(x); 4543: * where f is a class instance with overloaded () ? 4544: * Should we just disallow C-style function pointer declarations? 4545: */ 4546: if (t->value == TOKidentifier) 4547: { Token *t2 = peek(t); 4548: if (t2->value == TOKrparen) 4549: return FALSE; 4550: } 4551: 4552: 4553: if (!isDeclarator(&t, haveId, TOKrparen)) 4554: return FALSE; 4555: t = peek(t); 4556: parens = TRUE; 4557: break; 4558: 4559: case TOKdelegate: 4560: case TOKfunction: 4561: t = peek(t); 4562: if (!isParameters(&t)) 4563: return FALSE; 4564: continue; 4565: } 4566: break; 4567: } 4568: 4569: while (1) 4570: { 4571: switch (t->value) 4572: { 4573: #if CARRAYDECL 4574: case TOKlbracket: 4575: parens = FALSE; 4576: t = peek(t); 4577: if (t->value == TOKrbracket) 4578: { 4579: t = peek(t); 4580: } 4581: else if (isDeclaration(t, 0, TOKrbracket, &t)) 4582: { // It's an associative array declaration 4583: t = peek(t); 4584: } 4585: else 4586: { 4587: // [ expression ] 4588: if (!isExpression(&t)) 4589: return FALSE; 4590: if (t->value != TOKrbracket) 4591: return FALSE; 4592: t = peek(t); 4593: } 4594: continue; 4595: #endif 4596: 4597: case TOKlparen: 4598: parens = FALSE; 4599: if (!isParameters(&t)) 4600: return FALSE; 4601: #if DMDV2 4602: while (1) 4603: { 4604: switch (t->value) 4605: { 4606: case TOKconst: 4607: case TOKinvariant: 4608: case TOKimmutable: 4609: case TOKshared: 4610: case TOKwild: 4611: case TOKpure: 4612: case TOKnothrow: 4613: t = peek(t); 4614: continue; 4615: case TOKat: 4616: t = peek(t); // skip '@' 4617: t = peek(t); // skip identifier 4618: continue; 4619: default: 4620: break; 4621: } 4622: break; 4623: } 4624: #endif 4625: continue; 4626: 4627: // Valid tokens that follow a declaration 4628: case TOKrparen: 4629: case TOKrbracket: 4630: case TOKassign: 4631: case TOKcomma: 4632: case TOKsemicolon: 4633: case TOKlcurly: 4634: case TOKin: 4635: // The !parens is to disallow unnecessary parentheses 4636: if (!parens && (endtok == TOKreserved || endtok == t->value)) 4637: { *pt = t; 4638: return TRUE; 4639: } 4640: return FALSE; 4641: 4642: default: 4643: return FALSE; 4644: } 4645: } 4646: } 4647: 4648: 4649: int Parser::isParameters(Token **pt) 4650: { // This code parallels parseParameters() 4651: Token *t = *pt; 4652: 4653: //printf("isParameters()\n"); 4654: if (t->value != TOKlparen) 4655: return FALSE; 4656: 4657: t = peek(t); 4658: for (;1; t = peek(t)) 4659: { 4660: L1: 4661: switch (t->value) 4662: { 4663: case TOKrparen: 4664: break; 4665: 4666: case TOKdotdotdot: 4667: t = peek(t); 4668: break; 4669: 4670: #if D1INOUT 4671: case TOKinout: 4672: #endif 4673: case TOKin: 4674: case TOKout: 4675: case TOKref: 4676: case TOKlazy: 4677: case TOKfinal: 4678: case TOKauto: 4679: continue; 4680: 4681: case TOKconst: 4682: case TOKinvariant: 4683: case TOKimmutable: 4684: case TOKshared: 4685: case TOKwild: 4686: t = peek(t); 4687: if (t->value == TOKlparen) 4688: { 4689: t = peek(t); 4690: if (!isDeclaration(t, 0, TOKrparen, &t)) 4691: return FALSE; 4692: t = peek(t); // skip past closing ')' 4693: goto L2; 4694: } 4695: goto L1; 4696: 4697: #if 0 4698: case TOKstatic: 4699: continue; 4700: case TOKauto: 4701: case TOKalias: 4702: t = peek(t); 4703: if (t->value == TOKidentifier) 4704: t = peek(t); 4705: if (t->value == TOKassign) 4706: { t = peek(t); 4707: if (!isExpression(&t)) 4708: return FALSE; 4709: } 4710: goto L3; 4711: #endif 4712: 4713: default: 4714: { if (!isBasicType(&t)) 4715: return FALSE; 4716: L2: 4717: int tmp = FALSE; 4718: if (t->value != TOKdotdotdot && 4719: !isDeclarator(&t, &tmp, TOKreserved)) 4720: return FALSE; 4721: if (t->value == TOKassign) 4722: { t = peek(t); 4723: if (!isExpression(&t)) 4724: return FALSE; 4725: } 4726: if (t->value == TOKdotdotdot) 4727: { 4728: t = peek(t); 4729: break; 4730: } 4731: } 4732: L3:
warning C4102: 'L3' : unreferenced label
4733: if (t->value == TOKcomma) 4734: { 4735: continue; 4736: } 4737: break; 4738: } 4739: break; 4740: } 4741: if (t->value != TOKrparen) 4742: return FALSE; 4743: t = peek(t); 4744: *pt = t; 4745: return TRUE; 4746: } 4747: 4748: int Parser::isExpression(Token **pt) 4749: { 4750: // This is supposed to determine if something is an expression. 4751: // What it actually does is scan until a closing right bracket 4752: // is found. 4753: 4754: Token *t = *pt; 4755: int brnest = 0; 4756: int panest = 0; 4757: int curlynest = 0; 4758: 4759: for (;; t = peek(t)) 4760: { 4761: switch (t->value) 4762: { 4763: case TOKlbracket: 4764: brnest++; 4765: continue; 4766: 4767: case TOKrbracket: 4768: if (--brnest >= 0) 4769: continue; 4770: break; 4771: 4772: case TOKlparen: 4773: panest++; 4774: continue; 4775: 4776: case TOKcomma: 4777: if (brnest || panest) 4778: continue; 4779: break; 4780: 4781: case TOKrparen: 4782: if (--panest >= 0) 4783: continue; 4784: break; 4785: 4786: case TOKlcurly: 4787: curlynest++; 4788: continue; 4789: 4790: case TOKrcurly: 4791: if (--curlynest >= 0) 4792: continue; 4793: return FALSE; 4794: 4795: case TOKslice: 4796: if (brnest) 4797: continue; 4798: break; 4799: 4800: case TOKsemicolon: 4801: if (curlynest) 4802: continue; 4803: return FALSE; 4804: 4805: case TOKeof: 4806: return FALSE; 4807: 4808: default: 4809: continue; 4810: } 4811: break; 4812: } 4813: 4814: *pt = t; 4815: return TRUE; 4816: } 4817: 4818: /********************************************** 4819: * Skip over 4820: * instance foo.bar(parameters...) 4821: * Output: 4822: * if (pt), *pt is set to the token following the closing ) 4823: * Returns: 4824: * 1 it's valid instance syntax 4825: * 0 invalid instance syntax 4826: */ 4827: 4828: int Parser::isTemplateInstance(Token *t, Token **pt) 4829: { 4830: t = peek(t); 4831: if (t->value != TOKdot) 4832: { 4833: if (t->value != TOKidentifier) 4834: goto Lfalse; 4835: t = peek(t); 4836: } 4837: while (t->value == TOKdot) 4838: { 4839: t = peek(t); 4840: if (t->value != TOKidentifier) 4841: goto Lfalse; 4842: t = peek(t); 4843: } 4844: if (t->value != TOKlparen) 4845: goto Lfalse; 4846: 4847: // Skip over the template arguments 4848: while (1) 4849: { 4850: while (1) 4851: { 4852: t = peek(t); 4853: switch (t->value) 4854: { 4855: case TOKlparen: 4856: if (!skipParens(t, &t)) 4857: goto Lfalse; 4858: continue; 4859: case TOKrparen: 4860: break; 4861: case TOKcomma: 4862: break; 4863: case TOKeof: 4864: case TOKsemicolon: 4865: goto Lfalse; 4866: default: 4867: continue; 4868: } 4869: break; 4870: } 4871: 4872: if (t->value != TOKcomma) 4873: break; 4874: } 4875: if (t->value != TOKrparen) 4876: goto Lfalse; 4877: t = peek(t); 4878: if (pt) 4879: *pt = t; 4880: return 1; 4881: 4882: Lfalse: 4883: return 0; 4884: } 4885: 4886: /******************************************* 4887: * Skip parens, brackets. 4888: * Input: 4889: * t is on opening ( 4890: * Output: 4891: * *pt is set to closing token, which is ')' on success 4892: * Returns: 4893: * !=0 successful 4894: * 0 some parsing error 4895: */ 4896: 4897: int Parser::skipParens(Token *t, Token **pt) 4898: { 4899: int parens = 0; 4900: 4901: while (1) 4902: { 4903: switch (t->value) 4904: { 4905: case TOKlparen: 4906: parens++; 4907: break; 4908: 4909: case TOKrparen: 4910: parens--; 4911: if (parens < 0) 4912: goto Lfalse; 4913: if (parens == 0) 4914: goto Ldone; 4915: break; 4916: 4917: case TOKeof: 4918: goto Lfalse; 4919: 4920: default: 4921: break; 4922: } 4923: t = peek(t); 4924: } 4925: 4926: Ldone: 4927: if (*pt) 4928: *pt = t; 4929: return 1; 4930: 4931: Lfalse: 4932: return 0; 4933: } 4934: 4935: /******************************************* 4936: * Skip attributes. 4937: * Input: 4938: * t is on a candidate attribute 4939: * Output: 4940: * *pt is set to first non-attribute token on success 4941: * Returns: 4942: * !=0 successful 4943: * 0 some parsing error 4944: */ 4945: 4946: int Parser::skipAttributes(Token *t, Token **pt) 4947: { 4948: while (1) 4949: { 4950: switch (t->value) 4951: { 4952: case TOKconst: 4953: case TOKinvariant: 4954: case TOKimmutable: 4955: case TOKshared: 4956: case TOKwild: 4957: case TOKfinal: 4958: case TOKauto: 4959: case TOKscope: 4960: case TOKoverride: 4961: case TOKabstract: 4962: case TOKsynchronized: 4963: case TOKdeprecated: 4964: case TOKnothrow: 4965: case TOKpure: 4966: case TOKref: 4967: case TOKtls: 4968: case TOKgshared: 4969: //case TOKmanifest: 4970: break; 4971: case TOKat: 4972: if (parseAttribute() == STCundefined) 4973: break; 4974: goto Lerror; 4975: default: 4976: goto Ldone; 4977: } 4978: t = peek(t); 4979: } 4980: 4981: Ldone: 4982: if (*pt) 4983: *pt = t; 4984: return 1; 4985: 4986: Lerror: 4987: return 0; 4988: } 4989: 4990: /********************************* Expression Parser ***************************/ 4991: 4992: Expression *Parser::parsePrimaryExp() 4993: { Expression *e; 4994: Type *t; 4995: Identifier *id; 4996: enum TOK save; 4997: Loc loc = this->loc; 4998: 4999: //printf("parsePrimaryExp(): loc = %d\n", loc.linnum); 5000: switch (token.value) 5001: { 5002: case TOKidentifier: 5003: id = token.ident; 5004: nextToken(); 5005: if (token.value == TOKnot && (save = peekNext()) != TOKis && save != TOKin) 5006: { // identifier!(template-argument-list) 5007: TemplateInstance *tempinst; 5008: 5009: tempinst = new TemplateInstance(loc, id); 5010: nextToken(); 5011: if (token.value == TOKlparen) 5012: // ident!(template_arguments) 5013: tempinst->tiargs = parseTemplateArgumentList(); 5014: else 5015: // ident!template_argument 5016: tempinst->tiargs = parseTemplateArgument(); 5017: e = new ScopeExp(loc, tempinst); 5018: } 5019: else 5020: e = new IdentifierExp(loc, id); 5021: break; 5022: 5023: case TOKdollar: 5024: if (!inBrackets) 5025: error("'$' is valid only inside [] of index or slice"); 5026: e = new DollarExp(loc); 5027: nextToken(); 5028: break; 5029: 5030: case TOKdot: 5031: // Signal global scope '.' operator with "" identifier 5032: e = new IdentifierExp(loc, Id::empty); 5033: break; 5034: 5035: case TOKthis: 5036: e = new ThisExp(loc); 5037: nextToken(); 5038: break; 5039: 5040: case TOKsuper: 5041: e = new SuperExp(loc); 5042: nextToken(); 5043: break; 5044: 5045: case TOKint32v: 5046: e = new IntegerExp(loc, token.int32value, Type::tint32); 5047: nextToken(); 5048: break; 5049: 5050: case TOKuns32v: 5051: e = new IntegerExp(loc, token.uns32value, Type::tuns32); 5052: nextToken(); 5053: break; 5054: 5055: case TOKint64v: 5056: e = new IntegerExp(loc, token.int64value, Type::tint64); 5057: nextToken(); 5058: break; 5059: 5060: case TOKuns64v: 5061: e = new IntegerExp(loc, token.uns64value, Type::tuns64); 5062: nextToken(); 5063: break; 5064: 5065: case TOKfloat32v: 5066: e = new RealExp(loc, token.float80value, Type::tfloat32); 5067: nextToken(); 5068: break; 5069: 5070: case TOKfloat64v: 5071: e = new RealExp(loc, token.float80value, Type::tfloat64); 5072: nextToken(); 5073: break; 5074: 5075: case TOKfloat80v: 5076: e = new RealExp(loc, token.float80value, Type::tfloat80); 5077: nextToken(); 5078: break; 5079: 5080: case TOKimaginary32v: 5081: e = new RealExp(loc, token.float80value, Type::timaginary32); 5082: nextToken(); 5083: break; 5084: 5085: case TOKimaginary64v: 5086: e = new RealExp(loc, token.float80value, Type::timaginary64); 5087: nextToken(); 5088: break; 5089: 5090: case TOKimaginary80v: 5091: e = new RealExp(loc, token.float80value, Type::timaginary80); 5092: nextToken(); 5093: break; 5094: 5095: case TOKnull: 5096: e = new NullExp(loc); 5097: nextToken(); 5098: break; 5099: 5100: #if DMDV2 5101: case TOKfile: 5102: { const char *s = loc.filename ? loc.filename : mod->ident->toChars(); 5103: e = new StringExp(loc, (char *)s, strlen(s), 0); 5104: nextToken(); 5105: break; 5106: } 5107: 5108: case TOKline: 5109: e = new IntegerExp(loc, loc.linnum, Type::tint32); 5110: nextToken(); 5111: break; 5112: #endif 5113: 5114: case TOKtrue: 5115: e = new IntegerExp(loc, 1, Type::tbool); 5116: nextToken(); 5117: break; 5118: 5119: case TOKfalse: 5120: e = new IntegerExp(loc, 0, Type::tbool); 5121: nextToken(); 5122: break; 5123: 5124: case TOKcharv: 5125: e = new IntegerExp(loc, token.uns32value, Type::tchar); 5126: nextToken(); 5127: break; 5128: 5129: case TOKwcharv: 5130: e = new IntegerExp(loc, token.uns32value, Type::twchar); 5131: nextToken(); 5132: break; 5133: 5134: case TOKdcharv: 5135: e = new IntegerExp(loc, token.uns32value, Type::tdchar); 5136: nextToken(); 5137: break; 5138: 5139: case TOKstring: 5140: { unsigned char *s; 5141: unsigned len; 5142: unsigned char postfix; 5143: 5144: // cat adjacent strings 5145: s = token.ustring; 5146: len = token.len; 5147: postfix = token.postfix; 5148: while (1) 5149: { 5150: nextToken(); 5151: if (token.value == TOKstring) 5152: { unsigned len1; 5153: unsigned len2; 5154: unsigned char *s2; 5155: 5156: if (token.postfix) 5157: { if (token.postfix != postfix) 5158: error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix); 5159: postfix = token.postfix; 5160: } 5161: 5162: len1 = len; 5163: len2 = token.len; 5164: len = len1 + len2; 5165: s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char)); 5166: memcpy(s2, s, len1 * sizeof(unsigned char)); 5167: memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char)); 5168: s = s2; 5169: } 5170: else 5171: break; 5172: } 5173: e = new StringExp(loc, s, len, postfix); 5174: break; 5175: } 5176: 5177: case BASIC_TYPES_X(t): 5178: nextToken(); 5179: L1:
warning C4102: 'L1' : unreferenced label
5180: check(TOKdot, t->toChars()); 5181: if (token.value != TOKidentifier) 5182: { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars()); 5183: goto Lerr; 5184: } 5185: e = typeDotIdExp(loc, t, token.ident); 5186: nextToken(); 5187: break; 5188: 5189: case TOKtypeof: 5190: { 5191: t = parseTypeof(); 5192: e = new TypeExp(loc, t); 5193: break; 5194: } 5195: 5196: case TOKtypeid: 5197: { 5198: nextToken(); 5199: check(TOKlparen, "typeid"); 5200: Object *o; 5201: if (isDeclaration(&token, 0, TOKreserved, NULL)) 5202: { // argument is a type 5203: o = parseType(); 5204: } 5205: else 5206: { // argument is an expression 5207: o = parseAssignExp(); 5208: } 5209: check(TOKrparen); 5210: e = new TypeidExp(loc, o); 5211: break; 5212: } 5213: 5214: #if DMDV2 5215: case TOKtraits: 5216: { /* __traits(identifier, args...) 5217: */ 5218: Identifier *ident; 5219: Objects *args = NULL; 5220: 5221: nextToken(); 5222: check(TOKlparen); 5223: if (token.value != TOKidentifier) 5224: { error("__traits(identifier, args...) expected"); 5225: goto Lerr; 5226: } 5227: ident = token.ident; 5228: nextToken(); 5229: if (token.value == TOKcomma) 5230: args = parseTemplateArgumentList2(); // __traits(identifier, args...) 5231: else 5232: check(TOKrparen); // __traits(identifier) 5233: 5234: e = new TraitsExp(loc, ident, args); 5235: break; 5236: } 5237: #endif 5238: 5239: case TOKis: 5240: { Type *targ; 5241: Identifier *ident = NULL; 5242: Type *tspec = NULL; 5243: enum TOK tok = TOKreserved; 5244: enum TOK tok2 = TOKreserved; 5245: TemplateParameters *tpl = NULL; 5246: Loc loc = this->loc;
warning C6246: Local declaration of 'loc' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4997' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 4997
5247: 5248: nextToken(); 5249: if (token.value == TOKlparen) 5250: { 5251: nextToken(); 5252: targ = parseType(&ident); 5253: if (token.value == TOKcolon || token.value == TOKequal) 5254: { 5255: tok = token.value; 5256: nextToken(); 5257: if (tok == TOKequal && 5258: (token.value == TOKtypedef || 5259: token.value == TOKstruct || 5260: token.value == TOKunion || 5261: token.value == TOKclass || 5262: token.value == TOKsuper || 5263: token.value == TOKenum || 5264: token.value == TOKinterface || 5265: token.value == TOKargTypes || 5266: #if DMDV2 5267: token.value == TOKconst && peek(&token)->value == TOKrparen || 5268: token.value == TOKinvariant && peek(&token)->value == TOKrparen || 5269: token.value == TOKimmutable && peek(&token)->value == TOKrparen || 5270: token.value == TOKshared && peek(&token)->value == TOKrparen || 5271: token.value == TOKwild && peek(&token)->value == TOKrparen || 5272: #endif 5273: token.value == TOKfunction || 5274: token.value == TOKdelegate || 5275: token.value == TOKreturn)) 5276: { 5277: tok2 = token.value; 5278: nextToken(); 5279: } 5280: else 5281: { 5282: tspec = parseType(); 5283: } 5284: } 5285: if (ident && tspec) 5286: { 5287: if (token.value == TOKcomma) 5288: tpl = parseTemplateParameterList(1); 5289: else 5290: { tpl = new TemplateParameters(); 5291: check(TOKrparen); 5292: } 5293: TemplateParameter *tp = new TemplateTypeParameter(loc, ident, NULL, NULL); 5294: tpl->insert(0, tp); 5295: } 5296: else 5297: check(TOKrparen); 5298: } 5299: else 5300: { error("(type identifier : specialization) expected following is"); 5301: goto Lerr; 5302: } 5303: e = new IsExp(loc, targ, ident, tok, tspec, tok2, tpl); 5304: break; 5305: } 5306: 5307: case TOKassert: 5308: { Expression *msg = NULL; 5309: 5310: nextToken(); 5311: check(TOKlparen, "assert"); 5312: e = parseAssignExp(); 5313: if (token.value == TOKcomma) 5314: { nextToken(); 5315: msg = parseAssignExp(); 5316: } 5317: check(TOKrparen); 5318: e = new AssertExp(loc, e, msg); 5319: break; 5320: } 5321: 5322: case TOKmixin: 5323: { 5324: nextToken(); 5325: check(TOKlparen, "mixin"); 5326: e = parseAssignExp(); 5327: check(TOKrparen); 5328: e = new CompileExp(loc, e); 5329: break; 5330: } 5331: 5332: case TOKimport: 5333: { 5334: nextToken(); 5335: check(TOKlparen, "import"); 5336: e = parseAssignExp(); 5337: check(TOKrparen); 5338: e = new FileExp(loc, e); 5339: break; 5340: } 5341: 5342: case TOKlparen: 5343: if (peekPastParen(&token)->value == TOKlcurly) 5344: { // (arguments) { statements... } 5345: save = TOKdelegate; 5346: goto case_delegate; 5347: } 5348: // ( expression ) 5349: nextToken(); 5350: e = parseExpression(); 5351: e->parens = 1; 5352: check(loc, TOKrparen); 5353: break; 5354: 5355: case TOKlbracket: 5356: { /* Parse array literals and associative array literals: 5357: * [ value, value, value ... ] 5358: * [ key:value, key:value, key:value ... ] 5359: */ 5360: Expressions *values = new Expressions(); 5361: Expressions *keys = NULL; 5362: 5363: nextToken(); 5364: while (token.value != TOKrbracket && token.value != TOKeof) 5365: { 5366: Expression *e = parseAssignExp();
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4993' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 4993
5367: if (token.value == TOKcolon && (keys || values->dim == 0)) 5368: { nextToken(); 5369: if (!keys) 5370: keys = new Expressions(); 5371: keys->push(e); 5372: e = parseAssignExp(); 5373: } 5374: else if (keys) 5375: { error("'key:value' expected for associative array literal"); 5376: delete keys; 5377: keys = NULL; 5378: } 5379: values->push(e); 5380: if (token.value == TOKrbracket) 5381: break; 5382: check(TOKcomma); 5383: } 5384: check(loc, TOKrbracket); 5385: 5386: if (keys) 5387: e = new AssocArrayLiteralExp(loc, keys, values); 5388: else 5389: e = new ArrayLiteralExp(loc, values); 5390: break; 5391: } 5392: 5393: case TOKlcurly: 5394: // { statements... } 5395: save = TOKdelegate; 5396: goto case_delegate; 5397: 5398: case TOKfunction: 5399: case TOKdelegate: 5400: save = token.value; 5401: nextToken(); 5402: case_delegate: 5403: { 5404: /* function type(parameters) { body } pure nothrow 5405: * delegate type(parameters) { body } pure nothrow 5406: * (parameters) { body } 5407: * { body } 5408: */ 5409: Parameters *arguments; 5410: int varargs; 5411: FuncLiteralDeclaration *fd; 5412: Type *t;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4994' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 4994
5413: StorageClass stc = 0; 5414: 5415: if (token.value == TOKlcurly) 5416: { 5417: t = NULL; 5418: varargs = 0; 5419: arguments = new Parameters(); 5420: } 5421: else 5422: { 5423: if (token.value == TOKlparen) 5424: t = NULL; 5425: else 5426: { 5427: t = parseBasicType(); 5428: t = parseBasicType2(t); // function return type 5429: } 5430: arguments = parseParameters(&varargs); 5431: stc = parsePostfix(); 5432: if (stc & (STCconst | STCimmutable | STCshared | STCwild)) 5433: error("const/immutable/shared/inout attributes are only valid for non-static member functions"); 5434: } 5435: 5436: TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage, stc); 5437: 5438: fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL); 5439: parseContracts(fd); 5440: e = new FuncExp(loc, fd); 5441: break; 5442: } 5443: 5444: default: 5445: error("expression expected, not '%s'", token.toChars()); 5446: Lerr: 5447: // Anything for e, as long as it's not NULL 5448: e = new IntegerExp(loc, 0, Type::tint32); 5449: nextToken(); 5450: break; 5451: } 5452: return e; 5453: } 5454: 5455: Expression *Parser::parsePostExp(Expression *e) 5456: { 5457: Loc loc; 5458: 5459: while (1) 5460: { 5461: loc = this->loc; 5462: switch (token.value) 5463: { 5464: case TOKdot: 5465: nextToken(); 5466: if (token.value == TOKidentifier) 5467: { Identifier *id = token.ident; 5468: 5469: nextToken(); 5470: if (token.value == TOKnot && peekNext() != TOKis) 5471: { // identifier!(template-argument-list) 5472: TemplateInstance *tempinst = new TemplateInstance(loc, id); 5473: Objects *tiargs; 5474: nextToken(); 5475: if (token.value == TOKlparen) 5476: // ident!(template_arguments) 5477: tiargs = parseTemplateArgumentList(); 5478: else 5479: // ident!template_argument 5480: tiargs = parseTemplateArgument(); 5481: e = new DotTemplateInstanceExp(loc, e, id, tiargs); 5482: } 5483: else 5484: e = new DotIdExp(loc, e, id); 5485: continue; 5486: } 5487: else if (token.value == TOKnew) 5488: { 5489: e = parseNewExp(e); 5490: continue; 5491: } 5492: else 5493: error("identifier expected following '.', not '%s'", token.toChars()); 5494: break; 5495: 5496: case TOKplusplus: 5497: e = new PostExp(TOKplusplus, loc, e); 5498: break; 5499: 5500: case TOKminusminus: 5501: e = new PostExp(TOKminusminus, loc, e); 5502: break; 5503: 5504: case TOKlparen: 5505: e = new CallExp(loc, e, parseArguments()); 5506: continue; 5507: 5508: case TOKlbracket: 5509: { // array dereferences: 5510: // array[index] 5511: // array[] 5512: // array[lwr .. upr] 5513: Expression *index; 5514: Expression *upr; 5515: 5516: inBrackets++; 5517: nextToken(); 5518: if (token.value == TOKrbracket) 5519: { // array[] 5520: inBrackets--; 5521: e = new SliceExp(loc, e, NULL, NULL); 5522: nextToken(); 5523: } 5524: else 5525: { 5526: index = parseAssignExp(); 5527: if (token.value == TOKslice) 5528: { // array[lwr .. upr] 5529: nextToken(); 5530: upr = parseAssignExp(); 5531: e = new SliceExp(loc, e, index, upr); 5532: } 5533: else 5534: { // array[index, i2, i3, i4, ...] 5535: Expressions *arguments = new Expressions(); 5536: arguments->push(index); 5537: if (token.value == TOKcomma) 5538: { 5539: nextToken(); 5540: while (token.value != TOKrbracket && token.value != TOKeof) 5541: { 5542: Expression *arg = parseAssignExp(); 5543: arguments->push(arg); 5544: if (token.value == TOKrbracket) 5545: break; 5546: check(TOKcomma); 5547: } 5548: } 5549: e = new ArrayExp(loc, e, arguments);
warning C6211: Leaking memory 'e' due to an exception. Consider using a local catch block to clean up memory: Lines: 5457, 5459, 5461, 5462, 5508, 5513, 5514, 5516, 5517, 5518, 5526, 5527, 5535, 5536, 5537, 5549, 5551, 5552, 5459, 5461, 5462, 5508, 5513, 5514, 5516, 5517, 5518, 5526, 5527, 5535
5550: } 5551: check(TOKrbracket); 5552: inBrackets--; 5553: } 5554: continue; 5555: } 5556: 5557: default: 5558: return e; 5559: } 5560: nextToken(); 5561: } 5562: } 5563: 5564: Expression *Parser::parseUnaryExp() 5565: { Expression *e; 5566: Loc loc = this->loc; 5567: 5568: switch (token.value) 5569: { 5570: case TOKand: 5571: nextToken(); 5572: e = parseUnaryExp(); 5573: e = new AddrExp(loc, e); 5574: break; 5575: 5576: case TOKplusplus: 5577: nextToken(); 5578: e = parseUnaryExp(); 5579: //e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); 5580: e = new PreExp(TOKpreplusplus, loc, e); 5581: break; 5582: 5583: case TOKminusminus: 5584: nextToken(); 5585: e = parseUnaryExp(); 5586: //e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); 5587: e = new PreExp(TOKpreminusminus, loc, e); 5588: break; 5589: 5590: case TOKmul: 5591: nextToken(); 5592: e = parseUnaryExp(); 5593: e = new PtrExp(loc, e); 5594: break; 5595: 5596: case TOKmin: 5597: nextToken(); 5598: e = parseUnaryExp(); 5599: e = new NegExp(loc, e); 5600: break; 5601: 5602: case TOKadd: 5603: nextToken(); 5604: e = parseUnaryExp(); 5605: e = new UAddExp(loc, e); 5606: break; 5607: 5608: case TOKnot: 5609: nextToken(); 5610: e = parseUnaryExp(); 5611: e = new NotExp(loc, e); 5612: break; 5613: 5614: case TOKtilde: 5615: nextToken(); 5616: e = parseUnaryExp(); 5617: e = new ComExp(loc, e); 5618: break; 5619: 5620: case TOKdelete: 5621: nextToken(); 5622: e = parseUnaryExp(); 5623: e = new DeleteExp(loc, e); 5624: break; 5625: 5626: case TOKnew: 5627: e = parseNewExp(NULL); 5628: break; 5629: 5630: case TOKcast: // cast(type) expression 5631: { 5632: nextToken(); 5633: check(TOKlparen); 5634: /* Look for cast(), cast(const), cast(immutable), 5635: * cast(shared), cast(shared const), cast(wild), cast(shared wild) 5636: */ 5637: unsigned m; 5638: if (token.value == TOKrparen) 5639: { 5640: m = 0; 5641: goto Lmod1; 5642: } 5643: else if (token.value == TOKconst && peekNext() == TOKrparen) 5644: { 5645: m = MODconst; 5646: goto Lmod2; 5647: } 5648: else if ((token.value == TOKimmutable || token.value == TOKinvariant) && peekNext() == TOKrparen) 5649: { 5650: m = MODimmutable; 5651: goto Lmod2; 5652: } 5653: else if (token.value == TOKshared && peekNext() == TOKrparen) 5654: { 5655: m = MODshared; 5656: goto Lmod2; 5657: } 5658: else if (token.value == TOKwild && peekNext() == TOKrparen) 5659: { 5660: m = MODwild; 5661: goto Lmod2; 5662: } 5663: else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() == TOKrparen || 5664: token.value == TOKshared && peekNext() == TOKwild && peekNext2() == TOKrparen) 5665: { 5666: m = MODshared | MODwild; 5667: goto Lmod3; 5668: } 5669: else if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() == TOKrparen || 5670: token.value == TOKshared && peekNext() == TOKconst && peekNext2() == TOKrparen) 5671: { 5672: m = MODshared | MODconst; 5673: Lmod3: 5674: nextToken(); 5675: Lmod2: 5676: nextToken(); 5677: Lmod1: 5678: nextToken(); 5679: e = parseUnaryExp(); 5680: e = new CastExp(loc, e, m); 5681: } 5682: else 5683: { 5684: Type *t = parseType(); // ( type ) 5685: check(TOKrparen); 5686: e = parseUnaryExp(); 5687: e = new CastExp(loc, e, t); 5688: } 5689: break; 5690: } 5691: 5692: case TOKwild: 5693: case TOKshared: 5694: case TOKconst: 5695: case TOKinvariant: 5696: case TOKimmutable: // immutable(type)(arguments) 5697: { 5698: Type *t = parseBasicType(); 5699: if (token.value != TOKlparen) 5700: error("(arguments) expected following type"); 5701: e = new TypeExp(loc, t); 5702: e = new CallExp(loc, e, parseArguments()); 5703: break; 5704: } 5705: 5706: 5707: case TOKlparen: 5708: { Token *tk; 5709: 5710: tk = peek(&token); 5711: #if CCASTSYNTAX 5712: // If cast 5713: if (isDeclaration(tk, 0, TOKrparen, &tk)) 5714: { 5715: tk = peek(tk); // skip over right parenthesis 5716: switch (tk->value) 5717: { 5718: case TOKnot: 5719: tk = peek(tk); 5720: if (tk->value == TOKis || tk->value == TOKin) // !is or !in 5721: break; 5722: case TOKdot: 5723: case TOKplusplus: 5724: case TOKminusminus: 5725: case TOKdelete: 5726: case TOKnew: 5727: case TOKlparen: 5728: case TOKidentifier: 5729: case TOKthis: 5730: case TOKsuper: 5731: case TOKint32v: 5732: case TOKuns32v: 5733: case TOKint64v: 5734: case TOKuns64v: 5735: case TOKfloat32v: 5736: case TOKfloat64v: 5737: case TOKfloat80v: 5738: case TOKimaginary32v: 5739: case TOKimaginary64v: 5740: case TOKimaginary80v: 5741: case TOKnull: 5742: case TOKtrue: 5743: case TOKfalse: 5744: case TOKcharv: 5745: case TOKwcharv: 5746: case TOKdcharv: 5747: case TOKstring: 5748: #if 0 5749: case TOKtilde: 5750: case TOKand: 5751: case TOKmul: 5752: case TOKmin: 5753: case TOKadd: 5754: #endif 5755: case TOKfunction: 5756: case TOKdelegate: 5757: case TOKtypeof: 5758: #if DMDV2 5759: case TOKfile: 5760: case TOKline: 5761: #endif 5762: case BASIC_TYPES: // (type)int.size 5763: { // (type) una_exp 5764: Type *t; 5765: 5766: nextToken(); 5767: t = parseType(); 5768: check(TOKrparen); 5769: 5770: // if .identifier 5771: if (token.value == TOKdot) 5772: { 5773: nextToken(); 5774: if (token.value != TOKidentifier) 5775: { error("Identifier expected following (type)."); 5776: return NULL; 5777: } 5778: e = typeDotIdExp(loc, t, token.ident); 5779: nextToken(); 5780: e = parsePostExp(e); 5781: } 5782: else 5783: { 5784: e = parseUnaryExp(); 5785: e = new CastExp(loc, e, t); 5786: error("C style cast illegal, use %s", e->toChars()); 5787: } 5788: return e; 5789: } 5790: } 5791: } 5792: #endif 5793: e = parsePrimaryExp(); 5794: e = parsePostExp(e); 5795: break; 5796: } 5797: default: 5798: e = parsePrimaryExp(); 5799: e = parsePostExp(e); 5800: break; 5801: } 5802: assert(e); 5803: 5804: // ^^ is right associative and has higher precedence than the unary operators 5805: while (token.value == TOKpow) 5806: { 5807: nextToken(); 5808: Expression *e2 = parseUnaryExp(); 5809: e = new PowExp(loc, e, e2); 5810: } 5811: 5812: return e; 5813: } 5814: 5815: Expression *Parser::parseMulExp() 5816: { Expression *e; 5817: Expression *e2; 5818: Loc loc = this->loc; 5819: 5820: e = parseUnaryExp(); 5821: while (1) 5822: { 5823: switch (token.value) 5824: { 5825: case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; 5826: case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; 5827: case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; 5828: 5829: default: 5830: break; 5831: } 5832: break; 5833: } 5834: return e; 5835: } 5836: 5837: Expression *Parser::parseAddExp() 5838: { Expression *e; 5839: Expression *e2; 5840: Loc loc = this->loc; 5841: 5842: e = parseMulExp(); 5843: while (1) 5844: { 5845: switch (token.value) 5846: { 5847: case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue; 5848: case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue; 5849: case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue; 5850: 5851: default: 5852: break; 5853: } 5854: break; 5855: } 5856: return e; 5857: } 5858: 5859: Expression *Parser::parseShiftExp() 5860: { Expression *e; 5861: Expression *e2; 5862: Loc loc = this->loc; 5863: 5864: e = parseAddExp(); 5865: while (1) 5866: { 5867: switch (token.value) 5868: { 5869: case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue; 5870: case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue; 5871: case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue; 5872: 5873: default: 5874: break; 5875: } 5876: break; 5877: } 5878: return e; 5879: } 5880: 5881: #if DMDV1 5882: Expression *Parser::parseRelExp() 5883: { Expression *e; 5884: Expression *e2; 5885: enum TOK op; 5886: Loc loc = this->loc; 5887: 5888: e = parseShiftExp(); 5889: while (1) 5890: { 5891: switch (token.value) 5892: { 5893: case TOKlt: 5894: case TOKle: 5895: case TOKgt: 5896: case TOKge: 5897: case TOKunord: 5898: case TOKlg: 5899: case TOKleg: 5900: case TOKule: 5901: case TOKul: 5902: case TOKuge: 5903: case TOKug: 5904: case TOKue: 5905: op = token.value; 5906: nextToken(); 5907: e2 = parseShiftExp(); 5908: e = new CmpExp(op, loc, e, e2); 5909: continue; 5910: 5911: case TOKnot: // could be !in 5912: if (peekNext() == TOKin) 5913: { 5914: nextToken(); 5915: nextToken(); 5916: e2 = parseShiftExp(); 5917: e = new InExp(loc, e, e2); 5918: e = new NotExp(loc, e); 5919: continue; 5920: } 5921: break; 5922: 5923: case TOKin: 5924: nextToken(); 5925: e2 = parseShiftExp(); 5926: e = new InExp(loc, e, e2); 5927: continue; 5928: 5929: default: 5930: break; 5931: } 5932: break; 5933: } 5934: return e; 5935: } 5936: #endif 5937: 5938: #if DMDV1 5939: Expression *Parser::parseEqualExp() 5940: { Expression *e; 5941: Expression *e2; 5942: Token *t; 5943: Loc loc = this->loc; 5944: 5945: e = parseRelExp(); 5946: while (1) 5947: { enum TOK value = token.value; 5948: 5949: switch (value) 5950: { 5951: case TOKequal: 5952: case TOKnotequal: 5953: nextToken(); 5954: e2 = parseRelExp(); 5955: e = new EqualExp(value, loc, e, e2); 5956: continue; 5957: 5958: case TOKidentity: 5959: error("'===' is no longer legal, use 'is' instead"); 5960: goto L1; 5961: 5962: case TOKnotidentity: 5963: error("'!==' is no longer legal, use '!is' instead"); 5964: goto L1; 5965: 5966: case TOKis: 5967: value = TOKidentity; 5968: goto L1; 5969: 5970: case TOKnot: 5971: // Attempt to identify '!is' 5972: t = peek(&token); 5973: if (t->value != TOKis) 5974: break; 5975: nextToken(); 5976: value = TOKnotidentity; 5977: goto L1; 5978: 5979: L1: 5980: nextToken(); 5981: e2 = parseRelExp(); 5982: e = new IdentityExp(value, loc, e, e2); 5983: continue; 5984: 5985: default: 5986: break; 5987: } 5988: break; 5989: } 5990: return e; 5991: } 5992: #endif 5993: 5994: Expression *Parser::parseCmpExp() 5995: { Expression *e; 5996: Expression *e2; 5997: Token *t; 5998: Loc loc = this->loc; 5999: 6000: e = parseShiftExp(); 6001: enum TOK op = token.value; 6002: 6003: switch (op) 6004: { 6005: case TOKequal: 6006: case TOKnotequal: 6007: nextToken(); 6008: e2 = parseShiftExp(); 6009: e = new EqualExp(op, loc, e, e2); 6010: break; 6011: 6012: case TOKis: 6013: op = TOKidentity; 6014: goto L1; 6015: 6016: case TOKnot: 6017: // Attempt to identify '!is' 6018: t = peek(&token); 6019: if (t->value == TOKin) 6020: { 6021: nextToken(); 6022: nextToken(); 6023: e2 = parseShiftExp(); 6024: e = new InExp(loc, e, e2); 6025: e = new NotExp(loc, e); 6026: break; 6027: } 6028: if (t->value != TOKis) 6029: break; 6030: nextToken(); 6031: op = TOKnotidentity; 6032: goto L1; 6033: 6034: L1: 6035: nextToken(); 6036: e2 = parseShiftExp(); 6037: e = new IdentityExp(op, loc, e, e2); 6038: break; 6039: 6040: case TOKlt: 6041: case TOKle: 6042: case TOKgt: 6043: case TOKge: 6044: case TOKunord: 6045: case TOKlg: 6046: case TOKleg: 6047: case TOKule: 6048: case TOKul: 6049: case TOKuge: 6050: case TOKug: 6051: case TOKue: 6052: nextToken(); 6053: e2 = parseShiftExp(); 6054: e = new CmpExp(op, loc, e, e2); 6055: break; 6056: 6057: case TOKin: 6058: nextToken(); 6059: e2 = parseShiftExp(); 6060: e = new InExp(loc, e, e2); 6061: break; 6062: 6063: default: 6064: break; 6065: } 6066: return e; 6067: } 6068: 6069: Expression *Parser::parseAndExp() 6070: { 6071: Loc loc = this->loc; 6072: 6073: Expression *e = parseCmpExp(); 6074: while (token.value == TOKand) 6075: { 6076: checkParens(TOKand, e); 6077: nextToken(); 6078: Expression *e2 = parseCmpExp(); 6079: checkParens(TOKand, e2); 6080: e = new AndExp(loc,e,e2); 6081: loc = this->loc; 6082: } 6083: return e; 6084: } 6085: 6086: Expression *Parser::parseXorExp() 6087: { 6088: Loc loc = this->loc; 6089: 6090: Expression *e = parseAndExp(); 6091: while (token.value == TOKxor) 6092: { 6093: checkParens(TOKxor, e); 6094: nextToken(); 6095: Expression *e2 = parseAndExp(); 6096: checkParens(TOKxor, e2); 6097: e = new XorExp(loc, e, e2); 6098: } 6099: return e; 6100: } 6101: 6102: Expression *Parser::parseOrExp() 6103: { 6104: Loc loc = this->loc; 6105: 6106: Expression *e = parseXorExp(); 6107: while (token.value == TOKor) 6108: { 6109: checkParens(TOKor, e); 6110: nextToken(); 6111: Expression *e2 = parseXorExp(); 6112: checkParens(TOKor, e2); 6113: e = new OrExp(loc, e, e2); 6114: } 6115: return e; 6116: } 6117: 6118: Expression *Parser::parseAndAndExp() 6119: { Expression *e; 6120: Expression *e2; 6121: Loc loc = this->loc; 6122: 6123: e = parseOrExp(); 6124: while (token.value == TOKandand) 6125: { 6126: nextToken(); 6127: e2 = parseOrExp(); 6128: e = new AndAndExp(loc, e, e2); 6129: } 6130: return e; 6131: } 6132: 6133: Expression *Parser::parseOrOrExp() 6134: { Expression *e; 6135: Expression *e2; 6136: Loc loc = this->loc; 6137: 6138: e = parseAndAndExp(); 6139: while (token.value == TOKoror) 6140: { 6141: nextToken(); 6142: e2 = parseAndAndExp(); 6143: e = new OrOrExp(loc, e, e2); 6144: } 6145: return e; 6146: } 6147: 6148: Expression *Parser::parseCondExp() 6149: { Expression *e; 6150: Expression *e1; 6151: Expression *e2; 6152: Loc loc = this->loc; 6153: 6154: e = parseOrOrExp(); 6155: if (token.value == TOKquestion) 6156: { 6157: nextToken(); 6158: e1 = parseExpression(); 6159: check(TOKcolon); 6160: e2 = parseCondExp(); 6161: e = new CondExp(loc, e, e1, e2); 6162: } 6163: return e; 6164: } 6165: 6166: Expression *Parser::parseAssignExp() 6167: { Expression *e; 6168: Expression *e2; 6169: Loc loc; 6170: 6171: e = parseCondExp(); 6172: while (1) 6173: { 6174: loc = this->loc; 6175: switch (token.value) 6176: { 6177: #define X(tok,ector) \ 6178: case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue; 6179: 6180: X(TOKassign, AssignExp); 6181: X(TOKaddass, AddAssignExp); 6182: X(TOKminass, MinAssignExp); 6183: X(TOKmulass, MulAssignExp); 6184: X(TOKdivass, DivAssignExp); 6185: X(TOKmodass, ModAssignExp); 6186: X(TOKpowass, PowAssignExp); 6187: X(TOKandass, AndAssignExp); 6188: X(TOKorass, OrAssignExp); 6189: X(TOKxorass, XorAssignExp); 6190: X(TOKshlass, ShlAssignExp); 6191: X(TOKshrass, ShrAssignExp); 6192: X(TOKushrass, UshrAssignExp); 6193: X(TOKcatass, CatAssignExp); 6194: 6195: #undef X 6196: default: 6197: break; 6198: } 6199: break; 6200: } 6201: return e; 6202: } 6203: 6204: Expression *Parser::parseExpression() 6205: { Expression *e; 6206: Expression *e2; 6207: Loc loc = this->loc; 6208: 6209: //printf("Parser::parseExpression() loc = %d\n", loc.linnum); 6210: e = parseAssignExp(); 6211: while (token.value == TOKcomma) 6212: { 6213: nextToken(); 6214: e2 = parseAssignExp(); 6215: e = new CommaExp(loc, e, e2); 6216: loc = this->loc; 6217: } 6218: return e; 6219: } 6220: 6221: 6222: /************************* 6223: * Collect argument list. 6224: * Assume current token is ',', '(' or '['. 6225: */ 6226: 6227: Expressions *Parser::parseArguments() 6228: { // function call 6229: Expressions *arguments; 6230: Expression *arg; 6231: enum TOK endtok; 6232: 6233: arguments = new Expressions(); 6234: if (token.value == TOKlbracket) 6235: endtok = TOKrbracket; 6236: else 6237: endtok = TOKrparen; 6238: 6239: { 6240: nextToken(); 6241: while (token.value != endtok) 6242: { 6243: arg = parseAssignExp(); 6244: arguments->push(arg); 6245: if (token.value == endtok) 6246: break; 6247: check(TOKcomma); 6248: } 6249: check(endtok); 6250: } 6251: return arguments; 6252: } 6253: 6254: /******************************************* 6255: */ 6256: 6257: Expression *Parser::parseNewExp(Expression *thisexp) 6258: { Type *t; 6259: Expressions *newargs; 6260: Expressions *arguments = NULL; 6261: Expression *e; 6262: Loc loc = this->loc; 6263: 6264: nextToken(); 6265: newargs = NULL; 6266: if (token.value == TOKlparen) 6267: { 6268: newargs = parseArguments(); 6269: } 6270: 6271: // An anonymous nested class starts with "class" 6272: if (token.value == TOKclass) 6273: { 6274: nextToken(); 6275: if (token.value == TOKlparen) 6276: arguments = parseArguments(); 6277: 6278: BaseClasses *baseclasses = NULL; 6279: if (token.value != TOKlcurly) 6280: baseclasses = parseBaseClasses(); 6281: 6282: Identifier *id = NULL; 6283: ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses); 6284: 6285: if (token.value != TOKlcurly) 6286: { error("{ members } expected for anonymous class"); 6287: cd->members = NULL; 6288: } 6289: else 6290: { 6291: nextToken(); 6292: Dsymbols *decl = parseDeclDefs(0); 6293: if (token.value != TOKrcurly) 6294: error("class member expected"); 6295: nextToken(); 6296: cd->members = decl; 6297: } 6298: 6299: e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments); 6300: 6301: return e; 6302: } 6303: 6304: t = parseBasicType(); 6305: t = parseBasicType2(t); 6306: if (t->ty == Taarray) 6307: { TypeAArray *taa = (TypeAArray *)t; 6308: Type *index = taa->index; 6309: 6310: Expression *e = index->toExpression();
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6261' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 6261
6311: if (e) 6312: { arguments = new Expressions();
warning C6211: Leaking memory 'arguments' due to an exception. Consider using a local catch block to clean up memory: Lines: 6258, 6259, 6260, 6261, 6262, 6264, 6265, 6266, 6272, 6304, 6305, 6306, 6307, 6308, 6310, 6311, 6312, 6313, 6314
6313: arguments->push(e); 6314: t = new TypeDArray(taa->next); 6315: } 6316: else 6317: { 6318: error("need size of rightmost array, not type %s", index->toChars()); 6319: return new NullExp(loc); 6320: } 6321: } 6322: else if (t->ty == Tsarray) 6323: { 6324: TypeSArray *tsa = (TypeSArray *)t; 6325: Expression *e = tsa->dim;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6261' of 'c:\projects\extern\d\dmd\src\parse.c': Lines: 6261
6326: 6327: arguments = new Expressions(); 6328: arguments->push(e); 6329: t = new TypeDArray(tsa->next); 6330: } 6331: else if (token.value == TOKlparen) 6332: { 6333: arguments = parseArguments(); 6334: } 6335: e = new NewExp(loc, thisexp, newargs, t, arguments); 6336: return e; 6337: } 6338: 6339: /********************************************** 6340: */ 6341: 6342: void Parser::addComment(Dsymbol *s, unsigned char *blockComment) 6343: { 6344: s->addComment(combineComments(blockComment, token.lineComment)); 6345: token.lineComment = NULL; 6346: } 6347: 6348: 6349: /********************************** 6350: * Set operator precedence for each operator. 6351: */ 6352: 6353: enum PREC precedence[TOKMAX]; 6354: 6355: void initPrecedence() 6356: { 6357: for (int i = 0; i < TOKMAX; i++) 6358: precedence[i] = PREC_zero; 6359: 6360: precedence[TOKtype] = PREC_expr; 6361: precedence[TOKerror] = PREC_expr; 6362: 6363: precedence[TOKtypeof] = PREC_primary; 6364: precedence[TOKmixin] = PREC_primary; 6365: 6366: precedence[TOKdotvar] = PREC_primary; 6367: precedence[TOKimport] = PREC_primary; 6368: precedence[TOKidentifier] = PREC_primary; 6369: precedence[TOKthis] = PREC_primary; 6370: precedence[TOKsuper] = PREC_primary; 6371: precedence[TOKint64] = PREC_primary; 6372: precedence[TOKfloat64] = PREC_primary; 6373: precedence[TOKcomplex80] = PREC_primary; 6374: precedence[TOKnull] = PREC_primary; 6375: precedence[TOKstring] = PREC_primary; 6376: precedence[TOKarrayliteral] = PREC_primary; 6377: precedence[TOKassocarrayliteral] = PREC_primary; 6378: #if DMDV2 6379: precedence[TOKfile] = PREC_primary; 6380: precedence[TOKline] = PREC_primary; 6381: #endif 6382: precedence[TOKtypeid] = PREC_primary; 6383: precedence[TOKis] = PREC_primary; 6384: precedence[TOKassert] = PREC_primary; 6385: precedence[TOKhalt] = PREC_primary; 6386: precedence[TOKtemplate] = PREC_primary; 6387: precedence[TOKdsymbol] = PREC_primary; 6388: precedence[TOKfunction] = PREC_primary; 6389: precedence[TOKvar] = PREC_primary; 6390: precedence[TOKsymoff] = PREC_primary; 6391: precedence[TOKstructliteral] = PREC_primary; 6392: precedence[TOKarraylength] = PREC_primary; 6393: precedence[TOKremove] = PREC_primary; 6394: precedence[TOKtuple] = PREC_primary; 6395: #if DMDV2 6396: precedence[TOKtraits] = PREC_primary; 6397: precedence[TOKdefault] = PREC_primary; 6398: precedence[TOKoverloadset] = PREC_primary; 6399: #endif 6400: 6401: // post 6402: precedence[TOKdotti] = PREC_primary; 6403: precedence[TOKdot] = PREC_primary; 6404: precedence[TOKdottd] = PREC_primary; 6405: precedence[TOKdotexp] = PREC_primary; 6406: precedence[TOKdottype] = PREC_primary; 6407: // precedence[TOKarrow] = PREC_primary; 6408: precedence[TOKplusplus] = PREC_primary; 6409: precedence[TOKminusminus] = PREC_primary; 6410: #if DMDV2 6411: precedence[TOKpreplusplus] = PREC_primary; 6412: precedence[TOKpreminusminus] = PREC_primary; 6413: #endif 6414: precedence[TOKcall] = PREC_primary; 6415: precedence[TOKslice] = PREC_primary; 6416: precedence[TOKarray] = PREC_primary; 6417: precedence[TOKindex] = PREC_primary; 6418: 6419: precedence[TOKdelegate] = PREC_unary; 6420: precedence[TOKaddress] = PREC_unary; 6421: precedence[TOKstar] = PREC_unary; 6422: precedence[TOKneg] = PREC_unary; 6423: precedence[TOKuadd] = PREC_unary; 6424: precedence[TOKnot] = PREC_unary; 6425: precedence[TOKtobool] = PREC_add; 6426: precedence[TOKtilde] = PREC_unary; 6427: precedence[TOKdelete] = PREC_unary; 6428: precedence[TOKnew] = PREC_unary; 6429: precedence[TOKnewanonclass] = PREC_unary; 6430: precedence[TOKcast] = PREC_unary; 6431: 6432: #if DMDV2 6433: precedence[TOKpow] = PREC_pow; 6434: #endif 6435: 6436: precedence[TOKmul] = PREC_mul; 6437: precedence[TOKdiv] = PREC_mul; 6438: precedence[TOKmod] = PREC_mul; 6439: 6440: precedence[TOKadd] = PREC_add; 6441: precedence[TOKmin] = PREC_add; 6442: precedence[TOKcat] = PREC_add; 6443: 6444: precedence[TOKshl] = PREC_shift; 6445: precedence[TOKshr] = PREC_shift; 6446: precedence[TOKushr] = PREC_shift; 6447: 6448: precedence[TOKlt] = PREC_rel; 6449: precedence[TOKle] = PREC_rel; 6450: precedence[TOKgt] = PREC_rel; 6451: precedence[TOKge] = PREC_rel; 6452: precedence[TOKunord] = PREC_rel; 6453: precedence[TOKlg] = PREC_rel; 6454: precedence[TOKleg] = PREC_rel; 6455: precedence[TOKule] = PREC_rel; 6456: precedence[TOKul] = PREC_rel; 6457: precedence[TOKuge] = PREC_rel; 6458: precedence[TOKug] = PREC_rel; 6459: precedence[TOKue] = PREC_rel; 6460: precedence[TOKin] = PREC_rel; 6461: 6462: #if 0 6463: precedence[TOKequal] = PREC_equal; 6464: precedence[TOKnotequal] = PREC_equal; 6465: precedence[TOKidentity] = PREC_equal; 6466: precedence[TOKnotidentity] = PREC_equal; 6467: #else 6468: /* Note that we changed precedence, so that < and != have the same 6469: * precedence. This change is in the parser, too. 6470: */ 6471: precedence[TOKequal] = PREC_rel; 6472: precedence[TOKnotequal] = PREC_rel; 6473: precedence[TOKidentity] = PREC_rel; 6474: precedence[TOKnotidentity] = PREC_rel; 6475: #endif 6476: 6477: precedence[TOKand] = PREC_and; 6478: 6479: precedence[TOKxor] = PREC_xor; 6480: 6481: precedence[TOKor] = PREC_or; 6482: 6483: precedence[TOKandand] = PREC_andand; 6484: 6485: precedence[TOKoror] = PREC_oror; 6486: 6487: precedence[TOKquestion] = PREC_cond; 6488: 6489: precedence[TOKassign] = PREC_assign; 6490: precedence[TOKconstruct] = PREC_assign; 6491: precedence[TOKblit] = PREC_assign; 6492: precedence[TOKaddass] = PREC_assign; 6493: precedence[TOKminass] = PREC_assign; 6494: precedence[TOKcatass] = PREC_assign; 6495: precedence[TOKmulass] = PREC_assign; 6496: precedence[TOKdivass] = PREC_assign; 6497: precedence[TOKmodass] = PREC_assign; 6498: #if DMDV2 6499: precedence[TOKpowass] = PREC_assign; 6500: #endif 6501: precedence[TOKshlass] = PREC_assign; 6502: precedence[TOKshrass] = PREC_assign; 6503: precedence[TOKushrass] = PREC_assign; 6504: precedence[TOKandass] = PREC_assign; 6505: precedence[TOKorass] = PREC_assign; 6506: precedence[TOKxorass] = PREC_assign; 6507: 6508: precedence[TOKcomma] = PREC_expr; 6509: precedence[TOKdeclaration] = PREC_expr; 6510: } 6511: 6512: 6513: