comparison dmd2/parse.c @ 758:f04dde6e882c

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