Detect when the input ends in .dlt and use DltParser
[delight/core.git] / dmd / parse.c
blobe5d45e95fded28c11819c011db6487857c4b7790
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)
67 //printf("Parser::Parser()\n");
68 md = NULL;
69 linkage = LINKd;
70 endloc = 0;
71 inBrackets = 0;
72 //nextToken(); // start up the scanner
75 DltParser::DltParser(Module *module, unsigned char *base, unsigned length, int doDocComment)
76 : Parser(module, base, length, doDocComment)
78 //printf("DltParser::DltParser(%s)\n", module->ident->string);
81 Array *Parser::parseModule()
83 Array *decldefs;
85 // ModuleDeclation leads off
86 if (token.value == TOKmodule)
88 unsigned char *comment = token.blockComment;
90 nextToken();
91 if (token.value != TOKidentifier)
92 { error("Identifier expected following module");
93 goto Lerr;
95 else
97 Array *a = NULL;
98 Identifier *id;
100 id = token.ident;
101 while (nextToken() == TOKdot)
103 if (!a)
104 a = new Array();
105 a->push(id);
106 nextToken();
107 if (token.value != TOKidentifier)
108 { error("Identifier expected following package");
109 goto Lerr;
111 id = token.ident;
114 md = new ModuleDeclaration(a, id);
116 if (token.value != TOKsemicolon)
117 error("';' expected following module declaration instead of %s", token.toChars());
118 nextToken();
119 addComment(mod, comment);
123 decldefs = parseDeclDefs(0);
124 if (token.value != TOKeof)
125 { error("unrecognized declaration");
126 goto Lerr;
128 return decldefs;
130 Lerr:
131 while (token.value != TOKsemicolon && token.value != TOKeof)
132 nextToken();
133 nextToken();
134 return new Array();
137 Array *Parser::parseDeclDefs(int once)
138 { Dsymbol *s;
139 Array *decldefs;
140 Array *a;
141 Array *aelse;
142 enum PROT prot;
143 unsigned stc;
144 Condition *condition;
145 unsigned char *comment;
147 //printf("Parser::parseDeclDefs()\n");
148 decldefs = new Array();
151 comment = token.blockComment;
152 switch (token.value)
154 case TOKenum:
155 s = parseEnum();
156 break;
158 case TOKstruct:
159 case TOKunion:
160 case TOKclass:
161 case TOKinterface:
162 s = parseAggregate();
163 break;
165 case TOKimport:
166 s = parseImport(decldefs, 0);
167 break;
169 case TOKtemplate:
170 s = (Dsymbol *)parseTemplateDeclaration();
171 break;
173 case TOKmixin:
174 { Loc loc = this->loc;
175 if (peek(&token)->value == TOKlparen)
176 { // mixin(string)
177 nextToken();
178 check(TOKlparen, "mixin");
179 Expression *e = parseAssignExp();
180 check(TOKrparen);
181 check(TOKsemicolon);
182 s = new CompileDeclaration(loc, e);
183 break;
185 s = parseMixin();
186 break;
189 CASE_BASIC_TYPES:
190 case TOKalias:
191 case TOKtypedef:
192 case TOKidentifier:
193 case TOKtypeof:
194 case TOKdot:
195 Ldeclaration:
196 a = parseDeclarations();
197 decldefs->append(a);
198 continue;
200 case TOKthis:
201 s = parseCtor();
202 break;
204 case TOKtilde:
205 s = parseDtor();
206 break;
208 case TOKinvariant:
209 #if 1
210 s = parseInvariant();
211 #else
212 if (peek(&token)->value == TOKlcurly)
213 s = parseInvariant();
214 else
216 stc = STCinvariant;
217 goto Lstc;
219 #endif
220 break;
222 case TOKunittest:
223 s = parseUnitTest();
224 break;
226 case TOKnew:
227 s = parseNew();
228 break;
230 case TOKdelete:
231 s = parseDelete();
232 break;
234 case TOKeof:
235 case TOKrcurly:
236 return decldefs;
238 case TOKstatic:
239 nextToken();
240 if (token.value == TOKthis)
241 s = parseStaticCtor();
242 else if (token.value == TOKtilde)
243 s = parseStaticDtor();
244 else if (token.value == TOKassert)
245 s = parseStaticAssert();
246 else if (token.value == TOKif)
247 { condition = parseStaticIfCondition();
248 a = parseBlock();
249 aelse = NULL;
250 if (token.value == TOKelse)
251 { nextToken();
252 aelse = parseBlock();
254 s = new StaticIfDeclaration(condition, a, aelse);
255 break;
257 else if (token.value == TOKimport)
259 s = parseImport(decldefs, 1);
261 else
262 { stc = STCstatic;
263 goto Lstc2;
265 break;
267 case TOKconst: stc = STCconst; goto Lstc;
268 case TOKfinal: stc = STCfinal; goto Lstc;
269 case TOKauto: stc = STCauto; goto Lstc;
270 case TOKscope: stc = STCscope; goto Lstc;
271 case TOKoverride: stc = STCoverride; goto Lstc;
272 case TOKabstract: stc = STCabstract; goto Lstc;
273 case TOKsynchronized: stc = STCsynchronized; goto Lstc;
274 case TOKdeprecated: stc = STCdeprecated; goto Lstc;
276 Lstc:
277 nextToken();
278 Lstc2:
279 switch (token.value)
281 case TOKconst: stc |= STCconst; goto Lstc;
282 case TOKfinal: stc |= STCfinal; goto Lstc;
283 case TOKauto: stc |= STCauto; goto Lstc;
284 case TOKscope: stc |= STCscope; goto Lstc;
285 case TOKoverride: stc |= STCoverride; goto Lstc;
286 case TOKabstract: stc |= STCabstract; goto Lstc;
287 case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
288 case TOKdeprecated: stc |= STCdeprecated; goto Lstc;
289 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
290 default:
291 break;
294 /* Look for auto initializers:
295 * storage_class identifier = initializer;
297 if (token.value == TOKidentifier &&
298 peek(&token)->value == TOKassign)
300 while (1)
302 Identifier *ident = token.ident;
303 nextToken();
304 nextToken();
305 Initializer *init = parseInitializer();
306 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
307 v->storage_class = stc;
308 s = v;
309 if (token.value == TOKsemicolon)
311 nextToken();
313 else if (token.value == TOKcomma)
315 nextToken();
316 if (token.value == TOKidentifier &&
317 peek(&token)->value == TOKassign)
319 decldefs->push(s);
320 addComment(s, comment);
321 continue;
323 else
324 error("Identifier expected following comma");
326 else
327 error("semicolon expected following auto declaration, not '%s'", token.toChars());
328 break;
331 else
332 { a = parseBlock();
333 s = new StorageClassDeclaration(stc, a);
335 break;
337 case TOKextern:
338 if (peek(&token)->value != TOKlparen)
339 { stc = STCextern;
340 goto Lstc;
343 enum LINK linksave = linkage;
344 linkage = parseLinkage();
345 a = parseBlock();
346 s = new LinkDeclaration(linkage, a);
347 linkage = linksave;
348 break;
350 case TOKprivate: prot = PROTprivate; goto Lprot;
351 case TOKpackage: prot = PROTpackage; goto Lprot;
352 case TOKprotected: prot = PROTprotected; goto Lprot;
353 case TOKpublic: prot = PROTpublic; goto Lprot;
354 case TOKexport: prot = PROTexport; goto Lprot;
356 Lprot:
357 nextToken();
358 a = parseBlock();
359 s = new ProtDeclaration(prot, a);
360 break;
362 case TOKalign:
363 { unsigned n;
365 s = NULL;
366 nextToken();
367 if (token.value == TOKlparen)
369 nextToken();
370 if (token.value == TOKint32v)
371 n = (unsigned)token.uns64value;
372 else
373 { error("integer expected, not %s", token.toChars());
374 n = 1;
376 nextToken();
377 check(TOKrparen);
379 else
380 n = global.structalign; // default
382 a = parseBlock();
383 s = new AlignDeclaration(n, a);
384 break;
387 case TOKpragma:
388 { Identifier *ident;
389 Expressions *args = NULL;
391 nextToken();
392 check(TOKlparen);
393 if (token.value != TOKidentifier)
394 { error("pragma(identifier expected");
395 goto Lerror;
397 ident = token.ident;
398 nextToken();
399 if (token.value == TOKcomma)
400 args = parseArguments(); // pragma(identifier, args...)
401 else
402 check(TOKrparen); // pragma(identifier)
404 if (token.value == TOKsemicolon)
405 a = NULL;
406 else
407 a = parseBlock();
408 s = new PragmaDeclaration(loc, ident, args, a);
409 break;
412 case TOKdebug:
413 nextToken();
414 if (token.value == TOKassign)
416 nextToken();
417 if (token.value == TOKidentifier)
418 s = new DebugSymbol(loc, token.ident);
419 else if (token.value == TOKint32v)
420 s = new DebugSymbol(loc, (unsigned)token.uns64value);
421 else
422 { error("identifier or integer expected, not %s", token.toChars());
423 s = NULL;
425 nextToken();
426 if (token.value != TOKsemicolon)
427 error("semicolon expected");
428 nextToken();
429 break;
432 condition = parseDebugCondition();
433 goto Lcondition;
435 case TOKversion:
436 nextToken();
437 if (token.value == TOKassign)
439 nextToken();
440 if (token.value == TOKidentifier)
441 s = new VersionSymbol(loc, token.ident);
442 else if (token.value == TOKint32v)
443 s = new VersionSymbol(loc, (unsigned)token.uns64value);
444 else
445 { error("identifier or integer expected, not %s", token.toChars());
446 s = NULL;
448 nextToken();
449 if (token.value != TOKsemicolon)
450 error("semicolon expected");
451 nextToken();
452 break;
454 condition = parseVersionCondition();
455 goto Lcondition;
457 Lcondition:
458 a = parseBlock();
459 aelse = NULL;
460 if (token.value == TOKelse)
461 { nextToken();
462 aelse = parseBlock();
464 s = new ConditionalDeclaration(condition, a, aelse);
465 break;
467 case TOKsemicolon: // empty declaration
468 nextToken();
469 continue;
471 default:
472 error("Declaration expected, not '%s'",token.toChars());
473 Lerror:
474 while (token.value != TOKsemicolon && token.value != TOKeof)
475 nextToken();
476 nextToken();
477 s = NULL;
478 continue;
480 if (s)
481 { decldefs->push(s);
482 addComment(s, comment);
484 } while (!once);
485 return decldefs;
489 /********************************************
490 * Parse declarations after an align, protection, or extern decl.
493 Array *Parser::parseBlock()
495 Array *a = NULL;
496 Dsymbol *s;
498 //printf("parseBlock()\n");
499 switch (token.value)
501 case TOKsemicolon:
502 error("declaration expected following attribute, not ';'");
503 nextToken();
504 break;
506 case TOKlcurly:
507 nextToken();
508 a = parseDeclDefs(0);
509 if (token.value != TOKrcurly)
510 { /* { */
511 error("matching '}' expected, not %s", token.toChars());
513 else
514 nextToken();
515 break;
517 case TOKcolon:
518 nextToken();
519 #if 0
520 a = NULL;
521 #else
522 a = parseDeclDefs(0); // grab declarations up to closing curly bracket
523 #endif
524 break;
526 default:
527 a = parseDeclDefs(1);
528 break;
530 return a;
533 /**********************************
534 * Parse a static assertion.
537 StaticAssert *Parser::parseStaticAssert()
539 Loc loc = this->loc;
540 Expression *exp;
541 Expression *msg = NULL;
543 //printf("parseStaticAssert()\n");
544 nextToken();
545 check(TOKlparen);
546 exp = parseAssignExp();
547 if (token.value == TOKcomma)
548 { nextToken();
549 msg = parseAssignExp();
551 check(TOKrparen);
552 check(TOKsemicolon);
553 return new StaticAssert(loc, exp, msg);
557 /***********************************
558 * Parse extern (linkage)
559 * The parser is on the 'extern' token.
562 enum LINK Parser::parseLinkage()
564 enum LINK link = LINKdefault;
565 nextToken();
566 assert(token.value == TOKlparen);
567 nextToken();
568 if (token.value == TOKidentifier)
569 { Identifier *id = token.ident;
571 nextToken();
572 if (id == Id::Windows)
573 link = LINKwindows;
574 else if (id == Id::Pascal)
575 link = LINKpascal;
576 else if (id == Id::D)
577 link = LINKd;
578 else if (id == Id::C)
580 link = LINKc;
581 if (token.value == TOKplusplus)
582 { link = LINKcpp;
583 nextToken();
586 else if (id == Id::System)
588 #ifdef IN_GCC
589 link = d_gcc_is_target_win32() ? LINKwindows : LINKc;
590 #else
591 #if _WIN32
592 link = LINKwindows;
593 #else
594 link = LINKc;
595 #endif
596 #endif
598 else
600 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
601 link = LINKd;
604 else
606 link = LINKd; // default
608 check(TOKrparen);
609 return link;
612 /**************************************
613 * Parse a debug conditional
616 Condition *Parser::parseDebugCondition()
618 Condition *c;
620 if (token.value == TOKlparen)
622 nextToken();
623 unsigned level = 1;
624 Identifier *id = NULL;
626 if (token.value == TOKidentifier)
627 id = token.ident;
628 else if (token.value == TOKint32v)
629 level = (unsigned)token.uns64value;
630 else
631 error("identifier or integer expected, not %s", token.toChars());
632 nextToken();
633 check(TOKrparen);
634 c = new DebugCondition(mod, level, id);
636 else
637 c = new DebugCondition(mod, 1, NULL);
638 return c;
642 /**************************************
643 * Parse a version conditional
646 Condition *Parser::parseVersionCondition()
648 Condition *c;
649 unsigned level = 1;
650 Identifier *id = NULL;
652 if (token.value == TOKlparen)
654 nextToken();
655 if (token.value == TOKidentifier)
656 id = token.ident;
657 else if (token.value == TOKint32v)
658 level = (unsigned)token.uns64value;
659 #if V2
660 /* Allow:
661 * version (unittest)
662 * even though unittest is a keyword
664 else if (token.value == TOKunittest)
665 id = Lexer::idPool(Token::toChars(TOKunittest));
666 #endif
667 else
668 error("identifier or integer expected, not %s", token.toChars());
669 nextToken();
670 check(TOKrparen);
673 else
674 error("(condition) expected following version");
675 c = new VersionCondition(mod, level, id);
676 return c;
680 /***********************************************
681 * static if (expression)
682 * body
683 * else
684 * body
687 Condition *Parser::parseStaticIfCondition()
688 { Expression *exp;
689 Condition *condition;
690 Array *aif;
691 Array *aelse;
692 Loc loc = this->loc;
694 nextToken();
695 if (token.value == TOKlparen)
697 nextToken();
698 exp = parseAssignExp();
699 check(TOKrparen);
701 else
702 { error("(expression) expected following static if");
703 exp = NULL;
705 condition = new StaticIfCondition(loc, exp);
706 return condition;
710 /*****************************************
711 * Parse a constructor definition:
712 * this(arguments) { body }
713 * Current token is 'this'.
716 CtorDeclaration *Parser::parseCtor()
718 CtorDeclaration *f;
719 Arguments *arguments;
720 int varargs;
721 Loc loc = this->loc;
723 nextToken();
724 arguments = parseParameters(&varargs);
725 f = new CtorDeclaration(loc, 0, arguments, varargs);
726 parseContracts(f);
727 return f;
730 /*****************************************
731 * Parse a destructor definition:
732 * ~this() { body }
733 * Current token is '~'.
736 DtorDeclaration *Parser::parseDtor()
738 DtorDeclaration *f;
739 Loc loc = this->loc;
741 nextToken();
742 check(TOKthis);
743 check(TOKlparen);
744 check(TOKrparen);
746 f = new DtorDeclaration(loc, 0);
747 parseContracts(f);
748 return f;
751 /*****************************************
752 * Parse a static constructor definition:
753 * static this() { body }
754 * Current token is 'this'.
757 StaticCtorDeclaration *Parser::parseStaticCtor()
759 StaticCtorDeclaration *f;
760 Loc loc = this->loc;
762 nextToken();
763 check(TOKlparen);
764 check(TOKrparen);
766 f = new StaticCtorDeclaration(loc, 0);
767 parseContracts(f);
768 return f;
771 /*****************************************
772 * Parse a static destructor definition:
773 * static ~this() { body }
774 * Current token is '~'.
777 StaticDtorDeclaration *Parser::parseStaticDtor()
779 StaticDtorDeclaration *f;
780 Loc loc = this->loc;
782 nextToken();
783 check(TOKthis);
784 check(TOKlparen);
785 check(TOKrparen);
787 f = new StaticDtorDeclaration(loc, 0);
788 parseContracts(f);
789 return f;
792 /*****************************************
793 * Parse an invariant definition:
794 * invariant { body }
795 * Current token is 'invariant'.
798 InvariantDeclaration *Parser::parseInvariant()
800 InvariantDeclaration *f;
801 Loc loc = this->loc;
803 nextToken();
804 if (token.value == TOKlparen) // optional ()
806 nextToken();
807 check(TOKrparen);
810 f = new InvariantDeclaration(loc, 0);
811 f->fbody = parseStatement(PScurly);
812 return f;
815 /*****************************************
816 * Parse a unittest definition:
817 * unittest { body }
818 * Current token is 'unittest'.
821 UnitTestDeclaration *Parser::parseUnitTest()
823 UnitTestDeclaration *f;
824 Statement *body;
825 Loc loc = this->loc;
827 nextToken();
829 body = parseStatement(PScurly);
831 f = new UnitTestDeclaration(loc, this->loc);
832 f->fbody = body;
833 return f;
836 /*****************************************
837 * Parse a new definition:
838 * new(arguments) { body }
839 * Current token is 'new'.
842 NewDeclaration *Parser::parseNew()
844 NewDeclaration *f;
845 Arguments *arguments;
846 int varargs;
847 Loc loc = this->loc;
849 nextToken();
850 arguments = parseParameters(&varargs);
851 f = new NewDeclaration(loc, 0, arguments, varargs);
852 parseContracts(f);
853 return f;
856 /*****************************************
857 * Parse a delete definition:
858 * delete(arguments) { body }
859 * Current token is 'delete'.
862 DeleteDeclaration *Parser::parseDelete()
864 DeleteDeclaration *f;
865 Arguments *arguments;
866 int varargs;
867 Loc loc = this->loc;
869 nextToken();
870 arguments = parseParameters(&varargs);
871 if (varargs)
872 error("... not allowed in delete function parameter list");
873 f = new DeleteDeclaration(loc, 0, arguments);
874 parseContracts(f);
875 return f;
878 /**********************************************
879 * Parse parameter list.
882 Arguments *Parser::parseParameters(int *pvarargs)
884 Arguments *arguments = new Arguments();
885 int varargs = 0;
886 int hasdefault = 0;
888 check(TOKlparen);
889 while (1)
890 { Type *tb;
891 Identifier *ai;
892 Type *at;
893 Argument *a;
894 unsigned storageClass;
895 Expression *ae;
897 ai = NULL;
898 storageClass = STCin; // parameter is "in" by default
899 switch (token.value)
901 case TOKrparen:
902 break;
904 case TOKdotdotdot:
905 varargs = 1;
906 nextToken();
907 break;
909 case TOKin:
910 storageClass = STCin;
911 nextToken();
912 goto L1;
914 case TOKout:
915 storageClass = STCout;
916 nextToken();
917 goto L1;
919 case TOKinout:
920 case TOKref:
921 storageClass = STCref;
922 nextToken();
923 goto L1;
925 case TOKlazy:
926 storageClass = STClazy;
927 nextToken();
928 goto L1;
930 default:
932 tb = parseBasicType();
933 at = parseDeclarator(tb, &ai);
934 ae = NULL;
935 if (token.value == TOKassign) // = defaultArg
936 { nextToken();
937 ae = parseAssignExp();
938 hasdefault = 1;
940 else
941 { if (hasdefault)
942 error("default argument expected for %s",
943 ai ? ai->toChars() : at->toChars());
945 if (token.value == TOKdotdotdot)
946 { /* This is:
947 * at ai ...
950 if (storageClass & (STCout | STCref))
951 error("variadic argument cannot be out or ref");
952 varargs = 2;
953 a = new Argument(storageClass, at, ai, ae);
954 arguments->push(a);
955 nextToken();
956 break;
958 a = new Argument(storageClass, at, ai, ae);
959 arguments->push(a);
960 if (token.value == TOKcomma)
961 { nextToken();
962 continue;
964 break;
966 break;
968 check(TOKrparen);
969 *pvarargs = varargs;
970 return arguments;
974 /*************************************
977 EnumDeclaration *Parser::parseEnum()
978 { EnumDeclaration *e;
979 Identifier *id;
980 Type *t;
981 Loc loc = this->loc;
983 //printf("Parser::parseEnum()\n");
984 nextToken();
985 if (token.value == TOKidentifier)
986 { id = token.ident;
987 nextToken();
989 else
990 id = NULL;
992 if (token.value == TOKcolon)
994 nextToken();
995 t = parseBasicType();
997 else
998 t = NULL;
1000 e = new EnumDeclaration(loc, id, t);
1001 if (token.value == TOKsemicolon && id)
1002 nextToken();
1003 else if (token.value == TOKlcurly)
1005 //printf("enum definition\n");
1006 e->members = new Array();
1007 nextToken();
1008 unsigned char *comment = token.blockComment;
1009 while (token.value != TOKrcurly)
1011 if (token.value == TOKidentifier)
1012 { EnumMember *em;
1013 Expression *value;
1014 Identifier *ident;
1016 loc = this->loc;
1017 ident = token.ident;
1018 value = NULL;
1019 nextToken();
1020 if (token.value == TOKassign)
1022 nextToken();
1023 value = parseAssignExp();
1025 em = new EnumMember(loc, ident, value);
1026 e->members->push(em);
1027 if (token.value == TOKrcurly)
1029 else
1030 { addComment(em, comment);
1031 comment = NULL;
1032 check(TOKcomma);
1034 addComment(em, comment);
1035 comment = token.blockComment;
1037 else
1038 { error("enum member expected");
1039 nextToken();
1042 nextToken();
1044 else
1045 error("enum declaration is invalid");
1047 return e;
1050 Dsymbol *Parser::parseAggregate()
1051 { AggregateDeclaration *a = NULL;
1052 int anon = 0;
1053 enum TOK tok;
1054 Identifier *id;
1055 TemplateParameters *tpl = NULL;
1057 //printf("Parser::parseAggregate()\n");
1058 tok = token.value;
1059 nextToken();
1060 if (token.value != TOKidentifier)
1061 { id = NULL;
1063 else
1064 { id = token.ident;
1065 nextToken();
1067 if (token.value == TOKlparen)
1068 { // Class template declaration.
1070 // Gather template parameter list
1071 tpl = parseTemplateParameterList();
1075 Loc loc = this->loc;
1076 switch (tok)
1077 { case TOKclass:
1078 case TOKinterface:
1080 if (!id)
1081 error("anonymous classes not allowed");
1083 // Collect base class(es)
1084 BaseClasses *baseclasses = NULL;
1085 if (token.value == TOKcolon)
1087 nextToken();
1088 baseclasses = parseBaseClasses();
1090 if (token.value != TOKlcurly)
1091 error("members expected");
1094 if (tok == TOKclass)
1095 a = new ClassDeclaration(loc, id, baseclasses);
1096 else
1097 a = new InterfaceDeclaration(loc, id, baseclasses);
1098 break;
1101 case TOKstruct:
1102 if (id)
1103 a = new StructDeclaration(loc, id);
1104 else
1105 anon = 1;
1106 break;
1108 case TOKunion:
1109 if (id)
1110 a = new UnionDeclaration(loc, id);
1111 else
1112 anon = 2;
1113 break;
1115 default:
1116 assert(0);
1117 break;
1119 if (a && token.value == TOKsemicolon)
1120 { nextToken();
1122 else if (token.value == TOKlcurly)
1124 //printf("aggregate definition\n");
1125 nextToken();
1126 Array *decl = parseDeclDefs(0);
1127 if (token.value != TOKrcurly)
1128 error("} expected following member declarations in aggregate");
1129 nextToken();
1130 if (anon)
1132 /* Anonymous structs/unions are more like attributes.
1134 return new AnonDeclaration(loc, anon - 1, decl);
1136 else
1137 a->members = decl;
1139 else
1141 error("{ } expected following aggregate declaration");
1142 a = new StructDeclaration(loc, NULL);
1145 if (tpl)
1146 { Array *decldefs;
1147 TemplateDeclaration *tempdecl;
1149 // Wrap a template around the aggregate declaration
1150 decldefs = new Array();
1151 decldefs->push(a);
1152 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1153 return tempdecl;
1156 return a;
1159 /*******************************************
1162 BaseClasses *Parser::parseBaseClasses()
1164 enum PROT protection = PROTpublic;
1165 BaseClasses *baseclasses = new BaseClasses();
1167 for (; 1; nextToken())
1169 switch (token.value)
1171 case TOKidentifier:
1172 break;
1173 case TOKprivate:
1174 protection = PROTprivate;
1175 continue;
1176 case TOKpackage:
1177 protection = PROTpackage;
1178 continue;
1179 case TOKprotected:
1180 protection = PROTprotected;
1181 continue;
1182 case TOKpublic:
1183 protection = PROTpublic;
1184 continue;
1185 default:
1186 error("base classes expected instead of %s", token.toChars());
1187 return NULL;
1189 BaseClass *b = new BaseClass(parseBasicType(), protection);
1190 baseclasses->push(b);
1191 if (token.value != TOKcomma)
1192 break;
1193 protection = PROTpublic;
1195 return baseclasses;
1198 /**************************************
1199 * Parse a TemplateDeclaration.
1202 TemplateDeclaration *Parser::parseTemplateDeclaration()
1204 TemplateDeclaration *tempdecl;
1205 Identifier *id;
1206 TemplateParameters *tpl;
1207 Array *decldefs;
1208 Loc loc = this->loc;
1210 nextToken();
1211 if (token.value != TOKidentifier)
1212 { error("TemplateIdentifier expected following template");
1213 goto Lerr;
1215 id = token.ident;
1216 nextToken();
1217 tpl = parseTemplateParameterList();
1218 if (!tpl)
1219 goto Lerr;
1221 if (token.value != TOKlcurly)
1222 { error("members of template declaration expected");
1223 goto Lerr;
1225 else
1227 nextToken();
1228 decldefs = parseDeclDefs(0);
1229 if (token.value != TOKrcurly)
1230 { error("template member expected");
1231 goto Lerr;
1233 nextToken();
1236 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
1237 return tempdecl;
1239 Lerr:
1240 return NULL;
1243 /******************************************
1244 * Parse template parameter list.
1247 TemplateParameters *Parser::parseTemplateParameterList()
1249 TemplateParameters *tpl = new TemplateParameters();
1251 if (token.value != TOKlparen)
1252 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1253 goto Lerr;
1255 nextToken();
1257 // Get array of TemplateParameters
1258 if (token.value != TOKrparen)
1259 { int isvariadic = 0;
1261 while (1)
1262 { TemplateParameter *tp;
1263 Identifier *tp_ident = NULL;
1264 Type *tp_spectype = NULL;
1265 Type *tp_valtype = NULL;
1266 Type *tp_defaulttype = NULL;
1267 Expression *tp_specvalue = NULL;
1268 Expression *tp_defaultvalue = NULL;
1269 Token *t;
1271 // Get TemplateParameter
1273 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1274 t = peek(&token);
1275 if (token.value == TOKalias)
1276 { // AliasParameter
1277 nextToken();
1278 if (token.value != TOKidentifier)
1279 { error("Identifier expected for template parameter");
1280 goto Lerr;
1282 tp_ident = token.ident;
1283 nextToken();
1284 if (token.value == TOKcolon) // : Type
1286 nextToken();
1287 tp_spectype = parseBasicType();
1288 tp_spectype = parseDeclarator(tp_spectype, NULL);
1290 if (token.value == TOKassign) // = Type
1292 nextToken();
1293 tp_defaulttype = parseBasicType();
1294 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1296 tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1298 else if (t->value == TOKcolon || t->value == TOKassign ||
1299 t->value == TOKcomma || t->value == TOKrparen)
1300 { // TypeParameter
1301 if (token.value != TOKidentifier)
1302 { error("Identifier expected for template parameter");
1303 goto Lerr;
1305 tp_ident = token.ident;
1306 nextToken();
1307 if (token.value == TOKcolon) // : Type
1309 nextToken();
1310 tp_spectype = parseBasicType();
1311 tp_spectype = parseDeclarator(tp_spectype, NULL);
1313 if (token.value == TOKassign) // = Type
1315 nextToken();
1316 tp_defaulttype = parseBasicType();
1317 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1319 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1321 else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
1322 { // ident...
1323 if (isvariadic)
1324 error("variadic template parameter must be last");
1325 isvariadic = 1;
1326 tp_ident = token.ident;
1327 nextToken();
1328 nextToken();
1329 tp = new TemplateTupleParameter(loc, tp_ident);
1331 else
1332 { // ValueParameter
1333 tp_valtype = parseBasicType();
1334 tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
1335 if (!tp_ident)
1337 error("no identifier for template value parameter");
1338 tp_ident = new Identifier("error", TOKidentifier);
1340 if (token.value == TOKcolon) // : CondExpression
1342 nextToken();
1343 tp_specvalue = parseCondExp();
1345 if (token.value == TOKassign) // = CondExpression
1347 nextToken();
1348 tp_defaultvalue = parseCondExp();
1350 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
1352 tpl->push(tp);
1353 if (token.value != TOKcomma)
1354 break;
1355 nextToken();
1358 check(TOKrparen);
1359 Lerr:
1360 return tpl;
1363 /******************************************
1364 * Parse template mixin.
1365 * mixin Foo;
1366 * mixin Foo!(args);
1367 * mixin a.b.c!(args).Foo!(args);
1368 * mixin Foo!(args) identifier;
1369 * mixin typeof(expr).identifier!(args);
1372 Dsymbol *Parser::parseMixin()
1374 TemplateMixin *tm;
1375 Identifier *id;
1376 Type *tqual;
1377 Objects *tiargs;
1378 Array *idents;
1380 //printf("parseMixin()\n");
1381 nextToken();
1382 tqual = NULL;
1383 if (token.value == TOKdot)
1385 id = Id::empty;
1387 else
1389 if (token.value == TOKtypeof)
1390 { Expression *exp;
1392 nextToken();
1393 check(TOKlparen);
1394 exp = parseExpression();
1395 check(TOKrparen);
1396 tqual = new TypeTypeof(loc, exp);
1397 check(TOKdot);
1399 if (token.value != TOKidentifier)
1401 error("identifier expected, not %s", token.toChars());
1402 goto Lerr;
1404 id = token.ident;
1405 nextToken();
1408 idents = new Array();
1409 while (1)
1411 tiargs = NULL;
1412 if (token.value == TOKnot)
1414 nextToken();
1415 tiargs = parseTemplateArgumentList();
1418 if (token.value != TOKdot)
1419 break;
1421 if (tiargs)
1422 { TemplateInstance *tempinst = new TemplateInstance(loc, id);
1423 tempinst->tiargs = tiargs;
1424 id = (Identifier *)tempinst;
1425 tiargs = NULL;
1427 idents->push(id);
1429 nextToken();
1430 if (token.value != TOKidentifier)
1431 { error("identifier expected following '.' instead of '%s'", token.toChars());
1432 break;
1434 id = token.ident;
1435 nextToken();
1437 idents->push(id);
1439 if (token.value == TOKidentifier)
1441 id = token.ident;
1442 nextToken();
1444 else
1445 id = NULL;
1447 tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
1448 if (token.value != TOKsemicolon)
1449 error("';' expected after mixin");
1450 nextToken();
1452 return tm;
1454 Lerr:
1455 return NULL;
1458 /******************************************
1459 * Parse template argument list.
1460 * Input:
1461 * current token is opening '('
1462 * Output:
1463 * current token is one after closing ')'
1466 Objects *Parser::parseTemplateArgumentList()
1468 //printf("Parser::parseTemplateArgumentList()\n");
1469 Objects *tiargs = new Objects();
1470 if (token.value != TOKlparen)
1471 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1472 return tiargs;
1474 nextToken();
1476 // Get TemplateArgumentList
1477 if (token.value != TOKrparen)
1479 while (1)
1481 // See if it is an Expression or a Type
1482 if (isDeclaration(&token, 0, TOKreserved, NULL))
1483 { // Type
1484 Type *ta;
1486 // Get TemplateArgument
1487 ta = parseBasicType();
1488 ta = parseDeclarator(ta, NULL);
1489 tiargs->push(ta);
1491 else
1492 { // Expression
1493 Expression *ea;
1495 ea = parseAssignExp();
1496 tiargs->push(ea);
1498 if (token.value != TOKcomma)
1499 break;
1500 nextToken();
1503 check(TOKrparen, "template argument list");
1504 return tiargs;
1507 Import *Parser::parseImport(Array *decldefs, int isstatic)
1508 { Import *s;
1509 Identifier *id;
1510 Identifier *aliasid = NULL;
1511 Array *a;
1512 Loc loc;
1514 //printf("Parser::parseImport()\n");
1518 nextToken();
1519 if (token.value != TOKidentifier)
1520 { error("Identifier expected following import");
1521 break;
1524 loc = this->loc;
1525 a = NULL;
1526 id = token.ident;
1527 nextToken();
1528 if (!aliasid && token.value == TOKassign)
1530 aliasid = id;
1531 goto L1;
1533 while (token.value == TOKdot)
1535 if (!a)
1536 a = new Array();
1537 a->push(id);
1538 nextToken();
1539 if (token.value != TOKidentifier)
1540 { error("Identifier expected following package");
1541 break;
1543 id = token.ident;
1544 nextToken();
1547 s = new Import(loc, a, token.ident, aliasid, isstatic);
1548 decldefs->push(s);
1550 /* Look for
1551 * : alias=name, alias=name;
1552 * syntax.
1554 if (token.value == TOKcolon)
1557 { Identifier *name;
1558 Identifier *alias;
1560 nextToken();
1561 if (token.value != TOKidentifier)
1562 { error("Identifier expected following :");
1563 break;
1565 alias = token.ident;
1566 nextToken();
1567 if (token.value == TOKassign)
1569 nextToken();
1570 if (token.value != TOKidentifier)
1571 { error("Identifier expected following %s=", alias->toChars());
1572 break;
1574 name = token.ident;
1575 nextToken();
1577 else
1578 { name = alias;
1579 alias = NULL;
1581 s->addAlias(name, alias);
1582 } while (token.value == TOKcomma);
1583 break; // no comma-separated imports of this form
1586 aliasid = NULL;
1587 } while (token.value == TOKcomma);
1589 if (token.value == TOKsemicolon)
1590 nextToken();
1591 else
1593 error("';' expected");
1594 nextToken();
1597 return NULL;
1600 Type *Parser::parseBasicType()
1601 { Type *t;
1602 Identifier *id;
1603 TypeQualified *tid;
1604 TemplateInstance *tempinst;
1606 //printf("parseBasicType()\n");
1607 switch (token.value)
1609 CASE_BASIC_TYPES_X(t):
1610 nextToken();
1611 break;
1613 case TOKidentifier:
1614 id = token.ident;
1615 nextToken();
1616 if (token.value == TOKnot)
1618 nextToken();
1619 tempinst = new TemplateInstance(loc, id);
1620 tempinst->tiargs = parseTemplateArgumentList();
1621 tid = new TypeInstance(loc, tempinst);
1622 goto Lident2;
1624 Lident:
1625 tid = new TypeIdentifier(loc, id);
1626 Lident2:
1627 while (token.value == TOKdot)
1628 { nextToken();
1629 if (token.value != TOKidentifier)
1630 { error("identifier expected following '.' instead of '%s'", token.toChars());
1631 break;
1633 id = token.ident;
1634 nextToken();
1635 if (token.value == TOKnot)
1637 nextToken();
1638 tempinst = new TemplateInstance(loc, id);
1639 tempinst->tiargs = parseTemplateArgumentList();
1640 tid->addIdent((Identifier *)tempinst);
1642 else
1643 tid->addIdent(id);
1645 t = tid;
1646 break;
1648 case TOKdot:
1649 id = Id::empty;
1650 goto Lident;
1652 case TOKtypeof:
1653 { Expression *exp;
1655 nextToken();
1656 check(TOKlparen);
1657 exp = parseExpression();
1658 check(TOKrparen);
1659 tid = new TypeTypeof(loc, exp);
1660 goto Lident2;
1663 default:
1664 error("basic type expected, not %s", token.toChars());
1665 t = Type::tint32;
1666 break;
1668 return t;
1671 Type *Parser::parseBasicType2(Type *t)
1673 Type *ts;
1674 Type *ta;
1676 //printf("parseBasicType2()\n");
1677 while (1)
1679 switch (token.value)
1681 case TOKmul:
1682 t = new TypePointer(t);
1683 nextToken();
1684 continue;
1686 case TOKlbracket:
1687 #if LTORARRAYDECL
1688 // Handle []. Make sure things like
1689 // int[3][1] a;
1690 // is (array[1] of array[3] of int)
1691 nextToken();
1692 if (token.value == TOKrbracket)
1694 t = new TypeDArray(t); // []
1695 nextToken();
1697 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1698 { // It's an associative array declaration
1699 Type *index;
1701 //printf("it's an associative array\n");
1702 index = parseBasicType();
1703 index = parseDeclarator(index, NULL); // [ type ]
1704 t = new TypeAArray(t, index);
1705 check(TOKrbracket);
1707 else
1709 //printf("it's [expression]\n");
1710 inBrackets++;
1711 Expression *e = parseExpression(); // [ expression ]
1712 if (token.value == TOKslice)
1713 { Expression *e2;
1715 nextToken();
1716 e2 = parseExpression(); // [ exp .. exp ]
1717 t = new TypeSlice(t, e, e2);
1719 else
1720 t = new TypeSArray(t,e);
1721 inBrackets--;
1722 check(TOKrbracket);
1724 continue;
1725 #else
1726 // Handle []. Make sure things like
1727 // int[3][1] a;
1728 // is (array[3] of array[1] of int)
1729 ts = t;
1730 while (token.value == TOKlbracket)
1732 nextToken();
1733 if (token.value == TOKrbracket)
1735 ta = new TypeDArray(t); // []
1736 nextToken();
1738 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1739 { // It's an associative array declaration
1740 Type *index;
1742 //printf("it's an associative array\n");
1743 index = parseBasicType();
1744 index = parseDeclarator(index, NULL); // [ type ]
1745 check(TOKrbracket);
1746 ta = new TypeAArray(t, index);
1748 else
1750 //printf("it's [expression]\n");
1751 Expression *e = parseExpression(); // [ expression ]
1752 ta = new TypeSArray(t,e);
1753 check(TOKrbracket);
1755 Type **pt;
1756 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1758 *pt = ta;
1760 t = ts;
1761 continue;
1762 #endif
1764 case TOKdelegate:
1765 case TOKfunction:
1766 { // Handle delegate declaration:
1767 // t delegate(parameter list)
1768 // t function(parameter list)
1769 Arguments *arguments;
1770 int varargs;
1771 enum TOK save = token.value;
1773 nextToken();
1774 arguments = parseParameters(&varargs);
1775 t = new TypeFunction(arguments, t, varargs, linkage);
1776 if (save == TOKdelegate)
1777 t = new TypeDelegate(t);
1778 else
1779 t = new TypePointer(t); // pointer to function
1780 continue;
1783 default:
1784 ts = t;
1785 break;
1787 break;
1789 return ts;
1792 Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
1793 { Type *ts;
1794 Type *ta;
1796 //printf("parseDeclarator(tpl = %p)\n", tpl);
1797 t = parseBasicType2(t);
1799 switch (token.value)
1802 case TOKidentifier:
1803 if (pident)
1804 *pident = token.ident;
1805 else
1806 error("unexpected identifer '%s' in declarator", token.ident->toChars());
1807 ts = t;
1808 nextToken();
1809 break;
1811 case TOKlparen:
1812 nextToken();
1813 ts = parseDeclarator(t, pident);
1814 check(TOKrparen);
1815 break;
1817 default:
1818 ts = t;
1819 break;
1822 while (1)
1824 switch (token.value)
1826 #if CARRAYDECL
1827 case TOKlbracket:
1828 { // This is the old C-style post [] syntax.
1829 nextToken();
1830 if (token.value == TOKrbracket)
1832 ta = new TypeDArray(t); // []
1833 nextToken();
1835 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1836 { // It's an associative array declaration
1837 Type *index;
1839 //printf("it's an associative array\n");
1840 index = parseBasicType();
1841 index = parseDeclarator(index, NULL); // [ type ]
1842 check(TOKrbracket);
1843 ta = new TypeAArray(t, index);
1845 else
1847 //printf("it's [expression]\n");
1848 Expression *e = parseExpression(); // [ expression ]
1849 ta = new TypeSArray(t, e);
1850 check(TOKrbracket);
1852 Type **pt;
1853 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1855 *pt = ta;
1856 continue;
1858 #endif
1859 case TOKlparen:
1860 { Arguments *arguments;
1861 int varargs;
1863 if (tpl)
1865 /* Look ahead to see if this is (...)(...),
1866 * i.e. a function template declaration
1868 if (peekPastParen(&token)->value == TOKlparen)
1869 { // It's a function template declaration
1870 //printf("function template declaration\n");
1872 // Gather template parameter list
1873 *tpl = parseTemplateParameterList();
1877 arguments = parseParameters(&varargs);
1878 Type *ta = new TypeFunction(arguments, t, varargs, linkage);
1879 Type **pt;
1880 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1882 *pt = ta;
1883 break;
1886 break;
1889 return ts;
1892 /**********************************
1893 * Return array of Declaration *'s.
1896 Array *Parser::parseDeclarations()
1898 enum STC storage_class;
1899 enum STC stc;
1900 Type *ts;
1901 Type *t;
1902 Type *tfirst;
1903 Identifier *ident;
1904 Array *a;
1905 enum TOK tok;
1906 unsigned char *comment = token.blockComment;
1907 enum LINK link = linkage;
1909 //printf("parseDeclarations()\n");
1910 switch (token.value)
1912 case TOKtypedef:
1913 case TOKalias:
1914 tok = token.value;
1915 nextToken();
1916 break;
1918 default:
1919 tok = TOKreserved;
1920 break;
1923 storage_class = STCundefined;
1924 while (1)
1926 switch (token.value)
1928 case TOKconst: stc = STCconst; goto L1;
1929 case TOKstatic: stc = STCstatic; goto L1;
1930 case TOKfinal: stc = STCfinal; goto L1;
1931 case TOKauto: stc = STCauto; goto L1;
1932 case TOKscope: stc = STCscope; goto L1;
1933 case TOKoverride: stc = STCoverride; goto L1;
1934 case TOKabstract: stc = STCabstract; goto L1;
1935 case TOKsynchronized: stc = STCsynchronized; goto L1;
1936 case TOKdeprecated: stc = STCdeprecated; goto L1;
1938 if (storage_class & stc)
1939 error("redundant storage class '%s'", token.toChars());
1940 storage_class = (STC) (storage_class | stc);
1941 nextToken();
1942 continue;
1944 case TOKextern:
1945 if (peek(&token)->value != TOKlparen)
1946 { stc = STCextern;
1947 goto L1;
1950 link = parseLinkage();
1951 continue;
1953 default:
1954 break;
1956 break;
1959 a = new Array();
1961 /* Look for auto initializers:
1962 * storage_class identifier = initializer;
1964 while (storage_class &&
1965 token.value == TOKidentifier &&
1966 peek(&token)->value == TOKassign)
1968 ident = token.ident;
1969 nextToken();
1970 nextToken();
1971 Initializer *init = parseInitializer();
1972 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
1973 v->storage_class = storage_class;
1974 a->push(v);
1975 if (token.value == TOKsemicolon)
1977 nextToken();
1978 addComment(v, comment);
1980 else if (token.value == TOKcomma)
1982 nextToken();
1983 if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
1985 error("Identifier expected following comma");
1987 else
1988 continue;
1990 else
1991 error("semicolon expected following auto declaration, not '%s'", token.toChars());
1992 return a;
1995 if (token.value == TOKclass)
1996 { AggregateDeclaration *s;
1998 s = (AggregateDeclaration *)parseAggregate();
1999 s->storage_class |= storage_class;
2000 a->push(s);
2001 addComment(s, comment);
2002 return a;
2005 ts = parseBasicType();
2006 ts = parseBasicType2(ts);
2007 tfirst = NULL;
2009 while (1)
2011 Loc loc = this->loc;
2012 TemplateParameters *tpl = NULL;
2014 ident = NULL;
2015 t = parseDeclarator(ts, &ident, &tpl);
2016 assert(t);
2017 if (!tfirst)
2018 tfirst = t;
2019 else if (t != tfirst)
2020 error("multiple declarations must have the same type, not %s and %s",
2021 tfirst->toChars(), t->toChars());
2022 if (!ident)
2023 error("no identifier for declarator %s", t->toChars());
2025 if (tok == TOKtypedef || tok == TOKalias)
2026 { Declaration *v;
2027 Initializer *init;
2029 init = NULL;
2030 if (token.value == TOKassign)
2032 nextToken();
2033 init = parseInitializer();
2035 if (tok == TOKtypedef)
2036 v = new TypedefDeclaration(loc, ident, t, init);
2037 else
2038 { if (init)
2039 error("alias cannot have initializer");
2040 v = new AliasDeclaration(loc, ident, t);
2042 v->storage_class = storage_class;
2043 if (link == linkage)
2044 a->push(v);
2045 else
2047 Array *ax = new Array();
2048 ax->push(v);
2049 Dsymbol *s = new LinkDeclaration(link, ax);
2050 a->push(s);
2052 switch (token.value)
2053 { case TOKsemicolon:
2054 nextToken();
2055 addComment(v, comment);
2056 break;
2058 case TOKcomma:
2059 nextToken();
2060 addComment(v, comment);
2061 continue;
2063 default:
2064 error("semicolon expected to close %s declaration", Token::toChars(tok));
2065 break;
2068 else if (t->ty == Tfunction)
2069 { FuncDeclaration *f;
2070 Dsymbol *s;
2072 f = new FuncDeclaration(loc, 0, ident, storage_class, t);
2073 addComment(f, comment);
2074 parseContracts(f);
2075 addComment(f, NULL);
2076 if (link == linkage)
2078 s = f;
2080 else
2082 Array *ax = new Array();
2083 ax->push(f);
2084 s = new LinkDeclaration(link, ax);
2086 if (tpl) // it's a function template
2087 { Array *decldefs;
2088 TemplateDeclaration *tempdecl;
2090 // Wrap a template around the aggregate declaration
2091 decldefs = new Array();
2092 decldefs->push(s);
2093 tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs);
2094 s = tempdecl;
2096 addComment(s, comment);
2097 a->push(s);
2099 else
2100 { VarDeclaration *v;
2101 Initializer *init;
2103 init = NULL;
2104 if (token.value == TOKassign)
2106 nextToken();
2107 init = parseInitializer();
2109 v = new VarDeclaration(loc, t, ident, init);
2110 v->storage_class = storage_class;
2111 if (link == linkage)
2112 a->push(v);
2113 else
2115 Array *ax = new Array();
2116 ax->push(v);
2117 Dsymbol *s = new LinkDeclaration(link, ax);
2118 a->push(s);
2120 switch (token.value)
2121 { case TOKsemicolon:
2122 nextToken();
2123 addComment(v, comment);
2124 break;
2126 case TOKcomma:
2127 nextToken();
2128 addComment(v, comment);
2129 continue;
2131 default:
2132 error("semicolon expected, not '%s'", token.toChars());
2133 break;
2136 break;
2138 return a;
2141 /*****************************************
2142 * Parse contracts following function declaration.
2145 void Parser::parseContracts(FuncDeclaration *f)
2147 Type *tb;
2148 enum LINK linksave = linkage;
2150 // The following is irrelevant, as it is overridden by sc->linkage in
2151 // TypeFunction::semantic
2152 linkage = LINKd; // nested functions have D linkage
2154 switch (token.value)
2156 case TOKlcurly:
2157 if (f->frequire || f->fensure)
2158 error("missing body { ... } after in or out");
2159 f->fbody = parseStatement(PSsemi);
2160 f->endloc = endloc;
2161 break;
2163 case TOKbody:
2164 nextToken();
2165 f->fbody = parseStatement(PScurly);
2166 f->endloc = endloc;
2167 break;
2169 case TOKsemicolon:
2170 if (f->frequire || f->fensure)
2171 error("missing body { ... } after in or out");
2172 nextToken();
2173 break;
2175 #if 0 // Do we want this for function declarations, so we can do:
2176 // int x, y, foo(), z;
2177 case TOKcomma:
2178 nextToken();
2179 continue;
2180 #endif
2182 #if 0 // Dumped feature
2183 case TOKthrow:
2184 if (!f->fthrows)
2185 f->fthrows = new Array();
2186 nextToken();
2187 check(TOKlparen);
2188 while (1)
2190 tb = parseBasicType();
2191 f->fthrows->push(tb);
2192 if (token.value == TOKcomma)
2193 { nextToken();
2194 continue;
2196 break;
2198 check(TOKrparen);
2199 goto L1;
2200 #endif
2202 case TOKin:
2203 nextToken();
2204 if (f->frequire)
2205 error("redundant 'in' statement");
2206 f->frequire = parseStatement(PScurly | PSscope);
2207 goto L1;
2209 case TOKout:
2210 // parse: out (identifier) { statement }
2211 nextToken();
2212 if (token.value != TOKlcurly)
2214 check(TOKlparen);
2215 if (token.value != TOKidentifier)
2216 error("(identifier) following 'out' expected, not %s", token.toChars());
2217 f->outId = token.ident;
2218 nextToken();
2219 check(TOKrparen);
2221 if (f->fensure)
2222 error("redundant 'out' statement");
2223 f->fensure = parseStatement(PScurly | PSscope);
2224 goto L1;
2226 default:
2227 error("semicolon expected following function declaration");
2228 break;
2230 linkage = linksave;
2233 /*****************************************
2236 Initializer *Parser::parseInitializer()
2238 StructInitializer *is;
2239 ArrayInitializer *ia;
2240 ExpInitializer *ie;
2241 Expression *e;
2242 Identifier *id;
2243 Initializer *value;
2244 int comma;
2245 Loc loc = this->loc;
2246 Token *t;
2247 int braces;
2249 switch (token.value)
2251 case TOKlcurly:
2252 /* Scan ahead to see if it is a struct initializer or
2253 * a function literal.
2254 * If it contains a ';', it is a function literal.
2255 * Treat { } as a struct initializer.
2257 braces = 1;
2258 for (t = peek(&token); 1; t = peek(t))
2260 switch (t->value)
2262 case TOKsemicolon:
2263 case TOKreturn:
2264 goto Lexpression;
2266 case TOKlcurly:
2267 braces++;
2268 continue;
2270 case TOKrcurly:
2271 if (--braces == 0)
2272 break;
2273 continue;
2275 case TOKeof:
2276 break;
2278 default:
2279 continue;
2281 break;
2284 is = new StructInitializer(loc);
2285 nextToken();
2286 comma = 0;
2287 while (1)
2289 switch (token.value)
2291 case TOKidentifier:
2292 if (comma == 1)
2293 error("comma expected separating field initializers");
2294 t = peek(&token);
2295 if (t->value == TOKcolon)
2297 id = token.ident;
2298 nextToken();
2299 nextToken(); // skip over ':'
2301 else
2302 { id = NULL;
2304 value = parseInitializer();
2305 is->addInit(id, value);
2306 comma = 1;
2307 continue;
2309 case TOKcomma:
2310 nextToken();
2311 comma = 2;
2312 continue;
2314 case TOKrcurly: // allow trailing comma's
2315 nextToken();
2316 break;
2318 case TOKeof:
2319 error("found EOF instead of initializer");
2320 break;
2322 default:
2323 value = parseInitializer();
2324 is->addInit(NULL, value);
2325 comma = 1;
2326 continue;
2327 //error("found '%s' instead of field initializer", token.toChars());
2328 //break;
2330 break;
2332 return is;
2334 case TOKlbracket:
2335 ia = new ArrayInitializer(loc);
2336 nextToken();
2337 comma = 0;
2338 while (1)
2340 switch (token.value)
2342 default:
2343 if (comma == 1)
2344 { error("comma expected separating array initializers, not %s", token.toChars());
2345 nextToken();
2346 break;
2348 e = parseAssignExp();
2349 if (!e)
2350 break;
2351 if (token.value == TOKcolon)
2353 nextToken();
2354 value = parseInitializer();
2356 else
2357 { value = new ExpInitializer(e->loc, e);
2358 e = NULL;
2360 ia->addInit(e, value);
2361 comma = 1;
2362 continue;
2364 case TOKlcurly:
2365 case TOKlbracket:
2366 if (comma == 1)
2367 error("comma expected separating array initializers, not %s", token.toChars());
2368 value = parseInitializer();
2369 ia->addInit(NULL, value);
2370 comma = 1;
2371 continue;
2373 case TOKcomma:
2374 nextToken();
2375 comma = 2;
2376 continue;
2378 case TOKrbracket: // allow trailing comma's
2379 nextToken();
2380 break;
2382 case TOKeof:
2383 error("found '%s' instead of array initializer", token.toChars());
2384 break;
2386 break;
2388 return ia;
2390 case TOKvoid:
2391 t = peek(&token);
2392 if (t->value == TOKsemicolon || t->value == TOKcomma)
2394 nextToken();
2395 return new VoidInitializer(loc);
2397 goto Lexpression;
2399 default:
2400 Lexpression:
2401 e = parseAssignExp();
2402 ie = new ExpInitializer(loc, e);
2403 return ie;
2408 /*****************************************
2409 * Input:
2410 * flags PSxxxx
2413 Statement *Parser::parseStatement(int flags)
2414 { Statement *s;
2415 Token *t;
2416 Condition *condition;
2417 Statement *ifbody;
2418 Statement *elsebody;
2419 Loc loc = this->loc;
2421 //printf("parseStatement()\n");
2423 if (flags & PScurly && token.value != TOKlcurly)
2424 error("statement expected to be { }, not %s", token.toChars());
2426 switch (token.value)
2428 case TOKidentifier:
2429 // Need to look ahead to see if it is a declaration, label, or expression
2430 t = peek(&token);
2431 if (t->value == TOKcolon)
2432 { // It's a label
2433 Identifier *ident;
2435 ident = token.ident;
2436 nextToken();
2437 nextToken();
2438 s = parseStatement(PSsemi);
2439 s = new LabelStatement(loc, ident, s);
2440 break;
2442 // fallthrough to TOKdot
2443 case TOKdot:
2444 case TOKtypeof:
2445 if (isDeclaration(&token, 2, TOKreserved, NULL))
2446 goto Ldeclaration;
2447 else
2448 goto Lexp;
2449 break;
2451 case TOKassert:
2452 case TOKthis:
2453 case TOKsuper:
2454 case TOKint32v:
2455 case TOKuns32v:
2456 case TOKint64v:
2457 case TOKuns64v:
2458 case TOKfloat32v:
2459 case TOKfloat64v:
2460 case TOKfloat80v:
2461 case TOKimaginary32v:
2462 case TOKimaginary64v:
2463 case TOKimaginary80v:
2464 case TOKcharv:
2465 case TOKwcharv:
2466 case TOKdcharv:
2467 case TOKnull:
2468 case TOKtrue:
2469 case TOKfalse:
2470 case TOKstring:
2471 case TOKlparen:
2472 case TOKcast:
2473 case TOKmul:
2474 case TOKmin:
2475 case TOKadd:
2476 case TOKplusplus:
2477 case TOKminusminus:
2478 case TOKnew:
2479 case TOKdelete:
2480 case TOKdelegate:
2481 case TOKfunction:
2482 case TOKtypeid:
2483 case TOKis:
2484 case TOKlbracket:
2485 Lexp:
2486 { Expression *exp;
2488 exp = parseExpression();
2489 check(TOKsemicolon, "statement");
2490 s = new ExpStatement(loc, exp);
2491 break;
2494 case TOKstatic:
2495 { // Look ahead to see if it's static assert() or static if()
2496 Token *t;
2498 t = peek(&token);
2499 if (t->value == TOKassert)
2501 nextToken();
2502 s = new StaticAssertStatement(parseStaticAssert());
2503 break;
2505 if (t->value == TOKif)
2507 nextToken();
2508 condition = parseStaticIfCondition();
2509 goto Lcondition;
2511 goto Ldeclaration;
2514 CASE_BASIC_TYPES:
2515 case TOKtypedef:
2516 case TOKalias:
2517 case TOKconst:
2518 case TOKauto:
2519 case TOKextern:
2520 case TOKfinal:
2521 case TOKinvariant:
2522 // case TOKtypeof:
2523 Ldeclaration:
2524 { Array *a;
2526 a = parseDeclarations();
2527 if (a->dim > 1)
2529 Statements *as = new Statements();
2530 as->reserve(a->dim);
2531 for (int i = 0; i < a->dim; i++)
2533 Dsymbol *d = (Dsymbol *)a->data[i];
2534 s = new DeclarationStatement(loc, d);
2535 as->push(s);
2537 s = new CompoundStatement(loc, as);
2539 else if (a->dim == 1)
2541 Dsymbol *d = (Dsymbol *)a->data[0];
2542 s = new DeclarationStatement(loc, d);
2544 else
2545 assert(0);
2546 if (flags & PSscope)
2547 s = new ScopeStatement(loc, s);
2548 break;
2551 case TOKstruct:
2552 case TOKunion:
2553 case TOKclass:
2554 case TOKinterface:
2555 { Dsymbol *d;
2557 d = parseAggregate();
2558 s = new DeclarationStatement(loc, d);
2559 break;
2562 case TOKenum:
2563 { Dsymbol *d;
2565 d = parseEnum();
2566 s = new DeclarationStatement(loc, d);
2567 break;
2570 case TOKmixin:
2571 { t = peek(&token);
2572 if (t->value == TOKlparen)
2573 { // mixin(string)
2574 nextToken();
2575 check(TOKlparen, "mixin");
2576 Expression *e = parseAssignExp();
2577 check(TOKrparen);
2578 check(TOKsemicolon);
2579 s = new CompileStatement(loc, e);
2580 break;
2582 Dsymbol *d = parseMixin();
2583 s = new DeclarationStatement(loc, d);
2584 break;
2587 case TOKlcurly:
2588 { Statements *statements;
2590 nextToken();
2591 statements = new Statements();
2592 while (token.value != TOKrcurly)
2594 statements->push(parseStatement(PSsemi | PScurlyscope));
2596 endloc = this->loc;
2597 s = new CompoundStatement(loc, statements);
2598 if (flags & (PSscope | PScurlyscope))
2599 s = new ScopeStatement(loc, s);
2600 nextToken();
2601 break;
2604 case TOKwhile:
2605 { Expression *condition;
2606 Statement *body;
2608 nextToken();
2609 check(TOKlparen);
2610 condition = parseExpression();
2611 check(TOKrparen);
2612 body = parseStatement(PSscope);
2613 s = new WhileStatement(loc, condition, body);
2614 break;
2617 case TOKsemicolon:
2618 if (!(flags & PSsemi))
2619 error("use '{ }' for an empty statement, not a ';'");
2620 nextToken();
2621 s = new ExpStatement(loc, NULL);
2622 break;
2624 case TOKdo:
2625 { Statement *body;
2626 Expression *condition;
2628 nextToken();
2629 body = parseStatement(PSscope);
2630 check(TOKwhile);
2631 check(TOKlparen);
2632 condition = parseExpression();
2633 check(TOKrparen);
2634 s = new DoStatement(loc, body, condition);
2635 break;
2638 case TOKfor:
2640 Statement *init;
2641 Expression *condition;
2642 Expression *increment;
2643 Statement *body;
2645 nextToken();
2646 check(TOKlparen);
2647 if (token.value == TOKsemicolon)
2648 { init = NULL;
2649 nextToken();
2651 else
2652 { init = parseStatement(0);
2654 if (token.value == TOKsemicolon)
2656 condition = NULL;
2657 nextToken();
2659 else
2661 condition = parseExpression();
2662 check(TOKsemicolon, "for condition");
2664 if (token.value == TOKrparen)
2665 { increment = NULL;
2666 nextToken();
2668 else
2669 { increment = parseExpression();
2670 check(TOKrparen);
2672 body = parseStatement(PSscope);
2673 s = new ForStatement(loc, init, condition, increment, body);
2674 if (init)
2675 s = new ScopeStatement(loc, s);
2676 break;
2679 case TOKforeach:
2680 case TOKforeach_reverse:
2682 enum TOK op = token.value;
2683 Arguments *arguments;
2685 Statement *d;
2686 Statement *body;
2687 Expression *aggr;
2689 nextToken();
2690 check(TOKlparen);
2692 arguments = new Arguments();
2694 while (1)
2696 Type *tb;
2697 Identifier *ai = NULL;
2698 Type *at;
2699 unsigned storageClass;
2700 Argument *a;
2702 storageClass = STCin;
2703 if (token.value == TOKinout || token.value == TOKref)
2704 { storageClass = STCref;
2705 nextToken();
2707 if (token.value == TOKidentifier)
2709 Token *t = peek(&token);
2710 if (t->value == TOKcomma || t->value == TOKsemicolon)
2711 { ai = token.ident;
2712 at = NULL; // infer argument type
2713 nextToken();
2714 goto Larg;
2717 tb = parseBasicType();
2718 at = parseDeclarator(tb, &ai);
2719 if (!ai)
2720 error("no identifier for declarator %s", at->toChars());
2721 Larg:
2722 a = new Argument(storageClass, at, ai, NULL);
2723 arguments->push(a);
2724 if (token.value == TOKcomma)
2725 { nextToken();
2726 continue;
2728 break;
2730 check(TOKsemicolon);
2732 aggr = parseExpression();
2733 check(TOKrparen);
2734 body = parseStatement(0);
2735 s = new ForeachStatement(loc, op, arguments, aggr, body);
2736 break;
2739 case TOKif:
2740 { Argument *arg = NULL;
2741 Expression *condition;
2742 Statement *ifbody;
2743 Statement *elsebody;
2745 nextToken();
2746 check(TOKlparen);
2748 if (token.value == TOKauto)
2750 nextToken();
2751 if (token.value == TOKidentifier)
2753 Token *t = peek(&token);
2754 if (t->value == TOKassign)
2756 arg = new Argument(STCin, NULL, token.ident, NULL);
2757 nextToken();
2758 nextToken();
2760 else
2761 { error("= expected following auto identifier");
2762 goto Lerror;
2765 else
2766 { error("identifier expected following auto");
2767 goto Lerror;
2770 else if (isDeclaration(&token, 2, TOKassign, NULL))
2772 Type *tb;
2773 Type *at;
2774 Identifier *ai;
2776 tb = parseBasicType();
2777 at = parseDeclarator(tb, &ai);
2778 check(TOKassign);
2779 arg = new Argument(STCin, at, ai, NULL);
2782 // Check for " ident;"
2783 else if (token.value == TOKidentifier)
2785 Token *t = peek(&token);
2786 if (t->value == TOKcomma || t->value == TOKsemicolon)
2788 arg = new Argument(STCin, NULL, token.ident, NULL);
2789 nextToken();
2790 nextToken();
2791 if (1 || !global.params.useDeprecated)
2792 error("if (v; e) is deprecated, use if (auto v = e)");
2796 condition = parseExpression();
2797 check(TOKrparen);
2798 ifbody = parseStatement(PSscope);
2799 if (token.value == TOKelse)
2801 nextToken();
2802 elsebody = parseStatement(PSscope);
2804 else
2805 elsebody = NULL;
2806 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
2807 break;
2810 case TOKscope:
2811 if (peek(&token)->value != TOKlparen)
2812 goto Ldeclaration; // scope used as storage class
2813 nextToken();
2814 check(TOKlparen);
2815 if (token.value != TOKidentifier)
2816 { error("scope identifier expected");
2817 goto Lerror;
2819 else
2820 { TOK t = TOKon_scope_exit;
2821 Identifier *id = token.ident;
2823 if (id == Id::exit)
2824 t = TOKon_scope_exit;
2825 else if (id == Id::failure)
2826 t = TOKon_scope_failure;
2827 else if (id == Id::success)
2828 t = TOKon_scope_success;
2829 else
2830 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
2831 nextToken();
2832 check(TOKrparen);
2833 Statement *st = parseStatement(PScurlyscope);
2834 s = new OnScopeStatement(loc, t, st);
2835 break;
2838 case TOKdebug:
2839 nextToken();
2840 condition = parseDebugCondition();
2841 goto Lcondition;
2843 case TOKversion:
2844 nextToken();
2845 condition = parseVersionCondition();
2846 goto Lcondition;
2848 Lcondition:
2849 ifbody = parseStatement(0 /*PSsemi*/);
2850 elsebody = NULL;
2851 if (token.value == TOKelse)
2853 nextToken();
2854 elsebody = parseStatement(0 /*PSsemi*/);
2856 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
2857 break;
2859 case TOKpragma:
2860 { Identifier *ident;
2861 Expressions *args = NULL;
2862 Statement *body;
2864 nextToken();
2865 check(TOKlparen);
2866 if (token.value != TOKidentifier)
2867 { error("pragma(identifier expected");
2868 goto Lerror;
2870 ident = token.ident;
2871 nextToken();
2872 if (token.value == TOKcomma)
2873 args = parseArguments(); // pragma(identifier, args...);
2874 else
2875 check(TOKrparen); // pragma(identifier);
2876 if (token.value == TOKsemicolon)
2877 { nextToken();
2878 body = NULL;
2880 else
2881 body = parseStatement(PSsemi);
2882 s = new PragmaStatement(loc, ident, args, body);
2883 break;
2886 case TOKswitch:
2887 { Expression *condition;
2888 Statement *body;
2890 nextToken();
2891 check(TOKlparen);
2892 condition = parseExpression();
2893 check(TOKrparen);
2894 body = parseStatement(PSscope);
2895 s = new SwitchStatement(loc, condition, body);
2896 break;
2899 case TOKcase:
2900 { Expression *exp;
2901 Statements *statements;
2902 Array cases; // array of Expression's
2904 while (1)
2906 nextToken();
2907 exp = parseAssignExp();
2908 cases.push(exp);
2909 if (token.value != TOKcomma)
2910 break;
2912 check(TOKcolon);
2914 statements = new Statements();
2915 while (token.value != TOKcase &&
2916 token.value != TOKdefault &&
2917 token.value != TOKrcurly)
2919 statements->push(parseStatement(PSsemi | PScurlyscope));
2921 s = new CompoundStatement(loc, statements);
2922 s = new ScopeStatement(loc, s);
2924 // Keep cases in order by building the case statements backwards
2925 for (int i = cases.dim; i; i--)
2927 exp = (Expression *)cases.data[i - 1];
2928 s = new CaseStatement(loc, exp, s);
2930 break;
2933 case TOKdefault:
2935 Statements *statements;
2937 nextToken();
2938 check(TOKcolon);
2940 statements = new Statements();
2941 while (token.value != TOKcase &&
2942 token.value != TOKdefault &&
2943 token.value != TOKrcurly)
2945 statements->push(parseStatement(PSsemi | PScurlyscope));
2947 s = new CompoundStatement(loc, statements);
2948 s = new ScopeStatement(loc, s);
2949 s = new DefaultStatement(loc, s);
2950 break;
2953 case TOKreturn:
2954 { Expression *exp;
2956 nextToken();
2957 if (token.value == TOKsemicolon)
2958 exp = NULL;
2959 else
2960 exp = parseExpression();
2961 check(TOKsemicolon, "return statement");
2962 s = new ReturnStatement(loc, exp);
2963 break;
2966 case TOKbreak:
2967 { Identifier *ident;
2969 nextToken();
2970 if (token.value == TOKidentifier)
2971 { ident = token.ident;
2972 nextToken();
2974 else
2975 ident = NULL;
2976 check(TOKsemicolon, "break statement");
2977 s = new BreakStatement(loc, ident);
2978 break;
2981 case TOKcontinue:
2982 { Identifier *ident;
2984 nextToken();
2985 if (token.value == TOKidentifier)
2986 { ident = token.ident;
2987 nextToken();
2989 else
2990 ident = NULL;
2991 check(TOKsemicolon, "continue statement");
2992 s = new ContinueStatement(loc, ident);
2993 break;
2996 case TOKgoto:
2997 { Identifier *ident;
2999 nextToken();
3000 if (token.value == TOKdefault)
3002 nextToken();
3003 s = new GotoDefaultStatement(loc);
3005 else if (token.value == TOKcase)
3007 Expression *exp = NULL;
3009 nextToken();
3010 if (token.value != TOKsemicolon)
3011 exp = parseExpression();
3012 s = new GotoCaseStatement(loc, exp);
3014 else
3016 if (token.value != TOKidentifier)
3017 { error("Identifier expected following goto");
3018 ident = NULL;
3020 else
3021 { ident = token.ident;
3022 nextToken();
3024 s = new GotoStatement(loc, ident);
3026 check(TOKsemicolon, "goto statement");
3027 break;
3030 case TOKsynchronized:
3031 { Expression *exp;
3032 Statement *body;
3034 nextToken();
3035 if (token.value == TOKlparen)
3037 nextToken();
3038 exp = parseExpression();
3039 check(TOKrparen);
3041 else
3042 exp = NULL;
3043 body = parseStatement(PSscope);
3044 s = new SynchronizedStatement(loc, exp, body);
3045 break;
3048 case TOKwith:
3049 { Expression *exp;
3050 Statement *body;
3052 nextToken();
3053 check(TOKlparen);
3054 exp = parseExpression();
3055 check(TOKrparen);
3056 body = parseStatement(PSscope);
3057 s = new WithStatement(loc, exp, body);
3058 break;
3061 case TOKtry:
3062 { Statement *body;
3063 Array *catches = NULL;
3064 Statement *finalbody = NULL;
3066 nextToken();
3067 body = parseStatement(PSscope);
3068 while (token.value == TOKcatch)
3070 Statement *handler;
3071 Catch *c;
3072 Type *t;
3073 Identifier *id;
3074 Loc loc = this->loc;
3076 nextToken();
3077 if (token.value == TOKlcurly)
3079 t = NULL;
3080 id = NULL;
3082 else
3084 check(TOKlparen);
3085 t = parseBasicType();
3086 id = NULL;
3087 t = parseDeclarator(t, &id);
3088 check(TOKrparen);
3090 handler = parseStatement(0);
3091 c = new Catch(loc, t, id, handler);
3092 if (!catches)
3093 catches = new Array();
3094 catches->push(c);
3097 if (token.value == TOKfinally)
3098 { nextToken();
3099 finalbody = parseStatement(0);
3102 s = body;
3103 if (!catches && !finalbody)
3104 error("catch or finally expected following try");
3105 else
3106 { if (catches)
3107 s = new TryCatchStatement(loc, body, catches);
3108 if (finalbody)
3109 s = new TryFinallyStatement(loc, s, finalbody);
3111 break;
3114 case TOKthrow:
3115 { Expression *exp;
3117 nextToken();
3118 exp = parseExpression();
3119 check(TOKsemicolon, "throw statement");
3120 s = new ThrowStatement(loc, exp);
3121 break;
3124 case TOKvolatile:
3125 nextToken();
3126 s = parseStatement(PSsemi | PScurlyscope);
3127 s = new VolatileStatement(loc, s);
3128 break;
3130 case TOKasm:
3131 { Statements *statements;
3132 Identifier *label;
3133 Loc labelloc;
3134 Token *toklist;
3135 Token **ptoklist;
3137 // Parse the asm block into a sequence of AsmStatements,
3138 // each AsmStatement is one instruction.
3139 // Separate out labels.
3140 // Defer parsing of AsmStatements until semantic processing.
3142 nextToken();
3143 #if GDC_EXTENDED_ASM_SYNTAX
3144 if (token.value == TOKlparen)
3146 nextToken();
3147 s = parseExtAsm(1);
3148 break;
3150 #endif
3151 check(TOKlcurly);
3152 toklist = NULL;
3153 ptoklist = &toklist;
3154 label = NULL;
3155 statements = new Statements();
3156 while (1)
3158 switch (token.value)
3160 case TOKidentifier:
3161 if (!toklist)
3163 // Look ahead to see if it is a label
3164 t = peek(&token);
3165 if (t->value == TOKcolon)
3166 { // It's a label
3167 label = token.ident;
3168 labelloc = this->loc;
3169 nextToken();
3170 nextToken();
3171 continue;
3174 goto Ldefault;
3176 case TOKrcurly:
3177 if (toklist || label)
3179 error("asm statements must end in ';'");
3181 break;
3183 case TOKsemicolon:
3184 s = NULL;
3185 if (toklist || label)
3186 { // Create AsmStatement from list of tokens we've saved
3187 s = new AsmStatement(this->loc, toklist);
3188 toklist = NULL;
3189 ptoklist = &toklist;
3190 if (label)
3191 { s = new LabelStatement(labelloc, label, s);
3192 label = NULL;
3194 statements->push(s);
3196 nextToken();
3197 continue;
3199 case TOKeof:
3200 /* { */
3201 error("matching '}' expected, not end of file");
3202 break;
3204 case TOKlparen:
3205 case TOKstring:
3206 // If the first token is a string or '(', parse as extended asm.
3207 if (! toklist)
3209 s = parseExtAsm(0);
3210 statements->push(s);
3211 continue;
3213 // ...else, drop through.
3215 default:
3216 Ldefault:
3217 *ptoklist = new Token();
3218 memcpy(*ptoklist, &token, sizeof(Token));
3219 ptoklist = &(*ptoklist)->next;
3220 *ptoklist = NULL;
3222 nextToken();
3223 continue;
3225 break;
3227 s = new CompoundStatement(loc, statements);
3228 nextToken();
3229 break;
3232 default:
3233 error("found '%s' instead of statement", token.toChars());
3234 goto Lerror;
3236 Lerror:
3237 while (token.value != TOKrcurly &&
3238 token.value != TOKsemicolon &&
3239 token.value != TOKeof)
3240 nextToken();
3241 if (token.value == TOKsemicolon)
3242 nextToken();
3243 s = NULL;
3244 break;
3247 return s;
3250 Statement *Parser::parseExtAsm(int expect_rparen)
3252 Expression * insnTemplate;
3253 Expressions * args = NULL;
3254 Array * argNames = NULL;
3255 Expressions * argConstraints = NULL;
3256 int nOutputArgs = 0;
3257 Expressions * clobbers = NULL;
3258 bool isInputPhase = false; // Output operands first, then input.
3260 insnTemplate = parseExpression();
3261 if (token.value == TOKrparen || token.value == TOKsemicolon)
3262 goto Ldone;
3263 check(TOKcolon);
3264 while (1) {
3265 Expression * arg = NULL;
3266 Identifier * name = NULL;
3267 Expression * constraint = NULL;
3269 switch (token.value)
3271 case TOKsemicolon:
3272 case TOKrparen:
3273 goto Ldone;
3275 case TOKcolon:
3276 nextToken();
3277 goto LnextPhase;
3279 case TOKeof:
3280 error("unterminated statement");
3282 case TOKlbracket:
3283 nextToken();
3284 if (token.value == TOKidentifier)
3286 name = token.ident;
3287 nextToken();
3289 else
3290 error("expected identifier after '['");
3291 check(TOKrbracket);
3292 // drop through
3293 default:
3294 constraint = parsePrimaryExp();
3295 if (constraint->op != TOKstring)
3296 error("expected constant string constraint for operand");
3297 arg = parseAssignExp();
3298 if (! args)
3300 args = new Expressions;
3301 argConstraints = new Expressions;
3302 argNames = new Array;
3304 args->push(arg);
3305 argNames->push(name);
3306 argConstraints->push(constraint);
3307 if (! isInputPhase)
3308 nOutputArgs++;
3310 if (token.value == TOKcomma)
3311 nextToken();
3312 break;
3314 continue;
3315 LnextPhase:
3316 if (! isInputPhase)
3317 isInputPhase = true;
3318 else
3319 break;
3322 while (1)
3324 Expression * clobber;
3326 switch (token.value)
3328 case TOKsemicolon:
3329 case TOKrparen:
3330 goto Ldone;
3332 case TOKeof:
3333 error("unterminated statement");
3335 default:
3336 clobber = parseAssignExp();
3337 if (clobber->op != TOKstring)
3338 error("expected constant string constraint for clobber name");
3339 if (! clobbers)
3340 clobbers = new Expressions;
3341 clobbers->push(clobber);
3343 if (token.value == TOKcomma)
3344 nextToken();
3345 break;
3348 Ldone:
3349 if (expect_rparen)
3350 check(TOKrparen);
3351 else
3352 check(TOKsemicolon);
3354 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3355 argConstraints, nOutputArgs, clobbers);
3358 void Parser::check(enum TOK value)
3360 check(loc, value);
3363 void Parser::check(Loc loc, enum TOK value)
3365 if (token.value != value)
3366 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3367 nextToken();
3370 void Parser::check(enum TOK value, char *string)
3372 if (token.value != value)
3373 error("found '%s' when expecting '%s' following '%s'",
3374 token.toChars(), Token::toChars(value), string);
3375 nextToken();
3378 /************************************
3379 * Determine if the scanner is sitting on the start of a declaration.
3380 * Input:
3381 * needId 0 no identifier
3382 * 1 identifier optional
3383 * 2 must have identifier
3386 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3388 int haveId = 0;
3390 if (!isBasicType(&t))
3391 return FALSE;
3392 if (!isDeclarator(&t, &haveId, endtok))
3393 return FALSE;
3394 if ( needId == 1 ||
3395 (needId == 0 && !haveId) ||
3396 (needId == 2 && haveId))
3397 { if (pt)
3398 *pt = t;
3399 return TRUE;
3401 else
3402 return FALSE;
3405 int Parser::isBasicType(Token **pt)
3407 // This code parallels parseBasicType()
3408 Token *t = *pt;
3409 Token *t2;
3410 int parens;
3412 switch (t->value)
3414 CASE_BASIC_TYPES:
3415 t = peek(t);
3416 break;
3418 case TOKidentifier:
3419 t = peek(t);
3420 if (t->value == TOKnot)
3422 goto L4;
3424 goto L3;
3425 while (1)
3428 t = peek(t);
3430 if (t->value == TOKdot)
3432 Ldot:
3433 t = peek(t);
3434 if (t->value != TOKidentifier)
3435 goto Lfalse;
3436 t = peek(t);
3437 if (t->value != TOKnot)
3438 goto L3;
3440 t = peek(t);
3441 if (t->value != TOKlparen)
3442 goto Lfalse;
3443 if (!skipParens(t, &t))
3444 goto Lfalse;
3446 else
3447 break;
3449 break;
3451 case TOKdot:
3452 goto Ldot;
3454 case TOKtypeof:
3455 /* typeof(exp).identifier...
3457 t = peek(t);
3458 if (t->value != TOKlparen)
3459 goto Lfalse;
3460 if (!skipParens(t, &t))
3461 goto Lfalse;
3462 goto L2;
3464 default:
3465 goto Lfalse;
3467 *pt = t;
3468 return TRUE;
3470 Lfalse:
3471 return FALSE;
3474 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3475 { // This code parallels parseDeclarator()
3476 Token *t = *pt;
3477 int parens;
3479 //printf("Parser::isDeclarator()\n");
3480 //t->print();
3481 if (t->value == TOKassign)
3482 return FALSE;
3484 while (1)
3486 parens = FALSE;
3487 switch (t->value)
3489 case TOKmul:
3490 case TOKand:
3491 t = peek(t);
3492 continue;
3494 case TOKlbracket:
3495 t = peek(t);
3496 if (t->value == TOKrbracket)
3498 t = peek(t);
3500 else if (isDeclaration(t, 0, TOKrbracket, &t))
3501 { // It's an associative array declaration
3502 t = peek(t);
3504 else
3506 // [ expression ]
3507 // [ expression .. expression ]
3508 if (!isExpression(&t))
3509 return FALSE;
3510 if (t->value == TOKslice)
3511 { t = peek(t);
3512 if (!isExpression(&t))
3513 return FALSE;
3515 if (t->value != TOKrbracket)
3516 return FALSE;
3517 t = peek(t);
3519 continue;
3521 case TOKidentifier:
3522 if (*haveId)
3523 return FALSE;
3524 *haveId = TRUE;
3525 t = peek(t);
3526 break;
3528 case TOKlparen:
3529 t = peek(t);
3531 if (t->value == TOKrparen)
3532 return FALSE; // () is not a declarator
3534 /* Regard ( identifier ) as not a declarator
3535 * BUG: what about ( *identifier ) in
3536 * f(*p)(x);
3537 * where f is a class instance with overloaded () ?
3538 * Should we just disallow C-style function pointer declarations?
3540 if (t->value == TOKidentifier)
3541 { Token *t2 = peek(t);
3542 if (t2->value == TOKrparen)
3543 return FALSE;
3547 if (!isDeclarator(&t, haveId, TOKrparen))
3548 return FALSE;
3549 t = peek(t);
3550 parens = TRUE;
3551 break;
3553 case TOKdelegate:
3554 case TOKfunction:
3555 t = peek(t);
3556 if (!isParameters(&t))
3557 return FALSE;
3558 continue;
3560 break;
3563 while (1)
3565 switch (t->value)
3567 #if CARRAYDECL
3568 case TOKlbracket:
3569 parens = FALSE;
3570 t = peek(t);
3571 if (t->value == TOKrbracket)
3573 t = peek(t);
3575 else if (isDeclaration(t, 0, TOKrbracket, &t))
3576 { // It's an associative array declaration
3577 t = peek(t);
3579 else
3581 // [ expression ]
3582 if (!isExpression(&t))
3583 return FALSE;
3584 if (t->value != TOKrbracket)
3585 return FALSE;
3586 t = peek(t);
3588 continue;
3589 #endif
3591 case TOKlparen:
3592 parens = FALSE;
3593 if (!isParameters(&t))
3594 return FALSE;
3595 continue;
3597 // Valid tokens that follow a declaration
3598 case TOKrparen:
3599 case TOKrbracket:
3600 case TOKassign:
3601 case TOKcomma:
3602 case TOKsemicolon:
3603 case TOKlcurly:
3604 case TOKin:
3605 // The !parens is to disallow unnecessary parentheses
3606 if (!parens && (endtok == TOKreserved || endtok == t->value))
3607 { *pt = t;
3608 return TRUE;
3610 return FALSE;
3612 default:
3613 return FALSE;
3619 int Parser::isParameters(Token **pt)
3620 { // This code parallels parseParameters()
3621 Token *t = *pt;
3622 int tmp;
3624 //printf("isParameters()\n");
3625 if (t->value != TOKlparen)
3626 return FALSE;
3628 t = peek(t);
3629 while (1)
3631 switch (t->value)
3633 case TOKrparen:
3634 break;
3636 case TOKdotdotdot:
3637 t = peek(t);
3638 break;
3640 case TOKin:
3641 case TOKout:
3642 case TOKinout:
3643 case TOKref:
3644 case TOKlazy:
3645 t = peek(t);
3646 default:
3647 if (!isBasicType(&t))
3648 return FALSE;
3649 tmp = FALSE;
3650 if (t->value != TOKdotdotdot &&
3651 !isDeclarator(&t, &tmp, TOKreserved))
3652 return FALSE;
3653 if (t->value == TOKassign)
3654 { t = peek(t);
3655 if (!isExpression(&t))
3656 return FALSE;
3658 if (t->value == TOKdotdotdot)
3660 t = peek(t);
3661 break;
3663 if (t->value == TOKcomma)
3664 { t = peek(t);
3665 continue;
3667 break;
3669 break;
3671 if (t->value != TOKrparen)
3672 return FALSE;
3673 t = peek(t);
3674 *pt = t;
3675 return TRUE;
3678 int Parser::isExpression(Token **pt)
3680 // This is supposed to determine if something is an expression.
3681 // What it actually does is scan until a closing right bracket
3682 // is found.
3684 Token *t = *pt;
3685 int brnest = 0;
3686 int panest = 0;
3688 for (;; t = peek(t))
3690 switch (t->value)
3692 case TOKlbracket:
3693 brnest++;
3694 continue;
3696 case TOKrbracket:
3697 if (--brnest >= 0)
3698 continue;
3699 break;
3701 case TOKlparen:
3702 panest++;
3703 continue;
3705 case TOKcomma:
3706 if (brnest || panest)
3707 continue;
3708 break;
3710 case TOKrparen:
3711 if (--panest >= 0)
3712 continue;
3713 break;
3715 case TOKslice:
3716 if (brnest)
3717 continue;
3718 break;
3720 case TOKeof:
3721 return FALSE;
3723 default:
3724 continue;
3726 break;
3729 *pt = t;
3730 return TRUE;
3733 /**********************************************
3734 * Skip over
3735 * instance foo.bar(parameters...)
3736 * Output:
3737 * if (pt), *pt is set to the token following the closing )
3738 * Returns:
3739 * 1 it's valid instance syntax
3740 * 0 invalid instance syntax
3743 int Parser::isTemplateInstance(Token *t, Token **pt)
3745 t = peek(t);
3746 if (t->value != TOKdot)
3748 if (t->value != TOKidentifier)
3749 goto Lfalse;
3750 t = peek(t);
3752 while (t->value == TOKdot)
3754 t = peek(t);
3755 if (t->value != TOKidentifier)
3756 goto Lfalse;
3757 t = peek(t);
3759 if (t->value != TOKlparen)
3760 goto Lfalse;
3762 // Skip over the template arguments
3763 while (1)
3765 while (1)
3767 t = peek(t);
3768 switch (t->value)
3770 case TOKlparen:
3771 if (!skipParens(t, &t))
3772 goto Lfalse;
3773 continue;
3774 case TOKrparen:
3775 break;
3776 case TOKcomma:
3777 break;
3778 case TOKeof:
3779 case TOKsemicolon:
3780 goto Lfalse;
3781 default:
3782 continue;
3784 break;
3787 if (t->value != TOKcomma)
3788 break;
3790 if (t->value != TOKrparen)
3791 goto Lfalse;
3792 t = peek(t);
3793 if (pt)
3794 *pt = t;
3795 return 1;
3797 Lfalse:
3798 return 0;
3801 /*******************************************
3802 * Skip parens, brackets.
3803 * Input:
3804 * t is on opening (
3805 * Output:
3806 * *pt is set to closing token, which is ')' on success
3807 * Returns:
3808 * !=0 successful
3809 * 0 some parsing error
3812 int Parser::skipParens(Token *t, Token **pt)
3814 int parens = 0;
3816 while (1)
3818 switch (t->value)
3820 case TOKlparen:
3821 parens++;
3822 break;
3824 case TOKrparen:
3825 parens--;
3826 if (parens < 0)
3827 goto Lfalse;
3828 if (parens == 0)
3829 goto Ldone;
3830 break;
3832 case TOKeof:
3833 case TOKsemicolon:
3834 goto Lfalse;
3836 default:
3837 break;
3839 t = peek(t);
3842 Ldone:
3843 if (*pt)
3844 *pt = t;
3845 return 1;
3847 Lfalse:
3848 return 0;
3851 /********************************* Expression Parser ***************************/
3853 Expression *Parser::parsePrimaryExp()
3854 { Expression *e;
3855 Type *t;
3856 Identifier *id;
3857 enum TOK save;
3858 Loc loc = this->loc;
3860 switch (token.value)
3862 case TOKidentifier:
3863 id = token.ident;
3864 nextToken();
3865 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
3866 { // identifier!(template-argument-list)
3867 TemplateInstance *tempinst;
3869 tempinst = new TemplateInstance(loc, id);
3870 nextToken();
3871 tempinst->tiargs = parseTemplateArgumentList();
3872 e = new ScopeExp(loc, tempinst);
3874 else
3875 e = new IdentifierExp(loc, id);
3876 break;
3878 case TOKdollar:
3879 if (!inBrackets)
3880 error("'$' is valid only inside [] of index or slice");
3881 e = new DollarExp(loc);
3882 nextToken();
3883 break;
3885 case TOKdot:
3886 // Signal global scope '.' operator with "" identifier
3887 e = new IdentifierExp(loc, Id::empty);
3888 break;
3890 case TOKthis:
3891 e = new ThisExp(loc);
3892 nextToken();
3893 break;
3895 case TOKsuper:
3896 e = new SuperExp(loc);
3897 nextToken();
3898 break;
3900 case TOKint32v:
3901 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
3902 nextToken();
3903 break;
3905 case TOKuns32v:
3906 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
3907 nextToken();
3908 break;
3910 case TOKint64v:
3911 e = new IntegerExp(loc, token.int64value, Type::tint64);
3912 nextToken();
3913 break;
3915 case TOKuns64v:
3916 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
3917 nextToken();
3918 break;
3920 case TOKfloat32v:
3921 e = new RealExp(loc, token.float80value, Type::tfloat32);
3922 nextToken();
3923 break;
3925 case TOKfloat64v:
3926 e = new RealExp(loc, token.float80value, Type::tfloat64);
3927 nextToken();
3928 break;
3930 case TOKfloat80v:
3931 e = new RealExp(loc, token.float80value, Type::tfloat80);
3932 nextToken();
3933 break;
3935 case TOKimaginary32v:
3936 e = new RealExp(loc, token.float80value, Type::timaginary32);
3937 nextToken();
3938 break;
3940 case TOKimaginary64v:
3941 e = new RealExp(loc, token.float80value, Type::timaginary64);
3942 nextToken();
3943 break;
3945 case TOKimaginary80v:
3946 e = new RealExp(loc, token.float80value, Type::timaginary80);
3947 nextToken();
3948 break;
3950 case TOKnull:
3951 e = new NullExp(loc);
3952 nextToken();
3953 break;
3955 case TOKtrue:
3956 e = new IntegerExp(loc, 1, Type::tbool);
3957 nextToken();
3958 break;
3960 case TOKfalse:
3961 e = new IntegerExp(loc, 0, Type::tbool);
3962 nextToken();
3963 break;
3965 case TOKcharv:
3966 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
3967 nextToken();
3968 break;
3970 case TOKwcharv:
3971 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
3972 nextToken();
3973 break;
3975 case TOKdcharv:
3976 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
3977 nextToken();
3978 break;
3980 case TOKstring:
3981 { unsigned char *s;
3982 unsigned len;
3983 unsigned char postfix;
3985 // cat adjacent strings
3986 s = token.ustring;
3987 len = token.len;
3988 postfix = token.postfix;
3989 while (1)
3991 nextToken();
3992 if (token.value == TOKstring)
3993 { unsigned len1;
3994 unsigned len2;
3995 unsigned char *s2;
3997 if (token.postfix)
3998 { if (token.postfix != postfix)
3999 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4000 postfix = token.postfix;
4003 len1 = len;
4004 len2 = token.len;
4005 len = len1 + len2;
4006 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4007 memcpy(s2, s, len1 * sizeof(unsigned char));
4008 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4009 s = s2;
4011 else
4012 break;
4014 e = new StringExp(loc, s, len, postfix);
4015 break;
4018 CASE_BASIC_TYPES_X(t):
4019 nextToken();
4021 check(TOKdot, t->toChars());
4022 if (token.value != TOKidentifier)
4023 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4024 goto Lerr;
4026 e = new TypeDotIdExp(loc, t, token.ident);
4027 nextToken();
4028 break;
4030 case TOKtypeof:
4031 { Expression *exp;
4033 nextToken();
4034 check(TOKlparen);
4035 exp = parseExpression();
4036 check(TOKrparen);
4037 t = new TypeTypeof(loc, exp);
4038 if (token.value == TOKdot)
4039 goto L1;
4040 e = new TypeExp(loc, t);
4041 break;
4044 case TOKtypeid:
4045 { Type *t;
4047 nextToken();
4048 check(TOKlparen, "typeid");
4049 t = parseBasicType();
4050 t = parseDeclarator(t,NULL); // ( type )
4051 check(TOKrparen);
4052 e = new TypeidExp(loc, t);
4053 break;
4056 case TOKis:
4057 { Type *targ;
4058 Identifier *ident = NULL;
4059 Type *tspec = NULL;
4060 enum TOK tok = TOKreserved;
4061 enum TOK tok2 = TOKreserved;
4062 Loc loc = this->loc;
4064 nextToken();
4065 if (token.value == TOKlparen)
4067 nextToken();
4068 targ = parseBasicType();
4069 targ = parseDeclarator(targ, &ident);
4070 if (token.value == TOKcolon || token.value == TOKequal)
4072 tok = token.value;
4073 nextToken();
4074 if (tok == TOKequal &&
4075 (token.value == TOKtypedef ||
4076 token.value == TOKstruct ||
4077 token.value == TOKunion ||
4078 token.value == TOKclass ||
4079 token.value == TOKsuper ||
4080 token.value == TOKenum ||
4081 token.value == TOKinterface ||
4082 token.value == TOKfunction ||
4083 token.value == TOKdelegate ||
4084 token.value == TOKreturn))
4086 tok2 = token.value;
4087 nextToken();
4089 else
4091 tspec = parseBasicType();
4092 tspec = parseDeclarator(tspec, NULL);
4095 check(TOKrparen);
4097 else
4098 { error("(type identifier : specialization) expected following is");
4099 goto Lerr;
4101 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4102 break;
4105 case TOKassert:
4106 { Expression *msg = NULL;
4108 nextToken();
4109 check(TOKlparen, "assert");
4110 e = parseAssignExp();
4111 if (token.value == TOKcomma)
4112 { nextToken();
4113 msg = parseAssignExp();
4115 check(TOKrparen);
4116 e = new AssertExp(loc, e, msg);
4117 break;
4120 case TOKmixin:
4122 nextToken();
4123 check(TOKlparen, "mixin");
4124 e = parseAssignExp();
4125 check(TOKrparen);
4126 e = new CompileExp(loc, e);
4127 break;
4130 case TOKimport:
4132 nextToken();
4133 check(TOKlparen, "import");
4134 e = parseAssignExp();
4135 check(TOKrparen);
4136 e = new FileExp(loc, e);
4137 break;
4140 case TOKlparen:
4141 if (peekPastParen(&token)->value == TOKlcurly)
4142 { // (arguments) { statements... }
4143 save = TOKdelegate;
4144 goto case_delegate;
4146 // ( expression )
4147 nextToken();
4148 e = parseExpression();
4149 check(loc, TOKrparen);
4150 break;
4152 case TOKlbracket:
4153 { /* Parse array literals and associative array literals:
4154 * [ value, value, value ... ]
4155 * [ key:value, key:value, key:value ... ]
4157 Expressions *values = new Expressions();
4158 Expressions *keys = NULL;
4160 nextToken();
4161 if (token.value != TOKrbracket)
4163 while (1)
4165 Expression *e = parseAssignExp();
4166 if (token.value == TOKcolon && (keys || values->dim == 0))
4167 { nextToken();
4168 if (!keys)
4169 keys = new Expressions();
4170 keys->push(e);
4171 e = parseAssignExp();
4173 else if (keys)
4174 { error("'key:value' expected for associative array literal");
4175 delete keys;
4176 keys = NULL;
4178 values->push(e);
4179 if (token.value == TOKrbracket)
4180 break;
4181 check(TOKcomma);
4184 check(TOKrbracket);
4186 if (keys)
4187 e = new AssocArrayLiteralExp(loc, keys, values);
4188 else
4189 e = new ArrayLiteralExp(loc, values);
4190 break;
4193 case TOKlcurly:
4194 // { statements... }
4195 save = TOKdelegate;
4196 goto case_delegate;
4198 case TOKfunction:
4199 case TOKdelegate:
4200 save = token.value;
4201 nextToken();
4202 case_delegate:
4204 /* function type(parameters) { body }
4205 * delegate type(parameters) { body }
4207 Arguments *arguments;
4208 int varargs;
4209 FuncLiteralDeclaration *fd;
4210 Type *t;
4212 if (token.value == TOKlcurly)
4214 t = NULL;
4215 varargs = 0;
4216 arguments = new Arguments();
4218 else
4220 if (token.value == TOKlparen)
4221 t = NULL;
4222 else
4224 t = parseBasicType();
4225 t = parseBasicType2(t); // function return type
4227 arguments = parseParameters(&varargs);
4229 t = new TypeFunction(arguments, t, varargs, linkage);
4230 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4231 parseContracts(fd);
4232 e = new FuncExp(loc, fd);
4233 break;
4236 default:
4237 error("expression expected, not '%s'", token.toChars());
4238 Lerr:
4239 // Anything for e, as long as it's not NULL
4240 e = new IntegerExp(loc, 0, Type::tint32);
4241 nextToken();
4242 break;
4244 return parsePostExp(e);
4247 Expression *Parser::parsePostExp(Expression *e)
4249 Loc loc;
4251 while (1)
4253 loc = this->loc;
4254 switch (token.value)
4256 case TOKdot:
4257 nextToken();
4258 if (token.value == TOKidentifier)
4259 { Identifier *id = token.ident;
4261 nextToken();
4262 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4263 { // identifier!(template-argument-list)
4264 TemplateInstance *tempinst;
4266 tempinst = new TemplateInstance(loc, id);
4267 nextToken();
4268 tempinst->tiargs = parseTemplateArgumentList();
4269 e = new DotTemplateInstanceExp(loc, e, tempinst);
4271 else
4272 e = new DotIdExp(loc, e, id);
4273 continue;
4275 else if (token.value == TOKnew)
4277 e = parseNewExp(e);
4278 continue;
4280 else
4281 error("identifier expected following '.', not '%s'", token.toChars());
4282 break;
4284 case TOKplusplus:
4285 e = new PostExp(TOKplusplus, loc, e);
4286 break;
4288 case TOKminusminus:
4289 e = new PostExp(TOKminusminus, loc, e);
4290 break;
4292 case TOKlparen:
4293 e = new CallExp(loc, e, parseArguments());
4294 continue;
4296 case TOKlbracket:
4297 { // array dereferences:
4298 // array[index]
4299 // array[]
4300 // array[lwr .. upr]
4301 Expression *index;
4302 Expression *upr;
4304 inBrackets++;
4305 nextToken();
4306 if (token.value == TOKrbracket)
4307 { // array[]
4308 e = new SliceExp(loc, e, NULL, NULL);
4309 nextToken();
4311 else
4313 index = parseAssignExp();
4314 if (token.value == TOKslice)
4315 { // array[lwr .. upr]
4316 nextToken();
4317 upr = parseAssignExp();
4318 e = new SliceExp(loc, e, index, upr);
4320 else
4321 { // array[index, i2, i3, i4, ...]
4322 Expressions *arguments = new Expressions();
4323 arguments->push(index);
4324 if (token.value == TOKcomma)
4326 nextToken();
4327 while (1)
4328 { Expression *arg;
4330 arg = parseAssignExp();
4331 arguments->push(arg);
4332 if (token.value == TOKrbracket)
4333 break;
4334 check(TOKcomma);
4337 e = new ArrayExp(loc, e, arguments);
4339 check(TOKrbracket);
4340 inBrackets--;
4342 continue;
4345 default:
4346 return e;
4348 nextToken();
4352 Expression *Parser::parseUnaryExp()
4353 { Expression *e;
4354 Loc loc = this->loc;
4356 switch (token.value)
4358 case TOKand:
4359 nextToken();
4360 e = parseUnaryExp();
4361 e = new AddrExp(loc, e);
4362 break;
4364 case TOKplusplus:
4365 nextToken();
4366 e = parseUnaryExp();
4367 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4368 break;
4370 case TOKminusminus:
4371 nextToken();
4372 e = parseUnaryExp();
4373 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4374 break;
4376 case TOKmul:
4377 nextToken();
4378 e = parseUnaryExp();
4379 e = new PtrExp(loc, e);
4380 break;
4382 case TOKmin:
4383 nextToken();
4384 e = parseUnaryExp();
4385 e = new NegExp(loc, e);
4386 break;
4388 case TOKadd:
4389 nextToken();
4390 e = parseUnaryExp();
4391 e = new UAddExp(loc, e);
4392 break;
4394 case TOKnot:
4395 nextToken();
4396 e = parseUnaryExp();
4397 e = new NotExp(loc, e);
4398 break;
4400 case TOKtilde:
4401 nextToken();
4402 e = parseUnaryExp();
4403 e = new ComExp(loc, e);
4404 break;
4406 case TOKdelete:
4407 nextToken();
4408 e = parseUnaryExp();
4409 e = new DeleteExp(loc, e);
4410 break;
4412 case TOKnew:
4413 e = parseNewExp(NULL);
4414 break;
4416 case TOKcast: // cast(type) expression
4417 { Type *t;
4419 nextToken();
4420 check(TOKlparen);
4421 t = parseBasicType();
4422 t = parseDeclarator(t,NULL); // ( type )
4423 check(TOKrparen);
4425 e = parseUnaryExp();
4426 e = new CastExp(loc, e, t);
4427 break;
4430 case TOKlparen:
4431 { Token *tk;
4433 tk = peek(&token);
4434 #if CCASTSYNTAX
4435 // If cast
4436 if (isDeclaration(tk, 0, TOKrparen, &tk))
4438 tk = peek(tk); // skip over right parenthesis
4439 switch (tk->value)
4441 case TOKdot:
4442 case TOKplusplus:
4443 case TOKminusminus:
4444 case TOKnot:
4445 case TOKdelete:
4446 case TOKnew:
4447 case TOKlparen:
4448 case TOKidentifier:
4449 case TOKthis:
4450 case TOKsuper:
4451 case TOKint32v:
4452 case TOKuns32v:
4453 case TOKint64v:
4454 case TOKuns64v:
4455 case TOKfloat32v:
4456 case TOKfloat64v:
4457 case TOKfloat80v:
4458 case TOKimaginary32v:
4459 case TOKimaginary64v:
4460 case TOKimaginary80v:
4461 case TOKnull:
4462 case TOKtrue:
4463 case TOKfalse:
4464 case TOKcharv:
4465 case TOKwcharv:
4466 case TOKdcharv:
4467 case TOKstring:
4468 #if 0
4469 case TOKtilde:
4470 case TOKand:
4471 case TOKmul:
4472 case TOKmin:
4473 case TOKadd:
4474 #endif
4475 case TOKfunction:
4476 case TOKdelegate:
4477 case TOKtypeof:
4478 CASE_BASIC_TYPES: // (type)int.size
4479 { // (type) una_exp
4480 Type *t;
4482 nextToken();
4483 t = parseBasicType();
4484 t = parseDeclarator(t,NULL);
4485 check(TOKrparen);
4487 // if .identifier
4488 if (token.value == TOKdot)
4490 nextToken();
4491 if (token.value != TOKidentifier)
4492 { error("Identifier expected following (type).");
4493 return NULL;
4495 e = new TypeDotIdExp(loc, t, token.ident);
4496 nextToken();
4497 e = parsePostExp(e);
4499 else
4501 e = parseUnaryExp();
4502 e = new CastExp(loc, e, t);
4503 error("C style cast illegal, use %s", e->toChars());
4505 return e;
4509 #endif
4510 e = parsePrimaryExp();
4511 break;
4513 default:
4514 e = parsePrimaryExp();
4515 break;
4517 assert(e);
4518 return e;
4521 Expression *Parser::parseMulExp()
4522 { Expression *e;
4523 Expression *e2;
4524 Loc loc = this->loc;
4526 e = parseUnaryExp();
4527 while (1)
4529 switch (token.value)
4531 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4532 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4533 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4535 default:
4536 break;
4538 break;
4540 return e;
4543 Expression *Parser::parseAddExp()
4544 { Expression *e;
4545 Expression *e2;
4546 Loc loc = this->loc;
4548 e = parseMulExp();
4549 while (1)
4551 switch (token.value)
4553 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4554 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4555 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4557 default:
4558 break;
4560 break;
4562 return e;
4565 Expression *Parser::parseShiftExp()
4566 { Expression *e;
4567 Expression *e2;
4568 Loc loc = this->loc;
4570 e = parseAddExp();
4571 while (1)
4573 switch (token.value)
4575 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4576 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4577 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4579 default:
4580 break;
4582 break;
4584 return e;
4587 Expression *Parser::parseRelExp()
4588 { Expression *e;
4589 Expression *e2;
4590 enum TOK op;
4591 Loc loc = this->loc;
4593 e = parseShiftExp();
4594 while (1)
4596 switch (token.value)
4598 case TOKlt:
4599 case TOKle:
4600 case TOKgt:
4601 case TOKge:
4602 case TOKunord:
4603 case TOKlg:
4604 case TOKleg:
4605 case TOKule:
4606 case TOKul:
4607 case TOKuge:
4608 case TOKug:
4609 case TOKue:
4610 op = token.value;
4611 nextToken();
4612 e2 = parseShiftExp();
4613 e = new CmpExp(op, loc, e, e2);
4614 continue;
4616 case TOKin:
4617 nextToken();
4618 e2 = parseShiftExp();
4619 e = new InExp(loc, e, e2);
4620 continue;
4622 default:
4623 break;
4625 break;
4627 return e;
4630 Expression *Parser::parseEqualExp()
4631 { Expression *e;
4632 Expression *e2;
4633 Token *t;
4634 Loc loc = this->loc;
4636 e = parseRelExp();
4637 while (1)
4638 { enum TOK value = token.value;
4640 switch (value)
4642 case TOKequal:
4643 case TOKnotequal:
4644 nextToken();
4645 e2 = parseRelExp();
4646 e = new EqualExp(value, loc, e, e2);
4647 continue;
4649 case TOKidentity:
4650 error("'===' is no longer legal, use 'is' instead");
4651 goto L1;
4653 case TOKnotidentity:
4654 error("'!==' is no longer legal, use '!is' instead");
4655 goto L1;
4657 case TOKis:
4658 value = TOKidentity;
4659 goto L1;
4661 case TOKnot:
4662 // Attempt to identify '!is'
4663 t = peek(&token);
4664 if (t->value != TOKis)
4665 break;
4666 nextToken();
4667 value = TOKnotidentity;
4668 goto L1;
4671 nextToken();
4672 e2 = parseRelExp();
4673 e = new IdentityExp(value, loc, e, e2);
4674 continue;
4676 default:
4677 break;
4679 break;
4681 return e;
4684 Expression *Parser::parseCmpExp()
4685 { Expression *e;
4686 Expression *e2;
4687 Token *t;
4688 Loc loc = this->loc;
4690 e = parseShiftExp();
4691 enum TOK op = token.value;
4693 switch (op)
4695 case TOKequal:
4696 case TOKnotequal:
4697 nextToken();
4698 e2 = parseShiftExp();
4699 e = new EqualExp(op, loc, e, e2);
4700 break;
4702 case TOKis:
4703 op = TOKidentity;
4704 goto L1;
4706 case TOKnot:
4707 // Attempt to identify '!is'
4708 t = peek(&token);
4709 if (t->value != TOKis)
4710 break;
4711 nextToken();
4712 op = TOKnotidentity;
4713 goto L1;
4716 nextToken();
4717 e2 = parseShiftExp();
4718 e = new IdentityExp(op, loc, e, e2);
4719 break;
4721 case TOKlt:
4722 case TOKle:
4723 case TOKgt:
4724 case TOKge:
4725 case TOKunord:
4726 case TOKlg:
4727 case TOKleg:
4728 case TOKule:
4729 case TOKul:
4730 case TOKuge:
4731 case TOKug:
4732 case TOKue:
4733 nextToken();
4734 e2 = parseShiftExp();
4735 e = new CmpExp(op, loc, e, e2);
4736 break;
4738 case TOKin:
4739 nextToken();
4740 e2 = parseShiftExp();
4741 e = new InExp(loc, e, e2);
4742 break;
4744 default:
4745 break;
4747 return e;
4750 Expression *Parser::parseAndExp()
4751 { Expression *e;
4752 Expression *e2;
4753 Loc loc = this->loc;
4755 if (global.params.Dversion == 1)
4757 e = parseEqualExp();
4758 while (token.value == TOKand)
4760 nextToken();
4761 e2 = parseEqualExp();
4762 e = new AndExp(loc,e,e2);
4763 loc = this->loc;
4766 else
4768 e = parseCmpExp();
4769 while (token.value == TOKand)
4771 nextToken();
4772 e2 = parseCmpExp();
4773 e = new AndExp(loc,e,e2);
4774 loc = this->loc;
4777 return e;
4780 Expression *Parser::parseXorExp()
4781 { Expression *e;
4782 Expression *e2;
4783 Loc loc = this->loc;
4785 e = parseAndExp();
4786 while (token.value == TOKxor)
4788 nextToken();
4789 e2 = parseAndExp();
4790 e = new XorExp(loc, e, e2);
4792 return e;
4795 Expression *Parser::parseOrExp()
4796 { Expression *e;
4797 Expression *e2;
4798 Loc loc = this->loc;
4800 e = parseXorExp();
4801 while (token.value == TOKor)
4803 nextToken();
4804 e2 = parseXorExp();
4805 e = new OrExp(loc, e, e2);
4807 return e;
4810 Expression *Parser::parseAndAndExp()
4811 { Expression *e;
4812 Expression *e2;
4813 Loc loc = this->loc;
4815 e = parseOrExp();
4816 while (token.value == TOKandand)
4818 nextToken();
4819 e2 = parseOrExp();
4820 e = new AndAndExp(loc, e, e2);
4822 return e;
4825 Expression *Parser::parseOrOrExp()
4826 { Expression *e;
4827 Expression *e2;
4828 Loc loc = this->loc;
4830 e = parseAndAndExp();
4831 while (token.value == TOKoror)
4833 nextToken();
4834 e2 = parseAndAndExp();
4835 e = new OrOrExp(loc, e, e2);
4837 return e;
4840 Expression *Parser::parseCondExp()
4841 { Expression *e;
4842 Expression *e1;
4843 Expression *e2;
4844 Loc loc = this->loc;
4846 e = parseOrOrExp();
4847 if (token.value == TOKquestion)
4849 nextToken();
4850 e1 = parseExpression();
4851 check(TOKcolon);
4852 e2 = parseCondExp();
4853 e = new CondExp(loc, e, e1, e2);
4855 return e;
4858 Expression *Parser::parseAssignExp()
4859 { Expression *e;
4860 Expression *e2;
4861 Loc loc;
4863 e = parseCondExp();
4864 while (1)
4866 loc = this->loc;
4867 switch (token.value)
4869 #define X(tok,ector) \
4870 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
4872 X(TOKassign, AssignExp);
4873 X(TOKaddass, AddAssignExp);
4874 X(TOKminass, MinAssignExp);
4875 X(TOKmulass, MulAssignExp);
4876 X(TOKdivass, DivAssignExp);
4877 X(TOKmodass, ModAssignExp);
4878 X(TOKandass, AndAssignExp);
4879 X(TOKorass, OrAssignExp);
4880 X(TOKxorass, XorAssignExp);
4881 X(TOKshlass, ShlAssignExp);
4882 X(TOKshrass, ShrAssignExp);
4883 X(TOKushrass, UshrAssignExp);
4884 X(TOKcatass, CatAssignExp);
4886 #undef X
4887 default:
4888 break;
4890 break;
4892 return e;
4895 Expression *Parser::parseExpression()
4896 { Expression *e;
4897 Expression *e2;
4898 Loc loc = this->loc;
4900 //printf("Parser::parseExpression()\n");
4901 e = parseAssignExp();
4902 while (token.value == TOKcomma)
4904 nextToken();
4905 e2 = parseAssignExp();
4906 e = new CommaExp(loc, e, e2);
4907 loc = this->loc;
4909 return e;
4913 /*************************
4914 * Collect argument list.
4915 * Assume current token is '(' or '['.
4918 Expressions *Parser::parseArguments()
4919 { // function call
4920 Expressions *arguments;
4921 Expression *arg;
4922 enum TOK endtok;
4924 arguments = new Expressions();
4925 if (token.value == TOKlbracket)
4926 endtok = TOKrbracket;
4927 else
4928 endtok = TOKrparen;
4931 nextToken();
4932 if (token.value != endtok)
4934 while (1)
4936 arg = parseAssignExp();
4937 arguments->push(arg);
4938 if (token.value == endtok)
4939 break;
4940 check(TOKcomma);
4943 check(endtok);
4945 return arguments;
4948 /*******************************************
4951 Expression *Parser::parseNewExp(Expression *thisexp)
4952 { Type *t;
4953 Expressions *newargs;
4954 Expressions *arguments = NULL;
4955 Expression *e;
4956 Loc loc = this->loc;
4958 nextToken();
4959 newargs = NULL;
4960 if (token.value == TOKlparen)
4962 newargs = parseArguments();
4965 // An anonymous nested class starts with "class"
4966 if (token.value == TOKclass)
4968 nextToken();
4969 if (token.value == TOKlparen)
4970 arguments = parseArguments();
4972 BaseClasses *baseclasses = NULL;
4973 if (token.value != TOKlcurly)
4974 baseclasses = parseBaseClasses();
4976 Identifier *id = NULL;
4977 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
4979 if (token.value != TOKlcurly)
4980 { error("{ members } expected for anonymous class");
4981 cd->members = NULL;
4983 else
4985 nextToken();
4986 Array *decl = parseDeclDefs(0);
4987 if (token.value != TOKrcurly)
4988 error("class member expected");
4989 nextToken();
4990 cd->members = decl;
4993 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
4995 return e;
4998 #if LTORARRAYDECL
4999 t = parseBasicType();
5000 t = parseBasicType2(t);
5001 if (t->ty == Taarray)
5003 Type *index = ((TypeAArray *)t)->index;
5005 Expression *e = index->toExpression();
5006 if (e)
5007 { arguments = new Expressions();
5008 arguments->push(e);
5009 t = new TypeDArray(t->next);
5011 else
5013 error("need size of rightmost array, not type %s", index->toChars());
5014 return new NullExp(loc);
5017 else if (t->ty == Tsarray)
5019 TypeSArray *tsa = (TypeSArray *)t;
5020 Expression *e = tsa->dim;
5022 arguments = new Expressions();
5023 arguments->push(e);
5024 t = new TypeDArray(t->next);
5026 else if (token.value == TOKlparen)
5028 arguments = parseArguments();
5030 #else
5031 t = parseBasicType();
5032 while (token.value == TOKmul)
5033 { t = new TypePointer(t);
5034 nextToken();
5036 if (token.value == TOKlbracket)
5038 Expression *e;
5040 nextToken();
5041 e = parseAssignExp();
5042 arguments = new Array();
5043 arguments->push(e);
5044 check(TOKrbracket);
5045 t = parseDeclarator(t, NULL);
5046 t = new TypeDArray(t);
5048 else if (token.value == TOKlparen)
5049 arguments = parseArguments();
5050 #endif
5051 e = new NewExp(loc, thisexp, newargs, t, arguments);
5052 return e;
5055 /**********************************************
5058 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5060 s->addComment(combineComments(blockComment, token.lineComment));
5064 /********************************* ***************************/