comparison dmd/parse.c @ 1:c53b6e3fe49a trunk

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