Support maybe dynamic arrays.
[delight/core.git] / dmd / parse.c
blob95f20de1c8af355516fd0c3aae16981b592875af
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 TOKin:
276 nextToken();
277 stc = STCin;
278 goto Lstc2;
280 case TOKconst: stc = STCconst; goto Lstc;
281 case TOKfinal: stc = STCfinal; goto Lstc;
282 case TOKauto: stc = STCauto; goto Lstc;
283 case TOKscope: stc = STCscope; goto Lstc;
284 case TOKoverride: stc = STCoverride; goto Lstc;
285 case TOKabstract: stc = STCabstract; goto Lstc;
286 case TOKsynchronized: stc = STCsynchronized; goto Lstc;
287 case TOKdeprecated: stc = STCdeprecated; goto Lstc;
289 Lstc:
290 nextToken();
291 Lstc2:
292 switch (token.value)
294 case TOKconst: stc |= STCconst; goto Lstc;
295 case TOKfinal: stc |= STCfinal; goto Lstc;
296 case TOKauto: stc |= STCauto; goto Lstc;
297 case TOKscope: stc |= STCscope; goto Lstc;
298 case TOKoverride: stc |= STCoverride; goto Lstc;
299 case TOKabstract: stc |= STCabstract; goto Lstc;
300 case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
301 case TOKdeprecated: stc |= STCdeprecated; goto Lstc;
302 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
303 default:
304 break;
307 /* Look for auto initializers:
308 * storage_class identifier = initializer;
310 if (token.value == TOKidentifier &&
311 peek(&token)->value == TOKassign)
313 while (1)
315 Identifier *ident = token.ident;
316 nextToken();
317 nextToken();
318 Initializer *init = parseInitializer();
319 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
320 v->storage_class = stc;
321 s = v;
322 if (token.value == TOKsemicolon || token.value == TOKendline)
324 nextToken();
326 else if (token.value == TOKcomma)
328 nextToken();
329 if (token.value == TOKidentifier &&
330 peek(&token)->value == TOKassign)
332 decldefs->push(s);
333 addComment(s, comment);
334 continue;
336 else
337 error("Identifier expected following comma");
339 else
340 error("%s expected following declaration, not '%s'", endToken(), token.toChars());
341 break;
344 else
345 { a = parseBlock();
346 s = new StorageClassDeclaration(stc, a);
348 break;
350 case TOKextern:
351 if (peek(&token)->value != TOKlparen)
352 { stc = STCextern;
353 goto Lstc;
356 enum LINK linksave = linkage;
357 linkage = parseLinkage();
358 a = parseBlock();
359 s = new LinkDeclaration(linkage, a);
360 linkage = linksave;
361 break;
363 case TOKprivate: prot = PROTprivate; goto Lprot;
364 case TOKpackage: prot = PROTpackage; goto Lprot;
365 case TOKprotected: prot = PROTprotected; goto Lprot;
366 case TOKpublic: prot = PROTpublic; goto Lprot;
367 case TOKexport: prot = PROTexport; goto Lprot;
369 Lprot:
370 nextToken();
371 a = parseBlock();
372 s = new ProtDeclaration(prot, a);
373 break;
375 case TOKalign:
376 { unsigned n;
378 s = NULL;
379 nextToken();
380 if (token.value == TOKlparen)
382 nextToken();
383 if (token.value == TOKint32v)
384 n = (unsigned)token.uns64value;
385 else
386 { error("integer expected, not %s", token.toChars());
387 n = 1;
389 nextToken();
390 check(TOKrparen);
392 else
393 n = global.structalign; // default
395 a = parseBlock();
396 s = new AlignDeclaration(n, a);
397 break;
400 case TOKpragma:
401 { Identifier *ident;
402 Expressions *args = NULL;
404 nextToken();
405 check(TOKlparen);
406 if (token.value != TOKidentifier)
407 { error("pragma(identifier expected");
408 goto Lerror;
410 ident = token.ident;
411 nextToken();
412 if (token.value == TOKcomma)
413 args = parseArguments(); // pragma(identifier, args...)
414 else
415 check(TOKrparen); // pragma(identifier)
417 if (token.value == TOKsemicolon || token.value == TOKendline)
418 a = NULL;
419 else if (dltSyntax)
421 check(TOKcolon);
422 a = parseDeclDefs(0);
423 check(TOKrcurly);
425 else
426 a = parseBlock();
427 s = new PragmaDeclaration(loc, ident, args, a);
428 break;
431 case TOKdebug:
432 nextToken();
433 if (token.value == TOKassign)
435 nextToken();
436 if (token.value == TOKidentifier)
437 s = new DebugSymbol(loc, token.ident);
438 else if (token.value == TOKint32v)
439 s = new DebugSymbol(loc, (unsigned)token.uns64value);
440 else
441 { error("identifier or integer expected, not %s", token.toChars());
442 s = NULL;
444 nextToken();
445 if (token.value != TOKsemicolon)
446 error("semicolon expected");
447 nextToken();
448 break;
451 condition = parseDebugCondition();
452 goto Lcondition;
454 case TOKversion:
455 nextToken();
456 if (token.value == TOKassign)
458 nextToken();
459 if (token.value == TOKidentifier)
460 s = new VersionSymbol(loc, token.ident);
461 else if (token.value == TOKint32v)
462 s = new VersionSymbol(loc, (unsigned)token.uns64value);
463 else
464 { error("identifier or integer expected, not %s", token.toChars());
465 s = NULL;
467 nextToken();
468 if (token.value != TOKsemicolon && token.value != TOKendline)
469 error("%s expected after version assignment", endToken());
470 nextToken();
471 break;
473 condition = parseVersionCondition();
474 goto Lcondition;
476 Lcondition:
477 a = parseBlock();
478 aelse = NULL;
479 if (token.value == TOKelse)
480 { nextToken();
481 aelse = parseBlock();
483 s = new ConditionalDeclaration(condition, a, aelse);
484 break;
486 case TOKsemicolon: // empty declaration
487 nextToken();
488 continue;
490 default:
491 error("Declaration expected, not '%s'",token.toChars());
492 Lerror:
493 while (token.value != TOKsemicolon && token.value != TOKendline && token.value != TOKeof)
494 nextToken();
495 nextToken();
496 s = NULL;
497 continue;
499 if (s)
500 { decldefs->push(s);
501 addComment(s, comment);
503 } while (!once);
504 return decldefs;
508 /********************************************
509 * Parse declarations after an align, protection, or extern decl.
512 Array *Parser::parseBlock()
514 Array *a = NULL;
515 Dsymbol *s;
517 //printf("Parser::parseBlock()\n");
518 switch (token.value)
520 case TOKsemicolon:
521 error("declaration expected following attribute, not ';'");
522 nextToken();
523 break;
525 case TOKlcurly:
526 nextToken();
527 a = parseDeclDefs(0);
528 if (token.value != TOKrcurly)
529 { /* { */
530 error("matching '}' expected, not %s", token.toChars());
532 else
533 nextToken();
534 break;
536 case TOKcolon:
537 nextToken();
538 #if 0
539 a = NULL;
540 #else
541 a = parseDeclDefs(0); // grab declarations up to closing curly bracket
542 #endif
543 break;
545 default:
546 a = parseDeclDefs(1);
547 break;
549 return a;
552 Array *DltParser::parseBlock()
554 Array *a = NULL;
555 Dsymbol *s;
557 optionalEndline();
558 switch (token.value)
560 case TOKendline:
561 case TOKsemicolon:
562 error("declaration expected following attribute, not %s", token.toChars());
563 nextToken();
564 break;
566 case TOKcolon:
567 nextToken();
568 a = parseDeclDefs(0);
569 if (token.value != TOKrcurly)
571 error("matching end-of-block expected, not %s", token.toChars());
573 else
574 nextToken();
575 break;
577 default:
578 a = parseDeclDefs(1);
579 break;
581 return a;
584 /**********************************
585 * Parse a static assertion.
588 StaticAssert *Parser::parseStaticAssert()
590 Loc loc = this->loc;
591 Expression *exp;
592 Expression *msg = NULL;
594 //printf("parseStaticAssert()\n");
595 nextToken();
596 checkLParen();
597 exp = parseAssignExp();
598 if (token.value == TOKcomma)
599 { nextToken();
600 msg = parseAssignExp();
602 checkRParen();
603 if (token.value == TOKsemicolon || token.value == TOKendline) {
604 nextToken();
605 return new StaticAssert(loc, exp, msg);
607 error("expected %s after static assert", endToken());
611 /***********************************
612 * Parse extern (linkage)
613 * The parser is on the 'extern' token.
616 enum LINK Parser::parseLinkage()
618 enum LINK link = LINKdefault;
619 nextToken();
620 assert(token.value == TOKlparen);
621 nextToken();
622 if (token.value == TOKidentifier)
623 { Identifier *id = token.ident;
625 nextToken();
626 if (id == Id::Windows)
627 link = LINKwindows;
628 else if (id == Id::Pascal)
629 link = LINKpascal;
630 else if (id == Id::D)
631 link = LINKd;
632 else if (id == Id::C)
634 link = LINKc;
635 if (token.value == TOKplusplus)
636 { link = LINKcpp;
637 nextToken();
640 else if (id == Id::System)
642 #ifdef IN_GCC
643 link = d_gcc_is_target_win32() ? LINKwindows : LINKc;
644 #else
645 #if _WIN32
646 link = LINKwindows;
647 #else
648 link = LINKc;
649 #endif
650 #endif
652 else
654 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
655 link = LINKd;
658 else
660 link = LINKd; // default
662 check(TOKrparen);
663 return link;
666 /**************************************
667 * Parse a debug conditional
670 Condition *Parser::parseDebugCondition()
672 Condition *c;
674 if (token.value == TOKlparen)
676 nextToken();
677 unsigned level = 1;
678 Identifier *id = NULL;
680 if (token.value == TOKidentifier)
681 id = token.ident;
682 else if (token.value == TOKint32v)
683 level = (unsigned)token.uns64value;
684 else
685 error("identifier or integer expected, not %s", token.toChars());
686 nextToken();
687 check(TOKrparen);
688 c = new DebugCondition(mod, level, id);
689 if (dltSyntax && token.value != TOKcolon)
690 error("expected colon after debug(), not '%s'", token.toChars());
691 } else {
692 if (dltSyntax && token.value != TOKcolon)
693 error("expected ':' or '(' after 'debug', not '%s'", token.toChars());
694 c = new DebugCondition(mod, 1, NULL);
696 return c;
700 /**************************************
701 * Parse a version conditional
704 Condition *Parser::parseVersionCondition()
706 Condition *c;
707 unsigned level = 1;
708 Identifier *id = NULL;
710 if (token.value == TOKlparen)
712 nextToken();
713 if (token.value == TOKidentifier)
714 id = token.ident;
715 else if (token.value == TOKint32v)
716 level = (unsigned)token.uns64value;
717 #if V2
718 /* Allow:
719 * version (unittest)
720 * even though unittest is a keyword
722 else if (token.value == TOKunittest)
723 id = Lexer::idPool(Token::toChars(TOKunittest));
724 #endif
725 else
726 error("identifier or integer expected, not %s", token.toChars());
727 nextToken();
728 check(TOKrparen);
731 else
732 error("(condition) expected following version");
733 c = new VersionCondition(mod, level, id);
734 return c;
738 /***********************************************
739 * static if (expression)
740 * body
741 * else
742 * body
745 Condition *Parser::parseStaticIfCondition()
746 { Expression *exp;
747 Condition *condition;
748 Array *aif;
749 Array *aelse;
750 Loc loc = this->loc;
752 nextToken();
753 checkLParen();
754 exp = parseAssignExp();
755 checkRParen();
757 condition = new StaticIfCondition(loc, exp);
758 return condition;
762 /*****************************************
763 * Parse a constructor definition:
764 * this(arguments) { body }
765 * Current token is 'this'.
768 CtorDeclaration *Parser::parseCtor()
770 CtorDeclaration *f;
771 Arguments *arguments;
772 int varargs;
773 Loc loc = this->loc;
775 nextToken();
776 arguments = parseParameters(&varargs);
777 f = new CtorDeclaration(loc, 0, arguments, varargs);
778 parseContracts(f);
779 return f;
782 /*****************************************
783 * Parse a destructor definition:
784 * ~this() { body }
785 * Current token is '~'.
788 DtorDeclaration *Parser::parseDtor()
790 DtorDeclaration *f;
791 Loc loc = this->loc;
793 nextToken();
794 check(TOKthis);
795 check(TOKlparen);
796 check(TOKrparen);
798 f = new DtorDeclaration(loc, 0);
799 parseContracts(f);
800 return f;
803 /*****************************************
804 * Parse a static constructor definition:
805 * static this() { body }
806 * Current token is 'this'.
809 StaticCtorDeclaration *Parser::parseStaticCtor()
811 StaticCtorDeclaration *f;
812 Loc loc = this->loc;
814 nextToken();
815 check(TOKlparen);
816 check(TOKrparen);
818 f = new StaticCtorDeclaration(loc, 0);
819 parseContracts(f);
820 return f;
823 /*****************************************
824 * Parse a static destructor definition:
825 * static ~this() { body }
826 * Current token is '~'.
829 StaticDtorDeclaration *Parser::parseStaticDtor()
831 StaticDtorDeclaration *f;
832 Loc loc = this->loc;
834 nextToken();
835 check(TOKthis);
836 check(TOKlparen);
837 check(TOKrparen);
839 f = new StaticDtorDeclaration(loc, 0);
840 parseContracts(f);
841 return f;
844 /*****************************************
845 * Parse an invariant definition:
846 * invariant { body }
847 * Current token is 'invariant'.
850 InvariantDeclaration *Parser::parseInvariant()
852 InvariantDeclaration *f;
853 Loc loc = this->loc;
855 nextToken();
856 if (token.value == TOKlparen) // optional ()
858 nextToken();
859 check(TOKrparen);
862 f = new InvariantDeclaration(loc, 0);
863 f->fbody = parseStatement(PScurly);
864 return f;
867 /*****************************************
868 * Parse a unittest definition:
869 * unittest { body }
870 * Current token is 'unittest'.
873 UnitTestDeclaration *Parser::parseUnitTest()
875 UnitTestDeclaration *f;
876 Statement *body;
877 Loc loc = this->loc;
879 nextToken();
881 body = parseStatement(PScurly);
883 f = new UnitTestDeclaration(loc, this->loc);
884 f->fbody = body;
885 return f;
888 /*****************************************
889 * Parse a new definition:
890 * new(arguments) { body }
891 * Current token is 'new'.
894 NewDeclaration *Parser::parseNew()
896 NewDeclaration *f;
897 Arguments *arguments;
898 int varargs;
899 Loc loc = this->loc;
901 nextToken();
902 arguments = parseParameters(&varargs);
903 f = new NewDeclaration(loc, 0, arguments, varargs);
904 parseContracts(f);
905 return f;
908 /*****************************************
909 * Parse a delete definition:
910 * delete(arguments) { body }
911 * Current token is 'delete'.
914 DeleteDeclaration *Parser::parseDelete()
916 DeleteDeclaration *f;
917 Arguments *arguments;
918 int varargs;
919 Loc loc = this->loc;
921 nextToken();
922 arguments = parseParameters(&varargs);
923 if (varargs)
924 error("... not allowed in delete function parameter list");
925 f = new DeleteDeclaration(loc, 0, arguments);
926 parseContracts(f);
927 return f;
930 /**********************************************
931 * Parse parameter list.
934 Arguments *Parser::parseParameters(int *pvarargs)
936 Arguments *arguments = new Arguments();
937 int varargs = 0;
938 int hasdefault = 0;
940 check(TOKlparen);
941 while (1)
942 { Type *tb;
943 Identifier *ai;
944 Type *at;
945 Argument *a;
946 unsigned storageClass;
947 Expression *ae;
949 ai = NULL;
950 storageClass = STCin; // parameter is "in" by default
951 switch (token.value)
953 case TOKrparen:
954 break;
956 case TOKdotdotdot:
957 varargs = 1;
958 nextToken();
959 break;
961 case TOKin:
962 storageClass = STCin;
963 nextToken();
964 goto L1;
966 case TOKout:
967 storageClass = STCout;
968 nextToken();
969 goto L1;
971 case TOKinout:
972 case TOKref:
973 storageClass = STCref;
974 nextToken();
975 goto L1;
977 case TOKlazy:
978 storageClass = STClazy;
979 nextToken();
980 goto L1;
982 default:
984 tb = parseBasicType();
985 at = parseDeclarator(tb, &ai);
986 ae = NULL;
987 if (token.value == TOKassign) // = defaultArg
988 { nextToken();
989 ae = parseAssignExp();
990 hasdefault = 1;
992 else
993 { if (hasdefault)
994 error("default argument expected for %s",
995 ai ? ai->toChars() : at->toChars());
997 if (token.value == TOKdotdotdot)
998 { /* This is:
999 * at ai ...
1002 if (storageClass & (STCout | STCref))
1003 error("variadic argument cannot be out or ref");
1004 varargs = 2;
1005 a = new Argument(storageClass, at, ai, ae);
1006 arguments->push(a);
1007 nextToken();
1008 break;
1010 a = new Argument(storageClass, at, ai, ae);
1011 arguments->push(a);
1012 if (token.value == TOKcomma)
1013 { nextToken();
1014 continue;
1016 break;
1018 break;
1020 check(TOKrparen);
1021 *pvarargs = varargs;
1022 return arguments;
1026 /*************************************
1029 EnumDeclaration *Parser::parseEnum()
1030 { EnumDeclaration *e;
1031 Identifier *id;
1032 Type *t;
1033 Loc loc = this->loc;
1035 //printf("Parser::parseEnum()\n");
1036 nextToken();
1037 if (token.value == TOKidentifier)
1038 { id = token.ident;
1039 nextToken();
1041 else
1042 id = NULL;
1044 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1046 nextToken();
1047 t = parseBasicType();
1049 else
1050 t = NULL;
1052 e = new EnumDeclaration(loc, id, t);
1053 if (token.value == TOKsemicolon && id)
1054 nextToken();
1055 else if (token.value == startBlockTok)
1057 //printf("enum definition\n");
1058 e->members = new Array();
1059 nextToken();
1060 unsigned char *comment = token.blockComment;
1061 optionalEndline();
1062 while (token.value != TOKrcurly)
1064 if (token.value == TOKidentifier)
1065 { EnumMember *em;
1066 Expression *value;
1067 Identifier *ident;
1069 loc = this->loc;
1070 ident = token.ident;
1071 value = NULL;
1072 nextToken();
1073 if (token.value == TOKassign)
1075 nextToken();
1076 value = parseAssignExp();
1078 em = new EnumMember(loc, ident, value);
1079 e->members->push(em);
1080 optionalEndline();
1081 if (token.value == TOKrcurly)
1083 else
1084 { addComment(em, comment);
1085 comment = NULL;
1086 check(TOKcomma);
1087 optionalEndline();
1089 addComment(em, comment);
1090 comment = token.blockComment;
1092 else
1093 { error("enum member expected");
1094 nextToken();
1097 nextToken();
1099 else
1100 error("enum declaration is invalid");
1102 return e;
1105 Dsymbol *Parser::parseAggregate()
1106 { AggregateDeclaration *a = NULL;
1107 int anon = 0;
1108 enum TOK tok;
1109 Identifier *id;
1110 TemplateParameters *tpl = NULL;
1112 //printf("Parser::parseAggregate()\n");
1113 tok = token.value;
1114 nextToken();
1115 if (token.value != TOKidentifier)
1116 { id = NULL;
1118 else
1119 { id = token.ident;
1120 nextToken();
1122 if (token.value == TOKlparen)
1123 { // Class template declaration.
1125 // Gather template parameter list
1126 tpl = parseTemplateParameterList();
1130 Loc loc = this->loc;
1131 switch (tok)
1132 { case TOKclass:
1133 case TOKinterface:
1135 if (!id)
1136 error("anonymous classes not allowed");
1138 // Collect base class(es)
1139 BaseClasses *baseclasses = NULL;
1140 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1142 nextToken();
1143 baseclasses = parseBaseClasses();
1144 if (token.value != startBlockTok)
1145 error("members expected");
1148 if (tok == TOKclass)
1149 a = new ClassDeclaration(loc, id, baseclasses);
1150 else
1151 a = new InterfaceDeclaration(loc, id, baseclasses);
1152 break;
1155 case TOKstruct:
1156 if (id)
1157 a = new StructDeclaration(loc, id);
1158 else
1159 anon = 1;
1160 break;
1162 case TOKunion:
1163 if (id)
1164 a = new UnionDeclaration(loc, id);
1165 else
1166 anon = 2;
1167 break;
1169 default:
1170 assert(0);
1171 break;
1173 if (a && token.value == (dltSyntax ? TOKendline : TOKsemicolon))
1174 { nextToken();
1176 else if (token.value == startBlockTok)
1178 //printf("aggregate definition\n");
1179 nextToken();
1180 optionalEndline();
1181 Array *decl = parseDeclDefs(0);
1182 if (token.value != TOKrcurly)
1183 error("end-of-block expected following member declarations in aggregate");
1184 nextToken();
1185 if (anon)
1187 /* Anonymous structs/unions are more like attributes.
1189 return new AnonDeclaration(loc, anon - 1, decl);
1191 else
1192 a->members = decl;
1194 else
1196 error("%s expected following aggregate declaration", Token::toChars(startBlockTok));
1197 a = new StructDeclaration(loc, NULL);
1200 if (tpl)
1201 { Array *decldefs;
1202 TemplateDeclaration *tempdecl;
1204 // Wrap a template around the aggregate declaration
1205 decldefs = new Array();
1206 decldefs->push(a);
1207 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1208 return tempdecl;
1211 return a;
1214 /*******************************************
1217 BaseClasses *Parser::parseBaseClasses()
1219 enum PROT protection = PROTpublic;
1220 BaseClasses *baseclasses = new BaseClasses();
1222 for (; 1; nextToken())
1224 switch (token.value)
1226 case TOKidentifier:
1227 break;
1228 case TOKprivate:
1229 protection = PROTprivate;
1230 continue;
1231 case TOKpackage:
1232 protection = PROTpackage;
1233 continue;
1234 case TOKprotected:
1235 protection = PROTprotected;
1236 continue;
1237 case TOKpublic:
1238 protection = PROTpublic;
1239 continue;
1240 default:
1241 error("base classes expected instead of %s", token.toChars());
1242 return NULL;
1244 BaseClass *b = new BaseClass(parseBasicType(), protection);
1245 baseclasses->push(b);
1246 if (token.value != TOKcomma)
1247 break;
1248 protection = PROTpublic;
1250 return baseclasses;
1253 /**************************************
1254 * Parse a TemplateDeclaration.
1257 TemplateDeclaration *Parser::parseTemplateDeclaration()
1259 TemplateDeclaration *tempdecl;
1260 Identifier *id;
1261 TemplateParameters *tpl;
1262 Array *decldefs;
1263 Loc loc = this->loc;
1265 nextToken();
1266 if (token.value != TOKidentifier)
1267 { error("TemplateIdentifier expected following template");
1268 goto Lerr;
1270 id = token.ident;
1271 nextToken();
1272 tpl = parseTemplateParameterList();
1273 if (!tpl)
1274 goto Lerr;
1276 if (token.value != startBlockTok)
1277 { error("members of template declaration expected");
1278 goto Lerr;
1280 else
1282 nextToken();
1283 decldefs = parseDeclDefs(0);
1284 if (token.value != TOKrcurly)
1285 { error("template member expected");
1286 goto Lerr;
1288 nextToken();
1291 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1292 return tempdecl;
1294 Lerr:
1295 return NULL;
1298 /******************************************
1299 * Parse template parameter list.
1302 TemplateParameters *Parser::parseTemplateParameterList()
1304 TemplateParameters *tpl = new TemplateParameters();
1306 if (token.value != TOKlparen)
1307 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1308 goto Lerr;
1310 nextToken();
1312 // Get array of TemplateParameters
1313 if (token.value != TOKrparen)
1314 { int isvariadic = 0;
1316 while (1)
1317 { TemplateParameter *tp;
1318 Identifier *tp_ident = NULL;
1319 Type *tp_spectype = NULL;
1320 Type *tp_valtype = NULL;
1321 Type *tp_defaulttype = NULL;
1322 Expression *tp_specvalue = NULL;
1323 Expression *tp_defaultvalue = NULL;
1324 Token *t;
1326 // Get TemplateParameter
1328 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1329 t = peek(&token);
1330 if (token.value == TOKalias)
1331 { // AliasParameter
1332 nextToken();
1333 if (token.value != TOKidentifier)
1334 { error("Identifier expected for template parameter");
1335 goto Lerr;
1337 tp_ident = token.ident;
1338 nextToken();
1339 if (token.value == TOKcolon) // : Type
1341 nextToken();
1342 tp_spectype = parseBasicType();
1343 tp_spectype = parseDeclarator(tp_spectype, NULL);
1345 if (token.value == TOKassign) // = Type
1347 nextToken();
1348 tp_defaulttype = parseBasicType();
1349 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1351 tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1353 else if (t->value == TOKcolon || t->value == TOKassign ||
1354 t->value == TOKcomma || t->value == TOKrparen)
1355 { // TypeParameter
1356 if (token.value != TOKidentifier)
1357 { error("Identifier expected for template parameter");
1358 goto Lerr;
1360 tp_ident = token.ident;
1361 nextToken();
1362 if (token.value == TOKcolon) // : Type
1364 nextToken();
1365 tp_spectype = parseBasicType();
1366 tp_spectype = parseDeclarator(tp_spectype, NULL);
1368 if (token.value == TOKassign) // = Type
1370 nextToken();
1371 tp_defaulttype = parseBasicType();
1372 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1374 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1376 else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
1377 { // ident...
1378 if (isvariadic)
1379 error("variadic template parameter must be last");
1380 isvariadic = 1;
1381 tp_ident = token.ident;
1382 nextToken();
1383 nextToken();
1384 tp = new TemplateTupleParameter(loc, tp_ident);
1386 else
1387 { // ValueParameter
1388 tp_valtype = parseBasicType();
1389 tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
1390 if (!tp_ident)
1392 error("no identifier for template value parameter");
1393 tp_ident = new Identifier("error", TOKidentifier);
1395 if (token.value == TOKcolon) // : CondExpression
1397 nextToken();
1398 tp_specvalue = parseCondExp();
1400 if (token.value == TOKassign) // = CondExpression
1402 nextToken();
1403 tp_defaultvalue = parseCondExp();
1405 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
1407 tpl->push(tp);
1408 if (token.value != TOKcomma)
1409 break;
1410 nextToken();
1413 check(TOKrparen);
1414 Lerr:
1415 return tpl;
1418 /******************************************
1419 * Parse template mixin.
1420 * mixin Foo;
1421 * mixin Foo!(args);
1422 * mixin a.b.c!(args).Foo!(args);
1423 * mixin Foo!(args) identifier;
1424 * mixin typeof(expr).identifier!(args);
1427 Dsymbol *Parser::parseMixin()
1429 TemplateMixin *tm;
1430 Identifier *id;
1431 Type *tqual;
1432 Objects *tiargs;
1433 Array *idents;
1435 //printf("parseMixin()\n");
1436 nextToken();
1437 tqual = NULL;
1438 if (token.value == TOKdot)
1440 id = Id::empty;
1442 else
1444 if (token.value == TOKtypeof)
1445 { Expression *exp;
1447 nextToken();
1448 check(TOKlparen);
1449 exp = parseExpression();
1450 check(TOKrparen);
1451 tqual = new TypeTypeof(loc, exp);
1452 check(TOKdot);
1454 if (token.value != TOKidentifier)
1456 error("identifier expected, not %s", token.toChars());
1457 goto Lerr;
1459 id = token.ident;
1460 nextToken();
1463 idents = new Array();
1464 while (1)
1466 tiargs = NULL;
1467 if (token.value == TOKnot)
1469 nextToken();
1470 tiargs = parseTemplateArgumentList();
1473 if (token.value != TOKdot)
1474 break;
1476 if (tiargs)
1477 { TemplateInstance *tempinst = new TemplateInstance(loc, id);
1478 tempinst->tiargs = tiargs;
1479 id = (Identifier *)tempinst;
1480 tiargs = NULL;
1482 idents->push(id);
1484 nextToken();
1485 if (token.value != TOKidentifier)
1486 { error("identifier expected following '.' instead of '%s'", token.toChars());
1487 break;
1489 id = token.ident;
1490 nextToken();
1492 idents->push(id);
1494 if (token.value == TOKidentifier)
1496 id = token.ident;
1497 nextToken();
1499 else
1500 id = NULL;
1502 tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
1503 if (token.value != TOKsemicolon)
1504 error("';' expected after mixin");
1505 nextToken();
1507 return tm;
1509 Lerr:
1510 return NULL;
1513 /******************************************
1514 * Parse template argument list.
1515 * Input:
1516 * current token is opening '('
1517 * Output:
1518 * current token is one after closing ')'
1521 Objects *Parser::parseTemplateArgumentList()
1523 //printf("Parser::parseTemplateArgumentList()\n");
1524 Objects *tiargs = new Objects();
1525 if (token.value != TOKlparen)
1526 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1527 return tiargs;
1529 nextToken();
1531 // Get TemplateArgumentList
1532 if (token.value != TOKrparen)
1534 while (1)
1536 // See if it is an Expression or a Type
1537 if (isDeclaration(&token, 0, TOKreserved, NULL))
1538 { // Type
1539 Type *ta;
1541 // Get TemplateArgument
1542 ta = parseBasicType();
1543 ta = parseDeclarator(ta, NULL);
1544 tiargs->push(ta);
1546 else
1547 { // Expression
1548 Expression *ea;
1550 ea = parseAssignExp();
1551 tiargs->push(ea);
1553 if (token.value != TOKcomma)
1554 break;
1555 nextToken();
1558 check(TOKrparen, "template argument list");
1559 return tiargs;
1562 Import *Parser::parseImport(Array *decldefs, int isstatic)
1563 { Import *s;
1564 Identifier *id;
1565 Identifier *aliasid = NULL;
1566 Array *a;
1567 Loc loc;
1569 //printf("Parser::parseImport()\n");
1573 nextToken();
1574 if (token.value != TOKidentifier)
1575 { error("Identifier expected following import");
1576 break;
1579 loc = this->loc;
1580 a = NULL;
1581 id = token.ident;
1582 nextToken();
1583 if (!aliasid && token.value == TOKassign)
1585 aliasid = id;
1586 goto L1;
1588 while (token.value == TOKdot)
1590 if (!a)
1591 a = new Array();
1592 a->push(id);
1593 nextToken();
1594 if (token.value != TOKidentifier)
1595 { error("Identifier expected following package");
1596 break;
1598 id = token.ident;
1599 nextToken();
1602 s = new Import(loc, a, token.ident, aliasid, isstatic);
1603 decldefs->push(s);
1605 /* Look for
1606 * : alias=name, alias=name;
1607 * syntax.
1609 if (token.value == TOKcolon)
1611 nextToken();
1612 while (1)
1613 { Identifier *name;
1614 Identifier *alias;
1616 optionalEndline();
1618 if (dltSyntax && token.value == TOKrcurly)
1619 break;
1620 if (token.value != TOKidentifier)
1621 { error("Identifier expected following :");
1622 break;
1624 alias = token.ident;
1625 nextToken();
1626 if (token.value == TOKassign)
1628 nextToken();
1629 if (token.value != TOKidentifier)
1630 { error("Identifier expected following %s=", alias->toChars());
1631 break;
1633 name = token.ident;
1634 nextToken();
1636 else
1637 { name = alias;
1638 alias = NULL;
1640 s->addAlias(name, alias);
1641 if (token.value != TOKcomma && token.value != TOKendline)
1642 break;
1643 nextToken();
1645 if (dltSyntax)
1647 check(TOKrcurly);
1648 return NULL;
1650 else
1651 break;
1654 aliasid = NULL;
1655 } while (token.value == TOKcomma);
1657 if (token.value == TOKsemicolon || token.value == TOKendline)
1658 nextToken();
1659 else
1661 error("%s expected", endToken());
1662 nextToken();
1665 return NULL;
1668 Type *Parser::parseBasicType()
1669 { Type *t;
1670 Identifier *id;
1671 TypeQualified *tid;
1672 TemplateInstance *tempinst;
1674 //printf("parseBasicType()\n");
1675 switch (token.value)
1677 CASE_BASIC_TYPES_X(t):
1678 nextToken();
1679 break;
1681 case TOKidentifier:
1682 id = token.ident;
1683 nextToken();
1684 if (token.value == TOKnot)
1686 nextToken();
1687 tempinst = new TemplateInstance(loc, id);
1688 tempinst->tiargs = parseTemplateArgumentList();
1689 tid = new TypeInstance(loc, tempinst);
1690 goto Lident2;
1692 Lident:
1693 tid = new TypeIdentifier(loc, id);
1694 Lident2:
1695 while (token.value == TOKdot)
1696 { nextToken();
1697 if (token.value != TOKidentifier)
1698 { error("identifier expected following '.' instead of '%s'", token.toChars());
1699 break;
1701 id = token.ident;
1702 nextToken();
1703 if (token.value == TOKnot)
1705 nextToken();
1706 tempinst = new TemplateInstance(loc, id);
1707 tempinst->tiargs = parseTemplateArgumentList();
1708 tid->addIdent((Identifier *)tempinst);
1710 else
1711 tid->addIdent(id);
1713 t = tid;
1714 break;
1716 case TOKdot:
1717 id = Id::empty;
1718 goto Lident;
1720 case TOKtypeof:
1721 { Expression *exp;
1723 nextToken();
1724 check(TOKlparen);
1725 exp = parseExpression();
1726 check(TOKrparen);
1727 tid = new TypeTypeof(loc, exp);
1728 goto Lident2;
1731 default:
1732 error("basic type expected, not %s", token.toChars());
1733 t = Type::tint32;
1734 break;
1736 return t;
1739 Type *Parser::parseBasicType2(Type *t)
1741 Type *ts;
1742 Type *ta;
1744 //printf("parseBasicType2()\n");
1745 while (1)
1747 switch (token.value)
1749 case TOKmul:
1750 t = new TypePointer(t);
1751 nextToken();
1752 continue;
1754 case TOKlbracket:
1755 #if LTORARRAYDECL
1756 // Handle []. Make sure things like
1757 // int[3][1] a;
1758 // is (array[1] of array[3] of int)
1759 nextToken();
1760 if (token.value == TOKrbracket)
1762 t = new TypeDArray(t); // []
1763 nextToken();
1765 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1766 { // It's an associative array declaration
1767 Type *index;
1769 //printf("it's an associative array\n");
1770 index = parseBasicType();
1771 index = parseDeclarator(index, NULL); // [ type ]
1772 t = new TypeAArray(t, index);
1773 check(TOKrbracket);
1775 else
1777 //printf("it's [expression]\n");
1778 inBrackets++;
1779 Expression *e = parseExpression(); // [ expression ]
1780 if (token.value == TOKslice)
1781 { Expression *e2;
1783 nextToken();
1784 e2 = parseExpression(); // [ exp .. exp ]
1785 t = new TypeSlice(t, e, e2);
1787 else
1788 t = new TypeSArray(t,e);
1789 inBrackets--;
1790 check(TOKrbracket);
1792 continue;
1793 #else
1794 // Handle []. Make sure things like
1795 // int[3][1] a;
1796 // is (array[3] of array[1] of int)
1797 ts = t;
1798 while (token.value == TOKlbracket)
1800 nextToken();
1801 if (token.value == TOKrbracket)
1803 ta = new TypeDArray(t); // []
1804 nextToken();
1806 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1807 { // It's an associative array declaration
1808 Type *index;
1810 //printf("it's an associative array\n");
1811 index = parseBasicType();
1812 index = parseDeclarator(index, NULL); // [ type ]
1813 check(TOKrbracket);
1814 ta = new TypeAArray(t, index);
1816 else
1818 //printf("it's [expression]\n");
1819 Expression *e = parseExpression(); // [ expression ]
1820 ta = new TypeSArray(t,e);
1821 check(TOKrbracket);
1823 Type **pt;
1824 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1826 *pt = ta;
1828 t = ts;
1829 continue;
1830 #endif
1832 case TOKdelegate:
1833 case TOKfunction:
1834 { // Handle delegate declaration:
1835 // t delegate(parameter list)
1836 // t function(parameter list)
1837 Arguments *arguments;
1838 int varargs;
1839 enum TOK save = token.value;
1841 nextToken();
1842 arguments = parseParameters(&varargs);
1843 t = new TypeFunction(arguments, t, varargs, linkage);
1844 if (save == TOKdelegate)
1845 t = new TypeDelegate(t);
1846 else
1847 t = new TypePointer(t); // pointer to function
1848 continue;
1851 case TOKquestion:
1852 if (dltSyntax)
1854 t = t->maybe();
1855 nextToken();
1856 continue;
1858 // fall-through to default
1860 default:
1861 ts = t;
1862 break;
1864 break;
1867 if (!dltSyntax)
1869 switch (ts->ty) {
1870 case Tarray:
1871 case Tident:
1872 // TypeMaybe will unwrap itself later if this isn't a nullable type
1873 ts = ts->maybe();
1874 break;
1878 return ts;
1881 Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
1882 { Type *ts;
1883 Type *ta;
1885 //printf("parseDeclarator(tpl = %p)\n", tpl);
1886 t = parseBasicType2(t);
1888 switch (token.value)
1891 case TOKidentifier:
1892 if (pident)
1893 *pident = token.ident;
1894 else
1895 error("unexpected identifer '%s' in declarator", token.ident->toChars());
1896 ts = t;
1897 nextToken();
1898 break;
1900 case TOKlparen:
1901 nextToken();
1902 ts = parseDeclarator(t, pident);
1903 check(TOKrparen);
1904 break;
1906 default:
1907 ts = t;
1908 break;
1911 while (1)
1913 switch (token.value)
1915 #if CARRAYDECL
1916 case TOKlbracket:
1917 { // This is the old C-style post [] syntax.
1918 nextToken();
1919 if (token.value == TOKrbracket)
1921 ta = new TypeDArray(t); // []
1922 nextToken();
1924 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1925 { // It's an associative array declaration
1926 Type *index;
1928 //printf("it's an associative array\n");
1929 index = parseBasicType();
1930 index = parseDeclarator(index, NULL); // [ type ]
1931 check(TOKrbracket);
1932 ta = new TypeAArray(t, index);
1934 else
1936 //printf("it's [expression]\n");
1937 Expression *e = parseExpression(); // [ expression ]
1938 ta = new TypeSArray(t, e);
1939 check(TOKrbracket);
1941 Type **pt;
1942 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1944 *pt = ta;
1945 continue;
1947 #endif
1948 case TOKlparen:
1949 { Arguments *arguments;
1950 int varargs;
1952 if (tpl)
1954 /* Look ahead to see if this is (...)(...),
1955 * i.e. a function template declaration
1957 if (peekPastParen(&token)->value == TOKlparen)
1958 { // It's a function template declaration
1959 //printf("function template declaration\n");
1961 // Gather template parameter list
1962 *tpl = parseTemplateParameterList();
1966 arguments = parseParameters(&varargs);
1967 Type *ta = new TypeFunction(arguments, t, varargs, linkage);
1968 Type **pt;
1969 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1971 *pt = ta;
1972 break;
1975 break;
1978 return ts;
1981 /**********************************
1982 * Return array of Declaration *'s.
1985 Array *Parser::parseDeclarations()
1987 enum STC storage_class;
1988 enum STC stc;
1989 Type *ts;
1990 Type *t;
1991 Type *tfirst;
1992 Identifier *ident;
1993 Array *a;
1994 enum TOK tok;
1995 unsigned char *comment = token.blockComment;
1996 enum LINK link = linkage;
1998 //printf("parseDeclarations()\n");
1999 switch (token.value)
2001 case TOKtypedef:
2002 case TOKalias:
2003 tok = token.value;
2004 nextToken();
2005 break;
2007 default:
2008 tok = TOKreserved;
2009 break;
2012 storage_class = STCundefined;
2013 while (1)
2015 switch (token.value)
2017 case TOKconst: stc = STCconst; goto L1;
2018 case TOKstatic: stc = STCstatic; goto L1;
2019 case TOKfinal: stc = STCfinal; goto L1;
2020 case TOKauto: stc = STCauto; goto L1;
2021 case TOKscope: stc = STCscope; goto L1;
2022 case TOKoverride: stc = STCoverride; goto L1;
2023 case TOKabstract: stc = STCabstract; goto L1;
2024 case TOKsynchronized: stc = STCsynchronized; goto L1;
2025 case TOKdeprecated: stc = STCdeprecated; goto L1;
2027 if (storage_class & stc)
2028 error("redundant storage class '%s'", token.toChars());
2029 storage_class = (STC) (storage_class | stc);
2030 nextToken();
2031 continue;
2033 case TOKextern:
2034 if (peek(&token)->value != TOKlparen)
2035 { stc = STCextern;
2036 goto L1;
2039 link = parseLinkage();
2040 continue;
2042 default:
2043 break;
2045 break;
2048 a = new Array();
2050 /* Look for auto initializers:
2051 * storage_class identifier = initializer;
2053 while (storage_class &&
2054 token.value == TOKidentifier &&
2055 peek(&token)->value == TOKassign)
2057 ident = token.ident;
2058 nextToken();
2059 nextToken();
2060 Initializer *init = parseInitializer();
2061 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
2062 v->storage_class = storage_class;
2063 a->push(v);
2064 if (token.value == TOKsemicolon || token.value == TOKendline)
2066 nextToken();
2067 addComment(v, comment);
2069 else if (token.value == TOKcomma)
2071 nextToken();
2072 if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
2074 error("Identifier expected following comma");
2076 else
2077 continue;
2079 else
2080 error("%s expected following auto declaration, not '%s'", endToken(), token.toChars());
2081 return a;
2084 if (token.value == TOKclass)
2085 { AggregateDeclaration *s;
2087 s = (AggregateDeclaration *)parseAggregate();
2088 s->storage_class |= storage_class;
2089 a->push(s);
2090 addComment(s, comment);
2091 return a;
2094 ts = parseBasicType();
2095 ts = parseBasicType2(ts);
2096 tfirst = NULL;
2098 while (1)
2100 Loc loc = this->loc;
2101 TemplateParameters *tpl = NULL;
2103 ident = NULL;
2104 t = parseDeclarator(ts, &ident, &tpl);
2105 assert(t);
2106 if (!tfirst)
2107 tfirst = t;
2108 else if (t != tfirst)
2109 error("multiple declarations must have the same type, not %s and %s",
2110 tfirst->toChars(), t->toChars());
2111 if (!ident)
2112 error("no identifier for declarator %s", t->toChars());
2114 if (tok == TOKtypedef || tok == TOKalias)
2115 { Declaration *v;
2116 Initializer *init;
2118 init = NULL;
2119 if (token.value == TOKassign)
2121 nextToken();
2122 init = parseInitializer();
2124 if (tok == TOKtypedef)
2125 v = new TypedefDeclaration(loc, ident, t, init);
2126 else
2127 { if (init)
2128 error("alias cannot have initializer");
2129 v = new AliasDeclaration(loc, ident, t);
2131 v->storage_class = storage_class;
2132 if (link == linkage)
2133 a->push(v);
2134 else
2136 Array *ax = new Array();
2137 ax->push(v);
2138 Dsymbol *s = new LinkDeclaration(link, ax);
2139 a->push(s);
2141 switch (token.value)
2142 { case TOKsemicolon:
2143 case TOKendline:
2144 nextToken();
2145 addComment(v, comment);
2146 break;
2148 case TOKcomma:
2149 nextToken();
2150 addComment(v, comment);
2151 continue;
2153 default:
2154 error("%s expected to close %s declaration", endToken(), Token::toChars(tok));
2155 break;
2158 else if (t->ty == Tfunction)
2159 { FuncDeclaration *f;
2160 Dsymbol *s;
2162 f = new FuncDeclaration(loc, 0, ident, storage_class, t);
2163 addComment(f, comment);
2164 parseContracts(f);
2165 addComment(f, NULL);
2166 if (link == linkage)
2168 s = f;
2170 else
2172 Array *ax = new Array();
2173 ax->push(f);
2174 s = new LinkDeclaration(link, ax);
2176 if (tpl) // it's a function template
2177 { Array *decldefs;
2178 TemplateDeclaration *tempdecl;
2180 // Wrap a template around the aggregate declaration
2181 decldefs = new Array();
2182 decldefs->push(s);
2183 tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs);
2184 s = tempdecl;
2186 addComment(s, comment);
2187 a->push(s);
2189 else
2190 { VarDeclaration *v;
2191 Initializer *init;
2193 init = NULL;
2194 if (token.value == TOKassign)
2196 nextToken();
2197 init = parseInitializer();
2199 v = new VarDeclaration(loc, t, ident, init);
2200 v->storage_class = storage_class;
2201 if (link == linkage)
2202 a->push(v);
2203 else
2205 Array *ax = new Array();
2206 ax->push(v);
2207 Dsymbol *s = new LinkDeclaration(link, ax);
2208 a->push(s);
2210 switch (token.value)
2211 { case TOKsemicolon:
2212 case TOKendline:
2213 nextToken();
2214 addComment(v, comment);
2215 break;
2217 case TOKcomma:
2218 nextToken();
2219 addComment(v, comment);
2220 continue;
2222 default:
2223 error("%s expected, not '%s'", endToken(), token.toChars());
2224 break;
2227 break;
2229 return a;
2232 /*****************************************
2233 * Parse contracts following function declaration.
2236 void Parser::parseContracts(FuncDeclaration *f)
2238 Type *tb;
2239 enum LINK linksave = linkage;
2241 // The following is irrelevant, as it is overridden by sc->linkage in
2242 // TypeFunction::semantic
2243 linkage = LINKd; // nested functions have D linkage
2245 switch (token.value)
2247 case TOKlcurly:
2248 case TOKcolon:
2249 if (token.value != startBlockTok)
2250 error("use %s to start a new block", Token::toChars(startBlockTok));
2251 if (f->frequire || f->fensure)
2252 error("missing body { ... } after in or out");
2253 f->fbody = parseStatement(PSsemi | PScolon);
2254 f->endloc = endloc;
2255 break;
2257 case TOKbody:
2258 nextToken();
2259 f->fbody = parseStatement(PScurly);
2260 f->endloc = endloc;
2261 break;
2263 case TOKsemicolon:
2264 if (dltSyntax)
2265 error("unexpected semi-colon after function declaration");
2266 // fall-through
2267 case TOKendline:
2268 if (f->frequire || f->fensure)
2269 error("missing body { ... } after in or out");
2270 nextToken();
2271 break;
2273 #if 0 // Do we want this for function declarations, so we can do:
2274 // int x, y, foo(), z;
2275 case TOKcomma:
2276 nextToken();
2277 continue;
2278 #endif
2280 #if 0 // Dumped feature
2281 case TOKthrow:
2282 if (!f->fthrows)
2283 f->fthrows = new Array();
2284 nextToken();
2285 check(TOKlparen);
2286 while (1)
2288 tb = parseBasicType();
2289 f->fthrows->push(tb);
2290 if (token.value == TOKcomma)
2291 { nextToken();
2292 continue;
2294 break;
2296 check(TOKrparen);
2297 goto L1;
2298 #endif
2300 case TOKin:
2301 nextToken();
2302 if (f->frequire)
2303 error("redundant 'in' statement");
2304 f->frequire = parseStatement(PScurly | PSscope);
2305 goto L1;
2307 case TOKout:
2308 // parse: out (identifier) { statement }
2309 nextToken();
2310 if (token.value != startBlockTok)
2312 check(TOKlparen);
2313 if (token.value != TOKidentifier)
2314 error("(identifier) following 'out' expected, not %s", token.toChars());
2315 f->outId = token.ident;
2316 nextToken();
2317 check(TOKrparen);
2319 if (f->fensure)
2320 error("redundant 'out' statement");
2321 f->fensure = parseStatement(PScurly | PSscope);
2322 goto L1;
2324 default:
2325 error("%s expected following function declaration", endToken());
2326 break;
2328 linkage = linksave;
2331 /*****************************************
2334 Initializer *Parser::parseInitializer()
2336 StructInitializer *is;
2337 ArrayInitializer *ia;
2338 ExpInitializer *ie;
2339 Expression *e;
2340 Identifier *id;
2341 Initializer *value;
2342 int comma;
2343 Loc loc = this->loc;
2344 Token *t;
2345 int braces;
2347 switch (token.value)
2349 case TOKlcurly:
2350 /* Scan ahead to see if it is a struct initializer or
2351 * a function literal.
2352 * If it contains a ';', it is a function literal.
2353 * Treat { } as a struct initializer.
2355 braces = 1;
2356 for (t = peek(&token); 1; t = peek(t))
2358 switch (t->value)
2360 case TOKsemicolon:
2361 case TOKreturn:
2362 goto Lexpression;
2364 case TOKlcurly:
2365 braces++;
2366 continue;
2368 case TOKrcurly:
2369 if (--braces == 0)
2370 break;
2371 continue;
2373 case TOKeof:
2374 break;
2376 default:
2377 continue;
2379 break;
2382 is = new StructInitializer(loc);
2383 nextToken();
2384 comma = 0;
2385 while (1)
2387 switch (token.value)
2389 case TOKidentifier:
2390 if (comma == 1)
2391 error("comma expected separating field initializers");
2392 t = peek(&token);
2393 if (t->value == TOKcolon)
2395 id = token.ident;
2396 nextToken();
2397 nextToken(); // skip over ':'
2399 else
2400 { id = NULL;
2402 value = parseInitializer();
2403 is->addInit(id, value);
2404 comma = 1;
2405 continue;
2407 case TOKcomma:
2408 nextToken();
2409 comma = 2;
2410 continue;
2412 case TOKrcurly: // allow trailing comma's
2413 nextToken();
2414 break;
2416 case TOKeof:
2417 error("found EOF instead of initializer");
2418 break;
2420 default:
2421 value = parseInitializer();
2422 is->addInit(NULL, value);
2423 comma = 1;
2424 continue;
2425 //error("found '%s' instead of field initializer", token.toChars());
2426 //break;
2428 break;
2430 return is;
2432 case TOKlbracket:
2433 ia = new ArrayInitializer(loc);
2434 nextToken();
2435 comma = 0;
2436 while (1)
2438 switch (token.value)
2440 default:
2441 if (comma == 1)
2442 { error("comma expected separating array initializers, not %s", token.toChars());
2443 nextToken();
2444 break;
2446 e = parseAssignExp();
2447 if (!e)
2448 break;
2449 if (token.value == TOKcolon)
2451 nextToken();
2452 value = parseInitializer();
2454 else
2455 { value = new ExpInitializer(e->loc, e);
2456 e = NULL;
2458 ia->addInit(e, value);
2459 comma = 1;
2460 continue;
2462 case TOKlcurly:
2463 case TOKlbracket:
2464 if (comma == 1)
2465 error("comma expected separating array initializers, not %s", token.toChars());
2466 value = parseInitializer();
2467 ia->addInit(NULL, value);
2468 comma = 1;
2469 continue;
2471 case TOKcomma:
2472 nextToken();
2473 comma = 2;
2474 continue;
2476 case TOKrbracket: // allow trailing comma's
2477 nextToken();
2478 break;
2480 case TOKeof:
2481 error("found '%s' instead of array initializer", token.toChars());
2482 break;
2484 break;
2486 return ia;
2488 case TOKvoid:
2489 t = peek(&token);
2490 if (t->value == TOKsemicolon || t->value == TOKcomma || t->value == TOKendline)
2492 nextToken();
2493 return new VoidInitializer(loc);
2495 goto Lexpression;
2497 default:
2498 Lexpression:
2499 e = parseAssignExp();
2500 ie = new ExpInitializer(loc, e);
2501 return ie;
2505 Statement *Parser::logStatement(int level) {
2506 nextToken();
2507 if (token.value != TOKlparen)
2508 error(loc, "found '%s' when expecting '('", token.toChars());
2509 return new LogStatement(loc, level, parseArguments());
2512 /*****************************************
2513 * Input:
2514 * flags PSxxxx
2517 Statement *DltParser::parseStatement(int flags)
2519 optionalEndline();
2520 if (flags & (PScolon | PSscope))
2521 flags |= PScurly;
2522 return Parser::parseStatement(flags);
2525 Statement *Parser::parseStatement(int flags)
2526 { Statement *s;
2527 Token *t;
2528 Condition *condition;
2529 Statement *ifbody;
2530 Statement *elsebody;
2531 Loc loc = this->loc;
2533 //printf("parseStatement()\n");
2535 if ((flags & PScurly) && token.value != startBlockTok)
2536 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2538 int tok = token.value;
2540 switch (token.value)
2542 case TOKidentifier:
2543 if (!dltSyntax)
2545 // Need to look ahead to see if it is a declaration, label, or expression
2546 t = peek(&token);
2547 if (t->value == TOKcolon)
2548 { // It's a label
2549 Identifier *ident;
2551 ident = token.ident;
2552 nextToken();
2553 nextToken();
2554 s = parseStatement(PSsemi);
2555 s = new LabelStatement(loc, ident, s);
2556 break;
2559 // fallthrough to TOKdot
2560 case TOKdot:
2561 case TOKtypeof:
2562 if (isDeclaration(&token, 2, TOKreserved, NULL))
2563 goto Ldeclaration;
2564 else
2565 goto Lexp;
2566 break;
2568 case TOKassert:
2569 case TOKthis:
2570 case TOKsuper:
2571 case TOKint32v:
2572 case TOKuns32v:
2573 case TOKint64v:
2574 case TOKuns64v:
2575 case TOKfloat32v:
2576 case TOKfloat64v:
2577 case TOKfloat80v:
2578 case TOKimaginary32v:
2579 case TOKimaginary64v:
2580 case TOKimaginary80v:
2581 case TOKcharv:
2582 case TOKwcharv:
2583 case TOKdcharv:
2584 case TOKnull:
2585 case TOKtrue:
2586 case TOKfalse:
2587 case TOKstring:
2588 case TOKlparen:
2589 case TOKcast:
2590 case TOKmul:
2591 case TOKmin:
2592 case TOKadd:
2593 case TOKplusplus:
2594 case TOKminusminus:
2595 case TOKnew:
2596 case TOKdelete:
2597 case TOKdelegate:
2598 case TOKfunction:
2599 case TOKtypeid:
2600 case TOKis:
2601 case TOKlbracket:
2602 Lexp:
2603 { Expression *exp;
2605 exp = parseExpression();
2606 if (!dltSyntax)
2607 check(TOKsemicolon, "statement");
2608 s = new ExpStatement(loc, exp);
2609 break;
2612 case TOKstatic:
2613 { // Look ahead to see if it's static assert() or static if()
2614 Token *t;
2616 t = peek(&token);
2617 if (t->value == TOKassert)
2619 nextToken();
2620 s = new StaticAssertStatement(parseStaticAssert());
2621 break;
2623 if (t->value == TOKif)
2625 nextToken();
2626 condition = parseStaticIfCondition();
2627 goto Lcondition;
2629 goto Ldeclaration;
2632 CASE_BASIC_TYPES:
2633 case TOKtypedef:
2634 case TOKalias:
2635 case TOKconst:
2636 case TOKauto:
2637 case TOKextern:
2638 case TOKfinal:
2639 case TOKinvariant:
2640 // case TOKtypeof:
2641 Ldeclaration:
2642 { Array *a;
2644 a = parseDeclarations();
2645 if (a->dim > 1)
2647 Statements *as = new Statements();
2648 as->reserve(a->dim);
2649 for (int i = 0; i < a->dim; i++)
2651 Dsymbol *d = (Dsymbol *)a->data[i];
2652 s = new DeclarationStatement(loc, d);
2653 as->push(s);
2655 s = new CompoundStatement(loc, as);
2657 else if (a->dim == 1)
2659 Dsymbol *d = (Dsymbol *)a->data[0];
2660 s = new DeclarationStatement(loc, d);
2662 else
2663 assert(0);
2664 if (flags & PSscope)
2665 s = new ScopeStatement(loc, s);
2666 break;
2669 case TOKstruct:
2670 case TOKunion:
2671 case TOKclass:
2672 case TOKinterface:
2673 { Dsymbol *d;
2675 d = parseAggregate();
2676 s = new DeclarationStatement(loc, d);
2677 break;
2680 case TOKenum:
2681 { Dsymbol *d;
2683 d = parseEnum();
2684 s = new DeclarationStatement(loc, d);
2685 break;
2688 case TOKmixin:
2689 { t = peek(&token);
2690 if (t->value == TOKlparen)
2691 { // mixin(string)
2692 nextToken();
2693 check(TOKlparen, "mixin");
2694 Expression *e = parseAssignExp();
2695 check(TOKrparen);
2696 check(TOKsemicolon);
2697 s = new CompileStatement(loc, e);
2698 break;
2700 Dsymbol *d = parseMixin();
2701 s = new DeclarationStatement(loc, d);
2702 break;
2705 case TOKcolon:
2706 case TOKlcurly:
2707 { Statements *statements;
2709 if (token.value != startBlockTok)
2710 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2712 nextToken();
2713 optionalEndline();
2714 statements = new Statements();
2715 while (token.value != TOKrcurly)
2717 statements->push(parseStatement(PSsemi | PScurlyscope));
2718 optionalEndline();
2720 endloc = this->loc;
2721 s = new CompoundStatement(loc, statements);
2722 if (flags & (PSscope | PScurlyscope))
2723 s = new ScopeStatement(loc, s);
2724 nextToken();
2725 break;
2728 case TOKlog_error: s = logStatement(LogStatement::Error); break;
2729 case TOKlog_warning: s = logStatement(LogStatement::Warn); break;
2730 case TOKlog_info: s = logStatement(LogStatement::Info); break;
2731 case TOKlog_trace: s = logStatement(LogStatement::Trace); break;
2733 case TOKwhile:
2734 { Expression *condition;
2735 Statement *body;
2737 nextToken();
2738 checkLParen();
2739 condition = parseExpression();
2740 checkRParen();
2741 body = parseStatement(PSscope);
2742 s = new WhileStatement(loc, condition, body);
2743 break;
2746 case TOKsemicolon:
2747 if (!(flags & PSsemi))
2748 error("use '{ }' for an empty statement, not a ';'");
2749 nextToken();
2750 s = new ExpStatement(loc, NULL);
2751 break;
2753 case TOKdo:
2754 { Statement *body;
2755 Expression *condition;
2757 nextToken();
2758 body = parseStatement(PSscope);
2759 check(TOKwhile);
2760 checkLParen();
2761 condition = parseExpression();
2762 checkRParen();
2763 s = new DoStatement(loc, body, condition);
2764 break;
2767 case TOKfor:
2769 Statement *init;
2770 Expression *condition;
2771 Expression *increment;
2772 Statement *body;
2774 nextToken();
2776 if (token.value == TOKlparen) {
2777 /* for (init; cond; incr): ... */
2778 nextToken();
2779 if (token.value == TOKsemicolon)
2780 { init = NULL;
2781 nextToken();
2783 else
2784 { init = parseStatement(0);
2786 if (token.value == TOKsemicolon)
2788 condition = NULL;
2789 nextToken();
2791 else
2793 condition = parseExpression();
2794 check(TOKsemicolon, "for condition");
2796 if (token.value == TOKrparen)
2797 { increment = NULL;
2798 nextToken();
2800 else
2801 { increment = parseExpression();
2802 check(TOKrparen);
2804 body = parseStatement(PSscope);
2805 s = new ForStatement(loc, init, condition, increment, body);
2806 if (init)
2807 s = new ScopeStatement(loc, s);
2808 } else if (dltSyntax)
2809 goto caseForeach;
2810 break;
2813 caseForeach:
2814 case TOKforeach:
2815 case TOKforeach_reverse:
2817 /* for var in seq: ... */
2818 /* for index, var in seq: ... */
2819 Arguments *arguments;
2821 Statement *d;
2822 Statement *body;
2823 Expression *aggr;
2824 enum TOK op = (TOK) tok;
2826 if (tok != TOKfor)
2827 nextToken();
2829 checkLParen();
2831 TOK inTok = dltSyntax ? TOKin : TOKsemicolon;
2833 arguments = new Arguments();
2835 while (1)
2837 Type *tb;
2838 Identifier *ai = NULL;
2839 Type *at;
2840 unsigned storageClass;
2841 Argument *a;
2843 storageClass = STCin;
2844 if (token.value == TOKinout || token.value == TOKref)
2845 { storageClass = STCref;
2846 nextToken();
2848 if (token.value == TOKidentifier)
2850 Token *t = peek(&token);
2851 if (t->value == TOKcomma || t->value == inTok)
2852 { ai = token.ident;
2853 at = NULL; // infer argument type
2854 nextToken();
2855 goto Larg;
2858 tb = parseBasicType();
2859 at = parseDeclarator(tb, &ai);
2860 if (!ai)
2861 error("no identifier for declarator %s", at->toChars());
2862 Larg:
2863 a = new Argument(storageClass, at, ai, NULL);
2864 arguments->push(a);
2865 if (token.value == TOKcomma)
2866 { nextToken();
2867 continue;
2869 break;
2872 check(inTok);
2874 aggr = parseExpression();
2875 checkRParen();
2877 if (dltSyntax) {
2878 if (token.value == TOKreversed) {
2879 op = TOKforeach_reverse;
2880 nextToken();
2881 } else {
2882 op = TOKforeach;
2886 body = parseStatement(PScolon);
2887 s = new ForeachStatement(loc, op, arguments, aggr, body);
2888 break;
2891 case TOKif:
2892 { Argument *arg = NULL;
2893 Expression *condition;
2894 Statement *ifbody;
2895 Statement *elsebody;
2897 nextToken();
2898 checkLParen();
2900 if (token.value == TOKauto)
2902 nextToken();
2903 if (token.value == TOKidentifier)
2905 Token *t = peek(&token);
2906 if (t->value == TOKassign)
2908 arg = new Argument(STCin, NULL, token.ident, NULL);
2909 nextToken();
2910 nextToken();
2912 else
2913 { error("= expected following auto identifier");
2914 goto Lerror;
2917 else
2918 { error("identifier expected following auto");
2919 goto Lerror;
2922 else if (isDeclaration(&token, 2, TOKassign, NULL))
2924 Type *tb;
2925 Type *at;
2926 Identifier *ai;
2928 tb = parseBasicType();
2929 at = parseDeclarator(tb, &ai);
2930 check(TOKassign);
2931 arg = new Argument(STCin, at, ai, NULL);
2934 // Check for " ident;"
2935 else if (token.value == TOKidentifier && !dltSyntax)
2937 Token *t = peek(&token);
2938 if (t->value == TOKcomma || t->value == TOKsemicolon)
2940 arg = new Argument(STCin, NULL, token.ident, NULL);
2941 nextToken();
2942 nextToken();
2943 if (1 || !global.params.useDeprecated)
2944 error("if (v; e) is deprecated, use if (auto v = e)");
2948 condition = parseExpression();
2949 checkRParen();
2950 ifbody = parseStatement(PSscope);
2951 if (token.value == TOKelse)
2953 nextToken();
2954 if (dltSyntax)
2956 if (token.value == TOKcolon) {
2957 elsebody = parseStatement(PSscope);
2958 } else if (token.value == TOKif) {
2959 elsebody = parseStatement(0);
2960 } else {
2961 error("Expected 'else:' or 'else if', not 'else %s'", token.toChars());
2962 elsebody = NULL;
2965 else
2966 elsebody = parseStatement(PSscope);
2968 else
2969 elsebody = NULL;
2970 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
2971 break;
2974 case TOKscope:
2975 if (peek(&token)->value != TOKlparen)
2976 goto Ldeclaration; // scope used as storage class
2977 nextToken();
2978 check(TOKlparen);
2979 if (token.value != TOKidentifier)
2980 { error("scope identifier expected");
2981 goto Lerror;
2983 else
2984 { TOK t = TOKon_scope_exit;
2985 Identifier *id = token.ident;
2987 if (id == Id::exit)
2988 t = TOKon_scope_exit;
2989 else if (id == Id::failure)
2990 t = TOKon_scope_failure;
2991 else if (id == Id::success)
2992 t = TOKon_scope_success;
2993 else
2994 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
2995 nextToken();
2996 check(TOKrparen);
2997 Statement *st = parseStatement(PScolon | PScurlyscope);
2998 s = new OnScopeStatement(loc, t, st);
2999 break;
3002 case TOKdebug:
3003 nextToken();
3004 condition = parseDebugCondition();
3005 goto Lcondition;
3007 case TOKversion:
3008 nextToken();
3009 condition = parseVersionCondition();
3010 goto Lcondition;
3012 Lcondition:
3013 if (dltSyntax && token.value != TOKcolon)
3014 error("expected colon after condition, not '%s'", token.toChars());
3015 ifbody = parseStatement(PScolon /*PSsemi*/);
3016 elsebody = NULL;
3017 if (token.value == TOKelse)
3019 nextToken();
3020 elsebody = parseStatement(PScolon /*PSsemi*/);
3022 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
3023 break;
3025 case TOKpragma:
3026 { Identifier *ident;
3027 Expressions *args = NULL;
3028 Statement *body;
3030 nextToken();
3031 check(TOKlparen);
3032 if (token.value != TOKidentifier)
3033 { error("pragma(identifier expected");
3034 goto Lerror;
3036 ident = token.ident;
3037 nextToken();
3038 if (token.value == TOKcomma)
3039 args = parseArguments(); // pragma(identifier, args...);
3040 else
3041 check(TOKrparen); // pragma(identifier);
3042 if (token.value == TOKsemicolon)
3043 { nextToken();
3044 body = NULL;
3046 else
3047 body = parseStatement(PSsemi | PScolon);
3048 s = new PragmaStatement(loc, ident, args, body);
3049 break;
3052 case TOKswitch:
3053 { Expression *condition;
3054 Statement *body;
3056 nextToken();
3057 checkLParen();
3058 condition = parseExpression();
3059 checkRParen();
3060 body = parseStatement(PSscope | PScolon);
3061 s = new SwitchStatement(loc, condition, body);
3062 break;
3065 case TOKcase:
3066 { Expression *exp;
3067 Statements *statements;
3068 Array cases; // array of Expression's
3070 while (1)
3072 nextToken();
3073 exp = parseAssignExp();
3074 cases.push(exp);
3075 if (token.value != TOKcomma)
3076 break;
3079 if (dltSyntax)
3081 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3083 else
3085 check(TOKcolon);
3087 statements = new Statements();
3088 while (token.value != TOKcase &&
3089 token.value != TOKdefault &&
3090 token.value != TOKrcurly)
3092 statements->push(parseStatement(PSsemi | PScurlyscope));
3094 s = new CompoundStatement(loc, statements);
3097 s = new ScopeStatement(loc, s);
3099 // Keep cases in order by building the case statements backwards
3100 for (int i = cases.dim; i; i--)
3102 exp = (Expression *)cases.data[i - 1];
3103 s = new CaseStatement(loc, exp, s);
3105 break;
3108 case TOKdefault:
3110 Statements *statements;
3112 nextToken();
3114 if (dltSyntax)
3116 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3118 else
3120 check(TOKcolon);
3122 statements = new Statements();
3123 while (token.value != TOKcase &&
3124 token.value != TOKdefault &&
3125 token.value != TOKrcurly)
3127 statements->push(parseStatement(PSsemi | PScurlyscope));
3129 s = new CompoundStatement(loc, statements);
3132 s = new ScopeStatement(loc, s);
3133 s = new DefaultStatement(loc, s);
3134 break;
3137 case TOKreturn:
3138 { Expression *exp;
3140 nextToken();
3141 if (token.value == TOKsemicolon || token.value == TOKendline)
3142 exp = NULL;
3143 else
3144 exp = parseExpression();
3146 if (!dltSyntax)
3147 check(TOKsemicolon, "return statement");
3148 else if (token.value != TOKendline) {
3149 error("Expected end-of-line after return statement, but found '%s'", token.toChars());
3152 s = new ReturnStatement(loc, exp);
3153 break;
3156 case TOKbreak:
3157 { Identifier *ident;
3159 nextToken();
3160 if (token.value == TOKidentifier)
3161 { ident = token.ident;
3162 nextToken();
3164 else
3165 ident = NULL;
3166 if (token.value != TOKsemicolon && token.value != TOKendline) {
3167 error("expected %s after break, not '%s'", endToken(), token.toChars());
3169 if (!dltSyntax)
3170 nextToken();
3171 s = new BreakStatement(loc, ident);
3172 break;
3175 case TOKcontinue:
3176 { Identifier *ident;
3178 nextToken();
3179 if (token.value == TOKidentifier)
3180 { ident = token.ident;
3181 nextToken();
3183 else
3184 ident = NULL;
3185 check(TOKsemicolon, "continue statement");
3186 s = new ContinueStatement(loc, ident);
3187 break;
3190 case TOKgoto:
3191 { Identifier *ident;
3193 nextToken();
3194 if (token.value == TOKdefault)
3196 nextToken();
3197 s = new GotoDefaultStatement(loc);
3199 else if (token.value == TOKcase)
3201 Expression *exp = NULL;
3203 nextToken();
3204 if (token.value != TOKsemicolon)
3205 exp = parseExpression();
3206 s = new GotoCaseStatement(loc, exp);
3208 else
3210 if (token.value != TOKidentifier)
3211 { error("Identifier expected following goto");
3212 ident = NULL;
3214 else
3215 { ident = token.ident;
3216 nextToken();
3218 s = new GotoStatement(loc, ident);
3220 if (token.value != TOKsemicolon && token.value != TOKendline) {
3221 error("expected %s after goto statement, not '%s'", endToken(), token.toChars());
3223 break;
3226 case TOKsynchronized:
3227 { Expression *exp;
3228 Statement *body;
3230 nextToken();
3231 if (token.value == TOKlparen)
3233 nextToken();
3234 exp = parseExpression();
3235 check(TOKrparen);
3237 else
3238 exp = NULL;
3239 body = parseStatement(PSscope);
3240 s = new SynchronizedStatement(loc, exp, body);
3241 break;
3244 case TOKwith:
3245 { Expression *exp;
3246 Statement *body;
3248 nextToken();
3249 check(TOKlparen);
3250 exp = parseExpression();
3251 check(TOKrparen);
3252 body = parseStatement(PSscope);
3253 s = new WithStatement(loc, exp, body);
3254 break;
3257 case TOKtry:
3258 { Statement *body;
3259 Array *catches = NULL;
3260 Statement *finalbody = NULL;
3262 nextToken();
3263 body = parseStatement(PSscope);
3264 while (token.value == TOKcatch)
3266 Statement *handler;
3267 Catch *c;
3268 Type *t;
3269 Identifier *id;
3270 Loc loc = this->loc;
3272 nextToken();
3273 if (token.value == startBlockTok)
3275 t = NULL;
3276 id = NULL;
3278 else
3280 check(TOKlparen);
3281 t = parseBasicType();
3282 id = NULL;
3283 t = parseDeclarator(t, &id);
3284 check(TOKrparen);
3286 handler = parseStatement(PScolon);
3287 c = new Catch(loc, t, id, handler);
3288 if (!catches)
3289 catches = new Array();
3290 catches->push(c);
3293 if (token.value == TOKfinally)
3294 { nextToken();
3295 finalbody = parseStatement(PScolon);
3298 s = body;
3299 if (!catches && !finalbody)
3300 error("catch or finally expected following try");
3301 else
3302 { if (catches)
3303 s = new TryCatchStatement(loc, body, catches);
3304 if (finalbody)
3305 s = new TryFinallyStatement(loc, s, finalbody);
3307 break;
3310 case TOKthrow:
3311 { Expression *exp;
3313 nextToken();
3314 exp = parseExpression();
3315 if (token.value != TOKsemicolon && token.value != TOKendline) {
3316 error("%s expected after throw statement, not '%s'", endToken(), token.toChars());
3318 if (!dltSyntax)
3319 nextToken();
3320 s = new ThrowStatement(loc, exp);
3321 break;
3324 case TOKvolatile:
3325 nextToken();
3326 s = parseStatement(PSsemi | PScurlyscope);
3327 s = new VolatileStatement(loc, s);
3328 break;
3330 case TOKasm:
3331 { Statements *statements;
3332 Identifier *label;
3333 Loc labelloc;
3334 Token *toklist;
3335 Token **ptoklist;
3337 // Parse the asm block into a sequence of AsmStatements,
3338 // each AsmStatement is one instruction.
3339 // Separate out labels.
3340 // Defer parsing of AsmStatements until semantic processing.
3342 nextToken();
3343 #if GDC_EXTENDED_ASM_SYNTAX
3344 if (token.value == TOKlparen)
3346 nextToken();
3347 s = parseExtAsm(1);
3348 break;
3350 #endif
3351 check(startBlockTok);
3352 toklist = NULL;
3353 ptoklist = &toklist;
3354 label = NULL;
3355 statements = new Statements();
3356 while (1)
3358 switch (token.value)
3360 case TOKidentifier:
3361 if (!toklist)
3363 // Look ahead to see if it is a label
3364 t = peek(&token);
3365 if (t->value == TOKcolon)
3366 { // It's a label
3367 label = token.ident;
3368 labelloc = this->loc;
3369 nextToken();
3370 nextToken();
3371 continue;
3374 goto Ldefault;
3376 case TOKrcurly:
3377 if (toklist || label)
3379 error("asm statements must end in ';'");
3381 break;
3383 case TOKendline:
3384 case TOKsemicolon:
3385 s = NULL;
3386 if (toklist || label)
3387 { // Create AsmStatement from list of tokens we've saved
3388 s = new AsmStatement(this->loc, toklist);
3389 toklist = NULL;
3390 ptoklist = &toklist;
3391 if (label)
3392 { s = new LabelStatement(labelloc, label, s);
3393 label = NULL;
3395 statements->push(s);
3397 nextToken();
3398 continue;
3400 case TOKeof:
3401 /* { */
3402 error("matching '}' expected, not end of file");
3403 break;
3405 case TOKlparen:
3406 case TOKstring:
3407 // If the first token is a string or '(', parse as extended asm.
3408 if (! toklist)
3410 s = parseExtAsm(0);
3411 statements->push(s);
3412 continue;
3414 // ...else, drop through.
3416 default:
3417 Ldefault:
3418 *ptoklist = new Token();
3419 memcpy(*ptoklist, &token, sizeof(Token));
3420 ptoklist = &(*ptoklist)->next;
3421 *ptoklist = NULL;
3423 nextToken();
3424 continue;
3426 break;
3428 s = new CompoundStatement(loc, statements);
3429 nextToken();
3430 break;
3433 default:
3434 error("found '%s' instead of statement", token.toChars());
3435 goto Lerror;
3437 Lerror:
3438 while (token.value != TOKrcurly &&
3439 token.value != TOKsemicolon &&
3440 token.value != TOKeof)
3441 nextToken();
3442 if (token.value == TOKsemicolon)
3443 nextToken();
3444 s = NULL;
3445 break;
3448 return s;
3451 Statement *Parser::parseExtAsm(int expect_rparen)
3453 Expression * insnTemplate;
3454 Expressions * args = NULL;
3455 Array * argNames = NULL;
3456 Expressions * argConstraints = NULL;
3457 int nOutputArgs = 0;
3458 Expressions * clobbers = NULL;
3459 bool isInputPhase = false; // Output operands first, then input.
3461 insnTemplate = parseExpression();
3462 if (token.value == TOKrparen || token.value == TOKsemicolon)
3463 goto Ldone;
3464 check(TOKcolon);
3465 while (1) {
3466 Expression * arg = NULL;
3467 Identifier * name = NULL;
3468 Expression * constraint = NULL;
3470 switch (token.value)
3472 case TOKsemicolon:
3473 case TOKrparen:
3474 goto Ldone;
3476 case TOKcolon:
3477 nextToken();
3478 goto LnextPhase;
3480 case TOKeof:
3481 error("unterminated statement");
3483 case TOKlbracket:
3484 nextToken();
3485 if (token.value == TOKidentifier)
3487 name = token.ident;
3488 nextToken();
3490 else
3491 error("expected identifier after '['");
3492 check(TOKrbracket);
3493 // drop through
3494 default:
3495 constraint = parsePrimaryExp();
3496 if (constraint->op != TOKstring)
3497 error("expected constant string constraint for operand");
3498 arg = parseAssignExp();
3499 if (! args)
3501 args = new Expressions;
3502 argConstraints = new Expressions;
3503 argNames = new Array;
3505 args->push(arg);
3506 argNames->push(name);
3507 argConstraints->push(constraint);
3508 if (! isInputPhase)
3509 nOutputArgs++;
3511 if (token.value == TOKcomma)
3512 nextToken();
3513 break;
3515 continue;
3516 LnextPhase:
3517 if (! isInputPhase)
3518 isInputPhase = true;
3519 else
3520 break;
3523 while (1)
3525 Expression * clobber;
3527 switch (token.value)
3529 case TOKsemicolon:
3530 case TOKrparen:
3531 goto Ldone;
3533 case TOKeof:
3534 error("unterminated statement");
3536 default:
3537 clobber = parseAssignExp();
3538 if (clobber->op != TOKstring)
3539 error("expected constant string constraint for clobber name");
3540 if (! clobbers)
3541 clobbers = new Expressions;
3542 clobbers->push(clobber);
3544 if (token.value == TOKcomma)
3545 nextToken();
3546 break;
3549 Ldone:
3550 if (expect_rparen)
3551 check(TOKrparen);
3552 else
3553 check(TOKsemicolon);
3555 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3556 argConstraints, nOutputArgs, clobbers);
3559 void Parser::optionalEndline() {
3560 while (token.value == TOKendline) {
3561 nextToken();
3565 void Parser::check(enum TOK value)
3567 check(loc, value);
3570 void Parser::check(Loc loc, enum TOK value)
3572 if (token.value != value)
3573 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3574 nextToken();
3577 void Parser::check(enum TOK value, char *string)
3579 if (token.value != value)
3580 error("found '%s' when expecting '%s' following '%s'",
3581 token.toChars(), Token::toChars(value), string);
3582 nextToken();
3585 char *Parser::endToken()
3587 return "semicolon";
3590 char *DltParser::endToken()
3592 return "newline";
3595 void Parser::checkLParen() { check(TOKlparen); }
3596 void Parser::checkRParen() { check(TOKrparen); }
3598 void DltParser::checkLParen() { }
3599 void DltParser::checkRParen() { }
3601 /************************************
3602 * Determine if the scanner is sitting on the start of a declaration.
3603 * Input:
3604 * needId 0 no identifier
3605 * 1 identifier optional
3606 * 2 must have identifier
3609 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3611 int haveId = 0;
3613 if (!isBasicType(&t))
3614 return FALSE;
3615 if (!isDeclarator(&t, &haveId, endtok))
3616 return FALSE;
3617 if ( needId == 1 ||
3618 (needId == 0 && !haveId) ||
3619 (needId == 2 && haveId))
3620 { if (pt)
3621 *pt = t;
3622 return TRUE;
3624 else
3625 return FALSE;
3628 int Parser::isBasicType(Token **pt)
3630 // This code parallels parseBasicType()
3631 Token *t = *pt;
3632 Token *t2;
3633 int parens;
3635 switch (t->value)
3637 CASE_BASIC_TYPES:
3638 t = peek(t);
3639 break;
3641 case TOKidentifier:
3642 t = peek(t);
3643 if (t->value == TOKnot)
3645 goto L4;
3647 goto L3;
3648 while (1)
3651 t = peek(t);
3653 if (t->value == TOKdot)
3655 Ldot:
3656 t = peek(t);
3657 if (t->value != TOKidentifier)
3658 goto Lfalse;
3659 t = peek(t);
3660 if (t->value != TOKnot)
3661 goto L3;
3663 t = peek(t);
3664 if (t->value != TOKlparen)
3665 goto Lfalse;
3666 if (!skipParens(t, &t))
3667 goto Lfalse;
3669 else
3670 break;
3672 break;
3674 case TOKdot:
3675 goto Ldot;
3677 case TOKtypeof:
3678 /* typeof(exp).identifier...
3680 t = peek(t);
3681 if (t->value != TOKlparen)
3682 goto Lfalse;
3683 if (!skipParens(t, &t))
3684 goto Lfalse;
3685 goto L2;
3687 default:
3688 goto Lfalse;
3690 *pt = t;
3691 return TRUE;
3693 Lfalse:
3694 return FALSE;
3697 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3698 { // This code parallels parseDeclarator()
3699 Token *t = *pt;
3700 int parens;
3702 //printf("Parser::isDeclarator()\n");
3703 //t->print();
3704 if (t->value == TOKassign)
3705 return FALSE;
3707 while (1)
3709 parens = FALSE;
3710 switch (t->value)
3712 case TOKquestion:
3713 case TOKmul:
3714 case TOKand:
3715 t = peek(t);
3716 continue;
3718 case TOKlbracket:
3719 t = peek(t);
3720 if (t->value == TOKrbracket)
3722 t = peek(t);
3724 else if (isDeclaration(t, 0, TOKrbracket, &t))
3725 { // It's an associative array declaration
3726 t = peek(t);
3728 else
3730 // [ expression ]
3731 // [ expression .. expression ]
3732 if (!isExpression(&t))
3733 return FALSE;
3734 if (t->value == TOKslice)
3735 { t = peek(t);
3736 if (!isExpression(&t))
3737 return FALSE;
3739 if (t->value != TOKrbracket)
3740 return FALSE;
3741 t = peek(t);
3743 continue;
3745 case TOKidentifier:
3746 if (*haveId)
3747 return FALSE;
3748 *haveId = TRUE;
3749 t = peek(t);
3750 break;
3752 case TOKlparen:
3753 t = peek(t);
3755 if (t->value == TOKrparen)
3756 return FALSE; // () is not a declarator
3758 /* Regard ( identifier ) as not a declarator
3759 * BUG: what about ( *identifier ) in
3760 * f(*p)(x);
3761 * where f is a class instance with overloaded () ?
3762 * Should we just disallow C-style function pointer declarations?
3764 if (t->value == TOKidentifier)
3765 { Token *t2 = peek(t);
3766 if (t2->value == TOKrparen)
3767 return FALSE;
3771 if (!isDeclarator(&t, haveId, TOKrparen))
3772 return FALSE;
3773 t = peek(t);
3774 parens = TRUE;
3775 break;
3777 case TOKdelegate:
3778 case TOKfunction:
3779 t = peek(t);
3780 if (!isParameters(&t))
3781 return FALSE;
3782 continue;
3784 break;
3787 while (1)
3789 switch (t->value)
3791 #if CARRAYDECL
3792 case TOKlbracket:
3793 parens = FALSE;
3794 t = peek(t);
3795 if (t->value == TOKrbracket)
3797 t = peek(t);
3799 else if (isDeclaration(t, 0, TOKrbracket, &t))
3800 { // It's an associative array declaration
3801 t = peek(t);
3803 else
3805 // [ expression ]
3806 if (!isExpression(&t))
3807 return FALSE;
3808 if (t->value != TOKrbracket)
3809 return FALSE;
3810 t = peek(t);
3812 continue;
3813 #endif
3815 case TOKlparen:
3816 parens = FALSE;
3817 if (!isParameters(&t))
3818 return FALSE;
3819 continue;
3821 // Valid tokens that follow a declaration
3822 case TOKrparen:
3823 case TOKrbracket:
3824 case TOKassign:
3825 case TOKcomma:
3826 case TOKendline:
3827 case TOKsemicolon:
3828 case TOKlcurly:
3829 case TOKin:
3830 // The !parens is to disallow unnecessary parentheses
3831 if (!parens && (endtok == TOKreserved || endtok == t->value))
3832 { *pt = t;
3833 return TRUE;
3835 return FALSE;
3837 default:
3838 return FALSE;
3844 int Parser::isParameters(Token **pt)
3845 { // This code parallels parseParameters()
3846 Token *t = *pt;
3847 int tmp;
3849 //printf("isParameters()\n");
3850 if (t->value != TOKlparen)
3851 return FALSE;
3853 t = peek(t);
3854 while (1)
3856 switch (t->value)
3858 case TOKrparen:
3859 break;
3861 case TOKdotdotdot:
3862 t = peek(t);
3863 break;
3865 case TOKin:
3866 case TOKout:
3867 case TOKinout:
3868 case TOKref:
3869 case TOKlazy:
3870 t = peek(t);
3871 default:
3872 if (!isBasicType(&t))
3873 return FALSE;
3874 tmp = FALSE;
3875 if (t->value != TOKdotdotdot &&
3876 !isDeclarator(&t, &tmp, TOKreserved))
3877 return FALSE;
3878 if (t->value == TOKassign)
3879 { t = peek(t);
3880 if (!isExpression(&t))
3881 return FALSE;
3883 if (t->value == TOKdotdotdot)
3885 t = peek(t);
3886 break;
3888 if (t->value == TOKcomma)
3889 { t = peek(t);
3890 continue;
3892 break;
3894 break;
3896 if (t->value != TOKrparen)
3897 return FALSE;
3898 t = peek(t);
3899 *pt = t;
3900 return TRUE;
3903 int Parser::isExpression(Token **pt)
3905 // This is supposed to determine if something is an expression.
3906 // What it actually does is scan until a closing right bracket
3907 // is found.
3909 Token *t = *pt;
3910 int brnest = 0;
3911 int panest = 0;
3913 for (;; t = peek(t))
3915 switch (t->value)
3917 case TOKlbracket:
3918 brnest++;
3919 continue;
3921 case TOKrbracket:
3922 if (--brnest >= 0)
3923 continue;
3924 break;
3926 case TOKlparen:
3927 panest++;
3928 continue;
3930 case TOKcomma:
3931 if (brnest || panest)
3932 continue;
3933 break;
3935 case TOKrparen:
3936 if (--panest >= 0)
3937 continue;
3938 break;
3940 case TOKslice:
3941 if (brnest)
3942 continue;
3943 break;
3945 case TOKeof:
3946 return FALSE;
3948 default:
3949 continue;
3951 break;
3954 *pt = t;
3955 return TRUE;
3958 /**********************************************
3959 * Skip over
3960 * instance foo.bar(parameters...)
3961 * Output:
3962 * if (pt), *pt is set to the token following the closing )
3963 * Returns:
3964 * 1 it's valid instance syntax
3965 * 0 invalid instance syntax
3968 int Parser::isTemplateInstance(Token *t, Token **pt)
3970 t = peek(t);
3971 if (t->value != TOKdot)
3973 if (t->value != TOKidentifier)
3974 goto Lfalse;
3975 t = peek(t);
3977 while (t->value == TOKdot)
3979 t = peek(t);
3980 if (t->value != TOKidentifier)
3981 goto Lfalse;
3982 t = peek(t);
3984 if (t->value != TOKlparen)
3985 goto Lfalse;
3987 // Skip over the template arguments
3988 while (1)
3990 while (1)
3992 t = peek(t);
3993 switch (t->value)
3995 case TOKlparen:
3996 if (!skipParens(t, &t))
3997 goto Lfalse;
3998 continue;
3999 case TOKrparen:
4000 break;
4001 case TOKcomma:
4002 break;
4003 case TOKeof:
4004 case TOKsemicolon:
4005 goto Lfalse;
4006 default:
4007 continue;
4009 break;
4012 if (t->value != TOKcomma)
4013 break;
4015 if (t->value != TOKrparen)
4016 goto Lfalse;
4017 t = peek(t);
4018 if (pt)
4019 *pt = t;
4020 return 1;
4022 Lfalse:
4023 return 0;
4026 /*******************************************
4027 * Skip parens, brackets.
4028 * Input:
4029 * t is on opening (
4030 * Output:
4031 * *pt is set to closing token, which is ')' on success
4032 * Returns:
4033 * !=0 successful
4034 * 0 some parsing error
4037 int Parser::skipParens(Token *t, Token **pt)
4039 int parens = 0;
4041 while (1)
4043 switch (t->value)
4045 case TOKlparen:
4046 parens++;
4047 break;
4049 case TOKrparen:
4050 parens--;
4051 if (parens < 0)
4052 goto Lfalse;
4053 if (parens == 0)
4054 goto Ldone;
4055 break;
4057 case TOKeof:
4058 case TOKsemicolon:
4059 goto Lfalse;
4061 default:
4062 break;
4064 t = peek(t);
4067 Ldone:
4068 if (*pt)
4069 *pt = t;
4070 return 1;
4072 Lfalse:
4073 return 0;
4076 /********************************* Expression Parser ***************************/
4078 Expression *Parser::parsePrimaryExp()
4079 { Expression *e;
4080 Type *t;
4081 Identifier *id;
4082 enum TOK save;
4083 Loc loc = this->loc;
4085 switch (token.value)
4087 case TOKidentifier:
4088 id = token.ident;
4089 nextToken();
4090 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4091 { // identifier!(template-argument-list)
4092 TemplateInstance *tempinst;
4094 tempinst = new TemplateInstance(loc, id);
4095 nextToken();
4096 tempinst->tiargs = parseTemplateArgumentList();
4097 e = new ScopeExp(loc, tempinst);
4099 else
4100 e = new IdentifierExp(loc, id);
4101 break;
4103 case TOKdollar:
4104 if (!inBrackets)
4105 error("'$' is valid only inside [] of index or slice");
4106 e = new DollarExp(loc);
4107 nextToken();
4108 break;
4110 case TOKdot:
4111 // Signal global scope '.' operator with "" identifier
4112 e = new IdentifierExp(loc, Id::empty);
4113 break;
4115 case TOKthis:
4116 e = new ThisExp(loc);
4117 nextToken();
4118 break;
4120 case TOKsuper:
4121 e = new SuperExp(loc);
4122 nextToken();
4123 break;
4125 case TOKint32v:
4126 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
4127 nextToken();
4128 break;
4130 case TOKuns32v:
4131 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
4132 nextToken();
4133 break;
4135 case TOKint64v:
4136 e = new IntegerExp(loc, token.int64value, Type::tint64);
4137 nextToken();
4138 break;
4140 case TOKuns64v:
4141 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
4142 nextToken();
4143 break;
4145 case TOKfloat32v:
4146 e = new RealExp(loc, token.float80value, Type::tfloat32);
4147 nextToken();
4148 break;
4150 case TOKfloat64v:
4151 e = new RealExp(loc, token.float80value, Type::tfloat64);
4152 nextToken();
4153 break;
4155 case TOKfloat80v:
4156 e = new RealExp(loc, token.float80value, Type::tfloat80);
4157 nextToken();
4158 break;
4160 case TOKimaginary32v:
4161 e = new RealExp(loc, token.float80value, Type::timaginary32);
4162 nextToken();
4163 break;
4165 case TOKimaginary64v:
4166 e = new RealExp(loc, token.float80value, Type::timaginary64);
4167 nextToken();
4168 break;
4170 case TOKimaginary80v:
4171 e = new RealExp(loc, token.float80value, Type::timaginary80);
4172 nextToken();
4173 break;
4175 case TOKnull:
4176 e = new NullExp(loc);
4177 nextToken();
4178 break;
4180 case TOKtrue:
4181 e = new IntegerExp(loc, 1, Type::tbool);
4182 nextToken();
4183 break;
4185 case TOKfalse:
4186 e = new IntegerExp(loc, 0, Type::tbool);
4187 nextToken();
4188 break;
4190 case TOKcharv:
4191 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
4192 nextToken();
4193 break;
4195 case TOKwcharv:
4196 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
4197 nextToken();
4198 break;
4200 case TOKdcharv:
4201 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
4202 nextToken();
4203 break;
4205 case TOKstring:
4206 { unsigned char *s;
4207 unsigned len;
4208 unsigned char postfix;
4210 // cat adjacent strings
4211 s = token.ustring;
4212 len = token.len;
4213 postfix = token.postfix;
4214 while (1)
4216 nextToken();
4217 if (token.value == TOKstring)
4218 { unsigned len1;
4219 unsigned len2;
4220 unsigned char *s2;
4222 if (token.postfix)
4223 { if (token.postfix != postfix)
4224 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4225 postfix = token.postfix;
4228 len1 = len;
4229 len2 = token.len;
4230 len = len1 + len2;
4231 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4232 memcpy(s2, s, len1 * sizeof(unsigned char));
4233 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4234 s = s2;
4236 else
4237 break;
4239 e = new StringExp(loc, s, len, postfix);
4240 break;
4243 CASE_BASIC_TYPES_X(t):
4244 nextToken();
4246 check(TOKdot, t->toChars());
4247 if (token.value != TOKidentifier)
4248 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4249 goto Lerr;
4251 e = new TypeDotIdExp(loc, t, token.ident);
4252 nextToken();
4253 break;
4255 case TOKtypeof:
4256 { Expression *exp;
4258 nextToken();
4259 check(TOKlparen);
4260 exp = parseExpression();
4261 check(TOKrparen);
4262 t = new TypeTypeof(loc, exp);
4263 if (token.value == TOKdot)
4264 goto L1;
4265 e = new TypeExp(loc, t);
4266 break;
4269 case TOKtypeid:
4270 { Type *t;
4272 nextToken();
4273 check(TOKlparen, "typeid");
4274 t = parseBasicType();
4275 t = parseDeclarator(t,NULL); // ( type )
4276 check(TOKrparen);
4277 e = new TypeidExp(loc, t);
4278 break;
4281 case TOKis:
4282 { Type *targ;
4283 Identifier *ident = NULL;
4284 Type *tspec = NULL;
4285 enum TOK tok = TOKreserved;
4286 enum TOK tok2 = TOKreserved;
4287 Loc loc = this->loc;
4289 nextToken();
4290 if (token.value == TOKlparen)
4292 nextToken();
4293 targ = parseBasicType();
4294 targ = parseDeclarator(targ, &ident);
4295 if (token.value == TOKcolon || token.value == TOKequal)
4297 tok = token.value;
4298 nextToken();
4299 if (tok == TOKequal &&
4300 (token.value == TOKtypedef ||
4301 token.value == TOKstruct ||
4302 token.value == TOKunion ||
4303 token.value == TOKclass ||
4304 token.value == TOKsuper ||
4305 token.value == TOKenum ||
4306 token.value == TOKinterface ||
4307 token.value == TOKfunction ||
4308 token.value == TOKdelegate ||
4309 token.value == TOKreturn))
4311 tok2 = token.value;
4312 nextToken();
4314 else
4316 tspec = parseBasicType();
4317 tspec = parseDeclarator(tspec, NULL);
4320 check(TOKrparen);
4322 else
4323 { error("(type identifier : specialization) expected following is");
4324 goto Lerr;
4326 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4327 break;
4330 case TOKassert:
4331 { Expression *msg = NULL;
4333 nextToken();
4335 checkLParen();
4336 e = parseAssignExp();
4337 if (token.value == (dltSyntax ? TOKelse : TOKcomma))
4338 { nextToken();
4339 msg = parseAssignExp();
4341 checkRParen();
4343 e = new AssertExp(loc, e, msg);
4344 break;
4347 case TOKmixin:
4349 nextToken();
4350 check(TOKlparen, "mixin");
4351 e = parseAssignExp();
4352 check(TOKrparen);
4353 e = new CompileExp(loc, e);
4354 break;
4357 case TOKimport:
4359 nextToken();
4360 check(TOKlparen, "import");
4361 e = parseAssignExp();
4362 check(TOKrparen);
4363 e = new FileExp(loc, e);
4364 break;
4367 case TOKlparen:
4368 if (peekPastParen(&token)->value == TOKlcurly)
4369 { // (arguments) { statements... }
4370 save = TOKdelegate;
4371 goto case_delegate;
4373 // ( expression )
4374 nextToken();
4375 e = parseExpression();
4376 check(loc, TOKrparen);
4377 break;
4379 case TOKlbracket:
4380 { /* Parse array literals and associative array literals:
4381 * [ value, value, value ... ]
4382 * [ key:value, key:value, key:value ... ]
4384 Expressions *values = new Expressions();
4385 Expressions *keys = NULL;
4387 nextToken();
4388 if (token.value != TOKrbracket)
4390 while (1)
4392 Expression *e = parseAssignExp();
4393 if (token.value == TOKcolon && (keys || values->dim == 0))
4394 { nextToken();
4395 if (!keys)
4396 keys = new Expressions();
4397 keys->push(e);
4398 e = parseAssignExp();
4400 else if (keys)
4401 { error("'key:value' expected for associative array literal");
4402 delete keys;
4403 keys = NULL;
4405 values->push(e);
4406 if (token.value == TOKrbracket)
4407 break;
4408 check(TOKcomma);
4411 check(TOKrbracket);
4413 if (keys)
4414 e = new AssocArrayLiteralExp(loc, keys, values);
4415 else
4416 e = new ArrayLiteralExp(loc, values);
4417 break;
4420 case TOKlcurly:
4421 // { statements... }
4422 save = TOKdelegate;
4423 goto case_delegate;
4425 case TOKfunction:
4426 case TOKdelegate:
4427 save = token.value;
4428 nextToken();
4429 case_delegate:
4431 /* function type(parameters) { body }
4432 * delegate type(parameters) { body }
4434 Arguments *arguments;
4435 int varargs;
4436 FuncLiteralDeclaration *fd;
4437 Type *t;
4439 if (token.value == TOKlcurly)
4441 t = NULL;
4442 varargs = 0;
4443 arguments = new Arguments();
4445 else
4447 if (token.value == TOKlparen)
4448 t = NULL;
4449 else
4451 t = parseBasicType();
4452 t = parseBasicType2(t); // function return type
4454 arguments = parseParameters(&varargs);
4456 t = new TypeFunction(arguments, t, varargs, linkage);
4457 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4458 parseContracts(fd);
4459 e = new FuncExp(loc, fd);
4460 break;
4463 default:
4464 error("expression expected, not '%s'", token.toChars());
4465 Lerr:
4466 // Anything for e, as long as it's not NULL
4467 e = new IntegerExp(loc, 0, Type::tint32);
4468 nextToken();
4469 break;
4471 return parsePostExp(e);
4474 Expression *Parser::parsePostExp(Expression *e)
4476 Loc loc;
4478 while (1)
4480 loc = this->loc;
4481 switch (token.value)
4483 case TOKdot:
4484 nextToken();
4485 if (token.value == TOKidentifier)
4486 { Identifier *id = token.ident;
4488 nextToken();
4489 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4490 { // identifier!(template-argument-list)
4491 TemplateInstance *tempinst;
4493 tempinst = new TemplateInstance(loc, id);
4494 nextToken();
4495 tempinst->tiargs = parseTemplateArgumentList();
4496 e = new DotTemplateInstanceExp(loc, e, tempinst);
4498 else
4499 e = new DotIdExp(loc, e, id);
4500 continue;
4502 else if (token.value == TOKnew)
4504 e = parseNewExp(e);
4505 continue;
4507 else
4508 error("identifier expected following '.', not '%s'", token.toChars());
4509 break;
4511 case TOKplusplus:
4512 e = new PostExp(TOKplusplus, loc, e);
4513 break;
4515 case TOKminusminus:
4516 e = new PostExp(TOKminusminus, loc, e);
4517 break;
4519 case TOKlparen:
4520 e = new CallExp(loc, e, parseArguments());
4521 continue;
4523 case TOKlbracket:
4524 { // array dereferences:
4525 // array[index]
4526 // array[]
4527 // array[lwr .. upr]
4528 Expression *index;
4529 Expression *upr;
4531 inBrackets++;
4532 nextToken();
4533 if (token.value == TOKrbracket)
4534 { // array[]
4535 e = new SliceExp(loc, e, NULL, NULL);
4536 nextToken();
4538 else
4540 index = parseAssignExp();
4541 if (token.value == TOKslice)
4542 { // array[lwr .. upr]
4543 nextToken();
4544 upr = parseAssignExp();
4545 e = new SliceExp(loc, e, index, upr);
4547 else
4548 { // array[index, i2, i3, i4, ...]
4549 Expressions *arguments = new Expressions();
4550 arguments->push(index);
4551 if (token.value == TOKcomma)
4553 nextToken();
4554 while (1)
4555 { Expression *arg;
4557 arg = parseAssignExp();
4558 arguments->push(arg);
4559 if (token.value == TOKrbracket)
4560 break;
4561 check(TOKcomma);
4564 e = new ArrayExp(loc, e, arguments);
4566 check(TOKrbracket);
4567 inBrackets--;
4569 continue;
4572 default:
4573 return e;
4575 nextToken();
4579 Expression *Parser::parseUnaryExp()
4580 { Expression *e;
4581 Loc loc = this->loc;
4583 switch (token.value)
4585 case TOKand:
4586 nextToken();
4587 e = parseUnaryExp();
4588 e = new AddrExp(loc, e);
4589 break;
4591 case TOKplusplus:
4592 nextToken();
4593 e = parseUnaryExp();
4594 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4595 break;
4597 case TOKminusminus:
4598 nextToken();
4599 e = parseUnaryExp();
4600 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4601 break;
4603 case TOKmul:
4604 nextToken();
4605 e = parseUnaryExp();
4606 e = new PtrExp(loc, e);
4607 break;
4609 case TOKmin:
4610 nextToken();
4611 e = parseUnaryExp();
4612 e = new NegExp(loc, e);
4613 break;
4615 case TOKadd:
4616 nextToken();
4617 e = parseUnaryExp();
4618 e = new UAddExp(loc, e);
4619 break;
4621 case TOKnot:
4622 nextToken();
4623 e = parseUnaryExp();
4624 e = new NotExp(loc, e);
4625 break;
4627 case TOKtilde:
4628 nextToken();
4629 e = parseUnaryExp();
4630 e = new ComExp(loc, e);
4631 break;
4633 case TOKdelete:
4634 nextToken();
4635 e = parseUnaryExp();
4636 e = new DeleteExp(loc, e);
4637 break;
4639 case TOKnew:
4640 e = parseNewExp(NULL);
4641 break;
4643 case TOKcast: // cast(type) expression
4644 { Type *t;
4646 nextToken();
4647 check(TOKlparen);
4648 t = parseBasicType();
4649 t = parseDeclarator(t,NULL); // ( type )
4650 check(TOKrparen);
4652 e = parseUnaryExp();
4653 e = new CastExp(loc, e, t);
4654 break;
4657 case TOKlparen:
4658 { Token *tk;
4660 tk = peek(&token);
4661 #if CCASTSYNTAX
4662 // If cast
4663 if (isDeclaration(tk, 0, TOKrparen, &tk))
4665 tk = peek(tk); // skip over right parenthesis
4666 switch (tk->value)
4668 case TOKdot:
4669 case TOKplusplus:
4670 case TOKminusminus:
4671 case TOKnot:
4672 case TOKdelete:
4673 case TOKnew:
4674 case TOKlparen:
4675 case TOKidentifier:
4676 case TOKthis:
4677 case TOKsuper:
4678 case TOKint32v:
4679 case TOKuns32v:
4680 case TOKint64v:
4681 case TOKuns64v:
4682 case TOKfloat32v:
4683 case TOKfloat64v:
4684 case TOKfloat80v:
4685 case TOKimaginary32v:
4686 case TOKimaginary64v:
4687 case TOKimaginary80v:
4688 case TOKnull:
4689 case TOKtrue:
4690 case TOKfalse:
4691 case TOKcharv:
4692 case TOKwcharv:
4693 case TOKdcharv:
4694 case TOKstring:
4695 #if 0
4696 case TOKtilde:
4697 case TOKand:
4698 case TOKmul:
4699 case TOKmin:
4700 case TOKadd:
4701 #endif
4702 case TOKfunction:
4703 case TOKdelegate:
4704 case TOKtypeof:
4705 CASE_BASIC_TYPES: // (type)int.size
4706 { // (type) una_exp
4707 Type *t;
4709 nextToken();
4710 t = parseBasicType();
4711 t = parseDeclarator(t,NULL);
4712 check(TOKrparen);
4714 // if .identifier
4715 if (token.value == TOKdot)
4717 nextToken();
4718 if (token.value != TOKidentifier)
4719 { error("Identifier expected following (type).");
4720 return NULL;
4722 e = new TypeDotIdExp(loc, t, token.ident);
4723 nextToken();
4724 e = parsePostExp(e);
4726 else
4728 e = parseUnaryExp();
4729 e = new CastExp(loc, e, t);
4730 error("C style cast illegal, use %s", e->toChars());
4732 return e;
4736 #endif
4737 e = parsePrimaryExp();
4738 break;
4740 default:
4741 e = parsePrimaryExp();
4742 break;
4744 assert(e);
4745 return e;
4748 Expression *Parser::parseMulExp()
4749 { Expression *e;
4750 Expression *e2;
4751 Loc loc = this->loc;
4753 e = parseUnaryExp();
4754 while (1)
4756 switch (token.value)
4758 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4759 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4760 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4762 default:
4763 break;
4765 break;
4767 return e;
4770 Expression *Parser::parseAddExp()
4771 { Expression *e;
4772 Expression *e2;
4773 Loc loc = this->loc;
4775 e = parseMulExp();
4776 while (1)
4778 switch (token.value)
4780 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4781 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4782 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4784 default:
4785 break;
4787 break;
4789 return e;
4792 Expression *Parser::parseShiftExp()
4793 { Expression *e;
4794 Expression *e2;
4795 Loc loc = this->loc;
4797 e = parseAddExp();
4798 while (1)
4800 switch (token.value)
4802 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4803 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4804 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4806 default:
4807 break;
4809 break;
4811 return e;
4814 Expression *Parser::parseRelExp()
4815 { Expression *e;
4816 Expression *e2;
4817 enum TOK op;
4818 Loc loc = this->loc;
4820 e = parseShiftExp();
4821 while (1)
4823 switch (token.value)
4825 case TOKlt:
4826 case TOKle:
4827 case TOKgt:
4828 case TOKge:
4829 case TOKunord:
4830 case TOKlg:
4831 case TOKleg:
4832 case TOKule:
4833 case TOKul:
4834 case TOKuge:
4835 case TOKug:
4836 case TOKue:
4837 op = token.value;
4838 nextToken();
4839 e2 = parseShiftExp();
4840 e = new CmpExp(op, loc, e, e2);
4841 continue;
4843 case TOKin:
4844 nextToken();
4845 e2 = parseShiftExp();
4846 e = new InExp(loc, e, e2);
4847 continue;
4849 default:
4850 break;
4852 break;
4854 return e;
4857 Expression *Parser::parseEqualExp()
4858 { Expression *e;
4859 Expression *e2;
4860 Token *t;
4861 Loc loc = this->loc;
4863 e = parseRelExp();
4864 while (1)
4865 { enum TOK value = token.value;
4867 switch (value)
4869 case TOKequal:
4870 case TOKnotequal:
4871 nextToken();
4872 e2 = parseRelExp();
4873 e = new EqualExp(value, loc, e, e2);
4874 continue;
4876 case TOKidentity:
4877 error("'===' is no longer legal, use 'is' instead");
4878 goto L1;
4880 case TOKnotidentity:
4881 error("'!==' is no longer legal, use '!is' instead");
4882 goto L1;
4884 case TOKis:
4885 value = TOKidentity;
4886 goto L1;
4888 case TOKnot:
4889 // Attempt to identify '!is'
4890 t = peek(&token);
4891 if (t->value != TOKis)
4892 break;
4893 nextToken();
4894 value = TOKnotidentity;
4895 goto L1;
4898 nextToken();
4899 e2 = parseRelExp();
4900 e = new IdentityExp(value, loc, e, e2);
4901 continue;
4903 default:
4904 break;
4906 break;
4908 return e;
4911 Expression *Parser::parseCmpExp()
4912 { Expression *e;
4913 Expression *e2;
4914 Token *t;
4915 Loc loc = this->loc;
4917 e = parseShiftExp();
4918 enum TOK op = token.value;
4920 switch (op)
4922 case TOKequal:
4923 case TOKnotequal:
4924 nextToken();
4925 e2 = parseShiftExp();
4926 e = new EqualExp(op, loc, e, e2);
4927 break;
4929 case TOKis:
4930 op = TOKidentity;
4931 goto L1;
4933 case TOKnot:
4934 // Attempt to identify '!is'
4935 t = peek(&token);
4936 if (t->value != TOKis)
4937 break;
4938 nextToken();
4939 op = TOKnotidentity;
4940 goto L1;
4943 nextToken();
4944 e2 = parseShiftExp();
4945 e = new IdentityExp(op, loc, e, e2);
4946 break;
4948 case TOKlt:
4949 case TOKle:
4950 case TOKgt:
4951 case TOKge:
4952 case TOKunord:
4953 case TOKlg:
4954 case TOKleg:
4955 case TOKule:
4956 case TOKul:
4957 case TOKuge:
4958 case TOKug:
4959 case TOKue:
4960 nextToken();
4961 e2 = parseShiftExp();
4962 e = new CmpExp(op, loc, e, e2);
4963 break;
4965 case TOKin:
4966 nextToken();
4967 e2 = parseShiftExp();
4968 e = new InExp(loc, e, e2);
4969 break;
4971 default:
4972 break;
4974 return e;
4977 Expression *Parser::parseAndExp()
4978 { Expression *e;
4979 Expression *e2;
4980 Loc loc = this->loc;
4982 if (global.params.Dversion == 1)
4984 e = parseEqualExp();
4985 while (token.value == TOKand)
4987 nextToken();
4988 e2 = parseEqualExp();
4989 e = new AndExp(loc,e,e2);
4990 loc = this->loc;
4993 else
4995 e = parseCmpExp();
4996 while (token.value == TOKand)
4998 nextToken();
4999 e2 = parseCmpExp();
5000 e = new AndExp(loc,e,e2);
5001 loc = this->loc;
5004 return e;
5007 Expression *Parser::parseXorExp()
5008 { Expression *e;
5009 Expression *e2;
5010 Loc loc = this->loc;
5012 e = parseAndExp();
5013 while (token.value == TOKxor)
5015 nextToken();
5016 e2 = parseAndExp();
5017 e = new XorExp(loc, e, e2);
5019 return e;
5022 Expression *Parser::parseOrExp()
5023 { Expression *e;
5024 Expression *e2;
5025 Loc loc = this->loc;
5027 e = parseXorExp();
5028 while (token.value == TOKor)
5030 nextToken();
5031 e2 = parseXorExp();
5032 e = new OrExp(loc, e, e2);
5034 return e;
5037 Expression *Parser::parseAndAndExp()
5038 { Expression *e;
5039 Expression *e2;
5040 Loc loc = this->loc;
5042 e = parseOrExp();
5043 while (token.value == TOKandand)
5045 nextToken();
5046 e2 = parseOrExp();
5047 e = new AndAndExp(loc, e, e2);
5049 return e;
5052 Expression *Parser::parseOrOrExp()
5053 { Expression *e;
5054 Expression *e2;
5055 Loc loc = this->loc;
5057 e = parseAndAndExp();
5058 while (token.value == TOKoror)
5060 nextToken();
5061 e2 = parseAndAndExp();
5062 e = new OrOrExp(loc, e, e2);
5064 return e;
5067 Expression *Parser::parseCondExp()
5068 { Expression *e;
5069 Expression *e1;
5070 Expression *e2;
5071 Loc loc = this->loc;
5073 e = parseOrOrExp();
5074 if (token.value == TOKquestion)
5076 nextToken();
5077 e1 = parseExpression();
5078 check(TOKcolon);
5079 e2 = parseCondExp();
5080 e = new CondExp(loc, e, e1, e2);
5082 return e;
5085 Expression *DltParser::parseCondExp()
5086 { Expression *e;
5087 Expression *e1;
5088 Expression *e2;
5089 Loc loc = this->loc;
5091 e = parseOrOrExp();
5092 if (token.value == TOKif)
5094 nextToken();
5095 e1 = parseExpression();
5096 check(TOKelse);
5097 e2 = parseCondExp();
5098 e = new CondExp(loc, e1, e, e2);
5100 return e;
5103 Expression *Parser::parseAssignExp()
5104 { Expression *e;
5105 Expression *e2;
5106 Loc loc;
5108 e = parseCondExp();
5109 while (1)
5111 loc = this->loc;
5112 switch (token.value)
5114 #define X(tok,ector) \
5115 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5117 X(TOKassign, AssignExp);
5118 X(TOKaddass, AddAssignExp);
5119 X(TOKminass, MinAssignExp);
5120 X(TOKmulass, MulAssignExp);
5121 X(TOKdivass, DivAssignExp);
5122 X(TOKmodass, ModAssignExp);
5123 X(TOKandass, AndAssignExp);
5124 X(TOKorass, OrAssignExp);
5125 X(TOKxorass, XorAssignExp);
5126 X(TOKshlass, ShlAssignExp);
5127 X(TOKshrass, ShrAssignExp);
5128 X(TOKushrass, UshrAssignExp);
5129 X(TOKcatass, CatAssignExp);
5131 #undef X
5132 default:
5133 break;
5135 break;
5137 return e;
5140 Expression *Parser::parseExpression()
5141 { Expression *e;
5142 Expression *e2;
5143 Loc loc = this->loc;
5145 //printf("Parser::parseExpression()\n");
5146 e = parseAssignExp();
5147 while (token.value == TOKcomma)
5149 nextToken();
5150 e2 = parseAssignExp();
5151 e = new CommaExp(loc, e, e2);
5152 loc = this->loc;
5154 return e;
5158 /*************************
5159 * Collect argument list.
5160 * Assume current token is '(' or '['.
5163 Expressions *Parser::parseArguments()
5164 { // function call
5165 Expressions *arguments;
5166 Expression *arg;
5167 enum TOK endtok;
5169 arguments = new Expressions();
5170 if (token.value == TOKlbracket)
5171 endtok = TOKrbracket;
5172 else
5173 endtok = TOKrparen;
5176 nextToken();
5177 if (token.value != endtok)
5179 while (1)
5181 arg = parseAssignExp();
5182 arguments->push(arg);
5183 if (token.value == endtok)
5184 break;
5185 check(TOKcomma);
5188 check(endtok);
5190 return arguments;
5193 /*******************************************
5196 Expression *Parser::parseNewExp(Expression *thisexp)
5197 { Type *t;
5198 Expressions *newargs;
5199 Expressions *arguments = NULL;
5200 Expression *e;
5201 Loc loc = this->loc;
5203 nextToken();
5204 newargs = NULL;
5205 if (token.value == TOKlparen)
5207 newargs = parseArguments();
5210 // An anonymous nested class starts with "class"
5211 if (token.value == TOKclass)
5213 nextToken();
5214 if (token.value == TOKlparen)
5215 arguments = parseArguments();
5217 BaseClasses *baseclasses = NULL;
5218 if (token.value != TOKlcurly)
5219 baseclasses = parseBaseClasses();
5221 Identifier *id = NULL;
5222 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
5224 if (token.value != TOKlcurly)
5225 { error("{ members } expected for anonymous class");
5226 cd->members = NULL;
5228 else
5230 nextToken();
5231 Array *decl = parseDeclDefs(0);
5232 if (token.value != TOKrcurly)
5233 error("class member expected");
5234 nextToken();
5235 cd->members = decl;
5238 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
5240 return e;
5243 #if LTORARRAYDECL
5244 t = parseBasicType();
5245 t = parseBasicType2(t);
5246 if (t->ty == Taarray)
5248 Type *index = ((TypeAArray *)t)->index;
5250 Expression *e = index->toExpression();
5251 if (e)
5252 { arguments = new Expressions();
5253 arguments->push(e);
5254 t = new TypeDArray(t->next);
5256 else
5258 error("need size of rightmost array, not type %s", index->toChars());
5259 return new NullExp(loc);
5262 else if (t->ty == Tsarray)
5264 TypeSArray *tsa = (TypeSArray *)t;
5265 Expression *e = tsa->dim;
5267 arguments = new Expressions();
5268 arguments->push(e);
5269 t = new TypeDArray(t->next);
5271 else if (token.value == TOKlparen)
5273 arguments = parseArguments();
5275 #else
5276 t = parseBasicType();
5277 while (token.value == TOKmul)
5278 { t = new TypePointer(t);
5279 nextToken();
5281 if (token.value == TOKlbracket)
5283 Expression *e;
5285 nextToken();
5286 e = parseAssignExp();
5287 arguments = new Array();
5288 arguments->push(e);
5289 check(TOKrbracket);
5290 t = parseDeclarator(t, NULL);
5291 t = new TypeDArray(t);
5293 else if (token.value == TOKlparen)
5294 arguments = parseArguments();
5295 #endif
5296 e = new NewExp(loc, thisexp, newargs, t, arguments);
5297 return e;
5300 /**********************************************
5303 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5305 s->addComment(combineComments(blockComment, token.lineComment));
5309 /********************************* ***************************/