D import syntax works again
[delight/core.git] / dmd / parse.c
blobbe5891b38206d97d523fe84a128174affeb02b86
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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
17 #include <stdio.h>
18 #include <assert.h>
20 #include "mem.h"
21 #include "lexer.h"
22 #include "parse.h"
23 #include "init.h"
24 #include "attrib.h"
25 #include "cond.h"
26 #include "mtype.h"
27 #include "template.h"
28 #include "staticassert.h"
29 #include "expression.h"
30 #include "statement.h"
31 #include "module.h"
32 #include "dsymbol.h"
33 #include "import.h"
34 #include "declaration.h"
35 #include "aggregate.h"
36 #include "enum.h"
37 #include "id.h"
38 #include "version.h"
39 #ifdef IN_GCC
40 #include "d-dmd-gcc.h"
41 #endif
43 // How multiple declarations are parsed.
44 // If 1, treat as C.
45 // If 0, treat:
46 // int *p, i;
47 // as:
48 // int* p;
49 // int* i;
50 #define CDECLSYNTAX 0
52 // Support C cast syntax:
53 // (type)(expression)
54 #define CCASTSYNTAX 1
56 // Support C array declarations, such as
57 // int a[3][4];
58 #define CARRAYDECL 1
60 // Support left-to-right array declarations
61 #define LTORARRAYDECL 1
64 Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
65 : Lexer(module, base, 0, length, doDocComment, 0, module->isDltFile)
67 //printf("Parser::Parser()\n");
68 md = NULL;
69 linkage = LINKd;
70 endloc = 0;
71 inBrackets = 0;
72 startBlockTok = TOKlcurly;
73 //nextToken(); // start up the scanner
76 DltParser::DltParser(Module *module, unsigned char *base, unsigned length, int doDocComment)
77 : Parser(module, base, length, doDocComment)
79 //printf("DltParser::DltParser(%s)\n", module->ident->string);
80 startBlockTok = TOKcolon;
83 Array *Parser::parseModule()
85 Array *decldefs;
87 // ModuleDeclation leads off
88 optionalEndline();
89 if (token.value == TOKmodule)
91 unsigned char *comment = token.blockComment;
93 nextToken();
94 if (token.value != TOKidentifier)
95 { error("Identifier expected following module");
96 goto Lerr;
98 else
100 Array *a = NULL;
101 Identifier *id;
103 id = token.ident;
104 while (nextToken() == TOKdot)
106 if (!a)
107 a = new Array();
108 a->push(id);
109 nextToken();
110 if (token.value != TOKidentifier)
111 { error("Identifier expected following package");
112 goto Lerr;
114 id = token.ident;
117 md = new ModuleDeclaration(a, id);
119 TOK end = dltSyntax ? TOKendline : TOKsemicolon;
120 if (token.value != end)
121 error("%s expected following module declaration instead of %s", Token::toChars(end), token.toChars());
123 nextToken();
124 addComment(mod, comment);
128 decldefs = parseDeclDefs(0);
129 if (token.value != TOKeof)
130 { error("unrecognized declaration '%s'", token.toChars());
131 goto Lerr;
133 return decldefs;
135 Lerr:
136 while (token.value != TOKsemicolon && token.value != TOKeof)
137 nextToken();
138 nextToken();
139 return new Array();
142 Array *Parser::parseDeclDefs(int once)
143 { Dsymbol *s;
144 Array *decldefs;
145 Array *a;
146 Array *aelse;
147 enum PROT prot;
148 unsigned stc;
149 Condition *condition;
150 unsigned char *comment;
152 //printf("Parser::parseDeclDefs()\n");
153 decldefs = new Array();
156 comment = token.blockComment;
157 switch (token.value)
159 case TOKendline:
160 nextToken();
161 continue;
162 case TOKenum:
163 s = parseEnum();
164 break;
166 case TOKstruct:
167 case TOKunion:
168 case TOKclass:
169 case TOKinterface:
170 s = parseAggregate();
171 break;
173 case TOKimport:
174 s = parseImport(decldefs, 0);
175 break;
177 case TOKtemplate:
178 s = (Dsymbol *)parseTemplateDeclaration();
179 break;
181 case TOKmixin:
182 { Loc loc = this->loc;
183 if (peek(&token)->value == TOKlparen)
184 { // mixin(string)
185 nextToken();
186 check(TOKlparen, "mixin");
187 Expression *e = parseAssignExp();
188 check(TOKrparen);
189 check(TOKsemicolon);
190 s = new CompileDeclaration(loc, e);
191 break;
193 s = parseMixin();
194 break;
197 CASE_BASIC_TYPES:
198 case TOKalias:
199 case TOKtypedef:
200 case TOKidentifier:
201 case TOKtypeof:
202 case TOKdot:
203 Ldeclaration:
204 a = parseDeclarations();
205 decldefs->append(a);
206 continue;
208 case TOKthis:
209 s = parseCtor();
210 break;
212 case TOKtilde:
213 s = parseDtor();
214 break;
216 case TOKinvariant:
217 #if 1
218 s = parseInvariant();
219 #else
220 if (peek(&token)->value == TOKlcurly)
221 s = parseInvariant();
222 else
224 stc = STCinvariant;
225 goto Lstc;
227 #endif
228 break;
230 case TOKunittest:
231 s = parseUnitTest();
232 break;
234 case TOKnew:
235 s = parseNew();
236 break;
238 case TOKdelete:
239 s = parseDelete();
240 break;
242 case TOKeof:
243 case TOKrcurly:
244 return decldefs;
246 case TOKstatic:
247 nextToken();
248 if (token.value == TOKthis)
249 s = parseStaticCtor();
250 else if (token.value == TOKtilde)
251 s = parseStaticDtor();
252 else if (token.value == TOKassert)
253 s = parseStaticAssert();
254 else if (token.value == TOKif)
255 { condition = parseStaticIfCondition();
256 a = parseBlock();
257 aelse = NULL;
258 if (token.value == TOKelse)
259 { nextToken();
260 aelse = parseBlock();
262 s = new StaticIfDeclaration(condition, a, aelse);
263 break;
265 else if (token.value == TOKimport)
267 s = parseImport(decldefs, 1);
269 else
270 { stc = STCstatic;
271 goto Lstc2;
273 break;
275 case TOKconst: stc = STCconst; goto Lstc;
276 case TOKfinal: stc = STCfinal; goto Lstc;
277 case TOKauto: stc = STCauto; goto Lstc;
278 case TOKscope: stc = STCscope; goto Lstc;
279 case TOKoverride: stc = STCoverride; goto Lstc;
280 case TOKabstract: stc = STCabstract; goto Lstc;
281 case TOKsynchronized: stc = STCsynchronized; goto Lstc;
282 case TOKdeprecated: stc = STCdeprecated; goto Lstc;
284 Lstc:
285 nextToken();
286 Lstc2:
287 switch (token.value)
289 case TOKconst: stc |= STCconst; goto Lstc;
290 case TOKfinal: stc |= STCfinal; goto Lstc;
291 case TOKauto: stc |= STCauto; goto Lstc;
292 case TOKscope: stc |= STCscope; goto Lstc;
293 case TOKoverride: stc |= STCoverride; goto Lstc;
294 case TOKabstract: stc |= STCabstract; goto Lstc;
295 case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
296 case TOKdeprecated: stc |= STCdeprecated; goto Lstc;
297 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
298 default:
299 break;
302 /* Look for auto initializers:
303 * storage_class identifier = initializer;
305 if (token.value == TOKidentifier &&
306 peek(&token)->value == TOKassign)
308 while (1)
310 Identifier *ident = token.ident;
311 nextToken();
312 nextToken();
313 Initializer *init = parseInitializer();
314 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
315 v->storage_class = stc;
316 s = v;
317 if (token.value == TOKsemicolon || token.value == TOKendline)
319 nextToken();
321 else if (token.value == TOKcomma)
323 nextToken();
324 if (token.value == TOKidentifier &&
325 peek(&token)->value == TOKassign)
327 decldefs->push(s);
328 addComment(s, comment);
329 continue;
331 else
332 error("Identifier expected following comma");
334 else
335 error("%s expected following declaration, not '%s'", endToken(), token.toChars());
336 break;
339 else
340 { a = parseBlock();
341 s = new StorageClassDeclaration(stc, a);
343 break;
345 case TOKextern:
346 if (peek(&token)->value != TOKlparen)
347 { stc = STCextern;
348 goto Lstc;
351 enum LINK linksave = linkage;
352 linkage = parseLinkage();
353 a = parseBlock();
354 s = new LinkDeclaration(linkage, a);
355 linkage = linksave;
356 break;
358 case TOKprivate: prot = PROTprivate; goto Lprot;
359 case TOKpackage: prot = PROTpackage; goto Lprot;
360 case TOKprotected: prot = PROTprotected; goto Lprot;
361 case TOKpublic: prot = PROTpublic; goto Lprot;
362 case TOKexport: prot = PROTexport; goto Lprot;
364 Lprot:
365 nextToken();
366 a = parseBlock();
367 s = new ProtDeclaration(prot, a);
368 break;
370 case TOKalign:
371 { unsigned n;
373 s = NULL;
374 nextToken();
375 if (token.value == TOKlparen)
377 nextToken();
378 if (token.value == TOKint32v)
379 n = (unsigned)token.uns64value;
380 else
381 { error("integer expected, not %s", token.toChars());
382 n = 1;
384 nextToken();
385 check(TOKrparen);
387 else
388 n = global.structalign; // default
390 a = parseBlock();
391 s = new AlignDeclaration(n, a);
392 break;
395 case TOKpragma:
396 { Identifier *ident;
397 Expressions *args = NULL;
399 nextToken();
400 check(TOKlparen);
401 if (token.value != TOKidentifier)
402 { error("pragma(identifier expected");
403 goto Lerror;
405 ident = token.ident;
406 nextToken();
407 if (token.value == TOKcomma)
408 args = parseArguments(); // pragma(identifier, args...)
409 else
410 check(TOKrparen); // pragma(identifier)
412 if (token.value == TOKsemicolon || token.value == TOKendline)
413 a = NULL;
414 else if (dltSyntax)
416 check(TOKcolon);
417 a = parseDeclDefs(0);
418 check(TOKrcurly);
420 else
421 a = parseBlock();
422 s = new PragmaDeclaration(loc, ident, args, a);
423 break;
426 case TOKdebug:
427 nextToken();
428 if (token.value == TOKassign)
430 nextToken();
431 if (token.value == TOKidentifier)
432 s = new DebugSymbol(loc, token.ident);
433 else if (token.value == TOKint32v)
434 s = new DebugSymbol(loc, (unsigned)token.uns64value);
435 else
436 { error("identifier or integer expected, not %s", token.toChars());
437 s = NULL;
439 nextToken();
440 if (token.value != TOKsemicolon)
441 error("semicolon expected");
442 nextToken();
443 break;
446 condition = parseDebugCondition();
447 goto Lcondition;
449 case TOKversion:
450 nextToken();
451 if (token.value == TOKassign)
453 nextToken();
454 if (token.value == TOKidentifier)
455 s = new VersionSymbol(loc, token.ident);
456 else if (token.value == TOKint32v)
457 s = new VersionSymbol(loc, (unsigned)token.uns64value);
458 else
459 { error("identifier or integer expected, not %s", token.toChars());
460 s = NULL;
462 nextToken();
463 if (token.value != TOKsemicolon && token.value != TOKendline)
464 error("%s expected after version assignment", endToken());
465 nextToken();
466 break;
468 condition = parseVersionCondition();
469 goto Lcondition;
471 Lcondition:
472 a = parseBlock();
473 aelse = NULL;
474 if (token.value == TOKelse)
475 { nextToken();
476 aelse = parseBlock();
478 s = new ConditionalDeclaration(condition, a, aelse);
479 break;
481 case TOKsemicolon: // empty declaration
482 nextToken();
483 continue;
485 default:
486 error("Declaration expected, not '%s'",token.toChars());
487 Lerror:
488 while (token.value != TOKsemicolon && token.value != TOKendline && token.value != TOKeof)
489 nextToken();
490 nextToken();
491 s = NULL;
492 continue;
494 if (s)
495 { decldefs->push(s);
496 addComment(s, comment);
498 } while (!once);
499 return decldefs;
503 /********************************************
504 * Parse declarations after an align, protection, or extern decl.
507 Array *Parser::parseBlock()
509 Array *a = NULL;
510 Dsymbol *s;
512 //printf("Parser::parseBlock()\n");
513 switch (token.value)
515 case TOKsemicolon:
516 error("declaration expected following attribute, not ';'");
517 nextToken();
518 break;
520 case TOKlcurly:
521 nextToken();
522 a = parseDeclDefs(0);
523 if (token.value != TOKrcurly)
524 { /* { */
525 error("matching '}' expected, not %s", token.toChars());
527 else
528 nextToken();
529 break;
531 case TOKcolon:
532 nextToken();
533 #if 0
534 a = NULL;
535 #else
536 a = parseDeclDefs(0); // grab declarations up to closing curly bracket
537 #endif
538 break;
540 default:
541 a = parseDeclDefs(1);
542 break;
544 return a;
547 Array *DltParser::parseBlock()
549 Array *a = NULL;
550 Dsymbol *s;
552 optionalEndline();
553 switch (token.value)
555 case TOKendline:
556 case TOKsemicolon:
557 error("declaration expected following attribute, not %s", token.toChars());
558 nextToken();
559 break;
561 case TOKcolon:
562 nextToken();
563 a = parseDeclDefs(0);
564 if (token.value != TOKrcurly)
566 error("matching end-of-block expected, not %s", token.toChars());
568 else
569 nextToken();
570 break;
572 default:
573 a = parseDeclDefs(1);
574 break;
576 return a;
579 /**********************************
580 * Parse a static assertion.
583 StaticAssert *Parser::parseStaticAssert()
585 Loc loc = this->loc;
586 Expression *exp;
587 Expression *msg = NULL;
589 //printf("parseStaticAssert()\n");
590 nextToken();
591 checkLParen();
592 exp = parseAssignExp();
593 if (token.value == TOKcomma)
594 { nextToken();
595 msg = parseAssignExp();
597 checkRParen();
598 if (token.value == TOKsemicolon || token.value == TOKendline) {
599 nextToken();
600 return new StaticAssert(loc, exp, msg);
602 error("expected %s after static assert", endToken());
606 /***********************************
607 * Parse extern (linkage)
608 * The parser is on the 'extern' token.
611 enum LINK Parser::parseLinkage()
613 enum LINK link = LINKdefault;
614 nextToken();
615 assert(token.value == TOKlparen);
616 nextToken();
617 if (token.value == TOKidentifier)
618 { Identifier *id = token.ident;
620 nextToken();
621 if (id == Id::Windows)
622 link = LINKwindows;
623 else if (id == Id::Pascal)
624 link = LINKpascal;
625 else if (id == Id::D)
626 link = LINKd;
627 else if (id == Id::C)
629 link = LINKc;
630 if (token.value == TOKplusplus)
631 { link = LINKcpp;
632 nextToken();
635 else if (id == Id::System)
637 #ifdef IN_GCC
638 link = d_gcc_is_target_win32() ? LINKwindows : LINKc;
639 #else
640 #if _WIN32
641 link = LINKwindows;
642 #else
643 link = LINKc;
644 #endif
645 #endif
647 else
649 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
650 link = LINKd;
653 else
655 link = LINKd; // default
657 check(TOKrparen);
658 return link;
661 /**************************************
662 * Parse a debug conditional
665 Condition *Parser::parseDebugCondition()
667 Condition *c;
669 if (token.value == TOKlparen)
671 nextToken();
672 unsigned level = 1;
673 Identifier *id = NULL;
675 if (token.value == TOKidentifier)
676 id = token.ident;
677 else if (token.value == TOKint32v)
678 level = (unsigned)token.uns64value;
679 else
680 error("identifier or integer expected, not %s", token.toChars());
681 nextToken();
682 check(TOKrparen);
683 c = new DebugCondition(mod, level, id);
684 if (dltSyntax && token.value != TOKcolon)
685 error("expected colon after debug(), not '%s'", token.toChars());
686 } else {
687 if (dltSyntax && token.value != TOKcolon)
688 error("expected ':' or '(' after 'debug', not '%s'", token.toChars());
689 c = new DebugCondition(mod, 1, NULL);
691 return c;
695 /**************************************
696 * Parse a version conditional
699 Condition *Parser::parseVersionCondition()
701 Condition *c;
702 unsigned level = 1;
703 Identifier *id = NULL;
705 if (token.value == TOKlparen)
707 nextToken();
708 if (token.value == TOKidentifier)
709 id = token.ident;
710 else if (token.value == TOKint32v)
711 level = (unsigned)token.uns64value;
712 #if V2
713 /* Allow:
714 * version (unittest)
715 * even though unittest is a keyword
717 else if (token.value == TOKunittest)
718 id = Lexer::idPool(Token::toChars(TOKunittest));
719 #endif
720 else
721 error("identifier or integer expected, not %s", token.toChars());
722 nextToken();
723 check(TOKrparen);
726 else
727 error("(condition) expected following version");
728 c = new VersionCondition(mod, level, id);
729 return c;
733 /***********************************************
734 * static if (expression)
735 * body
736 * else
737 * body
740 Condition *Parser::parseStaticIfCondition()
741 { Expression *exp;
742 Condition *condition;
743 Array *aif;
744 Array *aelse;
745 Loc loc = this->loc;
747 nextToken();
748 if (token.value == TOKlparen)
750 nextToken();
751 exp = parseAssignExp();
752 check(TOKrparen);
754 else
755 { error("(expression) expected following static if");
756 exp = NULL;
758 condition = new StaticIfCondition(loc, exp);
759 return condition;
763 /*****************************************
764 * Parse a constructor definition:
765 * this(arguments) { body }
766 * Current token is 'this'.
769 CtorDeclaration *Parser::parseCtor()
771 CtorDeclaration *f;
772 Arguments *arguments;
773 int varargs;
774 Loc loc = this->loc;
776 nextToken();
777 arguments = parseParameters(&varargs);
778 f = new CtorDeclaration(loc, 0, arguments, varargs);
779 parseContracts(f);
780 return f;
783 /*****************************************
784 * Parse a destructor definition:
785 * ~this() { body }
786 * Current token is '~'.
789 DtorDeclaration *Parser::parseDtor()
791 DtorDeclaration *f;
792 Loc loc = this->loc;
794 nextToken();
795 check(TOKthis);
796 check(TOKlparen);
797 check(TOKrparen);
799 f = new DtorDeclaration(loc, 0);
800 parseContracts(f);
801 return f;
804 /*****************************************
805 * Parse a static constructor definition:
806 * static this() { body }
807 * Current token is 'this'.
810 StaticCtorDeclaration *Parser::parseStaticCtor()
812 StaticCtorDeclaration *f;
813 Loc loc = this->loc;
815 nextToken();
816 check(TOKlparen);
817 check(TOKrparen);
819 f = new StaticCtorDeclaration(loc, 0);
820 parseContracts(f);
821 return f;
824 /*****************************************
825 * Parse a static destructor definition:
826 * static ~this() { body }
827 * Current token is '~'.
830 StaticDtorDeclaration *Parser::parseStaticDtor()
832 StaticDtorDeclaration *f;
833 Loc loc = this->loc;
835 nextToken();
836 check(TOKthis);
837 check(TOKlparen);
838 check(TOKrparen);
840 f = new StaticDtorDeclaration(loc, 0);
841 parseContracts(f);
842 return f;
845 /*****************************************
846 * Parse an invariant definition:
847 * invariant { body }
848 * Current token is 'invariant'.
851 InvariantDeclaration *Parser::parseInvariant()
853 InvariantDeclaration *f;
854 Loc loc = this->loc;
856 nextToken();
857 if (token.value == TOKlparen) // optional ()
859 nextToken();
860 check(TOKrparen);
863 f = new InvariantDeclaration(loc, 0);
864 f->fbody = parseStatement(PScurly);
865 return f;
868 /*****************************************
869 * Parse a unittest definition:
870 * unittest { body }
871 * Current token is 'unittest'.
874 UnitTestDeclaration *Parser::parseUnitTest()
876 UnitTestDeclaration *f;
877 Statement *body;
878 Loc loc = this->loc;
880 nextToken();
882 body = parseStatement(PScurly);
884 f = new UnitTestDeclaration(loc, this->loc);
885 f->fbody = body;
886 return f;
889 /*****************************************
890 * Parse a new definition:
891 * new(arguments) { body }
892 * Current token is 'new'.
895 NewDeclaration *Parser::parseNew()
897 NewDeclaration *f;
898 Arguments *arguments;
899 int varargs;
900 Loc loc = this->loc;
902 nextToken();
903 arguments = parseParameters(&varargs);
904 f = new NewDeclaration(loc, 0, arguments, varargs);
905 parseContracts(f);
906 return f;
909 /*****************************************
910 * Parse a delete definition:
911 * delete(arguments) { body }
912 * Current token is 'delete'.
915 DeleteDeclaration *Parser::parseDelete()
917 DeleteDeclaration *f;
918 Arguments *arguments;
919 int varargs;
920 Loc loc = this->loc;
922 nextToken();
923 arguments = parseParameters(&varargs);
924 if (varargs)
925 error("... not allowed in delete function parameter list");
926 f = new DeleteDeclaration(loc, 0, arguments);
927 parseContracts(f);
928 return f;
931 /**********************************************
932 * Parse parameter list.
935 Arguments *Parser::parseParameters(int *pvarargs)
937 Arguments *arguments = new Arguments();
938 int varargs = 0;
939 int hasdefault = 0;
941 check(TOKlparen);
942 while (1)
943 { Type *tb;
944 Identifier *ai;
945 Type *at;
946 Argument *a;
947 unsigned storageClass;
948 Expression *ae;
950 ai = NULL;
951 storageClass = STCin; // parameter is "in" by default
952 switch (token.value)
954 case TOKrparen:
955 break;
957 case TOKdotdotdot:
958 varargs = 1;
959 nextToken();
960 break;
962 case TOKin:
963 storageClass = STCin;
964 nextToken();
965 goto L1;
967 case TOKout:
968 storageClass = STCout;
969 nextToken();
970 goto L1;
972 case TOKinout:
973 case TOKref:
974 storageClass = STCref;
975 nextToken();
976 goto L1;
978 case TOKlazy:
979 storageClass = STClazy;
980 nextToken();
981 goto L1;
983 default:
985 tb = parseBasicType();
986 at = parseDeclarator(tb, &ai);
987 ae = NULL;
988 if (token.value == TOKassign) // = defaultArg
989 { nextToken();
990 ae = parseAssignExp();
991 hasdefault = 1;
993 else
994 { if (hasdefault)
995 error("default argument expected for %s",
996 ai ? ai->toChars() : at->toChars());
998 if (token.value == TOKdotdotdot)
999 { /* This is:
1000 * at ai ...
1003 if (storageClass & (STCout | STCref))
1004 error("variadic argument cannot be out or ref");
1005 varargs = 2;
1006 a = new Argument(storageClass, at, ai, ae);
1007 arguments->push(a);
1008 nextToken();
1009 break;
1011 a = new Argument(storageClass, at, ai, ae);
1012 arguments->push(a);
1013 if (token.value == TOKcomma)
1014 { nextToken();
1015 continue;
1017 break;
1019 break;
1021 check(TOKrparen);
1022 *pvarargs = varargs;
1023 return arguments;
1027 /*************************************
1030 EnumDeclaration *Parser::parseEnum()
1031 { EnumDeclaration *e;
1032 Identifier *id;
1033 Type *t;
1034 Loc loc = this->loc;
1036 //printf("Parser::parseEnum()\n");
1037 nextToken();
1038 if (token.value == TOKidentifier)
1039 { id = token.ident;
1040 nextToken();
1042 else
1043 id = NULL;
1045 if (token.value == TOKcolon)
1047 nextToken();
1048 t = parseBasicType();
1050 else
1051 t = NULL;
1053 e = new EnumDeclaration(loc, id, t);
1054 if (token.value == TOKsemicolon && id)
1055 nextToken();
1056 else if (token.value == startBlockTok)
1058 //printf("enum definition\n");
1059 e->members = new Array();
1060 nextToken();
1061 unsigned char *comment = token.blockComment;
1062 optionalEndline();
1063 while (token.value != TOKrcurly)
1065 if (token.value == TOKidentifier)
1066 { EnumMember *em;
1067 Expression *value;
1068 Identifier *ident;
1070 loc = this->loc;
1071 ident = token.ident;
1072 value = NULL;
1073 nextToken();
1074 if (token.value == TOKassign)
1076 nextToken();
1077 value = parseAssignExp();
1079 em = new EnumMember(loc, ident, value);
1080 e->members->push(em);
1081 optionalEndline();
1082 if (token.value == TOKrcurly)
1084 else
1085 { addComment(em, comment);
1086 comment = NULL;
1087 check(TOKcomma);
1088 optionalEndline();
1090 addComment(em, comment);
1091 comment = token.blockComment;
1093 else
1094 { error("enum member expected");
1095 nextToken();
1098 nextToken();
1100 else
1101 error("enum declaration is invalid");
1103 return e;
1106 Dsymbol *Parser::parseAggregate()
1107 { AggregateDeclaration *a = NULL;
1108 int anon = 0;
1109 enum TOK tok;
1110 Identifier *id;
1111 TemplateParameters *tpl = NULL;
1113 //printf("Parser::parseAggregate()\n");
1114 tok = token.value;
1115 nextToken();
1116 if (token.value != TOKidentifier)
1117 { id = NULL;
1119 else
1120 { id = token.ident;
1121 nextToken();
1123 if (token.value == TOKlparen)
1124 { // Class template declaration.
1126 // Gather template parameter list
1127 tpl = parseTemplateParameterList();
1131 Loc loc = this->loc;
1132 switch (tok)
1133 { case TOKclass:
1134 case TOKinterface:
1136 if (!id)
1137 error("anonymous classes not allowed");
1139 // Collect base class(es)
1140 BaseClasses *baseclasses = NULL;
1141 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1143 nextToken();
1144 baseclasses = parseBaseClasses();
1145 if (token.value != startBlockTok)
1146 error("members expected");
1149 if (tok == TOKclass)
1150 a = new ClassDeclaration(loc, id, baseclasses);
1151 else
1152 a = new InterfaceDeclaration(loc, id, baseclasses);
1153 break;
1156 case TOKstruct:
1157 if (id)
1158 a = new StructDeclaration(loc, id);
1159 else
1160 anon = 1;
1161 break;
1163 case TOKunion:
1164 if (id)
1165 a = new UnionDeclaration(loc, id);
1166 else
1167 anon = 2;
1168 break;
1170 default:
1171 assert(0);
1172 break;
1174 if (a && token.value == (dltSyntax ? TOKendline : TOKsemicolon))
1175 { nextToken();
1177 else if (token.value == startBlockTok)
1179 //printf("aggregate definition\n");
1180 nextToken();
1181 optionalEndline();
1182 Array *decl = parseDeclDefs(0);
1183 if (token.value != TOKrcurly)
1184 error("end-of-block expected following member declarations in aggregate");
1185 nextToken();
1186 if (anon)
1188 /* Anonymous structs/unions are more like attributes.
1190 return new AnonDeclaration(loc, anon - 1, decl);
1192 else
1193 a->members = decl;
1195 else
1197 error("%s expected following aggregate declaration", Token::toChars(startBlockTok));
1198 a = new StructDeclaration(loc, NULL);
1201 if (tpl)
1202 { Array *decldefs;
1203 TemplateDeclaration *tempdecl;
1205 // Wrap a template around the aggregate declaration
1206 decldefs = new Array();
1207 decldefs->push(a);
1208 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1209 return tempdecl;
1212 return a;
1215 /*******************************************
1218 BaseClasses *Parser::parseBaseClasses()
1220 enum PROT protection = PROTpublic;
1221 BaseClasses *baseclasses = new BaseClasses();
1223 for (; 1; nextToken())
1225 switch (token.value)
1227 case TOKidentifier:
1228 break;
1229 case TOKprivate:
1230 protection = PROTprivate;
1231 continue;
1232 case TOKpackage:
1233 protection = PROTpackage;
1234 continue;
1235 case TOKprotected:
1236 protection = PROTprotected;
1237 continue;
1238 case TOKpublic:
1239 protection = PROTpublic;
1240 continue;
1241 default:
1242 error("base classes expected instead of %s", token.toChars());
1243 return NULL;
1245 BaseClass *b = new BaseClass(parseBasicType(), protection);
1246 baseclasses->push(b);
1247 if (token.value != TOKcomma)
1248 break;
1249 protection = PROTpublic;
1251 return baseclasses;
1254 /**************************************
1255 * Parse a TemplateDeclaration.
1258 TemplateDeclaration *Parser::parseTemplateDeclaration()
1260 TemplateDeclaration *tempdecl;
1261 Identifier *id;
1262 TemplateParameters *tpl;
1263 Array *decldefs;
1264 Loc loc = this->loc;
1266 nextToken();
1267 if (token.value != TOKidentifier)
1268 { error("TemplateIdentifier expected following template");
1269 goto Lerr;
1271 id = token.ident;
1272 nextToken();
1273 tpl = parseTemplateParameterList();
1274 if (!tpl)
1275 goto Lerr;
1277 if (token.value != startBlockTok)
1278 { error("members of template declaration expected");
1279 goto Lerr;
1281 else
1283 nextToken();
1284 decldefs = parseDeclDefs(0);
1285 if (token.value != TOKrcurly)
1286 { error("template member expected");
1287 goto Lerr;
1289 nextToken();
1292 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1293 return tempdecl;
1295 Lerr:
1296 return NULL;
1299 /******************************************
1300 * Parse template parameter list.
1303 TemplateParameters *Parser::parseTemplateParameterList()
1305 TemplateParameters *tpl = new TemplateParameters();
1307 if (token.value != TOKlparen)
1308 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1309 goto Lerr;
1311 nextToken();
1313 // Get array of TemplateParameters
1314 if (token.value != TOKrparen)
1315 { int isvariadic = 0;
1317 while (1)
1318 { TemplateParameter *tp;
1319 Identifier *tp_ident = NULL;
1320 Type *tp_spectype = NULL;
1321 Type *tp_valtype = NULL;
1322 Type *tp_defaulttype = NULL;
1323 Expression *tp_specvalue = NULL;
1324 Expression *tp_defaultvalue = NULL;
1325 Token *t;
1327 // Get TemplateParameter
1329 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1330 t = peek(&token);
1331 if (token.value == TOKalias)
1332 { // AliasParameter
1333 nextToken();
1334 if (token.value != TOKidentifier)
1335 { error("Identifier expected for template parameter");
1336 goto Lerr;
1338 tp_ident = token.ident;
1339 nextToken();
1340 if (token.value == TOKcolon) // : Type
1342 nextToken();
1343 tp_spectype = parseBasicType();
1344 tp_spectype = parseDeclarator(tp_spectype, NULL);
1346 if (token.value == TOKassign) // = Type
1348 nextToken();
1349 tp_defaulttype = parseBasicType();
1350 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1352 tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1354 else if (t->value == TOKcolon || t->value == TOKassign ||
1355 t->value == TOKcomma || t->value == TOKrparen)
1356 { // TypeParameter
1357 if (token.value != TOKidentifier)
1358 { error("Identifier expected for template parameter");
1359 goto Lerr;
1361 tp_ident = token.ident;
1362 nextToken();
1363 if (token.value == TOKcolon) // : Type
1365 nextToken();
1366 tp_spectype = parseBasicType();
1367 tp_spectype = parseDeclarator(tp_spectype, NULL);
1369 if (token.value == TOKassign) // = Type
1371 nextToken();
1372 tp_defaulttype = parseBasicType();
1373 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1375 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1377 else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
1378 { // ident...
1379 if (isvariadic)
1380 error("variadic template parameter must be last");
1381 isvariadic = 1;
1382 tp_ident = token.ident;
1383 nextToken();
1384 nextToken();
1385 tp = new TemplateTupleParameter(loc, tp_ident);
1387 else
1388 { // ValueParameter
1389 tp_valtype = parseBasicType();
1390 tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
1391 if (!tp_ident)
1393 error("no identifier for template value parameter");
1394 tp_ident = new Identifier("error", TOKidentifier);
1396 if (token.value == TOKcolon) // : CondExpression
1398 nextToken();
1399 tp_specvalue = parseCondExp();
1401 if (token.value == TOKassign) // = CondExpression
1403 nextToken();
1404 tp_defaultvalue = parseCondExp();
1406 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
1408 tpl->push(tp);
1409 if (token.value != TOKcomma)
1410 break;
1411 nextToken();
1414 check(TOKrparen);
1415 Lerr:
1416 return tpl;
1419 /******************************************
1420 * Parse template mixin.
1421 * mixin Foo;
1422 * mixin Foo!(args);
1423 * mixin a.b.c!(args).Foo!(args);
1424 * mixin Foo!(args) identifier;
1425 * mixin typeof(expr).identifier!(args);
1428 Dsymbol *Parser::parseMixin()
1430 TemplateMixin *tm;
1431 Identifier *id;
1432 Type *tqual;
1433 Objects *tiargs;
1434 Array *idents;
1436 //printf("parseMixin()\n");
1437 nextToken();
1438 tqual = NULL;
1439 if (token.value == TOKdot)
1441 id = Id::empty;
1443 else
1445 if (token.value == TOKtypeof)
1446 { Expression *exp;
1448 nextToken();
1449 check(TOKlparen);
1450 exp = parseExpression();
1451 check(TOKrparen);
1452 tqual = new TypeTypeof(loc, exp);
1453 check(TOKdot);
1455 if (token.value != TOKidentifier)
1457 error("identifier expected, not %s", token.toChars());
1458 goto Lerr;
1460 id = token.ident;
1461 nextToken();
1464 idents = new Array();
1465 while (1)
1467 tiargs = NULL;
1468 if (token.value == TOKnot)
1470 nextToken();
1471 tiargs = parseTemplateArgumentList();
1474 if (token.value != TOKdot)
1475 break;
1477 if (tiargs)
1478 { TemplateInstance *tempinst = new TemplateInstance(loc, id);
1479 tempinst->tiargs = tiargs;
1480 id = (Identifier *)tempinst;
1481 tiargs = NULL;
1483 idents->push(id);
1485 nextToken();
1486 if (token.value != TOKidentifier)
1487 { error("identifier expected following '.' instead of '%s'", token.toChars());
1488 break;
1490 id = token.ident;
1491 nextToken();
1493 idents->push(id);
1495 if (token.value == TOKidentifier)
1497 id = token.ident;
1498 nextToken();
1500 else
1501 id = NULL;
1503 tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
1504 if (token.value != TOKsemicolon)
1505 error("';' expected after mixin");
1506 nextToken();
1508 return tm;
1510 Lerr:
1511 return NULL;
1514 /******************************************
1515 * Parse template argument list.
1516 * Input:
1517 * current token is opening '('
1518 * Output:
1519 * current token is one after closing ')'
1522 Objects *Parser::parseTemplateArgumentList()
1524 //printf("Parser::parseTemplateArgumentList()\n");
1525 Objects *tiargs = new Objects();
1526 if (token.value != TOKlparen)
1527 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1528 return tiargs;
1530 nextToken();
1532 // Get TemplateArgumentList
1533 if (token.value != TOKrparen)
1535 while (1)
1537 // See if it is an Expression or a Type
1538 if (isDeclaration(&token, 0, TOKreserved, NULL))
1539 { // Type
1540 Type *ta;
1542 // Get TemplateArgument
1543 ta = parseBasicType();
1544 ta = parseDeclarator(ta, NULL);
1545 tiargs->push(ta);
1547 else
1548 { // Expression
1549 Expression *ea;
1551 ea = parseAssignExp();
1552 tiargs->push(ea);
1554 if (token.value != TOKcomma)
1555 break;
1556 nextToken();
1559 check(TOKrparen, "template argument list");
1560 return tiargs;
1563 Import *Parser::parseImport(Array *decldefs, int isstatic)
1564 { Import *s;
1565 Identifier *id;
1566 Identifier *aliasid = NULL;
1567 Array *a;
1568 Loc loc;
1570 //printf("Parser::parseImport()\n");
1574 nextToken();
1575 if (token.value != TOKidentifier)
1576 { error("Identifier expected following import");
1577 break;
1580 loc = this->loc;
1581 a = NULL;
1582 id = token.ident;
1583 nextToken();
1584 if (!aliasid && token.value == TOKassign)
1586 aliasid = id;
1587 goto L1;
1589 while (token.value == TOKdot)
1591 if (!a)
1592 a = new Array();
1593 a->push(id);
1594 nextToken();
1595 if (token.value != TOKidentifier)
1596 { error("Identifier expected following package");
1597 break;
1599 id = token.ident;
1600 nextToken();
1603 s = new Import(loc, a, token.ident, aliasid, isstatic);
1604 decldefs->push(s);
1606 /* Look for
1607 * : alias=name, alias=name;
1608 * syntax.
1610 if (token.value == TOKcolon)
1612 nextToken();
1613 while (1)
1614 { Identifier *name;
1615 Identifier *alias;
1617 optionalEndline();
1619 if (dltSyntax && token.value == TOKrcurly)
1620 break;
1621 if (token.value != TOKidentifier)
1622 { error("Identifier expected following :");
1623 break;
1625 alias = token.ident;
1626 nextToken();
1627 if (token.value == TOKassign)
1629 nextToken();
1630 if (token.value != TOKidentifier)
1631 { error("Identifier expected following %s=", alias->toChars());
1632 break;
1634 name = token.ident;
1635 nextToken();
1637 else
1638 { name = alias;
1639 alias = NULL;
1641 s->addAlias(name, alias);
1642 if (token.value != TOKcomma && token.value != TOKendline)
1643 break;
1644 nextToken();
1646 if (dltSyntax)
1648 check(TOKrcurly);
1649 return NULL;
1651 else
1652 break;
1655 aliasid = NULL;
1656 } while (token.value == TOKcomma);
1658 if (token.value == TOKsemicolon || token.value == TOKendline)
1659 nextToken();
1660 else
1662 error("%s expected", endToken());
1663 nextToken();
1666 return NULL;
1669 Type *Parser::parseBasicType()
1670 { Type *t;
1671 Identifier *id;
1672 TypeQualified *tid;
1673 TemplateInstance *tempinst;
1675 //printf("parseBasicType()\n");
1676 switch (token.value)
1678 CASE_BASIC_TYPES_X(t):
1679 nextToken();
1680 break;
1682 case TOKidentifier:
1683 id = token.ident;
1684 nextToken();
1685 if (token.value == TOKnot)
1687 nextToken();
1688 tempinst = new TemplateInstance(loc, id);
1689 tempinst->tiargs = parseTemplateArgumentList();
1690 tid = new TypeInstance(loc, tempinst);
1691 goto Lident2;
1693 Lident:
1694 tid = new TypeIdentifier(loc, id);
1695 Lident2:
1696 while (token.value == TOKdot)
1697 { nextToken();
1698 if (token.value != TOKidentifier)
1699 { error("identifier expected following '.' instead of '%s'", token.toChars());
1700 break;
1702 id = token.ident;
1703 nextToken();
1704 if (token.value == TOKnot)
1706 nextToken();
1707 tempinst = new TemplateInstance(loc, id);
1708 tempinst->tiargs = parseTemplateArgumentList();
1709 tid->addIdent((Identifier *)tempinst);
1711 else
1712 tid->addIdent(id);
1714 t = tid;
1715 break;
1717 case TOKdot:
1718 id = Id::empty;
1719 goto Lident;
1721 case TOKtypeof:
1722 { Expression *exp;
1724 nextToken();
1725 check(TOKlparen);
1726 exp = parseExpression();
1727 check(TOKrparen);
1728 tid = new TypeTypeof(loc, exp);
1729 goto Lident2;
1732 default:
1733 error("basic type expected, not %s", token.toChars());
1734 t = Type::tint32;
1735 break;
1737 return t;
1740 Type *Parser::parseBasicType2(Type *t)
1742 Type *ts;
1743 Type *ta;
1745 //printf("parseBasicType2()\n");
1746 while (1)
1748 switch (token.value)
1750 case TOKmul:
1751 t = new TypePointer(t);
1752 nextToken();
1753 continue;
1755 case TOKlbracket:
1756 #if LTORARRAYDECL
1757 // Handle []. Make sure things like
1758 // int[3][1] a;
1759 // is (array[1] of array[3] of int)
1760 nextToken();
1761 if (token.value == TOKrbracket)
1763 t = new TypeDArray(t); // []
1764 nextToken();
1766 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1767 { // It's an associative array declaration
1768 Type *index;
1770 //printf("it's an associative array\n");
1771 index = parseBasicType();
1772 index = parseDeclarator(index, NULL); // [ type ]
1773 t = new TypeAArray(t, index);
1774 check(TOKrbracket);
1776 else
1778 //printf("it's [expression]\n");
1779 inBrackets++;
1780 Expression *e = parseExpression(); // [ expression ]
1781 if (token.value == TOKslice)
1782 { Expression *e2;
1784 nextToken();
1785 e2 = parseExpression(); // [ exp .. exp ]
1786 t = new TypeSlice(t, e, e2);
1788 else
1789 t = new TypeSArray(t,e);
1790 inBrackets--;
1791 check(TOKrbracket);
1793 continue;
1794 #else
1795 // Handle []. Make sure things like
1796 // int[3][1] a;
1797 // is (array[3] of array[1] of int)
1798 ts = t;
1799 while (token.value == TOKlbracket)
1801 nextToken();
1802 if (token.value == TOKrbracket)
1804 ta = new TypeDArray(t); // []
1805 nextToken();
1807 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1808 { // It's an associative array declaration
1809 Type *index;
1811 //printf("it's an associative array\n");
1812 index = parseBasicType();
1813 index = parseDeclarator(index, NULL); // [ type ]
1814 check(TOKrbracket);
1815 ta = new TypeAArray(t, index);
1817 else
1819 //printf("it's [expression]\n");
1820 Expression *e = parseExpression(); // [ expression ]
1821 ta = new TypeSArray(t,e);
1822 check(TOKrbracket);
1824 Type **pt;
1825 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1827 *pt = ta;
1829 t = ts;
1830 continue;
1831 #endif
1833 case TOKdelegate:
1834 case TOKfunction:
1835 { // Handle delegate declaration:
1836 // t delegate(parameter list)
1837 // t function(parameter list)
1838 Arguments *arguments;
1839 int varargs;
1840 enum TOK save = token.value;
1842 nextToken();
1843 arguments = parseParameters(&varargs);
1844 t = new TypeFunction(arguments, t, varargs, linkage);
1845 if (save == TOKdelegate)
1846 t = new TypeDelegate(t);
1847 else
1848 t = new TypePointer(t); // pointer to function
1849 continue;
1852 default:
1853 ts = t;
1854 break;
1856 break;
1858 return ts;
1861 Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
1862 { Type *ts;
1863 Type *ta;
1865 //printf("parseDeclarator(tpl = %p)\n", tpl);
1866 t = parseBasicType2(t);
1868 switch (token.value)
1871 case TOKidentifier:
1872 if (pident)
1873 *pident = token.ident;
1874 else
1875 error("unexpected identifer '%s' in declarator", token.ident->toChars());
1876 ts = t;
1877 nextToken();
1878 break;
1880 case TOKlparen:
1881 nextToken();
1882 ts = parseDeclarator(t, pident);
1883 check(TOKrparen);
1884 break;
1886 default:
1887 ts = t;
1888 break;
1891 while (1)
1893 switch (token.value)
1895 #if CARRAYDECL
1896 case TOKlbracket:
1897 { // This is the old C-style post [] syntax.
1898 nextToken();
1899 if (token.value == TOKrbracket)
1901 ta = new TypeDArray(t); // []
1902 nextToken();
1904 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1905 { // It's an associative array declaration
1906 Type *index;
1908 //printf("it's an associative array\n");
1909 index = parseBasicType();
1910 index = parseDeclarator(index, NULL); // [ type ]
1911 check(TOKrbracket);
1912 ta = new TypeAArray(t, index);
1914 else
1916 //printf("it's [expression]\n");
1917 Expression *e = parseExpression(); // [ expression ]
1918 ta = new TypeSArray(t, e);
1919 check(TOKrbracket);
1921 Type **pt;
1922 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1924 *pt = ta;
1925 continue;
1927 #endif
1928 case TOKlparen:
1929 { Arguments *arguments;
1930 int varargs;
1932 if (tpl)
1934 /* Look ahead to see if this is (...)(...),
1935 * i.e. a function template declaration
1937 if (peekPastParen(&token)->value == TOKlparen)
1938 { // It's a function template declaration
1939 //printf("function template declaration\n");
1941 // Gather template parameter list
1942 *tpl = parseTemplateParameterList();
1946 arguments = parseParameters(&varargs);
1947 Type *ta = new TypeFunction(arguments, t, varargs, linkage);
1948 Type **pt;
1949 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1951 *pt = ta;
1952 break;
1955 break;
1958 return ts;
1961 /**********************************
1962 * Return array of Declaration *'s.
1965 Array *Parser::parseDeclarations()
1967 enum STC storage_class;
1968 enum STC stc;
1969 Type *ts;
1970 Type *t;
1971 Type *tfirst;
1972 Identifier *ident;
1973 Array *a;
1974 enum TOK tok;
1975 unsigned char *comment = token.blockComment;
1976 enum LINK link = linkage;
1978 //printf("parseDeclarations()\n");
1979 switch (token.value)
1981 case TOKtypedef:
1982 case TOKalias:
1983 tok = token.value;
1984 nextToken();
1985 break;
1987 default:
1988 tok = TOKreserved;
1989 break;
1992 storage_class = STCundefined;
1993 while (1)
1995 switch (token.value)
1997 case TOKconst: stc = STCconst; goto L1;
1998 case TOKstatic: stc = STCstatic; goto L1;
1999 case TOKfinal: stc = STCfinal; goto L1;
2000 case TOKauto: stc = STCauto; goto L1;
2001 case TOKscope: stc = STCscope; goto L1;
2002 case TOKoverride: stc = STCoverride; goto L1;
2003 case TOKabstract: stc = STCabstract; goto L1;
2004 case TOKsynchronized: stc = STCsynchronized; goto L1;
2005 case TOKdeprecated: stc = STCdeprecated; goto L1;
2007 if (storage_class & stc)
2008 error("redundant storage class '%s'", token.toChars());
2009 storage_class = (STC) (storage_class | stc);
2010 nextToken();
2011 continue;
2013 case TOKextern:
2014 if (peek(&token)->value != TOKlparen)
2015 { stc = STCextern;
2016 goto L1;
2019 link = parseLinkage();
2020 continue;
2022 default:
2023 break;
2025 break;
2028 a = new Array();
2030 /* Look for auto initializers:
2031 * storage_class identifier = initializer;
2033 while (storage_class &&
2034 token.value == TOKidentifier &&
2035 peek(&token)->value == TOKassign)
2037 ident = token.ident;
2038 nextToken();
2039 nextToken();
2040 Initializer *init = parseInitializer();
2041 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
2042 v->storage_class = storage_class;
2043 a->push(v);
2044 if (token.value == TOKsemicolon || token.value == TOKendline)
2046 nextToken();
2047 addComment(v, comment);
2049 else if (token.value == TOKcomma)
2051 nextToken();
2052 if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
2054 error("Identifier expected following comma");
2056 else
2057 continue;
2059 else
2060 error("%s expected following auto declaration, not '%s'", endToken(), token.toChars());
2061 return a;
2064 if (token.value == TOKclass)
2065 { AggregateDeclaration *s;
2067 s = (AggregateDeclaration *)parseAggregate();
2068 s->storage_class |= storage_class;
2069 a->push(s);
2070 addComment(s, comment);
2071 return a;
2074 ts = parseBasicType();
2075 ts = parseBasicType2(ts);
2076 tfirst = NULL;
2078 while (1)
2080 Loc loc = this->loc;
2081 TemplateParameters *tpl = NULL;
2083 ident = NULL;
2084 t = parseDeclarator(ts, &ident, &tpl);
2085 assert(t);
2086 if (!tfirst)
2087 tfirst = t;
2088 else if (t != tfirst)
2089 error("multiple declarations must have the same type, not %s and %s",
2090 tfirst->toChars(), t->toChars());
2091 if (!ident)
2092 error("no identifier for declarator %s", t->toChars());
2094 if (tok == TOKtypedef || tok == TOKalias)
2095 { Declaration *v;
2096 Initializer *init;
2098 init = NULL;
2099 if (token.value == TOKassign)
2101 nextToken();
2102 init = parseInitializer();
2104 if (tok == TOKtypedef)
2105 v = new TypedefDeclaration(loc, ident, t, init);
2106 else
2107 { if (init)
2108 error("alias cannot have initializer");
2109 v = new AliasDeclaration(loc, ident, t);
2111 v->storage_class = storage_class;
2112 if (link == linkage)
2113 a->push(v);
2114 else
2116 Array *ax = new Array();
2117 ax->push(v);
2118 Dsymbol *s = new LinkDeclaration(link, ax);
2119 a->push(s);
2121 switch (token.value)
2122 { case TOKsemicolon:
2123 case TOKendline:
2124 nextToken();
2125 addComment(v, comment);
2126 break;
2128 case TOKcomma:
2129 nextToken();
2130 addComment(v, comment);
2131 continue;
2133 default:
2134 error("%s expected to close %s declaration", endToken(), Token::toChars(tok));
2135 break;
2138 else if (t->ty == Tfunction)
2139 { FuncDeclaration *f;
2140 Dsymbol *s;
2142 f = new FuncDeclaration(loc, 0, ident, storage_class, t);
2143 addComment(f, comment);
2144 parseContracts(f);
2145 addComment(f, NULL);
2146 if (link == linkage)
2148 s = f;
2150 else
2152 Array *ax = new Array();
2153 ax->push(f);
2154 s = new LinkDeclaration(link, ax);
2156 if (tpl) // it's a function template
2157 { Array *decldefs;
2158 TemplateDeclaration *tempdecl;
2160 // Wrap a template around the aggregate declaration
2161 decldefs = new Array();
2162 decldefs->push(s);
2163 tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs);
2164 s = tempdecl;
2166 addComment(s, comment);
2167 a->push(s);
2169 else
2170 { VarDeclaration *v;
2171 Initializer *init;
2173 init = NULL;
2174 if (token.value == TOKassign)
2176 nextToken();
2177 init = parseInitializer();
2179 v = new VarDeclaration(loc, t, ident, init);
2180 v->storage_class = storage_class;
2181 if (link == linkage)
2182 a->push(v);
2183 else
2185 Array *ax = new Array();
2186 ax->push(v);
2187 Dsymbol *s = new LinkDeclaration(link, ax);
2188 a->push(s);
2190 switch (token.value)
2191 { case TOKsemicolon:
2192 case TOKendline:
2193 nextToken();
2194 addComment(v, comment);
2195 break;
2197 case TOKcomma:
2198 nextToken();
2199 addComment(v, comment);
2200 continue;
2202 default:
2203 error("%s expected, not '%s'", endToken(), token.toChars());
2204 break;
2207 break;
2209 return a;
2212 /*****************************************
2213 * Parse contracts following function declaration.
2216 void Parser::parseContracts(FuncDeclaration *f)
2218 Type *tb;
2219 enum LINK linksave = linkage;
2221 // The following is irrelevant, as it is overridden by sc->linkage in
2222 // TypeFunction::semantic
2223 linkage = LINKd; // nested functions have D linkage
2225 switch (token.value)
2227 case TOKlcurly:
2228 case TOKcolon:
2229 if (token.value != startBlockTok)
2230 error("use %s to start a new block", Token::toChars(startBlockTok));
2231 if (f->frequire || f->fensure)
2232 error("missing body { ... } after in or out");
2233 f->fbody = parseStatement(PSsemi | PScolon);
2234 f->endloc = endloc;
2235 break;
2237 case TOKbody:
2238 nextToken();
2239 f->fbody = parseStatement(PScurly);
2240 f->endloc = endloc;
2241 break;
2243 case TOKsemicolon:
2244 if (dltSyntax)
2245 error("unexpected semi-colon after function declaration");
2246 // fall-through
2247 case TOKendline:
2248 if (f->frequire || f->fensure)
2249 error("missing body { ... } after in or out");
2250 nextToken();
2251 break;
2253 #if 0 // Do we want this for function declarations, so we can do:
2254 // int x, y, foo(), z;
2255 case TOKcomma:
2256 nextToken();
2257 continue;
2258 #endif
2260 #if 0 // Dumped feature
2261 case TOKthrow:
2262 if (!f->fthrows)
2263 f->fthrows = new Array();
2264 nextToken();
2265 check(TOKlparen);
2266 while (1)
2268 tb = parseBasicType();
2269 f->fthrows->push(tb);
2270 if (token.value == TOKcomma)
2271 { nextToken();
2272 continue;
2274 break;
2276 check(TOKrparen);
2277 goto L1;
2278 #endif
2280 case TOKin:
2281 nextToken();
2282 if (f->frequire)
2283 error("redundant 'in' statement");
2284 f->frequire = parseStatement(PScurly | PSscope);
2285 goto L1;
2287 case TOKout:
2288 // parse: out (identifier) { statement }
2289 nextToken();
2290 if (token.value != startBlockTok)
2292 check(TOKlparen);
2293 if (token.value != TOKidentifier)
2294 error("(identifier) following 'out' expected, not %s", token.toChars());
2295 f->outId = token.ident;
2296 nextToken();
2297 check(TOKrparen);
2299 if (f->fensure)
2300 error("redundant 'out' statement");
2301 f->fensure = parseStatement(PScurly | PSscope);
2302 goto L1;
2304 default:
2305 error("%s expected following function declaration", endToken());
2306 break;
2308 linkage = linksave;
2311 /*****************************************
2314 Initializer *Parser::parseInitializer()
2316 StructInitializer *is;
2317 ArrayInitializer *ia;
2318 ExpInitializer *ie;
2319 Expression *e;
2320 Identifier *id;
2321 Initializer *value;
2322 int comma;
2323 Loc loc = this->loc;
2324 Token *t;
2325 int braces;
2327 switch (token.value)
2329 case TOKlcurly:
2330 /* Scan ahead to see if it is a struct initializer or
2331 * a function literal.
2332 * If it contains a ';', it is a function literal.
2333 * Treat { } as a struct initializer.
2335 braces = 1;
2336 for (t = peek(&token); 1; t = peek(t))
2338 switch (t->value)
2340 case TOKsemicolon:
2341 case TOKreturn:
2342 goto Lexpression;
2344 case TOKlcurly:
2345 braces++;
2346 continue;
2348 case TOKrcurly:
2349 if (--braces == 0)
2350 break;
2351 continue;
2353 case TOKeof:
2354 break;
2356 default:
2357 continue;
2359 break;
2362 is = new StructInitializer(loc);
2363 nextToken();
2364 comma = 0;
2365 while (1)
2367 switch (token.value)
2369 case TOKidentifier:
2370 if (comma == 1)
2371 error("comma expected separating field initializers");
2372 t = peek(&token);
2373 if (t->value == TOKcolon)
2375 id = token.ident;
2376 nextToken();
2377 nextToken(); // skip over ':'
2379 else
2380 { id = NULL;
2382 value = parseInitializer();
2383 is->addInit(id, value);
2384 comma = 1;
2385 continue;
2387 case TOKcomma:
2388 nextToken();
2389 comma = 2;
2390 continue;
2392 case TOKrcurly: // allow trailing comma's
2393 nextToken();
2394 break;
2396 case TOKeof:
2397 error("found EOF instead of initializer");
2398 break;
2400 default:
2401 value = parseInitializer();
2402 is->addInit(NULL, value);
2403 comma = 1;
2404 continue;
2405 //error("found '%s' instead of field initializer", token.toChars());
2406 //break;
2408 break;
2410 return is;
2412 case TOKlbracket:
2413 ia = new ArrayInitializer(loc);
2414 nextToken();
2415 comma = 0;
2416 while (1)
2418 switch (token.value)
2420 default:
2421 if (comma == 1)
2422 { error("comma expected separating array initializers, not %s", token.toChars());
2423 nextToken();
2424 break;
2426 e = parseAssignExp();
2427 if (!e)
2428 break;
2429 if (token.value == TOKcolon)
2431 nextToken();
2432 value = parseInitializer();
2434 else
2435 { value = new ExpInitializer(e->loc, e);
2436 e = NULL;
2438 ia->addInit(e, value);
2439 comma = 1;
2440 continue;
2442 case TOKlcurly:
2443 case TOKlbracket:
2444 if (comma == 1)
2445 error("comma expected separating array initializers, not %s", token.toChars());
2446 value = parseInitializer();
2447 ia->addInit(NULL, value);
2448 comma = 1;
2449 continue;
2451 case TOKcomma:
2452 nextToken();
2453 comma = 2;
2454 continue;
2456 case TOKrbracket: // allow trailing comma's
2457 nextToken();
2458 break;
2460 case TOKeof:
2461 error("found '%s' instead of array initializer", token.toChars());
2462 break;
2464 break;
2466 return ia;
2468 case TOKvoid:
2469 t = peek(&token);
2470 if (t->value == TOKsemicolon || t->value == TOKcomma || t->value == TOKendline)
2472 nextToken();
2473 return new VoidInitializer(loc);
2475 goto Lexpression;
2477 default:
2478 Lexpression:
2479 e = parseAssignExp();
2480 ie = new ExpInitializer(loc, e);
2481 return ie;
2486 /*****************************************
2487 * Input:
2488 * flags PSxxxx
2491 Statement *DltParser::parseStatement(int flags)
2493 optionalEndline();
2494 if (flags & (PScolon | PSscope))
2495 flags |= PScurly;
2496 return Parser::parseStatement(flags);
2499 Statement *Parser::parseStatement(int flags)
2500 { Statement *s;
2501 Token *t;
2502 Condition *condition;
2503 Statement *ifbody;
2504 Statement *elsebody;
2505 Loc loc = this->loc;
2507 //printf("parseStatement()\n");
2509 if ((flags & PScurly) && token.value != startBlockTok)
2510 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2512 int tok = token.value;
2514 switch (token.value)
2516 case TOKidentifier:
2517 if (!dltSyntax)
2519 // Need to look ahead to see if it is a declaration, label, or expression
2520 t = peek(&token);
2521 if (t->value == TOKcolon)
2522 { // It's a label
2523 Identifier *ident;
2525 ident = token.ident;
2526 nextToken();
2527 nextToken();
2528 s = parseStatement(PSsemi);
2529 s = new LabelStatement(loc, ident, s);
2530 break;
2533 // fallthrough to TOKdot
2534 case TOKdot:
2535 case TOKtypeof:
2536 if (isDeclaration(&token, 2, TOKreserved, NULL))
2537 goto Ldeclaration;
2538 else
2539 goto Lexp;
2540 break;
2542 case TOKassert:
2543 case TOKthis:
2544 case TOKsuper:
2545 case TOKint32v:
2546 case TOKuns32v:
2547 case TOKint64v:
2548 case TOKuns64v:
2549 case TOKfloat32v:
2550 case TOKfloat64v:
2551 case TOKfloat80v:
2552 case TOKimaginary32v:
2553 case TOKimaginary64v:
2554 case TOKimaginary80v:
2555 case TOKcharv:
2556 case TOKwcharv:
2557 case TOKdcharv:
2558 case TOKnull:
2559 case TOKtrue:
2560 case TOKfalse:
2561 case TOKstring:
2562 case TOKlparen:
2563 case TOKcast:
2564 case TOKmul:
2565 case TOKmin:
2566 case TOKadd:
2567 case TOKplusplus:
2568 case TOKminusminus:
2569 case TOKnew:
2570 case TOKdelete:
2571 case TOKdelegate:
2572 case TOKfunction:
2573 case TOKtypeid:
2574 case TOKis:
2575 case TOKlbracket:
2576 Lexp:
2577 { Expression *exp;
2579 exp = parseExpression();
2580 if (!dltSyntax)
2581 check(TOKsemicolon, "statement");
2582 s = new ExpStatement(loc, exp);
2583 break;
2586 case TOKstatic:
2587 { // Look ahead to see if it's static assert() or static if()
2588 Token *t;
2590 t = peek(&token);
2591 if (t->value == TOKassert)
2593 nextToken();
2594 s = new StaticAssertStatement(parseStaticAssert());
2595 break;
2597 if (t->value == TOKif)
2599 nextToken();
2600 condition = parseStaticIfCondition();
2601 goto Lcondition;
2603 goto Ldeclaration;
2606 CASE_BASIC_TYPES:
2607 case TOKtypedef:
2608 case TOKalias:
2609 case TOKconst:
2610 case TOKauto:
2611 case TOKextern:
2612 case TOKfinal:
2613 case TOKinvariant:
2614 // case TOKtypeof:
2615 Ldeclaration:
2616 { Array *a;
2618 a = parseDeclarations();
2619 if (a->dim > 1)
2621 Statements *as = new Statements();
2622 as->reserve(a->dim);
2623 for (int i = 0; i < a->dim; i++)
2625 Dsymbol *d = (Dsymbol *)a->data[i];
2626 s = new DeclarationStatement(loc, d);
2627 as->push(s);
2629 s = new CompoundStatement(loc, as);
2631 else if (a->dim == 1)
2633 Dsymbol *d = (Dsymbol *)a->data[0];
2634 s = new DeclarationStatement(loc, d);
2636 else
2637 assert(0);
2638 if (flags & PSscope)
2639 s = new ScopeStatement(loc, s);
2640 break;
2643 case TOKstruct:
2644 case TOKunion:
2645 case TOKclass:
2646 case TOKinterface:
2647 { Dsymbol *d;
2649 d = parseAggregate();
2650 s = new DeclarationStatement(loc, d);
2651 break;
2654 case TOKenum:
2655 { Dsymbol *d;
2657 d = parseEnum();
2658 s = new DeclarationStatement(loc, d);
2659 break;
2662 case TOKmixin:
2663 { t = peek(&token);
2664 if (t->value == TOKlparen)
2665 { // mixin(string)
2666 nextToken();
2667 check(TOKlparen, "mixin");
2668 Expression *e = parseAssignExp();
2669 check(TOKrparen);
2670 check(TOKsemicolon);
2671 s = new CompileStatement(loc, e);
2672 break;
2674 Dsymbol *d = parseMixin();
2675 s = new DeclarationStatement(loc, d);
2676 break;
2679 case TOKcolon:
2680 case TOKlcurly:
2681 { Statements *statements;
2683 if (token.value != startBlockTok)
2684 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2686 nextToken();
2687 optionalEndline();
2688 statements = new Statements();
2689 while (token.value != TOKrcurly)
2691 statements->push(parseStatement(PSsemi | PScurlyscope));
2692 optionalEndline();
2694 endloc = this->loc;
2695 s = new CompoundStatement(loc, statements);
2696 if (flags & (PSscope | PScurlyscope))
2697 s = new ScopeStatement(loc, s);
2698 nextToken();
2699 break;
2702 case TOKwhile:
2703 { Expression *condition;
2704 Statement *body;
2706 nextToken();
2707 checkLParen();
2708 condition = parseExpression();
2709 checkRParen();
2710 body = parseStatement(PSscope);
2711 s = new WhileStatement(loc, condition, body);
2712 break;
2715 case TOKsemicolon:
2716 if (!(flags & PSsemi))
2717 error("use '{ }' for an empty statement, not a ';'");
2718 nextToken();
2719 s = new ExpStatement(loc, NULL);
2720 break;
2722 case TOKdo:
2723 { Statement *body;
2724 Expression *condition;
2726 nextToken();
2727 body = parseStatement(PSscope);
2728 check(TOKwhile);
2729 checkLParen();
2730 condition = parseExpression();
2731 checkRParen();
2732 s = new DoStatement(loc, body, condition);
2733 break;
2736 case TOKfor:
2738 Statement *init;
2739 Expression *condition;
2740 Expression *increment;
2741 Statement *body;
2743 nextToken();
2745 if (token.value == TOKlparen) {
2746 /* for (init; cond; incr): ... */
2747 nextToken();
2748 if (token.value == TOKsemicolon)
2749 { init = NULL;
2750 nextToken();
2752 else
2753 { init = parseStatement(0);
2754 if (dltSyntax)
2755 check(TOKsemicolon);
2757 if (token.value == TOKsemicolon)
2759 condition = NULL;
2760 nextToken();
2762 else
2764 condition = parseExpression();
2765 check(TOKsemicolon, "for condition");
2767 if (token.value == TOKrparen)
2768 { increment = NULL;
2769 nextToken();
2771 else
2772 { increment = parseExpression();
2773 check(TOKrparen);
2775 body = parseStatement(PSscope);
2776 s = new ForStatement(loc, init, condition, increment, body);
2777 if (init)
2778 s = new ScopeStatement(loc, s);
2779 } else if (dltSyntax)
2780 goto caseForeach;
2781 break;
2784 caseForeach:
2785 case TOKforeach:
2786 case TOKforeach_reverse:
2788 /* for var in seq: ... */
2789 /* for index, var in seq: ... */
2790 Arguments *arguments;
2792 Statement *d;
2793 Statement *body;
2794 Expression *aggr;
2795 enum TOK op = (TOK) tok;
2797 if (tok != TOKfor)
2798 nextToken();
2800 checkLParen();
2802 TOK inTok = dltSyntax ? TOKin : TOKsemicolon;
2804 arguments = new Arguments();
2806 while (1)
2808 Type *tb;
2809 Identifier *ai = NULL;
2810 Type *at;
2811 unsigned storageClass;
2812 Argument *a;
2814 storageClass = STCin;
2815 if (token.value == TOKinout || token.value == TOKref)
2816 { storageClass = STCref;
2817 nextToken();
2819 if (token.value == TOKidentifier)
2821 Token *t = peek(&token);
2822 if (t->value == TOKcomma || t->value == inTok)
2823 { ai = token.ident;
2824 at = NULL; // infer argument type
2825 nextToken();
2826 goto Larg;
2829 tb = parseBasicType();
2830 at = parseDeclarator(tb, &ai);
2831 if (!ai)
2832 error("no identifier for declarator %s", at->toChars());
2833 Larg:
2834 a = new Argument(storageClass, at, ai, NULL);
2835 arguments->push(a);
2836 if (token.value == TOKcomma)
2837 { nextToken();
2838 continue;
2840 break;
2843 check(inTok);
2845 aggr = parseExpression();
2846 checkRParen();
2848 if (dltSyntax) {
2849 if (token.value == TOKreversed) {
2850 op = TOKforeach_reverse;
2851 nextToken();
2852 } else {
2853 op = TOKforeach;
2857 body = parseStatement(PScolon);
2858 s = new ForeachStatement(loc, op, arguments, aggr, body);
2859 break;
2862 case TOKif:
2863 { Argument *arg = NULL;
2864 Expression *condition;
2865 Statement *ifbody;
2866 Statement *elsebody;
2868 nextToken();
2869 checkLParen();
2871 if (token.value == TOKauto)
2873 nextToken();
2874 if (token.value == TOKidentifier)
2876 Token *t = peek(&token);
2877 if (t->value == TOKassign)
2879 arg = new Argument(STCin, NULL, token.ident, NULL);
2880 nextToken();
2881 nextToken();
2883 else
2884 { error("= expected following auto identifier");
2885 goto Lerror;
2888 else
2889 { error("identifier expected following auto");
2890 goto Lerror;
2893 else if (isDeclaration(&token, 2, TOKassign, NULL))
2895 Type *tb;
2896 Type *at;
2897 Identifier *ai;
2899 tb = parseBasicType();
2900 at = parseDeclarator(tb, &ai);
2901 check(TOKassign);
2902 arg = new Argument(STCin, at, ai, NULL);
2905 // Check for " ident;"
2906 else if (token.value == TOKidentifier && !dltSyntax)
2908 Token *t = peek(&token);
2909 if (t->value == TOKcomma || t->value == TOKsemicolon)
2911 arg = new Argument(STCin, NULL, token.ident, NULL);
2912 nextToken();
2913 nextToken();
2914 if (1 || !global.params.useDeprecated)
2915 error("if (v; e) is deprecated, use if (auto v = e)");
2919 condition = parseExpression();
2920 checkRParen();
2921 ifbody = parseStatement(PSscope);
2922 if (token.value == TOKelse)
2924 nextToken();
2925 if (dltSyntax)
2927 if (token.value == TOKcolon) {
2928 elsebody = parseStatement(PSscope);
2929 } else if (token.value == TOKif) {
2930 elsebody = parseStatement(0);
2931 } else {
2932 error("Expected 'else:' or 'else if', not 'else %s'", token.toChars());
2933 elsebody = NULL;
2936 else
2937 elsebody = parseStatement(PSscope);
2939 else
2940 elsebody = NULL;
2941 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
2942 break;
2945 case TOKscope:
2946 if (peek(&token)->value != TOKlparen)
2947 goto Ldeclaration; // scope used as storage class
2948 nextToken();
2949 check(TOKlparen);
2950 if (token.value != TOKidentifier)
2951 { error("scope identifier expected");
2952 goto Lerror;
2954 else
2955 { TOK t = TOKon_scope_exit;
2956 Identifier *id = token.ident;
2958 if (id == Id::exit)
2959 t = TOKon_scope_exit;
2960 else if (id == Id::failure)
2961 t = TOKon_scope_failure;
2962 else if (id == Id::success)
2963 t = TOKon_scope_success;
2964 else
2965 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
2966 nextToken();
2967 check(TOKrparen);
2968 Statement *st = parseStatement(PScolon | PScurlyscope);
2969 s = new OnScopeStatement(loc, t, st);
2970 break;
2973 case TOKdebug:
2974 nextToken();
2975 condition = parseDebugCondition();
2976 goto Lcondition;
2978 case TOKversion:
2979 nextToken();
2980 condition = parseVersionCondition();
2981 goto Lcondition;
2983 Lcondition:
2984 if (dltSyntax && token.value != TOKcolon)
2985 error("expected colon after condition, not '%s'", token.toChars());
2986 ifbody = parseStatement(PScolon /*PSsemi*/);
2987 elsebody = NULL;
2988 if (token.value == TOKelse)
2990 nextToken();
2991 elsebody = parseStatement(PScolon /*PSsemi*/);
2993 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
2994 break;
2996 case TOKpragma:
2997 { Identifier *ident;
2998 Expressions *args = NULL;
2999 Statement *body;
3001 nextToken();
3002 check(TOKlparen);
3003 if (token.value != TOKidentifier)
3004 { error("pragma(identifier expected");
3005 goto Lerror;
3007 ident = token.ident;
3008 nextToken();
3009 if (token.value == TOKcomma)
3010 args = parseArguments(); // pragma(identifier, args...);
3011 else
3012 check(TOKrparen); // pragma(identifier);
3013 if (token.value == TOKsemicolon)
3014 { nextToken();
3015 body = NULL;
3017 else
3018 body = parseStatement(PSsemi | PScolon);
3019 s = new PragmaStatement(loc, ident, args, body);
3020 break;
3023 case TOKswitch:
3024 { Expression *condition;
3025 Statement *body;
3027 nextToken();
3028 checkLParen();
3029 condition = parseExpression();
3030 checkRParen();
3031 body = parseStatement(PSscope | PScolon);
3032 s = new SwitchStatement(loc, condition, body);
3033 break;
3036 case TOKcase:
3037 { Expression *exp;
3038 Statements *statements;
3039 Array cases; // array of Expression's
3041 while (1)
3043 nextToken();
3044 exp = parseAssignExp();
3045 cases.push(exp);
3046 if (token.value != TOKcomma)
3047 break;
3050 if (dltSyntax)
3052 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3054 else
3056 check(TOKcolon);
3058 statements = new Statements();
3059 while (token.value != TOKcase &&
3060 token.value != TOKdefault &&
3061 token.value != TOKrcurly)
3063 statements->push(parseStatement(PSsemi | PScurlyscope));
3065 s = new CompoundStatement(loc, statements);
3068 s = new ScopeStatement(loc, s);
3070 // Keep cases in order by building the case statements backwards
3071 for (int i = cases.dim; i; i--)
3073 exp = (Expression *)cases.data[i - 1];
3074 s = new CaseStatement(loc, exp, s);
3076 break;
3079 case TOKdefault:
3081 Statements *statements;
3083 nextToken();
3085 if (dltSyntax)
3087 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3089 else
3091 check(TOKcolon);
3093 statements = new Statements();
3094 while (token.value != TOKcase &&
3095 token.value != TOKdefault &&
3096 token.value != TOKrcurly)
3098 statements->push(parseStatement(PSsemi | PScurlyscope));
3100 s = new CompoundStatement(loc, statements);
3103 s = new ScopeStatement(loc, s);
3104 s = new DefaultStatement(loc, s);
3105 break;
3108 case TOKreturn:
3109 { Expression *exp;
3111 nextToken();
3112 if (token.value == TOKsemicolon || token.value == TOKendline)
3113 exp = NULL;
3114 else {
3115 exp = parseExpression();
3116 if (!dltSyntax)
3117 check(TOKsemicolon, "return statement");
3118 else if (token.value == TOKsemicolon)
3119 nextToken(); // Or we get unreachable statement errors
3120 else if (token.value != TOKendline) {
3121 error("Expected end-of-line after return statement, but found '%s'", token.toChars());
3124 s = new ReturnStatement(loc, exp);
3125 break;
3128 case TOKbreak:
3129 { Identifier *ident;
3131 nextToken();
3132 if (token.value == TOKidentifier)
3133 { ident = token.ident;
3134 nextToken();
3136 else
3137 ident = NULL;
3138 if (token.value != TOKsemicolon && token.value != TOKendline) {
3139 error("expected %s after break, not '%s'", endToken(), token.toChars());
3141 s = new BreakStatement(loc, ident);
3142 break;
3145 case TOKcontinue:
3146 { Identifier *ident;
3148 nextToken();
3149 if (token.value == TOKidentifier)
3150 { ident = token.ident;
3151 nextToken();
3153 else
3154 ident = NULL;
3155 check(TOKsemicolon, "continue statement");
3156 s = new ContinueStatement(loc, ident);
3157 break;
3160 case TOKgoto:
3161 { Identifier *ident;
3163 nextToken();
3164 if (token.value == TOKdefault)
3166 nextToken();
3167 s = new GotoDefaultStatement(loc);
3169 else if (token.value == TOKcase)
3171 Expression *exp = NULL;
3173 nextToken();
3174 if (token.value != TOKsemicolon)
3175 exp = parseExpression();
3176 s = new GotoCaseStatement(loc, exp);
3178 else
3180 if (token.value != TOKidentifier)
3181 { error("Identifier expected following goto");
3182 ident = NULL;
3184 else
3185 { ident = token.ident;
3186 nextToken();
3188 s = new GotoStatement(loc, ident);
3190 if (token.value != TOKsemicolon && token.value != TOKendline) {
3191 error("expected %s after goto statement, not '%s'", endToken(), token.toChars());
3193 break;
3196 case TOKsynchronized:
3197 { Expression *exp;
3198 Statement *body;
3200 nextToken();
3201 if (token.value == TOKlparen)
3203 nextToken();
3204 exp = parseExpression();
3205 check(TOKrparen);
3207 else
3208 exp = NULL;
3209 body = parseStatement(PSscope);
3210 s = new SynchronizedStatement(loc, exp, body);
3211 break;
3214 case TOKwith:
3215 { Expression *exp;
3216 Statement *body;
3218 nextToken();
3219 check(TOKlparen);
3220 exp = parseExpression();
3221 check(TOKrparen);
3222 body = parseStatement(PSscope);
3223 s = new WithStatement(loc, exp, body);
3224 break;
3227 case TOKtry:
3228 { Statement *body;
3229 Array *catches = NULL;
3230 Statement *finalbody = NULL;
3232 nextToken();
3233 body = parseStatement(PSscope);
3234 while (token.value == TOKcatch)
3236 Statement *handler;
3237 Catch *c;
3238 Type *t;
3239 Identifier *id;
3240 Loc loc = this->loc;
3242 nextToken();
3243 if (token.value == startBlockTok)
3245 t = NULL;
3246 id = NULL;
3248 else
3250 check(TOKlparen);
3251 t = parseBasicType();
3252 id = NULL;
3253 t = parseDeclarator(t, &id);
3254 check(TOKrparen);
3256 handler = parseStatement(PScolon);
3257 c = new Catch(loc, t, id, handler);
3258 if (!catches)
3259 catches = new Array();
3260 catches->push(c);
3263 if (token.value == TOKfinally)
3264 { nextToken();
3265 finalbody = parseStatement(PScolon);
3268 s = body;
3269 if (!catches && !finalbody)
3270 error("catch or finally expected following try");
3271 else
3272 { if (catches)
3273 s = new TryCatchStatement(loc, body, catches);
3274 if (finalbody)
3275 s = new TryFinallyStatement(loc, s, finalbody);
3277 break;
3280 case TOKthrow:
3281 { Expression *exp;
3283 nextToken();
3284 exp = parseExpression();
3285 if (token.value != TOKsemicolon && token.value != TOKendline) {
3286 error("%s expected after throw statement, not '%s'", endToken(), token.toChars());
3288 s = new ThrowStatement(loc, exp);
3289 break;
3292 case TOKvolatile:
3293 nextToken();
3294 s = parseStatement(PSsemi | PScurlyscope);
3295 s = new VolatileStatement(loc, s);
3296 break;
3298 case TOKasm:
3299 { Statements *statements;
3300 Identifier *label;
3301 Loc labelloc;
3302 Token *toklist;
3303 Token **ptoklist;
3305 // Parse the asm block into a sequence of AsmStatements,
3306 // each AsmStatement is one instruction.
3307 // Separate out labels.
3308 // Defer parsing of AsmStatements until semantic processing.
3310 nextToken();
3311 #if GDC_EXTENDED_ASM_SYNTAX
3312 if (token.value == TOKlparen)
3314 nextToken();
3315 s = parseExtAsm(1);
3316 break;
3318 #endif
3319 check(startBlockTok);
3320 toklist = NULL;
3321 ptoklist = &toklist;
3322 label = NULL;
3323 statements = new Statements();
3324 while (1)
3326 switch (token.value)
3328 case TOKidentifier:
3329 if (!toklist)
3331 // Look ahead to see if it is a label
3332 t = peek(&token);
3333 if (t->value == TOKcolon)
3334 { // It's a label
3335 label = token.ident;
3336 labelloc = this->loc;
3337 nextToken();
3338 nextToken();
3339 continue;
3342 goto Ldefault;
3344 case TOKrcurly:
3345 if (toklist || label)
3347 error("asm statements must end in ';'");
3349 break;
3351 case TOKendline:
3352 case TOKsemicolon:
3353 s = NULL;
3354 if (toklist || label)
3355 { // Create AsmStatement from list of tokens we've saved
3356 s = new AsmStatement(this->loc, toklist);
3357 toklist = NULL;
3358 ptoklist = &toklist;
3359 if (label)
3360 { s = new LabelStatement(labelloc, label, s);
3361 label = NULL;
3363 statements->push(s);
3365 nextToken();
3366 continue;
3368 case TOKeof:
3369 /* { */
3370 error("matching '}' expected, not end of file");
3371 break;
3373 case TOKlparen:
3374 case TOKstring:
3375 // If the first token is a string or '(', parse as extended asm.
3376 if (! toklist)
3378 s = parseExtAsm(0);
3379 statements->push(s);
3380 continue;
3382 // ...else, drop through.
3384 default:
3385 Ldefault:
3386 *ptoklist = new Token();
3387 memcpy(*ptoklist, &token, sizeof(Token));
3388 ptoklist = &(*ptoklist)->next;
3389 *ptoklist = NULL;
3391 nextToken();
3392 continue;
3394 break;
3396 s = new CompoundStatement(loc, statements);
3397 nextToken();
3398 break;
3401 default:
3402 error("found '%s' instead of statement", token.toChars());
3403 goto Lerror;
3405 Lerror:
3406 while (token.value != TOKrcurly &&
3407 token.value != TOKsemicolon &&
3408 token.value != TOKeof)
3409 nextToken();
3410 if (token.value == TOKsemicolon)
3411 nextToken();
3412 s = NULL;
3413 break;
3416 return s;
3419 Statement *Parser::parseExtAsm(int expect_rparen)
3421 Expression * insnTemplate;
3422 Expressions * args = NULL;
3423 Array * argNames = NULL;
3424 Expressions * argConstraints = NULL;
3425 int nOutputArgs = 0;
3426 Expressions * clobbers = NULL;
3427 bool isInputPhase = false; // Output operands first, then input.
3429 insnTemplate = parseExpression();
3430 if (token.value == TOKrparen || token.value == TOKsemicolon)
3431 goto Ldone;
3432 check(TOKcolon);
3433 while (1) {
3434 Expression * arg = NULL;
3435 Identifier * name = NULL;
3436 Expression * constraint = NULL;
3438 switch (token.value)
3440 case TOKsemicolon:
3441 case TOKrparen:
3442 goto Ldone;
3444 case TOKcolon:
3445 nextToken();
3446 goto LnextPhase;
3448 case TOKeof:
3449 error("unterminated statement");
3451 case TOKlbracket:
3452 nextToken();
3453 if (token.value == TOKidentifier)
3455 name = token.ident;
3456 nextToken();
3458 else
3459 error("expected identifier after '['");
3460 check(TOKrbracket);
3461 // drop through
3462 default:
3463 constraint = parsePrimaryExp();
3464 if (constraint->op != TOKstring)
3465 error("expected constant string constraint for operand");
3466 arg = parseAssignExp();
3467 if (! args)
3469 args = new Expressions;
3470 argConstraints = new Expressions;
3471 argNames = new Array;
3473 args->push(arg);
3474 argNames->push(name);
3475 argConstraints->push(constraint);
3476 if (! isInputPhase)
3477 nOutputArgs++;
3479 if (token.value == TOKcomma)
3480 nextToken();
3481 break;
3483 continue;
3484 LnextPhase:
3485 if (! isInputPhase)
3486 isInputPhase = true;
3487 else
3488 break;
3491 while (1)
3493 Expression * clobber;
3495 switch (token.value)
3497 case TOKsemicolon:
3498 case TOKrparen:
3499 goto Ldone;
3501 case TOKeof:
3502 error("unterminated statement");
3504 default:
3505 clobber = parseAssignExp();
3506 if (clobber->op != TOKstring)
3507 error("expected constant string constraint for clobber name");
3508 if (! clobbers)
3509 clobbers = new Expressions;
3510 clobbers->push(clobber);
3512 if (token.value == TOKcomma)
3513 nextToken();
3514 break;
3517 Ldone:
3518 if (expect_rparen)
3519 check(TOKrparen);
3520 else
3521 check(TOKsemicolon);
3523 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3524 argConstraints, nOutputArgs, clobbers);
3527 void Parser::optionalEndline() {
3528 while (token.value == TOKendline) {
3529 nextToken();
3533 void Parser::check(enum TOK value)
3535 check(loc, value);
3538 void Parser::check(Loc loc, enum TOK value)
3540 if (token.value != value)
3541 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3542 nextToken();
3545 void Parser::check(enum TOK value, char *string)
3547 if (token.value != value)
3548 error("found '%s' when expecting '%s' following '%s'",
3549 token.toChars(), Token::toChars(value), string);
3550 nextToken();
3553 char *Parser::endToken()
3555 return "semicolon";
3558 char *DltParser::endToken()
3560 return "newline";
3563 void Parser::checkLParen() { check(TOKlparen); }
3564 void Parser::checkRParen() { check(TOKrparen); }
3566 void DltParser::checkLParen() { }
3567 void DltParser::checkRParen() { }
3569 /************************************
3570 * Determine if the scanner is sitting on the start of a declaration.
3571 * Input:
3572 * needId 0 no identifier
3573 * 1 identifier optional
3574 * 2 must have identifier
3577 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3579 int haveId = 0;
3581 if (!isBasicType(&t))
3582 return FALSE;
3583 if (!isDeclarator(&t, &haveId, endtok))
3584 return FALSE;
3585 if ( needId == 1 ||
3586 (needId == 0 && !haveId) ||
3587 (needId == 2 && haveId))
3588 { if (pt)
3589 *pt = t;
3590 return TRUE;
3592 else
3593 return FALSE;
3596 int Parser::isBasicType(Token **pt)
3598 // This code parallels parseBasicType()
3599 Token *t = *pt;
3600 Token *t2;
3601 int parens;
3603 switch (t->value)
3605 CASE_BASIC_TYPES:
3606 t = peek(t);
3607 break;
3609 case TOKidentifier:
3610 t = peek(t);
3611 if (t->value == TOKnot)
3613 goto L4;
3615 goto L3;
3616 while (1)
3619 t = peek(t);
3621 if (t->value == TOKdot)
3623 Ldot:
3624 t = peek(t);
3625 if (t->value != TOKidentifier)
3626 goto Lfalse;
3627 t = peek(t);
3628 if (t->value != TOKnot)
3629 goto L3;
3631 t = peek(t);
3632 if (t->value != TOKlparen)
3633 goto Lfalse;
3634 if (!skipParens(t, &t))
3635 goto Lfalse;
3637 else
3638 break;
3640 break;
3642 case TOKdot:
3643 goto Ldot;
3645 case TOKtypeof:
3646 /* typeof(exp).identifier...
3648 t = peek(t);
3649 if (t->value != TOKlparen)
3650 goto Lfalse;
3651 if (!skipParens(t, &t))
3652 goto Lfalse;
3653 goto L2;
3655 default:
3656 goto Lfalse;
3658 *pt = t;
3659 return TRUE;
3661 Lfalse:
3662 return FALSE;
3665 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3666 { // This code parallels parseDeclarator()
3667 Token *t = *pt;
3668 int parens;
3670 //printf("Parser::isDeclarator()\n");
3671 //t->print();
3672 if (t->value == TOKassign)
3673 return FALSE;
3675 while (1)
3677 parens = FALSE;
3678 switch (t->value)
3680 case TOKmul:
3681 case TOKand:
3682 t = peek(t);
3683 continue;
3685 case TOKlbracket:
3686 t = peek(t);
3687 if (t->value == TOKrbracket)
3689 t = peek(t);
3691 else if (isDeclaration(t, 0, TOKrbracket, &t))
3692 { // It's an associative array declaration
3693 t = peek(t);
3695 else
3697 // [ expression ]
3698 // [ expression .. expression ]
3699 if (!isExpression(&t))
3700 return FALSE;
3701 if (t->value == TOKslice)
3702 { t = peek(t);
3703 if (!isExpression(&t))
3704 return FALSE;
3706 if (t->value != TOKrbracket)
3707 return FALSE;
3708 t = peek(t);
3710 continue;
3712 case TOKidentifier:
3713 if (*haveId)
3714 return FALSE;
3715 *haveId = TRUE;
3716 t = peek(t);
3717 break;
3719 case TOKlparen:
3720 t = peek(t);
3722 if (t->value == TOKrparen)
3723 return FALSE; // () is not a declarator
3725 /* Regard ( identifier ) as not a declarator
3726 * BUG: what about ( *identifier ) in
3727 * f(*p)(x);
3728 * where f is a class instance with overloaded () ?
3729 * Should we just disallow C-style function pointer declarations?
3731 if (t->value == TOKidentifier)
3732 { Token *t2 = peek(t);
3733 if (t2->value == TOKrparen)
3734 return FALSE;
3738 if (!isDeclarator(&t, haveId, TOKrparen))
3739 return FALSE;
3740 t = peek(t);
3741 parens = TRUE;
3742 break;
3744 case TOKdelegate:
3745 case TOKfunction:
3746 t = peek(t);
3747 if (!isParameters(&t))
3748 return FALSE;
3749 continue;
3751 break;
3754 while (1)
3756 switch (t->value)
3758 #if CARRAYDECL
3759 case TOKlbracket:
3760 parens = FALSE;
3761 t = peek(t);
3762 if (t->value == TOKrbracket)
3764 t = peek(t);
3766 else if (isDeclaration(t, 0, TOKrbracket, &t))
3767 { // It's an associative array declaration
3768 t = peek(t);
3770 else
3772 // [ expression ]
3773 if (!isExpression(&t))
3774 return FALSE;
3775 if (t->value != TOKrbracket)
3776 return FALSE;
3777 t = peek(t);
3779 continue;
3780 #endif
3782 case TOKlparen:
3783 parens = FALSE;
3784 if (!isParameters(&t))
3785 return FALSE;
3786 continue;
3788 // Valid tokens that follow a declaration
3789 case TOKrparen:
3790 case TOKrbracket:
3791 case TOKassign:
3792 case TOKcomma:
3793 case TOKendline:
3794 case TOKsemicolon:
3795 case TOKlcurly:
3796 case TOKin:
3797 // The !parens is to disallow unnecessary parentheses
3798 if (!parens && (endtok == TOKreserved || endtok == t->value))
3799 { *pt = t;
3800 return TRUE;
3802 return FALSE;
3804 default:
3805 return FALSE;
3811 int Parser::isParameters(Token **pt)
3812 { // This code parallels parseParameters()
3813 Token *t = *pt;
3814 int tmp;
3816 //printf("isParameters()\n");
3817 if (t->value != TOKlparen)
3818 return FALSE;
3820 t = peek(t);
3821 while (1)
3823 switch (t->value)
3825 case TOKrparen:
3826 break;
3828 case TOKdotdotdot:
3829 t = peek(t);
3830 break;
3832 case TOKin:
3833 case TOKout:
3834 case TOKinout:
3835 case TOKref:
3836 case TOKlazy:
3837 t = peek(t);
3838 default:
3839 if (!isBasicType(&t))
3840 return FALSE;
3841 tmp = FALSE;
3842 if (t->value != TOKdotdotdot &&
3843 !isDeclarator(&t, &tmp, TOKreserved))
3844 return FALSE;
3845 if (t->value == TOKassign)
3846 { t = peek(t);
3847 if (!isExpression(&t))
3848 return FALSE;
3850 if (t->value == TOKdotdotdot)
3852 t = peek(t);
3853 break;
3855 if (t->value == TOKcomma)
3856 { t = peek(t);
3857 continue;
3859 break;
3861 break;
3863 if (t->value != TOKrparen)
3864 return FALSE;
3865 t = peek(t);
3866 *pt = t;
3867 return TRUE;
3870 int Parser::isExpression(Token **pt)
3872 // This is supposed to determine if something is an expression.
3873 // What it actually does is scan until a closing right bracket
3874 // is found.
3876 Token *t = *pt;
3877 int brnest = 0;
3878 int panest = 0;
3880 for (;; t = peek(t))
3882 switch (t->value)
3884 case TOKlbracket:
3885 brnest++;
3886 continue;
3888 case TOKrbracket:
3889 if (--brnest >= 0)
3890 continue;
3891 break;
3893 case TOKlparen:
3894 panest++;
3895 continue;
3897 case TOKcomma:
3898 if (brnest || panest)
3899 continue;
3900 break;
3902 case TOKrparen:
3903 if (--panest >= 0)
3904 continue;
3905 break;
3907 case TOKslice:
3908 if (brnest)
3909 continue;
3910 break;
3912 case TOKeof:
3913 return FALSE;
3915 default:
3916 continue;
3918 break;
3921 *pt = t;
3922 return TRUE;
3925 /**********************************************
3926 * Skip over
3927 * instance foo.bar(parameters...)
3928 * Output:
3929 * if (pt), *pt is set to the token following the closing )
3930 * Returns:
3931 * 1 it's valid instance syntax
3932 * 0 invalid instance syntax
3935 int Parser::isTemplateInstance(Token *t, Token **pt)
3937 t = peek(t);
3938 if (t->value != TOKdot)
3940 if (t->value != TOKidentifier)
3941 goto Lfalse;
3942 t = peek(t);
3944 while (t->value == TOKdot)
3946 t = peek(t);
3947 if (t->value != TOKidentifier)
3948 goto Lfalse;
3949 t = peek(t);
3951 if (t->value != TOKlparen)
3952 goto Lfalse;
3954 // Skip over the template arguments
3955 while (1)
3957 while (1)
3959 t = peek(t);
3960 switch (t->value)
3962 case TOKlparen:
3963 if (!skipParens(t, &t))
3964 goto Lfalse;
3965 continue;
3966 case TOKrparen:
3967 break;
3968 case TOKcomma:
3969 break;
3970 case TOKeof:
3971 case TOKsemicolon:
3972 goto Lfalse;
3973 default:
3974 continue;
3976 break;
3979 if (t->value != TOKcomma)
3980 break;
3982 if (t->value != TOKrparen)
3983 goto Lfalse;
3984 t = peek(t);
3985 if (pt)
3986 *pt = t;
3987 return 1;
3989 Lfalse:
3990 return 0;
3993 /*******************************************
3994 * Skip parens, brackets.
3995 * Input:
3996 * t is on opening (
3997 * Output:
3998 * *pt is set to closing token, which is ')' on success
3999 * Returns:
4000 * !=0 successful
4001 * 0 some parsing error
4004 int Parser::skipParens(Token *t, Token **pt)
4006 int parens = 0;
4008 while (1)
4010 switch (t->value)
4012 case TOKlparen:
4013 parens++;
4014 break;
4016 case TOKrparen:
4017 parens--;
4018 if (parens < 0)
4019 goto Lfalse;
4020 if (parens == 0)
4021 goto Ldone;
4022 break;
4024 case TOKeof:
4025 case TOKsemicolon:
4026 goto Lfalse;
4028 default:
4029 break;
4031 t = peek(t);
4034 Ldone:
4035 if (*pt)
4036 *pt = t;
4037 return 1;
4039 Lfalse:
4040 return 0;
4043 /********************************* Expression Parser ***************************/
4045 Expression *Parser::parsePrimaryExp()
4046 { Expression *e;
4047 Type *t;
4048 Identifier *id;
4049 enum TOK save;
4050 Loc loc = this->loc;
4052 switch (token.value)
4054 case TOKidentifier:
4055 id = token.ident;
4056 nextToken();
4057 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4058 { // identifier!(template-argument-list)
4059 TemplateInstance *tempinst;
4061 tempinst = new TemplateInstance(loc, id);
4062 nextToken();
4063 tempinst->tiargs = parseTemplateArgumentList();
4064 e = new ScopeExp(loc, tempinst);
4066 else
4067 e = new IdentifierExp(loc, id);
4068 break;
4070 case TOKdollar:
4071 if (!inBrackets)
4072 error("'$' is valid only inside [] of index or slice");
4073 e = new DollarExp(loc);
4074 nextToken();
4075 break;
4077 case TOKdot:
4078 // Signal global scope '.' operator with "" identifier
4079 e = new IdentifierExp(loc, Id::empty);
4080 break;
4082 case TOKthis:
4083 e = new ThisExp(loc);
4084 nextToken();
4085 break;
4087 case TOKsuper:
4088 e = new SuperExp(loc);
4089 nextToken();
4090 break;
4092 case TOKint32v:
4093 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
4094 nextToken();
4095 break;
4097 case TOKuns32v:
4098 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
4099 nextToken();
4100 break;
4102 case TOKint64v:
4103 e = new IntegerExp(loc, token.int64value, Type::tint64);
4104 nextToken();
4105 break;
4107 case TOKuns64v:
4108 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
4109 nextToken();
4110 break;
4112 case TOKfloat32v:
4113 e = new RealExp(loc, token.float80value, Type::tfloat32);
4114 nextToken();
4115 break;
4117 case TOKfloat64v:
4118 e = new RealExp(loc, token.float80value, Type::tfloat64);
4119 nextToken();
4120 break;
4122 case TOKfloat80v:
4123 e = new RealExp(loc, token.float80value, Type::tfloat80);
4124 nextToken();
4125 break;
4127 case TOKimaginary32v:
4128 e = new RealExp(loc, token.float80value, Type::timaginary32);
4129 nextToken();
4130 break;
4132 case TOKimaginary64v:
4133 e = new RealExp(loc, token.float80value, Type::timaginary64);
4134 nextToken();
4135 break;
4137 case TOKimaginary80v:
4138 e = new RealExp(loc, token.float80value, Type::timaginary80);
4139 nextToken();
4140 break;
4142 case TOKnull:
4143 e = new NullExp(loc);
4144 nextToken();
4145 break;
4147 case TOKtrue:
4148 e = new IntegerExp(loc, 1, Type::tbool);
4149 nextToken();
4150 break;
4152 case TOKfalse:
4153 e = new IntegerExp(loc, 0, Type::tbool);
4154 nextToken();
4155 break;
4157 case TOKcharv:
4158 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
4159 nextToken();
4160 break;
4162 case TOKwcharv:
4163 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
4164 nextToken();
4165 break;
4167 case TOKdcharv:
4168 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
4169 nextToken();
4170 break;
4172 case TOKstring:
4173 { unsigned char *s;
4174 unsigned len;
4175 unsigned char postfix;
4177 // cat adjacent strings
4178 s = token.ustring;
4179 len = token.len;
4180 postfix = token.postfix;
4181 while (1)
4183 nextToken();
4184 if (token.value == TOKstring)
4185 { unsigned len1;
4186 unsigned len2;
4187 unsigned char *s2;
4189 if (token.postfix)
4190 { if (token.postfix != postfix)
4191 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4192 postfix = token.postfix;
4195 len1 = len;
4196 len2 = token.len;
4197 len = len1 + len2;
4198 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4199 memcpy(s2, s, len1 * sizeof(unsigned char));
4200 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4201 s = s2;
4203 else
4204 break;
4206 e = new StringExp(loc, s, len, postfix);
4207 break;
4210 CASE_BASIC_TYPES_X(t):
4211 nextToken();
4213 check(TOKdot, t->toChars());
4214 if (token.value != TOKidentifier)
4215 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4216 goto Lerr;
4218 e = new TypeDotIdExp(loc, t, token.ident);
4219 nextToken();
4220 break;
4222 case TOKtypeof:
4223 { Expression *exp;
4225 nextToken();
4226 check(TOKlparen);
4227 exp = parseExpression();
4228 check(TOKrparen);
4229 t = new TypeTypeof(loc, exp);
4230 if (token.value == TOKdot)
4231 goto L1;
4232 e = new TypeExp(loc, t);
4233 break;
4236 case TOKtypeid:
4237 { Type *t;
4239 nextToken();
4240 check(TOKlparen, "typeid");
4241 t = parseBasicType();
4242 t = parseDeclarator(t,NULL); // ( type )
4243 check(TOKrparen);
4244 e = new TypeidExp(loc, t);
4245 break;
4248 case TOKis:
4249 { Type *targ;
4250 Identifier *ident = NULL;
4251 Type *tspec = NULL;
4252 enum TOK tok = TOKreserved;
4253 enum TOK tok2 = TOKreserved;
4254 Loc loc = this->loc;
4256 nextToken();
4257 if (token.value == TOKlparen)
4259 nextToken();
4260 targ = parseBasicType();
4261 targ = parseDeclarator(targ, &ident);
4262 if (token.value == TOKcolon || token.value == TOKequal)
4264 tok = token.value;
4265 nextToken();
4266 if (tok == TOKequal &&
4267 (token.value == TOKtypedef ||
4268 token.value == TOKstruct ||
4269 token.value == TOKunion ||
4270 token.value == TOKclass ||
4271 token.value == TOKsuper ||
4272 token.value == TOKenum ||
4273 token.value == TOKinterface ||
4274 token.value == TOKfunction ||
4275 token.value == TOKdelegate ||
4276 token.value == TOKreturn))
4278 tok2 = token.value;
4279 nextToken();
4281 else
4283 tspec = parseBasicType();
4284 tspec = parseDeclarator(tspec, NULL);
4287 check(TOKrparen);
4289 else
4290 { error("(type identifier : specialization) expected following is");
4291 goto Lerr;
4293 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4294 break;
4297 case TOKassert:
4298 { Expression *msg = NULL;
4300 nextToken();
4302 checkLParen();
4303 e = parseAssignExp();
4304 if (token.value == (dltSyntax ? TOKelse : TOKcomma))
4305 { nextToken();
4306 msg = parseAssignExp();
4308 checkRParen();
4310 e = new AssertExp(loc, e, msg);
4311 break;
4314 case TOKmixin:
4316 nextToken();
4317 check(TOKlparen, "mixin");
4318 e = parseAssignExp();
4319 check(TOKrparen);
4320 e = new CompileExp(loc, e);
4321 break;
4324 case TOKimport:
4326 nextToken();
4327 check(TOKlparen, "import");
4328 e = parseAssignExp();
4329 check(TOKrparen);
4330 e = new FileExp(loc, e);
4331 break;
4334 case TOKlparen:
4335 if (peekPastParen(&token)->value == TOKlcurly)
4336 { // (arguments) { statements... }
4337 save = TOKdelegate;
4338 goto case_delegate;
4340 // ( expression )
4341 nextToken();
4342 e = parseExpression();
4343 check(loc, TOKrparen);
4344 break;
4346 case TOKlbracket:
4347 { /* Parse array literals and associative array literals:
4348 * [ value, value, value ... ]
4349 * [ key:value, key:value, key:value ... ]
4351 Expressions *values = new Expressions();
4352 Expressions *keys = NULL;
4354 nextToken();
4355 if (token.value != TOKrbracket)
4357 while (1)
4359 Expression *e = parseAssignExp();
4360 if (token.value == TOKcolon && (keys || values->dim == 0))
4361 { nextToken();
4362 if (!keys)
4363 keys = new Expressions();
4364 keys->push(e);
4365 e = parseAssignExp();
4367 else if (keys)
4368 { error("'key:value' expected for associative array literal");
4369 delete keys;
4370 keys = NULL;
4372 values->push(e);
4373 if (token.value == TOKrbracket)
4374 break;
4375 check(TOKcomma);
4378 check(TOKrbracket);
4380 if (keys)
4381 e = new AssocArrayLiteralExp(loc, keys, values);
4382 else
4383 e = new ArrayLiteralExp(loc, values);
4384 break;
4387 case TOKlcurly:
4388 // { statements... }
4389 save = TOKdelegate;
4390 goto case_delegate;
4392 case TOKfunction:
4393 case TOKdelegate:
4394 save = token.value;
4395 nextToken();
4396 case_delegate:
4398 /* function type(parameters) { body }
4399 * delegate type(parameters) { body }
4401 Arguments *arguments;
4402 int varargs;
4403 FuncLiteralDeclaration *fd;
4404 Type *t;
4406 if (token.value == TOKlcurly)
4408 t = NULL;
4409 varargs = 0;
4410 arguments = new Arguments();
4412 else
4414 if (token.value == TOKlparen)
4415 t = NULL;
4416 else
4418 t = parseBasicType();
4419 t = parseBasicType2(t); // function return type
4421 arguments = parseParameters(&varargs);
4423 t = new TypeFunction(arguments, t, varargs, linkage);
4424 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4425 parseContracts(fd);
4426 e = new FuncExp(loc, fd);
4427 break;
4430 default:
4431 error("expression expected, not '%s'", token.toChars());
4432 Lerr:
4433 // Anything for e, as long as it's not NULL
4434 e = new IntegerExp(loc, 0, Type::tint32);
4435 nextToken();
4436 break;
4438 return parsePostExp(e);
4441 Expression *Parser::parsePostExp(Expression *e)
4443 Loc loc;
4445 while (1)
4447 loc = this->loc;
4448 switch (token.value)
4450 case TOKdot:
4451 nextToken();
4452 if (token.value == TOKidentifier)
4453 { Identifier *id = token.ident;
4455 nextToken();
4456 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4457 { // identifier!(template-argument-list)
4458 TemplateInstance *tempinst;
4460 tempinst = new TemplateInstance(loc, id);
4461 nextToken();
4462 tempinst->tiargs = parseTemplateArgumentList();
4463 e = new DotTemplateInstanceExp(loc, e, tempinst);
4465 else
4466 e = new DotIdExp(loc, e, id);
4467 continue;
4469 else if (token.value == TOKnew)
4471 e = parseNewExp(e);
4472 continue;
4474 else
4475 error("identifier expected following '.', not '%s'", token.toChars());
4476 break;
4478 case TOKplusplus:
4479 e = new PostExp(TOKplusplus, loc, e);
4480 break;
4482 case TOKminusminus:
4483 e = new PostExp(TOKminusminus, loc, e);
4484 break;
4486 case TOKlparen:
4487 e = new CallExp(loc, e, parseArguments());
4488 continue;
4490 case TOKlbracket:
4491 { // array dereferences:
4492 // array[index]
4493 // array[]
4494 // array[lwr .. upr]
4495 Expression *index;
4496 Expression *upr;
4498 inBrackets++;
4499 nextToken();
4500 if (token.value == TOKrbracket)
4501 { // array[]
4502 e = new SliceExp(loc, e, NULL, NULL);
4503 nextToken();
4505 else
4507 index = parseAssignExp();
4508 if (token.value == TOKslice)
4509 { // array[lwr .. upr]
4510 nextToken();
4511 upr = parseAssignExp();
4512 e = new SliceExp(loc, e, index, upr);
4514 else
4515 { // array[index, i2, i3, i4, ...]
4516 Expressions *arguments = new Expressions();
4517 arguments->push(index);
4518 if (token.value == TOKcomma)
4520 nextToken();
4521 while (1)
4522 { Expression *arg;
4524 arg = parseAssignExp();
4525 arguments->push(arg);
4526 if (token.value == TOKrbracket)
4527 break;
4528 check(TOKcomma);
4531 e = new ArrayExp(loc, e, arguments);
4533 check(TOKrbracket);
4534 inBrackets--;
4536 continue;
4539 default:
4540 return e;
4542 nextToken();
4546 Expression *Parser::parseUnaryExp()
4547 { Expression *e;
4548 Loc loc = this->loc;
4550 switch (token.value)
4552 case TOKand:
4553 nextToken();
4554 e = parseUnaryExp();
4555 e = new AddrExp(loc, e);
4556 break;
4558 case TOKplusplus:
4559 nextToken();
4560 e = parseUnaryExp();
4561 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4562 break;
4564 case TOKminusminus:
4565 nextToken();
4566 e = parseUnaryExp();
4567 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4568 break;
4570 case TOKmul:
4571 nextToken();
4572 e = parseUnaryExp();
4573 e = new PtrExp(loc, e);
4574 break;
4576 case TOKmin:
4577 nextToken();
4578 e = parseUnaryExp();
4579 e = new NegExp(loc, e);
4580 break;
4582 case TOKadd:
4583 nextToken();
4584 e = parseUnaryExp();
4585 e = new UAddExp(loc, e);
4586 break;
4588 case TOKnot:
4589 nextToken();
4590 e = parseUnaryExp();
4591 e = new NotExp(loc, e);
4592 break;
4594 case TOKtilde:
4595 nextToken();
4596 e = parseUnaryExp();
4597 e = new ComExp(loc, e);
4598 break;
4600 case TOKdelete:
4601 nextToken();
4602 e = parseUnaryExp();
4603 e = new DeleteExp(loc, e);
4604 break;
4606 case TOKnew:
4607 e = parseNewExp(NULL);
4608 break;
4610 case TOKcast: // cast(type) expression
4611 { Type *t;
4613 nextToken();
4614 check(TOKlparen);
4615 t = parseBasicType();
4616 t = parseDeclarator(t,NULL); // ( type )
4617 check(TOKrparen);
4619 e = parseUnaryExp();
4620 e = new CastExp(loc, e, t);
4621 break;
4624 case TOKlparen:
4625 { Token *tk;
4627 tk = peek(&token);
4628 #if CCASTSYNTAX
4629 // If cast
4630 if (isDeclaration(tk, 0, TOKrparen, &tk))
4632 tk = peek(tk); // skip over right parenthesis
4633 switch (tk->value)
4635 case TOKdot:
4636 case TOKplusplus:
4637 case TOKminusminus:
4638 case TOKnot:
4639 case TOKdelete:
4640 case TOKnew:
4641 case TOKlparen:
4642 case TOKidentifier:
4643 case TOKthis:
4644 case TOKsuper:
4645 case TOKint32v:
4646 case TOKuns32v:
4647 case TOKint64v:
4648 case TOKuns64v:
4649 case TOKfloat32v:
4650 case TOKfloat64v:
4651 case TOKfloat80v:
4652 case TOKimaginary32v:
4653 case TOKimaginary64v:
4654 case TOKimaginary80v:
4655 case TOKnull:
4656 case TOKtrue:
4657 case TOKfalse:
4658 case TOKcharv:
4659 case TOKwcharv:
4660 case TOKdcharv:
4661 case TOKstring:
4662 #if 0
4663 case TOKtilde:
4664 case TOKand:
4665 case TOKmul:
4666 case TOKmin:
4667 case TOKadd:
4668 #endif
4669 case TOKfunction:
4670 case TOKdelegate:
4671 case TOKtypeof:
4672 CASE_BASIC_TYPES: // (type)int.size
4673 { // (type) una_exp
4674 Type *t;
4676 nextToken();
4677 t = parseBasicType();
4678 t = parseDeclarator(t,NULL);
4679 check(TOKrparen);
4681 // if .identifier
4682 if (token.value == TOKdot)
4684 nextToken();
4685 if (token.value != TOKidentifier)
4686 { error("Identifier expected following (type).");
4687 return NULL;
4689 e = new TypeDotIdExp(loc, t, token.ident);
4690 nextToken();
4691 e = parsePostExp(e);
4693 else
4695 e = parseUnaryExp();
4696 e = new CastExp(loc, e, t);
4697 error("C style cast illegal, use %s", e->toChars());
4699 return e;
4703 #endif
4704 e = parsePrimaryExp();
4705 break;
4707 default:
4708 e = parsePrimaryExp();
4709 break;
4711 assert(e);
4712 return e;
4715 Expression *Parser::parseMulExp()
4716 { Expression *e;
4717 Expression *e2;
4718 Loc loc = this->loc;
4720 e = parseUnaryExp();
4721 while (1)
4723 switch (token.value)
4725 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4726 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4727 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4729 default:
4730 break;
4732 break;
4734 return e;
4737 Expression *Parser::parseAddExp()
4738 { Expression *e;
4739 Expression *e2;
4740 Loc loc = this->loc;
4742 e = parseMulExp();
4743 while (1)
4745 switch (token.value)
4747 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4748 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4749 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4751 default:
4752 break;
4754 break;
4756 return e;
4759 Expression *Parser::parseShiftExp()
4760 { Expression *e;
4761 Expression *e2;
4762 Loc loc = this->loc;
4764 e = parseAddExp();
4765 while (1)
4767 switch (token.value)
4769 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4770 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4771 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4773 default:
4774 break;
4776 break;
4778 return e;
4781 Expression *Parser::parseRelExp()
4782 { Expression *e;
4783 Expression *e2;
4784 enum TOK op;
4785 Loc loc = this->loc;
4787 e = parseShiftExp();
4788 while (1)
4790 switch (token.value)
4792 case TOKlt:
4793 case TOKle:
4794 case TOKgt:
4795 case TOKge:
4796 case TOKunord:
4797 case TOKlg:
4798 case TOKleg:
4799 case TOKule:
4800 case TOKul:
4801 case TOKuge:
4802 case TOKug:
4803 case TOKue:
4804 op = token.value;
4805 nextToken();
4806 e2 = parseShiftExp();
4807 e = new CmpExp(op, loc, e, e2);
4808 continue;
4810 case TOKin:
4811 nextToken();
4812 e2 = parseShiftExp();
4813 e = new InExp(loc, e, e2);
4814 continue;
4816 default:
4817 break;
4819 break;
4821 return e;
4824 Expression *Parser::parseEqualExp()
4825 { Expression *e;
4826 Expression *e2;
4827 Token *t;
4828 Loc loc = this->loc;
4830 e = parseRelExp();
4831 while (1)
4832 { enum TOK value = token.value;
4834 switch (value)
4836 case TOKequal:
4837 case TOKnotequal:
4838 nextToken();
4839 e2 = parseRelExp();
4840 e = new EqualExp(value, loc, e, e2);
4841 continue;
4843 case TOKidentity:
4844 error("'===' is no longer legal, use 'is' instead");
4845 goto L1;
4847 case TOKnotidentity:
4848 error("'!==' is no longer legal, use '!is' instead");
4849 goto L1;
4851 case TOKis:
4852 value = TOKidentity;
4853 goto L1;
4855 case TOKnot:
4856 // Attempt to identify '!is'
4857 t = peek(&token);
4858 if (t->value != TOKis)
4859 break;
4860 nextToken();
4861 value = TOKnotidentity;
4862 goto L1;
4865 nextToken();
4866 e2 = parseRelExp();
4867 e = new IdentityExp(value, loc, e, e2);
4868 continue;
4870 default:
4871 break;
4873 break;
4875 return e;
4878 Expression *Parser::parseCmpExp()
4879 { Expression *e;
4880 Expression *e2;
4881 Token *t;
4882 Loc loc = this->loc;
4884 e = parseShiftExp();
4885 enum TOK op = token.value;
4887 switch (op)
4889 case TOKequal:
4890 case TOKnotequal:
4891 nextToken();
4892 e2 = parseShiftExp();
4893 e = new EqualExp(op, loc, e, e2);
4894 break;
4896 case TOKis:
4897 op = TOKidentity;
4898 goto L1;
4900 case TOKnot:
4901 // Attempt to identify '!is'
4902 t = peek(&token);
4903 if (t->value != TOKis)
4904 break;
4905 nextToken();
4906 op = TOKnotidentity;
4907 goto L1;
4910 nextToken();
4911 e2 = parseShiftExp();
4912 e = new IdentityExp(op, loc, e, e2);
4913 break;
4915 case TOKlt:
4916 case TOKle:
4917 case TOKgt:
4918 case TOKge:
4919 case TOKunord:
4920 case TOKlg:
4921 case TOKleg:
4922 case TOKule:
4923 case TOKul:
4924 case TOKuge:
4925 case TOKug:
4926 case TOKue:
4927 nextToken();
4928 e2 = parseShiftExp();
4929 e = new CmpExp(op, loc, e, e2);
4930 break;
4932 case TOKin:
4933 nextToken();
4934 e2 = parseShiftExp();
4935 e = new InExp(loc, e, e2);
4936 break;
4938 default:
4939 break;
4941 return e;
4944 Expression *Parser::parseAndExp()
4945 { Expression *e;
4946 Expression *e2;
4947 Loc loc = this->loc;
4949 if (global.params.Dversion == 1)
4951 e = parseEqualExp();
4952 while (token.value == TOKand)
4954 nextToken();
4955 e2 = parseEqualExp();
4956 e = new AndExp(loc,e,e2);
4957 loc = this->loc;
4960 else
4962 e = parseCmpExp();
4963 while (token.value == TOKand)
4965 nextToken();
4966 e2 = parseCmpExp();
4967 e = new AndExp(loc,e,e2);
4968 loc = this->loc;
4971 return e;
4974 Expression *Parser::parseXorExp()
4975 { Expression *e;
4976 Expression *e2;
4977 Loc loc = this->loc;
4979 e = parseAndExp();
4980 while (token.value == TOKxor)
4982 nextToken();
4983 e2 = parseAndExp();
4984 e = new XorExp(loc, e, e2);
4986 return e;
4989 Expression *Parser::parseOrExp()
4990 { Expression *e;
4991 Expression *e2;
4992 Loc loc = this->loc;
4994 e = parseXorExp();
4995 while (token.value == TOKor)
4997 nextToken();
4998 e2 = parseXorExp();
4999 e = new OrExp(loc, e, e2);
5001 return e;
5004 Expression *Parser::parseAndAndExp()
5005 { Expression *e;
5006 Expression *e2;
5007 Loc loc = this->loc;
5009 e = parseOrExp();
5010 while (token.value == TOKandand)
5012 nextToken();
5013 e2 = parseOrExp();
5014 e = new AndAndExp(loc, e, e2);
5016 return e;
5019 Expression *Parser::parseOrOrExp()
5020 { Expression *e;
5021 Expression *e2;
5022 Loc loc = this->loc;
5024 e = parseAndAndExp();
5025 while (token.value == TOKoror)
5027 nextToken();
5028 e2 = parseAndAndExp();
5029 e = new OrOrExp(loc, e, e2);
5031 return e;
5034 Expression *Parser::parseCondExp()
5035 { Expression *e;
5036 Expression *e1;
5037 Expression *e2;
5038 Loc loc = this->loc;
5040 e = parseOrOrExp();
5041 if (token.value == TOKquestion)
5043 nextToken();
5044 e1 = parseExpression();
5045 check(TOKcolon);
5046 e2 = parseCondExp();
5047 e = new CondExp(loc, e, e1, e2);
5049 return e;
5052 Expression *Parser::parseAssignExp()
5053 { Expression *e;
5054 Expression *e2;
5055 Loc loc;
5057 e = parseCondExp();
5058 while (1)
5060 loc = this->loc;
5061 switch (token.value)
5063 #define X(tok,ector) \
5064 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5066 X(TOKassign, AssignExp);
5067 X(TOKaddass, AddAssignExp);
5068 X(TOKminass, MinAssignExp);
5069 X(TOKmulass, MulAssignExp);
5070 X(TOKdivass, DivAssignExp);
5071 X(TOKmodass, ModAssignExp);
5072 X(TOKandass, AndAssignExp);
5073 X(TOKorass, OrAssignExp);
5074 X(TOKxorass, XorAssignExp);
5075 X(TOKshlass, ShlAssignExp);
5076 X(TOKshrass, ShrAssignExp);
5077 X(TOKushrass, UshrAssignExp);
5078 X(TOKcatass, CatAssignExp);
5080 #undef X
5081 default:
5082 break;
5084 break;
5086 return e;
5089 Expression *Parser::parseExpression()
5090 { Expression *e;
5091 Expression *e2;
5092 Loc loc = this->loc;
5094 //printf("Parser::parseExpression()\n");
5095 e = parseAssignExp();
5096 while (token.value == TOKcomma)
5098 nextToken();
5099 e2 = parseAssignExp();
5100 e = new CommaExp(loc, e, e2);
5101 loc = this->loc;
5103 return e;
5107 /*************************
5108 * Collect argument list.
5109 * Assume current token is '(' or '['.
5112 Expressions *Parser::parseArguments()
5113 { // function call
5114 Expressions *arguments;
5115 Expression *arg;
5116 enum TOK endtok;
5118 arguments = new Expressions();
5119 if (token.value == TOKlbracket)
5120 endtok = TOKrbracket;
5121 else
5122 endtok = TOKrparen;
5125 nextToken();
5126 if (token.value != endtok)
5128 while (1)
5130 arg = parseAssignExp();
5131 arguments->push(arg);
5132 if (token.value == endtok)
5133 break;
5134 check(TOKcomma);
5137 check(endtok);
5139 return arguments;
5142 /*******************************************
5145 Expression *Parser::parseNewExp(Expression *thisexp)
5146 { Type *t;
5147 Expressions *newargs;
5148 Expressions *arguments = NULL;
5149 Expression *e;
5150 Loc loc = this->loc;
5152 nextToken();
5153 newargs = NULL;
5154 if (token.value == TOKlparen)
5156 newargs = parseArguments();
5159 // An anonymous nested class starts with "class"
5160 if (token.value == TOKclass)
5162 nextToken();
5163 if (token.value == TOKlparen)
5164 arguments = parseArguments();
5166 BaseClasses *baseclasses = NULL;
5167 if (token.value != TOKlcurly)
5168 baseclasses = parseBaseClasses();
5170 Identifier *id = NULL;
5171 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
5173 if (token.value != TOKlcurly)
5174 { error("{ members } expected for anonymous class");
5175 cd->members = NULL;
5177 else
5179 nextToken();
5180 Array *decl = parseDeclDefs(0);
5181 if (token.value != TOKrcurly)
5182 error("class member expected");
5183 nextToken();
5184 cd->members = decl;
5187 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
5189 return e;
5192 #if LTORARRAYDECL
5193 t = parseBasicType();
5194 t = parseBasicType2(t);
5195 if (t->ty == Taarray)
5197 Type *index = ((TypeAArray *)t)->index;
5199 Expression *e = index->toExpression();
5200 if (e)
5201 { arguments = new Expressions();
5202 arguments->push(e);
5203 t = new TypeDArray(t->next);
5205 else
5207 error("need size of rightmost array, not type %s", index->toChars());
5208 return new NullExp(loc);
5211 else if (t->ty == Tsarray)
5213 TypeSArray *tsa = (TypeSArray *)t;
5214 Expression *e = tsa->dim;
5216 arguments = new Expressions();
5217 arguments->push(e);
5218 t = new TypeDArray(t->next);
5220 else if (token.value == TOKlparen)
5222 arguments = parseArguments();
5224 #else
5225 t = parseBasicType();
5226 while (token.value == TOKmul)
5227 { t = new TypePointer(t);
5228 nextToken();
5230 if (token.value == TOKlbracket)
5232 Expression *e;
5234 nextToken();
5235 e = parseAssignExp();
5236 arguments = new Array();
5237 arguments->push(e);
5238 check(TOKrbracket);
5239 t = parseDeclarator(t, NULL);
5240 t = new TypeDArray(t);
5242 else if (token.value == TOKlparen)
5243 arguments = parseArguments();
5244 #endif
5245 e = new NewExp(loc, thisexp, newargs, t, arguments);
5246 return e;
5249 /**********************************************
5252 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5254 s->addComment(combineComments(blockComment, token.lineComment));
5258 /********************************* ***************************/