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