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