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