Added Delight "normal" mode restrictions
[delight/core.git] / dmd / parse.c
blob5d64fbe8a69da0b695bc6c96cdf3d8d08bc734ed
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
17 #include <stdio.h>
18 #include <assert.h>
20 #include "mem.h"
21 #include "lexer.h"
22 #include "parse.h"
23 #include "init.h"
24 #include "attrib.h"
25 #include "cond.h"
26 #include "mtype.h"
27 #include "template.h"
28 #include "staticassert.h"
29 #include "expression.h"
30 #include "statement.h"
31 #include "module.h"
32 #include "dsymbol.h"
33 #include "import.h"
34 #include "declaration.h"
35 #include "aggregate.h"
36 #include "enum.h"
37 #include "id.h"
38 #include "version.h"
39 #ifdef IN_GCC
40 #include "d-dmd-gcc.h"
41 #endif
43 // How multiple declarations are parsed.
44 // If 1, treat as C.
45 // If 0, treat:
46 // int *p, i;
47 // as:
48 // int* p;
49 // int* i;
50 #define CDECLSYNTAX 0
52 // Support C cast syntax:
53 // (type)(expression)
54 #define CCASTSYNTAX 1
56 // Support C array declarations, such as
57 // int a[3][4];
58 #define CARRAYDECL 1
60 // Support left-to-right array declarations
61 #define LTORARRAYDECL 1
64 Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
65 : Lexer(module, base, 0, length, doDocComment, 0, module->isDltFile)
67 //printf("Parser::Parser()\n");
68 md = NULL;
69 linkage = LINKd;
70 dltNormalMode = FALSE;
71 endloc = 0;
72 inBrackets = 0;
73 startBlockTok = TOKlcurly;
74 //nextToken(); // start up the scanner
77 DltParser::DltParser(Module *module, unsigned char *base, unsigned length, int doDocComment)
78 : Parser(module, base, length, doDocComment)
80 //printf("DltParser::DltParser(%s)\n", module->ident->string);
81 startBlockTok = TOKcolon;
82 dltNormalMode = TRUE; // becomes false if we find a "module dlt.*"
85 Array *Parser::parseModule()
87 Array *decldefs;
89 // ModuleDeclation leads off
90 optionalEndline();
91 if (token.value == TOKmodule)
93 unsigned char *comment = token.blockComment;
95 nextToken();
96 if (token.value != TOKidentifier)
97 { error("Identifier expected following module");
98 goto Lerr;
100 else
102 Array *a = NULL;
103 Identifier *id;
105 id = token.ident;
107 if (dltSyntax && id == Id::dlt)
108 dltNormalMode = FALSE;
110 while (nextToken() == TOKdot)
112 if (!a)
113 a = new Array();
114 a->push(id);
115 nextToken();
116 if (token.value != TOKidentifier)
117 { error("Identifier expected following package");
118 goto Lerr;
120 id = token.ident;
123 md = new ModuleDeclaration(a, id);
125 TOK end = dltSyntax ? TOKendline : TOKsemicolon;
126 if (token.value != end)
127 error("%s expected following module declaration instead of %s", Token::toChars(end), token.toChars());
129 nextToken();
130 addComment(mod, comment);
134 decldefs = parseDeclDefs(0);
135 if (token.value != TOKeof)
136 { error("unrecognized declaration '%s'", token.toChars());
137 goto Lerr;
140 if (dltNormalMode)
142 // Check for global variables
143 for (int i = 0; i < decldefs->dim; i++)
145 Dsymbol *d = (Dsymbol *) decldefs->data[i];
146 if (d->isVarDeclaration()) {
147 error("no global variables (%s) allowed in Delight; "
148 "try const, or put it in a class", d->toChars());
153 return decldefs;
155 Lerr:
156 while (token.value != TOKsemicolon && token.value != TOKeof)
157 nextToken();
158 nextToken();
159 return new Array();
162 Array *Parser::parseDeclDefs(int once)
163 { Dsymbol *s;
164 Array *decldefs;
165 Array *a;
166 Array *aelse;
167 enum PROT prot;
168 unsigned stc;
169 Condition *condition;
170 unsigned char *comment;
172 //printf("Parser::parseDeclDefs()\n");
173 decldefs = new Array();
176 comment = token.blockComment;
177 switch (token.value)
179 case TOKendline:
180 nextToken();
181 continue;
182 case TOKenum:
183 s = parseEnum();
184 break;
186 case TOKstruct:
187 case TOKunion:
188 case TOKclass:
189 case TOKinterface:
190 s = parseAggregate();
191 break;
193 case TOKimport:
194 s = parseImport(decldefs, 0);
195 break;
197 case TOKtemplate:
198 s = (Dsymbol *)parseTemplateDeclaration();
199 break;
201 case TOKmixin:
202 { Loc loc = this->loc;
203 if (peek(&token)->value == TOKlparen)
204 { // mixin(string)
205 nextToken();
206 check(TOKlparen, "mixin");
207 Expression *e = parseAssignExp();
208 check(TOKrparen);
209 check(TOKsemicolon);
210 s = new CompileDeclaration(loc, e);
211 break;
213 s = parseMixin();
214 break;
217 CASE_BASIC_TYPES:
218 case TOKalias:
219 case TOKtypedef:
220 case TOKidentifier:
221 case TOKtypeof:
222 case TOKdot:
223 Ldeclaration:
224 a = parseDeclarations();
225 decldefs->append(a);
226 continue;
228 case TOKthis:
229 s = parseCtor();
230 break;
232 case TOKtilde:
233 s = parseDtor();
234 break;
236 case TOKinvariant:
237 #if 1
238 s = parseInvariant();
239 #else
240 if (peek(&token)->value == TOKlcurly)
241 s = parseInvariant();
242 else
244 stc = STCinvariant;
245 goto Lstc;
247 #endif
248 break;
250 case TOKunittest:
251 s = parseUnitTest();
252 break;
254 case TOKnew:
255 s = parseNew();
256 break;
258 case TOKdelete:
259 s = parseDelete();
260 break;
262 case TOKeof:
263 case TOKrcurly:
264 return decldefs;
266 case TOKstatic:
267 nextToken();
268 if (token.value == TOKthis)
270 s = parseStaticCtor();
271 if (dltNormalMode)
272 error("no static constructors in Delight");
274 else if (token.value == TOKtilde)
276 s = parseStaticDtor();
277 if (dltNormalMode)
278 error("no static destructors in Delight");
280 else if (token.value == TOKassert)
281 s = parseStaticAssert();
282 else if (token.value == TOKif)
283 { condition = parseStaticIfCondition();
284 a = parseBlock();
285 aelse = NULL;
286 if (token.value == TOKelse)
287 { nextToken();
288 aelse = parseBlock();
290 s = new StaticIfDeclaration(condition, a, aelse);
291 break;
293 else if (token.value == TOKimport)
295 s = parseImport(decldefs, 1);
297 else
298 { stc = STCstatic;
299 if (dltNormalMode)
300 error("no static variables in Delight");
301 goto Lstc2;
303 break;
305 case TOKin:
306 nextToken();
307 stc = STCin;
308 goto Lstc2;
310 case TOKconst: stc = STCconst; goto Lstc;
311 case TOKfinal: stc = STCfinal; goto Lstc;
312 case TOKauto: stc = STCauto; goto Lstc;
313 case TOKscope: stc = STCscope; goto Lstc;
314 case TOKoverride: stc = STCoverride; goto Lstc;
315 case TOKabstract: stc = STCabstract; goto Lstc;
316 case TOKsynchronized: stc = STCsynchronized; goto Lstc;
317 case TOKdeprecated: stc = STCdeprecated; goto Lstc;
319 Lstc:
320 nextToken();
321 Lstc2:
322 switch (token.value)
324 case TOKconst: stc |= STCconst; goto Lstc;
325 case TOKfinal: stc |= STCfinal; goto Lstc;
326 case TOKauto: stc |= STCauto; goto Lstc;
327 case TOKscope: stc |= STCscope; goto Lstc;
328 case TOKoverride: stc |= STCoverride; goto Lstc;
329 case TOKabstract: stc |= STCabstract; goto Lstc;
330 case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
331 case TOKdeprecated: stc |= STCdeprecated; goto Lstc;
332 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
333 default:
334 break;
337 /* Look for auto initializers:
338 * storage_class identifier = initializer;
340 if (token.value == TOKidentifier &&
341 peek(&token)->value == TOKassign)
343 while (1)
345 Identifier *ident = token.ident;
346 nextToken();
347 nextToken();
348 Initializer *init = parseInitializer();
349 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
350 v->storage_class = stc;
351 s = v;
352 if (token.value == TOKsemicolon || token.value == TOKendline)
354 nextToken();
356 else if (token.value == TOKcomma)
358 nextToken();
359 if (token.value == TOKidentifier &&
360 peek(&token)->value == TOKassign)
362 decldefs->push(s);
363 addComment(s, comment);
364 continue;
366 else
367 error("Identifier expected following comma");
369 else
370 error("%s expected following declaration, not '%s'", endToken(), token.toChars());
371 break;
374 else
375 { a = parseBlock();
376 s = new StorageClassDeclaration(stc, a);
378 break;
380 case TOKextern:
381 if (peek(&token)->value != TOKlparen)
382 { stc = STCextern;
383 goto Lstc;
386 enum LINK linksave = linkage;
387 linkage = parseLinkage();
388 a = parseBlock();
389 s = new LinkDeclaration(linkage, a);
390 linkage = linksave;
392 if (dltNormalMode)
393 error("access to external symbols can be done only by dlt.* modules");
394 break;
396 case TOKprivate: prot = PROTprivate; goto Lprot;
397 case TOKpackage: prot = PROTpackage; goto Lprot;
398 case TOKprotected: prot = PROTprotected; goto Lprot;
399 case TOKpublic: prot = PROTpublic; goto Lprot;
400 case TOKexport: prot = PROTexport; goto Lprot;
402 Lprot:
403 nextToken();
404 a = parseBlock();
405 s = new ProtDeclaration(prot, a);
406 break;
408 case TOKalign:
409 { unsigned n;
411 s = NULL;
412 nextToken();
413 if (token.value == TOKlparen)
415 nextToken();
416 if (token.value == TOKint32v)
417 n = (unsigned)token.uns64value;
418 else
419 { error("integer expected, not %s", token.toChars());
420 n = 1;
422 nextToken();
423 check(TOKrparen);
425 else
426 n = global.structalign; // default
428 a = parseBlock();
429 s = new AlignDeclaration(n, a);
430 break;
433 case TOKpragma:
434 { Identifier *ident;
435 Expressions *args = NULL;
437 nextToken();
438 check(TOKlparen);
439 if (token.value != TOKidentifier)
440 { error("pragma(identifier expected");
441 goto Lerror;
443 ident = token.ident;
444 nextToken();
445 if (token.value == TOKcomma)
446 args = parseArguments(); // pragma(identifier, args...)
447 else
448 check(TOKrparen); // pragma(identifier)
450 if (token.value == TOKsemicolon || token.value == TOKendline)
451 a = NULL;
452 else if (dltSyntax)
454 check(TOKcolon);
455 a = parseDeclDefs(0);
456 check(TOKrcurly);
458 else
459 a = parseBlock();
460 s = new PragmaDeclaration(loc, ident, args, a);
461 break;
464 case TOKdebug:
465 nextToken();
466 if (token.value == TOKassign)
468 nextToken();
469 if (token.value == TOKidentifier)
470 s = new DebugSymbol(loc, token.ident);
471 else if (token.value == TOKint32v)
472 s = new DebugSymbol(loc, (unsigned)token.uns64value);
473 else
474 { error("identifier or integer expected, not %s", token.toChars());
475 s = NULL;
477 nextToken();
478 if (token.value != TOKsemicolon)
479 error("semicolon expected");
480 nextToken();
481 break;
484 condition = parseDebugCondition();
485 goto Lcondition;
487 case TOKversion:
488 nextToken();
489 if (token.value == TOKassign)
491 nextToken();
492 if (token.value == TOKidentifier)
493 s = new VersionSymbol(loc, token.ident);
494 else if (token.value == TOKint32v)
495 s = new VersionSymbol(loc, (unsigned)token.uns64value);
496 else
497 { error("identifier or integer expected, not %s", token.toChars());
498 s = NULL;
500 nextToken();
501 if (token.value != TOKsemicolon && token.value != TOKendline)
502 error("%s expected after version assignment", endToken());
503 nextToken();
504 break;
506 condition = parseVersionCondition();
507 goto Lcondition;
509 Lcondition:
510 a = parseBlock();
511 aelse = NULL;
512 if (token.value == TOKelse)
513 { nextToken();
514 aelse = parseBlock();
516 s = new ConditionalDeclaration(condition, a, aelse);
517 break;
519 case TOKsemicolon: // empty declaration
520 nextToken();
521 continue;
523 default:
524 error("Declaration expected, not '%s'",token.toChars());
525 Lerror:
526 while (token.value != TOKsemicolon && token.value != TOKendline && token.value != TOKeof)
527 nextToken();
528 nextToken();
529 s = NULL;
530 continue;
532 if (s)
533 { decldefs->push(s);
534 addComment(s, comment);
536 } while (!once);
537 return decldefs;
541 /********************************************
542 * Parse declarations after an align, protection, or extern decl.
545 Array *Parser::parseBlock()
547 Array *a = NULL;
548 Dsymbol *s;
550 //printf("Parser::parseBlock()\n");
551 switch (token.value)
553 case TOKsemicolon:
554 error("declaration expected following attribute, not ';'");
555 nextToken();
556 break;
558 case TOKlcurly:
559 nextToken();
560 a = parseDeclDefs(0);
561 if (token.value != TOKrcurly)
562 { /* { */
563 error("matching '}' expected, not %s", token.toChars());
565 else
566 nextToken();
567 break;
569 case TOKcolon:
570 nextToken();
571 #if 0
572 a = NULL;
573 #else
574 a = parseDeclDefs(0); // grab declarations up to closing curly bracket
575 #endif
576 break;
578 default:
579 a = parseDeclDefs(1);
580 break;
582 return a;
585 Array *DltParser::parseBlock()
587 Array *a = NULL;
588 Dsymbol *s;
590 optionalEndline();
591 switch (token.value)
593 case TOKendline:
594 case TOKsemicolon:
595 error("declaration expected following attribute, not %s", token.toChars());
596 nextToken();
597 break;
599 case TOKcolon:
600 nextToken();
601 a = parseDeclDefs(0);
602 if (token.value != TOKrcurly)
604 error("matching end-of-block expected, not %s", token.toChars());
606 else
607 nextToken();
608 break;
610 default:
611 a = parseDeclDefs(1);
612 break;
614 return a;
617 /**********************************
618 * Parse a static assertion.
621 StaticAssert *Parser::parseStaticAssert()
623 Loc loc = this->loc;
624 Expression *exp;
625 Expression *msg = NULL;
627 //printf("parseStaticAssert()\n");
628 nextToken();
629 checkLParen();
630 exp = parseAssignExp();
631 if (token.value == TOKcomma)
632 { nextToken();
633 msg = parseAssignExp();
635 checkRParen();
636 if (token.value == TOKsemicolon || token.value == TOKendline) {
637 nextToken();
638 return new StaticAssert(loc, exp, msg);
640 error("expected %s after static assert", endToken());
644 /***********************************
645 * Parse extern (linkage)
646 * The parser is on the 'extern' token.
649 enum LINK Parser::parseLinkage()
651 enum LINK link = LINKdefault;
652 nextToken();
653 assert(token.value == TOKlparen);
654 nextToken();
655 if (token.value == TOKidentifier)
656 { Identifier *id = token.ident;
658 nextToken();
659 if (id == Id::Windows)
660 link = LINKwindows;
661 else if (id == Id::Pascal)
662 link = LINKpascal;
663 else if (id == Id::D)
664 link = LINKd;
665 else if (id == Id::C)
667 link = LINKc;
668 if (token.value == TOKplusplus)
669 { link = LINKcpp;
670 nextToken();
673 else if (id == Id::System)
675 #ifdef IN_GCC
676 link = d_gcc_is_target_win32() ? LINKwindows : LINKc;
677 #else
678 #if _WIN32
679 link = LINKwindows;
680 #else
681 link = LINKc;
682 #endif
683 #endif
685 else
687 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
688 link = LINKd;
691 else
693 link = LINKd; // default
695 check(TOKrparen);
696 return link;
699 /**************************************
700 * Parse a debug conditional
703 Condition *Parser::parseDebugCondition()
705 Condition *c;
707 if (token.value == TOKlparen)
709 nextToken();
710 unsigned level = 1;
711 Identifier *id = NULL;
713 if (token.value == TOKidentifier)
714 id = token.ident;
715 else if (token.value == TOKint32v)
716 level = (unsigned)token.uns64value;
717 else
718 error("identifier or integer expected, not %s", token.toChars());
719 nextToken();
720 check(TOKrparen);
721 c = new DebugCondition(mod, level, id);
722 if (dltSyntax && token.value != TOKcolon)
723 error("expected colon after debug(), not '%s'", token.toChars());
724 } else {
725 if (dltSyntax && token.value != TOKcolon)
726 error("expected ':' or '(' after 'debug', not '%s'", token.toChars());
727 c = new DebugCondition(mod, 1, NULL);
729 return c;
733 /**************************************
734 * Parse a version conditional
737 Condition *Parser::parseVersionCondition()
739 Condition *c;
740 unsigned level = 1;
741 Identifier *id = NULL;
743 if (token.value == TOKlparen)
745 nextToken();
746 if (token.value == TOKidentifier)
747 id = token.ident;
748 else if (token.value == TOKint32v)
749 level = (unsigned)token.uns64value;
750 #if V2
751 /* Allow:
752 * version (unittest)
753 * even though unittest is a keyword
755 else if (token.value == TOKunittest)
756 id = Lexer::idPool(Token::toChars(TOKunittest));
757 #endif
758 else
759 error("identifier or integer expected, not %s", token.toChars());
760 nextToken();
761 check(TOKrparen);
764 else
765 error("(condition) expected following version");
766 c = new VersionCondition(mod, level, id);
767 return c;
771 /***********************************************
772 * static if (expression)
773 * body
774 * else
775 * body
778 Condition *Parser::parseStaticIfCondition()
779 { Expression *exp;
780 Condition *condition;
781 Array *aif;
782 Array *aelse;
783 Loc loc = this->loc;
785 nextToken();
786 checkLParen();
787 exp = parseAssignExp();
788 checkRParen();
790 condition = new StaticIfCondition(loc, exp);
791 return condition;
795 /*****************************************
796 * Parse a constructor definition:
797 * this(arguments) { body }
798 * Current token is 'this'.
801 CtorDeclaration *Parser::parseCtor()
803 CtorDeclaration *f;
804 Arguments *arguments;
805 int varargs;
806 Loc loc = this->loc;
808 nextToken();
809 arguments = parseParameters(&varargs);
810 f = new CtorDeclaration(loc, 0, arguments, varargs);
811 parseContracts(f);
812 return f;
815 /*****************************************
816 * Parse a destructor definition:
817 * ~this() { body }
818 * Current token is '~'.
821 DtorDeclaration *Parser::parseDtor()
823 DtorDeclaration *f;
824 Loc loc = this->loc;
826 nextToken();
827 check(TOKthis);
828 check(TOKlparen);
829 check(TOKrparen);
831 f = new DtorDeclaration(loc, 0);
832 parseContracts(f);
833 return f;
836 /*****************************************
837 * Parse a static constructor definition:
838 * static this() { body }
839 * Current token is 'this'.
842 StaticCtorDeclaration *Parser::parseStaticCtor()
844 StaticCtorDeclaration *f;
845 Loc loc = this->loc;
847 nextToken();
848 check(TOKlparen);
849 check(TOKrparen);
851 f = new StaticCtorDeclaration(loc, 0);
852 parseContracts(f);
853 return f;
856 /*****************************************
857 * Parse a static destructor definition:
858 * static ~this() { body }
859 * Current token is '~'.
862 StaticDtorDeclaration *Parser::parseStaticDtor()
864 StaticDtorDeclaration *f;
865 Loc loc = this->loc;
867 nextToken();
868 check(TOKthis);
869 check(TOKlparen);
870 check(TOKrparen);
872 f = new StaticDtorDeclaration(loc, 0);
873 parseContracts(f);
874 return f;
877 /*****************************************
878 * Parse an invariant definition:
879 * invariant { body }
880 * Current token is 'invariant'.
883 InvariantDeclaration *Parser::parseInvariant()
885 InvariantDeclaration *f;
886 Loc loc = this->loc;
888 nextToken();
889 if (token.value == TOKlparen) // optional ()
891 nextToken();
892 check(TOKrparen);
895 f = new InvariantDeclaration(loc, 0);
896 f->fbody = parseStatement(PScurly);
897 return f;
900 /*****************************************
901 * Parse a unittest definition:
902 * unittest { body }
903 * Current token is 'unittest'.
906 UnitTestDeclaration *Parser::parseUnitTest()
908 UnitTestDeclaration *f;
909 Statement *body;
910 Loc loc = this->loc;
912 nextToken();
914 body = parseStatement(PScurly);
916 f = new UnitTestDeclaration(loc, this->loc);
917 f->fbody = body;
918 return f;
921 /*****************************************
922 * Parse a new definition:
923 * new(arguments) { body }
924 * Current token is 'new'.
927 NewDeclaration *Parser::parseNew()
929 NewDeclaration *f;
930 Arguments *arguments;
931 int varargs;
932 Loc loc = this->loc;
934 nextToken();
935 arguments = parseParameters(&varargs);
936 f = new NewDeclaration(loc, 0, arguments, varargs);
937 parseContracts(f);
938 return f;
941 /*****************************************
942 * Parse a delete definition:
943 * delete(arguments) { body }
944 * Current token is 'delete'.
947 DeleteDeclaration *Parser::parseDelete()
949 DeleteDeclaration *f;
950 Arguments *arguments;
951 int varargs;
952 Loc loc = this->loc;
954 nextToken();
955 arguments = parseParameters(&varargs);
956 if (varargs)
957 error("... not allowed in delete function parameter list");
958 f = new DeleteDeclaration(loc, 0, arguments);
959 parseContracts(f);
960 return f;
963 /**********************************************
964 * Parse parameter list.
967 Arguments *Parser::parseParameters(int *pvarargs)
969 Arguments *arguments = new Arguments();
970 int varargs = 0;
971 int hasdefault = 0;
973 check(TOKlparen);
974 while (1)
975 { Type *tb;
976 Identifier *ai;
977 Type *at;
978 Argument *a;
979 unsigned storageClass;
980 Expression *ae;
982 ai = NULL;
983 storageClass = STCin; // parameter is "in" by default
984 switch (token.value)
986 case TOKrparen:
987 break;
989 case TOKdotdotdot:
990 varargs = 1;
991 nextToken();
992 break;
994 case TOKin:
995 storageClass = STCin;
996 nextToken();
997 goto L1;
999 case TOKout:
1000 storageClass = STCout;
1001 nextToken();
1002 goto L1;
1004 case TOKinout:
1005 case TOKref:
1006 storageClass = STCref;
1007 nextToken();
1008 goto L1;
1010 case TOKlazy:
1011 storageClass = STClazy;
1012 nextToken();
1013 goto L1;
1015 default:
1017 tb = parseBasicType();
1018 at = parseDeclarator(tb, &ai);
1019 ae = NULL;
1020 if (token.value == TOKassign) // = defaultArg
1021 { nextToken();
1022 ae = parseAssignExp();
1023 hasdefault = 1;
1025 else
1026 { if (hasdefault)
1027 error("default argument expected for %s",
1028 ai ? ai->toChars() : at->toChars());
1030 if (token.value == TOKdotdotdot)
1031 { /* This is:
1032 * at ai ...
1035 if (storageClass & (STCout | STCref))
1036 error("variadic argument cannot be out or ref");
1037 varargs = 2;
1038 a = new Argument(storageClass, at, ai, ae);
1039 arguments->push(a);
1040 nextToken();
1041 break;
1043 a = new Argument(storageClass, at, ai, ae);
1044 arguments->push(a);
1045 if (token.value == TOKcomma)
1046 { nextToken();
1047 continue;
1049 break;
1051 break;
1053 check(TOKrparen);
1054 *pvarargs = varargs;
1055 return arguments;
1059 /*************************************
1062 EnumDeclaration *Parser::parseEnum()
1063 { EnumDeclaration *e;
1064 Identifier *id;
1065 Type *t;
1066 Loc loc = this->loc;
1068 //printf("Parser::parseEnum()\n");
1069 nextToken();
1070 if (token.value == TOKidentifier)
1071 { id = token.ident;
1072 nextToken();
1074 else
1075 id = NULL;
1077 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1079 nextToken();
1080 t = parseBasicType();
1082 else
1083 t = NULL;
1085 e = new EnumDeclaration(loc, id, t);
1086 if (token.value == TOKsemicolon && id)
1087 nextToken();
1088 else if (token.value == startBlockTok)
1090 //printf("enum definition\n");
1091 e->members = new Array();
1092 nextToken();
1093 unsigned char *comment = token.blockComment;
1094 optionalEndline();
1095 while (token.value != TOKrcurly)
1097 if (token.value == TOKidentifier)
1098 { EnumMember *em;
1099 Expression *value;
1100 Identifier *ident;
1102 loc = this->loc;
1103 ident = token.ident;
1104 value = NULL;
1105 nextToken();
1106 if (token.value == TOKassign)
1108 nextToken();
1109 value = parseAssignExp();
1111 em = new EnumMember(loc, ident, value);
1112 e->members->push(em);
1113 optionalEndline();
1114 if (token.value == TOKrcurly)
1116 else
1117 { addComment(em, comment);
1118 comment = NULL;
1119 check(TOKcomma);
1120 optionalEndline();
1122 addComment(em, comment);
1123 comment = token.blockComment;
1125 else
1126 { error("enum member expected");
1127 nextToken();
1130 nextToken();
1132 else
1133 error("enum declaration is invalid");
1135 return e;
1138 Dsymbol *Parser::parseAggregate()
1139 { AggregateDeclaration *a = NULL;
1140 int anon = 0;
1141 enum TOK tok;
1142 Identifier *id;
1143 TemplateParameters *tpl = NULL;
1145 //printf("Parser::parseAggregate()\n");
1146 tok = token.value;
1147 nextToken();
1148 if (token.value != TOKidentifier)
1149 { id = NULL;
1151 else
1152 { id = token.ident;
1153 nextToken();
1155 if (token.value == TOKlparen)
1156 { // Class template declaration.
1158 // Gather template parameter list
1159 tpl = parseTemplateParameterList();
1163 Loc loc = this->loc;
1164 switch (tok)
1165 { case TOKclass:
1166 case TOKinterface:
1168 if (!id)
1169 error("anonymous classes not allowed");
1171 // Collect base class(es)
1172 BaseClasses *baseclasses = NULL;
1173 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1175 nextToken();
1176 baseclasses = parseBaseClasses();
1177 if (token.value != startBlockTok)
1178 error("members expected");
1181 if (tok == TOKclass)
1182 a = new ClassDeclaration(loc, id, baseclasses);
1183 else
1184 a = new InterfaceDeclaration(loc, id, baseclasses);
1185 break;
1188 case TOKstruct:
1189 if (id)
1190 a = new StructDeclaration(loc, id);
1191 else
1192 anon = 1;
1193 break;
1195 case TOKunion:
1196 if (id)
1197 a = new UnionDeclaration(loc, id);
1198 else
1199 anon = 2;
1200 break;
1202 default:
1203 assert(0);
1204 break;
1206 if (a && token.value == (dltSyntax ? TOKendline : TOKsemicolon))
1207 { nextToken();
1209 else if (token.value == startBlockTok)
1211 //printf("aggregate definition\n");
1212 nextToken();
1213 optionalEndline();
1214 Array *decl = parseDeclDefs(0);
1215 if (token.value != TOKrcurly)
1216 error("end-of-block expected following member declarations in aggregate");
1217 nextToken();
1218 if (anon)
1220 /* Anonymous structs/unions are more like attributes.
1222 return new AnonDeclaration(loc, anon - 1, decl);
1224 else
1225 a->members = decl;
1227 else
1229 error("%s expected following aggregate declaration", Token::toChars(startBlockTok));
1230 a = new StructDeclaration(loc, NULL);
1233 if (tpl)
1234 { Array *decldefs;
1235 TemplateDeclaration *tempdecl;
1237 // Wrap a template around the aggregate declaration
1238 decldefs = new Array();
1239 decldefs->push(a);
1240 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs, dltSyntax);
1241 return tempdecl;
1244 return a;
1247 /*******************************************
1250 BaseClasses *Parser::parseBaseClasses()
1252 enum PROT protection = PROTpublic;
1253 BaseClasses *baseclasses = new BaseClasses();
1255 for (; 1; nextToken())
1257 switch (token.value)
1259 case TOKidentifier:
1260 break;
1261 case TOKprivate:
1262 protection = PROTprivate;
1263 continue;
1264 case TOKpackage:
1265 protection = PROTpackage;
1266 continue;
1267 case TOKprotected:
1268 protection = PROTprotected;
1269 continue;
1270 case TOKpublic:
1271 protection = PROTpublic;
1272 continue;
1273 default:
1274 error("base classes expected instead of %s", token.toChars());
1275 return NULL;
1277 BaseClass *b = new BaseClass(parseBasicType(), protection);
1278 baseclasses->push(b);
1279 if (token.value != TOKcomma)
1280 break;
1281 protection = PROTpublic;
1283 return baseclasses;
1286 /**************************************
1287 * Parse a TemplateDeclaration.
1290 TemplateDeclaration *Parser::parseTemplateDeclaration()
1292 TemplateDeclaration *tempdecl;
1293 Identifier *id;
1294 TemplateParameters *tpl;
1295 Array *decldefs;
1296 Loc loc = this->loc;
1298 nextToken();
1299 if (token.value != TOKidentifier)
1300 { error("TemplateIdentifier expected following template");
1301 goto Lerr;
1303 id = token.ident;
1304 nextToken();
1305 tpl = parseTemplateParameterList();
1306 if (!tpl)
1307 goto Lerr;
1309 if (token.value != startBlockTok)
1310 { error("members of template declaration expected");
1311 goto Lerr;
1313 else
1315 nextToken();
1316 decldefs = parseDeclDefs(0);
1317 if (token.value != TOKrcurly)
1318 { error("template member expected");
1319 goto Lerr;
1321 nextToken();
1324 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs, dltSyntax);
1325 return tempdecl;
1327 Lerr:
1328 return NULL;
1331 /******************************************
1332 * Parse template parameter list.
1335 TemplateParameters *Parser::parseTemplateParameterList()
1337 TemplateParameters *tpl = new TemplateParameters();
1339 if (token.value != TOKlparen)
1340 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1341 goto Lerr;
1343 nextToken();
1345 // Get array of TemplateParameters
1346 if (token.value != TOKrparen)
1347 { int isvariadic = 0;
1349 while (1)
1350 { TemplateParameter *tp;
1351 Identifier *tp_ident = NULL;
1352 Type *tp_spectype = NULL;
1353 Type *tp_valtype = NULL;
1354 Type *tp_defaulttype = NULL;
1355 Expression *tp_specvalue = NULL;
1356 Expression *tp_defaultvalue = NULL;
1357 Token *t;
1359 // Get TemplateParameter
1361 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1362 t = peek(&token);
1363 if (token.value == TOKalias)
1364 { // AliasParameter
1365 nextToken();
1366 if (token.value != TOKidentifier)
1367 { error("Identifier expected for template parameter");
1368 goto Lerr;
1370 tp_ident = token.ident;
1371 nextToken();
1372 if (token.value == TOKcolon) // : Type
1374 nextToken();
1375 tp_spectype = parseBasicType();
1376 tp_spectype = parseDeclarator(tp_spectype, NULL);
1378 if (token.value == TOKassign) // = Type
1380 nextToken();
1381 tp_defaulttype = parseBasicType();
1382 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1384 tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1386 else if (t->value == TOKcolon || t->value == TOKassign ||
1387 t->value == TOKcomma || t->value == TOKrparen)
1388 { // TypeParameter
1389 if (token.value != TOKidentifier)
1390 { error("Identifier expected for template parameter");
1391 goto Lerr;
1393 tp_ident = token.ident;
1394 nextToken();
1395 if (token.value == TOKcolon) // : Type
1397 nextToken();
1398 tp_spectype = parseBasicType();
1399 tp_spectype = parseDeclarator(tp_spectype, NULL);
1401 if (token.value == TOKassign) // = Type
1403 nextToken();
1404 tp_defaulttype = parseBasicType();
1405 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1407 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1409 else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
1410 { // ident...
1411 if (isvariadic)
1412 error("variadic template parameter must be last");
1413 isvariadic = 1;
1414 tp_ident = token.ident;
1415 nextToken();
1416 nextToken();
1417 tp = new TemplateTupleParameter(loc, tp_ident);
1419 else
1420 { // ValueParameter
1421 tp_valtype = parseBasicType();
1422 tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
1423 if (!tp_ident)
1425 error("no identifier for template value parameter");
1426 tp_ident = new Identifier("error", TOKidentifier);
1428 if (token.value == TOKcolon) // : CondExpression
1430 nextToken();
1431 tp_specvalue = parseCondExp();
1433 if (token.value == TOKassign) // = CondExpression
1435 nextToken();
1436 tp_defaultvalue = parseCondExp();
1438 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
1440 tpl->push(tp);
1441 if (token.value != TOKcomma)
1442 break;
1443 nextToken();
1446 check(TOKrparen);
1447 Lerr:
1448 return tpl;
1451 /******************************************
1452 * Parse template mixin.
1453 * mixin Foo;
1454 * mixin Foo!(args);
1455 * mixin a.b.c!(args).Foo!(args);
1456 * mixin Foo!(args) identifier;
1457 * mixin typeof(expr).identifier!(args);
1460 Dsymbol *Parser::parseMixin()
1462 TemplateMixin *tm;
1463 Identifier *id;
1464 Type *tqual;
1465 Objects *tiargs;
1466 Array *idents;
1468 //printf("parseMixin()\n");
1469 nextToken();
1470 tqual = NULL;
1471 if (token.value == TOKdot)
1473 id = Id::empty;
1475 else
1477 if (token.value == TOKtypeof)
1478 { Expression *exp;
1480 nextToken();
1481 check(TOKlparen);
1482 exp = parseExpression();
1483 check(TOKrparen);
1484 tqual = new TypeTypeof(loc, exp);
1485 check(TOKdot);
1487 if (token.value != TOKidentifier)
1489 error("identifier expected, not %s", token.toChars());
1490 goto Lerr;
1492 id = token.ident;
1493 nextToken();
1496 idents = new Array();
1497 while (1)
1499 tiargs = NULL;
1500 if (token.value == TOKnot)
1502 nextToken();
1503 tiargs = parseTemplateArgumentList();
1506 if (token.value != TOKdot)
1507 break;
1509 if (tiargs)
1510 { TemplateInstance *tempinst = new TemplateInstance(loc, id);
1511 tempinst->tiargs = tiargs;
1512 id = (Identifier *)tempinst;
1513 tiargs = NULL;
1515 idents->push(id);
1517 nextToken();
1518 if (token.value != TOKidentifier)
1519 { error("identifier expected following '.' instead of '%s'", token.toChars());
1520 break;
1522 id = token.ident;
1523 nextToken();
1525 idents->push(id);
1527 if (token.value == TOKidentifier)
1529 id = token.ident;
1530 nextToken();
1532 else
1533 id = NULL;
1535 tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
1536 if (token.value != TOKsemicolon)
1537 error("';' expected after mixin");
1538 nextToken();
1540 return tm;
1542 Lerr:
1543 return NULL;
1546 /******************************************
1547 * Parse template argument list.
1548 * Input:
1549 * current token is opening '('
1550 * Output:
1551 * current token is one after closing ')'
1554 Objects *Parser::parseTemplateArgumentList()
1556 //printf("Parser::parseTemplateArgumentList()\n");
1557 Objects *tiargs = new Objects();
1558 if (token.value != TOKlparen)
1559 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1560 return tiargs;
1562 nextToken();
1564 // Get TemplateArgumentList
1565 if (token.value != TOKrparen)
1567 while (1)
1569 // See if it is an Expression or a Type
1570 if (isDeclaration(&token, 0, TOKreserved, NULL))
1571 { // Type
1572 Type *ta;
1574 // Get TemplateArgument
1575 ta = parseBasicType();
1576 ta = parseDeclarator(ta, NULL);
1577 tiargs->push(ta);
1579 else
1580 { // Expression
1581 Expression *ea;
1583 ea = parseAssignExp();
1584 tiargs->push(ea);
1586 if (token.value != TOKcomma)
1587 break;
1588 nextToken();
1591 check(TOKrparen, "template argument list");
1592 return tiargs;
1595 Import *Parser::parseImport(Array *decldefs, int isstatic)
1596 { Import *s;
1597 Identifier *id;
1598 Identifier *aliasid = NULL;
1599 Array *a;
1600 Loc loc;
1602 //printf("Parser::parseImport()\n");
1606 nextToken();
1607 if (token.value != TOKidentifier)
1608 { error("Identifier expected following import");
1609 break;
1612 loc = this->loc;
1613 a = NULL;
1614 id = token.ident;
1615 nextToken();
1616 if (!aliasid && token.value == TOKassign)
1618 aliasid = id;
1619 goto L1;
1621 while (token.value == TOKdot)
1623 if (!a)
1624 a = new Array();
1625 a->push(id);
1626 nextToken();
1627 if (token.value != TOKidentifier)
1628 { error("Identifier expected following package");
1629 break;
1631 id = token.ident;
1632 nextToken();
1635 s = new Import(loc, a, token.ident, aliasid, isstatic);
1636 decldefs->push(s);
1638 /* Look for
1639 * : alias=name, alias=name;
1640 * syntax.
1642 if (token.value == TOKcolon)
1644 nextToken();
1645 while (1)
1646 { Identifier *name;
1647 Identifier *alias;
1649 optionalEndline();
1651 if (dltSyntax && token.value == TOKrcurly)
1652 break;
1653 if (token.value != TOKidentifier)
1654 { error("Identifier expected following :");
1655 break;
1657 alias = token.ident;
1658 nextToken();
1659 if (token.value == TOKassign)
1661 nextToken();
1662 if (token.value != TOKidentifier)
1663 { error("Identifier expected following %s=", alias->toChars());
1664 break;
1666 name = token.ident;
1667 nextToken();
1669 else
1670 { name = alias;
1671 alias = NULL;
1673 s->addAlias(name, alias);
1674 if (token.value != TOKcomma && token.value != TOKendline)
1675 break;
1676 nextToken();
1678 if (dltSyntax)
1680 check(TOKrcurly);
1681 return NULL;
1683 else
1684 break;
1687 aliasid = NULL;
1688 } while (token.value == TOKcomma);
1690 if (token.value == TOKsemicolon || token.value == TOKendline)
1691 nextToken();
1692 else
1694 error("%s expected", endToken());
1695 nextToken();
1698 return NULL;
1701 Type *Parser::parseBasicType()
1702 { Type *t;
1703 Identifier *id;
1704 TypeQualified *tid;
1705 TemplateInstance *tempinst;
1707 //printf("parseBasicType()\n");
1708 switch (token.value)
1710 CASE_BASIC_TYPES_X(t):
1711 nextToken();
1712 break;
1714 case TOKidentifier:
1715 id = token.ident;
1716 nextToken();
1717 if (token.value == TOKnot)
1719 nextToken();
1720 tempinst = new TemplateInstance(loc, id);
1721 tempinst->tiargs = parseTemplateArgumentList();
1722 tid = new TypeInstance(loc, tempinst);
1723 goto Lident2;
1725 Lident:
1726 tid = new TypeIdentifier(loc, id);
1727 Lident2:
1728 while (token.value == TOKdot)
1729 { nextToken();
1730 if (token.value != TOKidentifier)
1731 { error("identifier expected following '.' instead of '%s'", token.toChars());
1732 break;
1734 id = token.ident;
1735 nextToken();
1736 if (token.value == TOKnot)
1738 nextToken();
1739 tempinst = new TemplateInstance(loc, id);
1740 tempinst->tiargs = parseTemplateArgumentList();
1741 tid->addIdent((Identifier *)tempinst);
1743 else
1744 tid->addIdent(id);
1746 t = tid;
1747 break;
1749 case TOKdot:
1750 id = Id::empty;
1751 goto Lident;
1753 case TOKtypeof:
1754 { Expression *exp;
1756 nextToken();
1757 check(TOKlparen);
1758 exp = parseExpression();
1759 check(TOKrparen);
1760 tid = new TypeTypeof(loc, exp);
1761 goto Lident2;
1764 default:
1765 error("basic type expected, not %s", token.toChars());
1766 t = Type::tint32;
1767 break;
1769 return t;
1772 Type *Parser::parseBasicType2(Type *t)
1774 Type *ts;
1775 Type *ta;
1777 //printf("parseBasicType2()\n");
1778 while (1)
1780 switch (token.value)
1782 case TOKmul:
1783 t = new TypePointer(t);
1784 nextToken();
1785 continue;
1787 case TOKlbracket:
1788 #if LTORARRAYDECL
1789 // Handle []. Make sure things like
1790 // int[3][1] a;
1791 // is (array[1] of array[3] of int)
1792 nextToken();
1793 if (token.value == TOKrbracket)
1795 t = new TypeDArray(t); // []
1796 nextToken();
1798 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1799 { // It's an associative array declaration
1800 Type *index;
1802 //printf("it's an associative array\n");
1803 index = parseBasicType();
1804 index = parseDeclarator(index, NULL); // [ type ]
1805 t = new TypeAArray(t, index);
1806 check(TOKrbracket);
1808 else
1810 //printf("it's [expression]\n");
1811 inBrackets++;
1812 Expression *e = parseExpression(); // [ expression ]
1813 if (token.value == TOKslice)
1814 { Expression *e2;
1816 nextToken();
1817 e2 = parseExpression(); // [ exp .. exp ]
1818 t = new TypeSlice(t, e, e2);
1820 else
1821 t = new TypeSArray(t,e);
1822 inBrackets--;
1823 check(TOKrbracket);
1825 continue;
1826 #else
1827 // Handle []. Make sure things like
1828 // int[3][1] a;
1829 // is (array[3] of array[1] of int)
1830 ts = t;
1831 while (token.value == TOKlbracket)
1833 nextToken();
1834 if (token.value == TOKrbracket)
1836 ta = new TypeDArray(t); // []
1837 nextToken();
1839 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1840 { // It's an associative array declaration
1841 Type *index;
1843 //printf("it's an associative array\n");
1844 index = parseBasicType();
1845 index = parseDeclarator(index, NULL); // [ type ]
1846 check(TOKrbracket);
1847 ta = new TypeAArray(t, index);
1849 else
1851 //printf("it's [expression]\n");
1852 Expression *e = parseExpression(); // [ expression ]
1853 ta = new TypeSArray(t,e);
1854 check(TOKrbracket);
1856 Type **pt;
1857 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1859 *pt = ta;
1861 t = ts;
1862 continue;
1863 #endif
1865 case TOKdelegate:
1866 case TOKfunction:
1867 { // Handle delegate declaration:
1868 // t delegate(parameter list)
1869 // t function(parameter list)
1870 Arguments *arguments;
1871 int varargs;
1872 enum TOK save = token.value;
1874 nextToken();
1875 arguments = parseParameters(&varargs);
1876 t = new TypeFunction(arguments, t, varargs, linkage);
1877 if (save == TOKdelegate)
1878 t = new TypeDelegate(t);
1879 else
1880 t = new TypePointer(t); // pointer to function
1881 continue;
1884 case TOKquestion:
1885 if (dltSyntax)
1887 Type *old = t;
1888 t = t->maybe();
1889 if (t == old)
1890 error("Type %s cannot be null; ? is pointless", old->toChars());
1891 nextToken();
1892 continue;
1894 // fall-through to default
1896 default:
1897 ts = t;
1898 break;
1900 break;
1903 if (!dltSyntax)
1905 switch (ts->ty) {
1906 case Tident:
1907 // Don't wrap it yet, because that confuses resolve()
1908 ((TypeIdentifier *) ts)->maybe = 1;
1909 break;
1910 case Tpointer:
1911 // TypeMaybe will unwrap itself later if this isn't a nullable type
1912 ts = ts->maybe();
1913 break;
1917 return ts;
1920 Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
1921 { Type *ts;
1922 Type *ta;
1924 //printf("parseDeclarator(tpl = %p)\n", tpl);
1925 t = parseBasicType2(t);
1927 switch (token.value)
1930 case TOKidentifier:
1931 if (pident)
1932 *pident = token.ident;
1933 else
1934 error("unexpected identifer '%s' in declarator", token.ident->toChars());
1935 ts = t;
1936 nextToken();
1937 break;
1939 case TOKlparen:
1940 nextToken();
1941 ts = parseDeclarator(t, pident);
1942 check(TOKrparen);
1943 break;
1945 default:
1946 ts = t;
1947 break;
1950 while (1)
1952 switch (token.value)
1954 #if CARRAYDECL
1955 case TOKlbracket:
1956 { // This is the old C-style post [] syntax.
1957 nextToken();
1958 if (token.value == TOKrbracket)
1960 ta = new TypeDArray(t); // []
1961 nextToken();
1963 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1964 { // It's an associative array declaration
1965 Type *index;
1967 //printf("it's an associative array\n");
1968 index = parseBasicType();
1969 index = parseDeclarator(index, NULL); // [ type ]
1970 check(TOKrbracket);
1971 ta = new TypeAArray(t, index);
1973 else
1975 //printf("it's [expression]\n");
1976 Expression *e = parseExpression(); // [ expression ]
1977 ta = new TypeSArray(t, e);
1978 check(TOKrbracket);
1980 Type **pt;
1981 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1983 *pt = ta;
1984 continue;
1986 #endif
1987 case TOKlparen:
1988 { Arguments *arguments;
1989 int varargs;
1991 if (tpl)
1993 /* Look ahead to see if this is (...)(...),
1994 * i.e. a function template declaration
1996 if (peekPastParen(&token)->value == TOKlparen)
1997 { // It's a function template declaration
1998 //printf("function template declaration\n");
2000 // Gather template parameter list
2001 *tpl = parseTemplateParameterList();
2005 arguments = parseParameters(&varargs);
2006 Type *ta = new TypeFunction(arguments, t, varargs, linkage);
2007 Type **pt;
2008 for (pt = &ts; *pt != t; pt = &(*pt)->next)
2010 *pt = ta;
2011 break;
2014 break;
2017 return ts;
2020 /**********************************
2021 * Return array of Declaration *'s.
2024 Array *Parser::parseDeclarations()
2026 enum STC storage_class;
2027 enum STC stc;
2028 Type *ts;
2029 Type *t;
2030 Type *tfirst;
2031 Identifier *ident;
2032 Array *a;
2033 enum TOK tok;
2034 unsigned char *comment = token.blockComment;
2035 enum LINK link = linkage;
2037 //printf("parseDeclarations()\n");
2038 switch (token.value)
2040 case TOKtypedef:
2041 case TOKalias:
2042 tok = token.value;
2043 nextToken();
2044 break;
2046 default:
2047 tok = TOKreserved;
2048 break;
2051 storage_class = STCundefined;
2052 while (1)
2054 switch (token.value)
2056 case TOKconst: stc = STCconst; goto L1;
2057 case TOKstatic: stc = STCstatic; goto L1;
2058 case TOKfinal: stc = STCfinal; goto L1;
2059 case TOKauto: stc = STCauto; goto L1;
2060 case TOKscope: stc = STCscope; goto L1;
2061 case TOKoverride: stc = STCoverride; goto L1;
2062 case TOKabstract: stc = STCabstract; goto L1;
2063 case TOKsynchronized: stc = STCsynchronized; goto L1;
2064 case TOKdeprecated: stc = STCdeprecated; goto L1;
2066 if (storage_class & stc)
2067 error("redundant storage class '%s'", token.toChars());
2068 storage_class = (STC) (storage_class | stc);
2069 nextToken();
2070 continue;
2072 case TOKextern:
2073 if (peek(&token)->value != TOKlparen)
2074 { stc = STCextern;
2075 goto L1;
2078 link = parseLinkage();
2079 continue;
2081 default:
2082 break;
2084 break;
2087 a = new Array();
2089 /* Look for auto initializers:
2090 * storage_class identifier = initializer;
2092 while (storage_class &&
2093 token.value == TOKidentifier &&
2094 peek(&token)->value == TOKassign)
2096 ident = token.ident;
2097 nextToken();
2098 nextToken();
2099 Initializer *init = parseInitializer();
2100 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
2101 v->storage_class = storage_class;
2102 a->push(v);
2103 if (token.value == TOKsemicolon || token.value == TOKendline)
2105 nextToken();
2106 addComment(v, comment);
2108 else if (token.value == TOKcomma)
2110 nextToken();
2111 if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
2113 error("Identifier expected following comma");
2115 else
2116 continue;
2118 else
2119 error("%s expected following auto declaration, not '%s'", endToken(), token.toChars());
2120 return a;
2123 if (token.value == TOKclass)
2124 { AggregateDeclaration *s;
2126 s = (AggregateDeclaration *)parseAggregate();
2127 s->storage_class |= storage_class;
2128 a->push(s);
2129 addComment(s, comment);
2130 return a;
2133 ts = parseBasicType();
2134 ts = parseBasicType2(ts);
2135 tfirst = NULL;
2137 while (1)
2139 Loc loc = this->loc;
2140 TemplateParameters *tpl = NULL;
2142 ident = NULL;
2143 t = parseDeclarator(ts, &ident, &tpl);
2144 assert(t);
2145 if (!tfirst)
2146 tfirst = t;
2147 else if (t != tfirst)
2148 error("multiple declarations must have the same type, not %s and %s",
2149 tfirst->toChars(), t->toChars());
2150 if (!ident)
2151 error("no identifier for declarator %s", t->toChars());
2153 if (tok == TOKtypedef || tok == TOKalias)
2154 { Declaration *v;
2155 Initializer *init;
2157 if (!dltSyntax)
2159 /* Unwrap maybe qualifiers from aliases.
2160 * Otherwise, it thinks we're aliasing types when we're not.
2162 if (t->ty == Tmaybe) {
2163 t = t->next;
2167 init = NULL;
2168 if (token.value == TOKassign)
2170 nextToken();
2171 init = parseInitializer();
2173 if (tok == TOKtypedef)
2174 v = new TypedefDeclaration(loc, ident, t, init);
2175 else
2176 { if (init)
2177 error("alias cannot have initializer");
2178 v = new AliasDeclaration(loc, ident, t);
2180 v->storage_class = storage_class;
2181 if (link == linkage)
2182 a->push(v);
2183 else
2185 Array *ax = new Array();
2186 ax->push(v);
2187 Dsymbol *s = new LinkDeclaration(link, ax);
2188 a->push(s);
2190 switch (token.value)
2191 { case TOKsemicolon:
2192 case TOKendline:
2193 nextToken();
2194 addComment(v, comment);
2195 break;
2197 case TOKcomma:
2198 nextToken();
2199 addComment(v, comment);
2200 continue;
2202 default:
2203 error("%s expected to close %s declaration", endToken(), Token::toChars(tok));
2204 break;
2207 else if (t->ty == Tfunction)
2208 { FuncDeclaration *f;
2209 Dsymbol *s;
2211 f = new FuncDeclaration(loc, 0, ident, storage_class, t);
2212 addComment(f, comment);
2213 parseContracts(f);
2214 addComment(f, NULL);
2215 if (link == linkage)
2217 s = f;
2219 else
2221 Array *ax = new Array();
2222 ax->push(f);
2223 s = new LinkDeclaration(link, ax);
2225 if (tpl) // it's a function template
2226 { Array *decldefs;
2227 TemplateDeclaration *tempdecl;
2229 // Wrap a template around the aggregate declaration
2230 decldefs = new Array();
2231 decldefs->push(s);
2232 tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs, dltSyntax);
2233 s = tempdecl;
2235 addComment(s, comment);
2236 a->push(s);
2238 else
2239 { VarDeclaration *v;
2240 Initializer *init;
2242 init = NULL;
2243 if (token.value == TOKassign)
2245 nextToken();
2246 init = parseInitializer();
2248 v = new VarDeclaration(loc, t, ident, init);
2249 v->storage_class = storage_class;
2250 if (link == linkage)
2251 a->push(v);
2252 else
2254 Array *ax = new Array();
2255 ax->push(v);
2256 Dsymbol *s = new LinkDeclaration(link, ax);
2257 a->push(s);
2259 switch (token.value)
2260 { case TOKsemicolon:
2261 case TOKendline:
2262 nextToken();
2263 addComment(v, comment);
2264 break;
2266 case TOKcomma:
2267 nextToken();
2268 addComment(v, comment);
2269 continue;
2271 default:
2272 error("%s expected, not '%s'", endToken(), token.toChars());
2273 break;
2276 break;
2278 return a;
2281 /*****************************************
2282 * Parse contracts following function declaration.
2285 void Parser::parseContracts(FuncDeclaration *f)
2287 Type *tb;
2288 enum LINK linksave = linkage;
2290 // The following is irrelevant, as it is overridden by sc->linkage in
2291 // TypeFunction::semantic
2292 linkage = LINKd; // nested functions have D linkage
2294 switch (token.value)
2296 case TOKlcurly:
2297 case TOKcolon:
2298 if (token.value != startBlockTok)
2299 error("use %s to start a new block", Token::toChars(startBlockTok));
2300 if (f->frequire || f->fensure)
2301 error("missing body { ... } after in or out");
2302 f->fbody = parseStatement(PSsemi | PScolon);
2303 f->endloc = endloc;
2304 break;
2306 case TOKbody:
2307 nextToken();
2308 f->fbody = parseStatement(PScurly);
2309 f->endloc = endloc;
2310 break;
2312 case TOKsemicolon:
2313 if (dltSyntax)
2314 error("unexpected semi-colon after function declaration");
2315 // fall-through
2316 case TOKendline:
2317 if (f->frequire || f->fensure)
2318 error("missing body { ... } after in or out");
2319 nextToken();
2320 break;
2322 #if 0 // Do we want this for function declarations, so we can do:
2323 // int x, y, foo(), z;
2324 case TOKcomma:
2325 nextToken();
2326 continue;
2327 #endif
2329 #if 0 // Dumped feature
2330 case TOKthrow:
2331 if (!f->fthrows)
2332 f->fthrows = new Array();
2333 nextToken();
2334 check(TOKlparen);
2335 while (1)
2337 tb = parseBasicType();
2338 f->fthrows->push(tb);
2339 if (token.value == TOKcomma)
2340 { nextToken();
2341 continue;
2343 break;
2345 check(TOKrparen);
2346 goto L1;
2347 #endif
2349 case TOKin:
2350 nextToken();
2351 if (f->frequire)
2352 error("redundant 'in' statement");
2353 f->frequire = parseStatement(PScurly | PSscope);
2354 goto L1;
2356 case TOKout:
2357 // parse: out (identifier) { statement }
2358 nextToken();
2359 if (token.value != startBlockTok)
2361 check(TOKlparen);
2362 if (token.value != TOKidentifier)
2363 error("(identifier) following 'out' expected, not %s", token.toChars());
2364 f->outId = token.ident;
2365 nextToken();
2366 check(TOKrparen);
2368 if (f->fensure)
2369 error("redundant 'out' statement");
2370 f->fensure = parseStatement(PScurly | PSscope);
2371 goto L1;
2373 default:
2374 error("%s expected following function declaration", endToken());
2375 break;
2377 linkage = linksave;
2380 /*****************************************
2383 Initializer *Parser::parseInitializer()
2385 StructInitializer *is;
2386 ArrayInitializer *ia;
2387 ExpInitializer *ie;
2388 Expression *e;
2389 Identifier *id;
2390 Initializer *value;
2391 int comma;
2392 Loc loc = this->loc;
2393 Token *t;
2394 int braces;
2396 switch (token.value)
2398 case TOKlcurly:
2399 /* Scan ahead to see if it is a struct initializer or
2400 * a function literal.
2401 * If it contains a ';', it is a function literal.
2402 * Treat { } as a struct initializer.
2404 braces = 1;
2405 for (t = peek(&token); 1; t = peek(t))
2407 switch (t->value)
2409 case TOKsemicolon:
2410 case TOKreturn:
2411 goto Lexpression;
2413 case TOKlcurly:
2414 braces++;
2415 continue;
2417 case TOKrcurly:
2418 if (--braces == 0)
2419 break;
2420 continue;
2422 case TOKeof:
2423 break;
2425 default:
2426 continue;
2428 break;
2431 is = new StructInitializer(loc);
2432 nextToken();
2433 comma = 0;
2434 while (1)
2436 switch (token.value)
2438 case TOKidentifier:
2439 if (comma == 1)
2440 error("comma expected separating field initializers");
2441 t = peek(&token);
2442 if (t->value == TOKcolon)
2444 id = token.ident;
2445 nextToken();
2446 nextToken(); // skip over ':'
2448 else
2449 { id = NULL;
2451 value = parseInitializer();
2452 is->addInit(id, value);
2453 comma = 1;
2454 continue;
2456 case TOKcomma:
2457 nextToken();
2458 comma = 2;
2459 continue;
2461 case TOKrcurly: // allow trailing comma's
2462 nextToken();
2463 break;
2465 case TOKeof:
2466 error("found EOF instead of initializer");
2467 break;
2469 default:
2470 value = parseInitializer();
2471 is->addInit(NULL, value);
2472 comma = 1;
2473 continue;
2474 //error("found '%s' instead of field initializer", token.toChars());
2475 //break;
2477 break;
2479 return is;
2481 case TOKlbracket:
2482 ia = new ArrayInitializer(loc);
2483 nextToken();
2484 comma = 0;
2485 while (1)
2487 switch (token.value)
2489 default:
2490 if (comma == 1)
2491 { error("comma expected separating array initializers, not %s", token.toChars());
2492 nextToken();
2493 break;
2495 e = parseAssignExp();
2496 if (!e)
2497 break;
2498 if (token.value == TOKcolon)
2500 nextToken();
2501 value = parseInitializer();
2503 else
2504 { value = new ExpInitializer(e->loc, e);
2505 e = NULL;
2507 ia->addInit(e, value);
2508 comma = 1;
2509 continue;
2511 case TOKlcurly:
2512 case TOKlbracket:
2513 if (comma == 1)
2514 error("comma expected separating array initializers, not %s", token.toChars());
2515 value = parseInitializer();
2516 ia->addInit(NULL, value);
2517 comma = 1;
2518 continue;
2520 case TOKcomma:
2521 nextToken();
2522 comma = 2;
2523 continue;
2525 case TOKrbracket: // allow trailing comma's
2526 nextToken();
2527 break;
2529 case TOKeof:
2530 error("found '%s' instead of array initializer", token.toChars());
2531 break;
2533 break;
2535 return ia;
2537 case TOKvoid:
2538 t = peek(&token);
2539 if (t->value == TOKsemicolon || t->value == TOKcomma || t->value == TOKendline)
2541 nextToken();
2542 return new VoidInitializer(loc);
2544 goto Lexpression;
2546 default:
2547 Lexpression:
2548 e = parseAssignExp();
2549 ie = new ExpInitializer(loc, e);
2550 return ie;
2554 Statement *Parser::logStatement(int level) {
2555 nextToken();
2556 if (token.value != TOKlparen)
2557 error(loc, "found '%s' when expecting '('", token.toChars());
2558 return new LogStatement(loc, level, parseArguments());
2561 /*****************************************
2562 * Input:
2563 * flags PSxxxx
2566 Statement *DltParser::parseStatement(int flags)
2568 optionalEndline();
2569 if (flags & (PScolon | PSscope))
2570 flags |= PScurly;
2571 return Parser::parseStatement(flags);
2574 Statement *Parser::parseStatement(int flags)
2575 { Statement *s;
2576 Token *t;
2577 Condition *condition;
2578 Statement *ifbody;
2579 Statement *elsebody;
2580 Loc loc = this->loc;
2582 //printf("parseStatement()\n");
2584 if ((flags & PScurly) && token.value != startBlockTok)
2585 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2587 int tok = token.value;
2589 switch (token.value)
2591 case TOKidentifier:
2592 if (!dltSyntax)
2594 // Need to look ahead to see if it is a declaration, label, or expression
2595 t = peek(&token);
2596 if (t->value == TOKcolon)
2597 { // It's a label
2598 Identifier *ident;
2600 ident = token.ident;
2601 nextToken();
2602 nextToken();
2603 s = parseStatement(PSsemi);
2604 s = new LabelStatement(loc, ident, s);
2605 break;
2608 // fallthrough to TOKdot
2609 case TOKdot:
2610 case TOKtypeof:
2611 if (isDeclaration(&token, 2, TOKreserved, NULL))
2612 goto Ldeclaration;
2613 else
2614 goto Lexp;
2615 break;
2617 case TOKassert:
2618 case TOKthis:
2619 case TOKsuper:
2620 case TOKint32v:
2621 case TOKuns32v:
2622 case TOKint64v:
2623 case TOKuns64v:
2624 case TOKfloat32v:
2625 case TOKfloat64v:
2626 case TOKfloat80v:
2627 case TOKimaginary32v:
2628 case TOKimaginary64v:
2629 case TOKimaginary80v:
2630 case TOKcharv:
2631 case TOKwcharv:
2632 case TOKdcharv:
2633 case TOKnull:
2634 case TOKtrue:
2635 case TOKfalse:
2636 case TOKstring:
2637 case TOKlparen:
2638 case TOKcast:
2639 case TOKmul:
2640 case TOKmin:
2641 case TOKadd:
2642 case TOKplusplus:
2643 case TOKminusminus:
2644 case TOKnew:
2645 case TOKdelete:
2646 case TOKdelegate:
2647 case TOKfunction:
2648 case TOKtypeid:
2649 case TOKis:
2650 case TOKlbracket:
2651 Lexp:
2652 { Expression *exp;
2654 exp = parseExpression();
2655 if (!dltSyntax)
2656 check(TOKsemicolon, "statement");
2657 s = new ExpStatement(loc, exp);
2658 break;
2661 case TOKstatic:
2662 { // Look ahead to see if it's static assert() or static if()
2663 Token *t;
2665 t = peek(&token);
2666 if (t->value == TOKassert)
2668 nextToken();
2669 s = new StaticAssertStatement(parseStaticAssert());
2670 break;
2672 if (t->value == TOKif)
2674 nextToken();
2675 condition = parseStaticIfCondition();
2676 goto Lcondition;
2678 if (dltNormalMode)
2679 error("no static variables in Delight");
2680 goto Ldeclaration;
2683 CASE_BASIC_TYPES:
2684 case TOKtypedef:
2685 case TOKalias:
2686 case TOKconst:
2687 case TOKauto:
2688 case TOKextern:
2689 case TOKfinal:
2690 case TOKinvariant:
2691 // case TOKtypeof:
2692 Ldeclaration:
2693 { Array *a;
2695 a = parseDeclarations();
2696 if (a->dim > 1)
2698 Statements *as = new Statements();
2699 as->reserve(a->dim);
2700 for (int i = 0; i < a->dim; i++)
2702 Dsymbol *d = (Dsymbol *)a->data[i];
2703 s = new DeclarationStatement(loc, d);
2704 as->push(s);
2706 s = new CompoundStatement(loc, as);
2708 else if (a->dim == 1)
2710 Dsymbol *d = (Dsymbol *)a->data[0];
2711 s = new DeclarationStatement(loc, d);
2713 else
2714 assert(0);
2715 if (flags & PSscope)
2716 s = new ScopeStatement(loc, s);
2717 break;
2720 case TOKstruct:
2721 case TOKunion:
2722 case TOKclass:
2723 case TOKinterface:
2724 { Dsymbol *d;
2726 d = parseAggregate();
2727 s = new DeclarationStatement(loc, d);
2728 break;
2731 case TOKenum:
2732 { Dsymbol *d;
2734 d = parseEnum();
2735 s = new DeclarationStatement(loc, d);
2736 break;
2739 case TOKmixin:
2740 { t = peek(&token);
2741 if (t->value == TOKlparen)
2742 { // mixin(string)
2743 nextToken();
2744 check(TOKlparen, "mixin");
2745 Expression *e = parseAssignExp();
2746 check(TOKrparen);
2747 check(TOKsemicolon);
2748 s = new CompileStatement(loc, e);
2749 break;
2751 Dsymbol *d = parseMixin();
2752 s = new DeclarationStatement(loc, d);
2753 break;
2756 case TOKcolon:
2757 case TOKlcurly:
2758 { Statements *statements;
2760 if (token.value != startBlockTok)
2761 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2763 nextToken();
2764 optionalEndline();
2765 statements = new Statements();
2766 while (token.value != TOKrcurly)
2768 statements->push(parseStatement(PSsemi | PScurlyscope));
2769 optionalEndline();
2771 endloc = this->loc;
2772 s = new CompoundStatement(loc, statements);
2773 if (flags & (PSscope | PScurlyscope))
2774 s = new ScopeStatement(loc, s);
2775 nextToken();
2776 break;
2779 case TOKlog_error: s = logStatement(LogStatement::Error); break;
2780 case TOKlog_warning: s = logStatement(LogStatement::Warn); break;
2781 case TOKlog_info: s = logStatement(LogStatement::Info); break;
2782 case TOKlog_trace: s = logStatement(LogStatement::Trace); break;
2784 case TOKwhile:
2785 { Expression *condition;
2786 Statement *body;
2788 nextToken();
2789 checkLParen();
2790 condition = parseExpression();
2791 checkRParen();
2792 body = parseStatement(PSscope);
2793 s = new WhileStatement(loc, condition, body);
2794 break;
2797 case TOKsemicolon:
2798 if (!(flags & PSsemi))
2799 error("use '{ }' for an empty statement, not a ';'");
2800 nextToken();
2801 s = new ExpStatement(loc, NULL);
2802 break;
2804 case TOKdo:
2805 { Statement *body;
2806 Expression *condition;
2808 nextToken();
2809 body = parseStatement(PSscope);
2810 check(TOKwhile);
2811 checkLParen();
2812 condition = parseExpression();
2813 checkRParen();
2814 s = new DoStatement(loc, body, condition);
2815 break;
2818 case TOKfor:
2820 Statement *init;
2821 Expression *condition;
2822 Expression *increment;
2823 Statement *body;
2825 nextToken();
2827 if (token.value == TOKlparen) {
2828 /* for (init; cond; incr): ... */
2829 nextToken();
2830 if (token.value == TOKsemicolon)
2831 { init = NULL;
2832 nextToken();
2834 else
2835 { init = parseStatement(0);
2837 if (token.value == TOKsemicolon)
2839 condition = NULL;
2840 nextToken();
2842 else
2844 condition = parseExpression();
2845 check(TOKsemicolon, "for condition");
2847 if (token.value == TOKrparen)
2848 { increment = NULL;
2849 nextToken();
2851 else
2852 { increment = parseExpression();
2853 check(TOKrparen);
2855 body = parseStatement(PSscope);
2856 s = new ForStatement(loc, init, condition, increment, body);
2857 if (init)
2858 s = new ScopeStatement(loc, s);
2859 } else if (dltSyntax)
2860 goto caseForeach;
2861 break;
2864 caseForeach:
2865 case TOKforeach:
2866 case TOKforeach_reverse:
2868 /* for var in seq: ... */
2869 /* for index, var in seq: ... */
2870 Arguments *arguments;
2872 Statement *d;
2873 Statement *body;
2874 Expression *aggr;
2875 enum TOK op = (TOK) tok;
2877 if (tok != TOKfor)
2878 nextToken();
2880 checkLParen();
2882 TOK inTok = dltSyntax ? TOKin : TOKsemicolon;
2884 arguments = new Arguments();
2886 while (1)
2888 Type *tb;
2889 Identifier *ai = NULL;
2890 Type *at;
2891 unsigned storageClass;
2892 Argument *a;
2894 storageClass = STCin;
2895 if (token.value == TOKinout || token.value == TOKref)
2896 { storageClass = STCref;
2897 nextToken();
2899 if (token.value == TOKidentifier)
2901 Token *t = peek(&token);
2902 if (t->value == TOKcomma || t->value == inTok)
2903 { ai = token.ident;
2904 at = NULL; // infer argument type
2905 nextToken();
2906 goto Larg;
2909 tb = parseBasicType();
2910 at = parseDeclarator(tb, &ai);
2911 if (!ai)
2912 error("no identifier for declarator %s", at->toChars());
2913 Larg:
2914 a = new Argument(storageClass, at, ai, NULL);
2915 arguments->push(a);
2916 if (token.value == TOKcomma)
2917 { nextToken();
2918 continue;
2920 break;
2923 check(inTok);
2925 aggr = parseExpression();
2926 checkRParen();
2928 if (dltSyntax) {
2929 if (token.value == TOKreversed) {
2930 op = TOKforeach_reverse;
2931 nextToken();
2932 } else {
2933 op = TOKforeach;
2937 body = parseStatement(PScolon);
2938 s = new ForeachStatement(loc, op, arguments, aggr, body);
2939 break;
2942 case TOKif:
2943 { Argument *arg = NULL;
2944 Expression *condition;
2945 Statement *ifbody;
2946 Statement *elsebody;
2948 nextToken();
2949 checkLParen();
2951 if (token.value == TOKauto)
2953 nextToken();
2954 if (token.value == TOKidentifier)
2956 Token *t = peek(&token);
2957 if (t->value == TOKassign)
2959 arg = new Argument(STCin, NULL, token.ident, NULL);
2960 nextToken();
2961 nextToken();
2963 else
2964 { error("= expected following auto identifier");
2965 goto Lerror;
2968 else
2969 { error("identifier expected following auto");
2970 goto Lerror;
2973 else if (isDeclaration(&token, 2, TOKassign, NULL))
2975 Type *tb;
2976 Type *at;
2977 Identifier *ai;
2979 tb = parseBasicType();
2980 at = parseDeclarator(tb, &ai);
2981 check(TOKassign);
2982 arg = new Argument(STCin, at, ai, NULL);
2985 // Check for " ident;"
2986 else if (token.value == TOKidentifier && !dltSyntax)
2988 Token *t = peek(&token);
2989 if (t->value == TOKcomma || t->value == TOKsemicolon)
2991 arg = new Argument(STCin, NULL, token.ident, NULL);
2992 nextToken();
2993 nextToken();
2994 if (1 || !global.params.useDeprecated)
2995 error("if (v; e) is deprecated, use if (auto v = e)");
2999 condition = parseExpression();
3000 checkRParen();
3001 ifbody = parseStatement(PSscope);
3002 if (token.value == TOKelse)
3004 nextToken();
3005 if (dltSyntax)
3007 if (token.value == TOKcolon) {
3008 elsebody = parseStatement(PSscope);
3009 } else if (token.value == TOKif) {
3010 elsebody = parseStatement(0);
3011 } else {
3012 error("Expected 'else:' or 'else if', not 'else %s'", token.toChars());
3013 elsebody = NULL;
3016 else
3017 elsebody = parseStatement(PSscope);
3019 else
3020 elsebody = NULL;
3021 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
3022 break;
3025 case TOKscope:
3026 if (peek(&token)->value != TOKlparen)
3027 goto Ldeclaration; // scope used as storage class
3028 nextToken();
3029 check(TOKlparen);
3030 if (token.value != TOKidentifier)
3031 { error("scope identifier expected");
3032 goto Lerror;
3034 else
3035 { TOK t = TOKon_scope_exit;
3036 Identifier *id = token.ident;
3038 if (id == Id::exit)
3039 t = TOKon_scope_exit;
3040 else if (id == Id::failure)
3041 t = TOKon_scope_failure;
3042 else if (id == Id::success)
3043 t = TOKon_scope_success;
3044 else
3045 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
3046 nextToken();
3047 check(TOKrparen);
3048 Statement *st = parseStatement(PScolon | PScurlyscope);
3049 s = new OnScopeStatement(loc, t, st);
3050 break;
3053 case TOKdebug:
3054 nextToken();
3055 condition = parseDebugCondition();
3056 goto Lcondition;
3058 case TOKversion:
3059 nextToken();
3060 condition = parseVersionCondition();
3061 goto Lcondition;
3063 Lcondition:
3064 if (dltSyntax && token.value != TOKcolon)
3065 error("expected colon after condition, not '%s'", token.toChars());
3066 ifbody = parseStatement(PScolon /*PSsemi*/);
3067 elsebody = NULL;
3068 if (token.value == TOKelse)
3070 nextToken();
3071 elsebody = parseStatement(PScolon /*PSsemi*/);
3073 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
3074 break;
3076 case TOKpragma:
3077 { Identifier *ident;
3078 Expressions *args = NULL;
3079 Statement *body;
3081 nextToken();
3082 check(TOKlparen);
3083 if (token.value != TOKidentifier)
3084 { error("pragma(identifier expected");
3085 goto Lerror;
3087 ident = token.ident;
3088 nextToken();
3089 if (token.value == TOKcomma)
3090 args = parseArguments(); // pragma(identifier, args...);
3091 else
3092 check(TOKrparen); // pragma(identifier);
3093 if (token.value == TOKsemicolon)
3094 { nextToken();
3095 body = NULL;
3097 else
3098 body = parseStatement(PSsemi | PScolon);
3099 s = new PragmaStatement(loc, ident, args, body);
3100 break;
3103 case TOKswitch:
3104 { Expression *condition;
3105 Statement *body;
3107 nextToken();
3108 checkLParen();
3109 condition = parseExpression();
3110 checkRParen();
3111 body = parseStatement(PSscope | PScolon);
3112 s = new SwitchStatement(loc, condition, body);
3113 break;
3116 case TOKcase:
3117 { Expression *exp;
3118 Statements *statements;
3119 Array cases; // array of Expression's
3121 while (1)
3123 nextToken();
3124 exp = parseAssignExp();
3125 cases.push(exp);
3126 if (token.value != TOKcomma)
3127 break;
3130 if (dltSyntax)
3132 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3134 else
3136 check(TOKcolon);
3138 statements = new Statements();
3139 while (token.value != TOKcase &&
3140 token.value != TOKdefault &&
3141 token.value != TOKrcurly)
3143 statements->push(parseStatement(PSsemi | PScurlyscope));
3145 s = new CompoundStatement(loc, statements);
3148 s = new ScopeStatement(loc, s);
3150 // Keep cases in order by building the case statements backwards
3151 for (int i = cases.dim; i; i--)
3153 exp = (Expression *)cases.data[i - 1];
3154 s = new CaseStatement(loc, exp, s);
3156 break;
3159 case TOKdefault:
3161 Statements *statements;
3163 nextToken();
3165 if (dltSyntax)
3167 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3169 else
3171 check(TOKcolon);
3173 statements = new Statements();
3174 while (token.value != TOKcase &&
3175 token.value != TOKdefault &&
3176 token.value != TOKrcurly)
3178 statements->push(parseStatement(PSsemi | PScurlyscope));
3180 s = new CompoundStatement(loc, statements);
3183 s = new ScopeStatement(loc, s);
3184 s = new DefaultStatement(loc, s);
3185 break;
3188 case TOKreturn:
3189 { Expression *exp;
3191 nextToken();
3192 if (token.value == TOKsemicolon || token.value == TOKendline)
3193 exp = NULL;
3194 else
3195 exp = parseExpression();
3197 if (!dltSyntax)
3198 check(TOKsemicolon, "return statement");
3199 else if (token.value != TOKendline) {
3200 error("Expected end-of-line after return statement, but found '%s'", token.toChars());
3203 s = new ReturnStatement(loc, exp);
3204 break;
3207 case TOKbreak:
3208 { Identifier *ident;
3210 nextToken();
3211 if (token.value == TOKidentifier)
3212 { ident = token.ident;
3213 nextToken();
3215 else
3216 ident = NULL;
3217 if (token.value != TOKsemicolon && token.value != TOKendline) {
3218 error("expected %s after break, not '%s'", endToken(), token.toChars());
3220 if (!dltSyntax)
3221 nextToken();
3222 s = new BreakStatement(loc, ident);
3223 break;
3226 case TOKcontinue:
3227 { Identifier *ident;
3229 nextToken();
3230 if (token.value == TOKidentifier)
3231 { ident = token.ident;
3232 nextToken();
3234 else
3235 ident = NULL;
3236 check(TOKsemicolon, "continue statement");
3237 s = new ContinueStatement(loc, ident);
3238 break;
3241 case TOKgoto:
3242 { Identifier *ident;
3244 nextToken();
3245 if (token.value == TOKdefault)
3247 nextToken();
3248 s = new GotoDefaultStatement(loc);
3250 else if (token.value == TOKcase)
3252 Expression *exp = NULL;
3254 nextToken();
3255 if (token.value != TOKsemicolon)
3256 exp = parseExpression();
3257 s = new GotoCaseStatement(loc, exp);
3259 else
3261 if (token.value != TOKidentifier)
3262 { error("Identifier expected following goto");
3263 ident = NULL;
3265 else
3266 { ident = token.ident;
3267 nextToken();
3269 s = new GotoStatement(loc, ident);
3271 if (token.value != TOKsemicolon && token.value != TOKendline) {
3272 error("expected %s after goto statement, not '%s'", endToken(), token.toChars());
3274 break;
3277 case TOKsynchronized:
3278 { Expression *exp;
3279 Statement *body;
3281 nextToken();
3282 if (token.value == TOKlparen)
3284 nextToken();
3285 exp = parseExpression();
3286 check(TOKrparen);
3288 else
3289 exp = NULL;
3290 body = parseStatement(PSscope);
3291 s = new SynchronizedStatement(loc, exp, body);
3292 break;
3295 case TOKwith:
3296 { Expression *exp;
3297 Statement *body;
3299 nextToken();
3300 check(TOKlparen);
3301 exp = parseExpression();
3302 check(TOKrparen);
3303 body = parseStatement(PSscope);
3304 s = new WithStatement(loc, exp, body);
3305 break;
3308 case TOKtry:
3309 { Statement *body;
3310 Array *catches = NULL;
3311 Statement *finalbody = NULL;
3313 nextToken();
3314 body = parseStatement(PSscope);
3315 while (token.value == TOKcatch)
3317 Statement *handler;
3318 Catch *c;
3319 Type *t;
3320 Identifier *id;
3321 Loc loc = this->loc;
3323 nextToken();
3324 if (token.value == startBlockTok)
3326 t = NULL;
3327 id = NULL;
3329 else
3331 check(TOKlparen);
3332 t = parseBasicType();
3333 id = NULL;
3334 t = parseDeclarator(t, &id);
3335 check(TOKrparen);
3337 handler = parseStatement(PScolon);
3338 c = new Catch(loc, t, id, handler);
3339 if (!catches)
3340 catches = new Array();
3341 catches->push(c);
3344 if (token.value == TOKfinally)
3345 { nextToken();
3346 finalbody = parseStatement(PScolon);
3349 s = body;
3350 if (!catches && !finalbody)
3351 error("catch or finally expected following try");
3352 else
3353 { if (catches)
3354 s = new TryCatchStatement(loc, body, catches);
3355 if (finalbody)
3356 s = new TryFinallyStatement(loc, s, finalbody);
3358 break;
3361 case TOKthrow:
3362 { Expression *exp;
3364 nextToken();
3365 exp = parseExpression();
3366 if (token.value != TOKsemicolon && token.value != TOKendline) {
3367 error("%s expected after throw statement, not '%s'", endToken(), token.toChars());
3369 if (!dltSyntax)
3370 nextToken();
3371 s = new ThrowStatement(loc, exp);
3372 break;
3375 case TOKvolatile:
3376 nextToken();
3377 s = parseStatement(PSsemi | PScurlyscope);
3378 s = new VolatileStatement(loc, s);
3379 break;
3381 case TOKasm:
3382 { Statements *statements;
3383 Identifier *label;
3384 Loc labelloc;
3385 Token *toklist;
3386 Token **ptoklist;
3388 // Parse the asm block into a sequence of AsmStatements,
3389 // each AsmStatement is one instruction.
3390 // Separate out labels.
3391 // Defer parsing of AsmStatements until semantic processing.
3393 nextToken();
3394 #if GDC_EXTENDED_ASM_SYNTAX
3395 if (token.value == TOKlparen)
3397 nextToken();
3398 s = parseExtAsm(1);
3399 break;
3401 #endif
3402 check(startBlockTok);
3403 toklist = NULL;
3404 ptoklist = &toklist;
3405 label = NULL;
3406 statements = new Statements();
3407 while (1)
3409 switch (token.value)
3411 case TOKidentifier:
3412 if (!toklist)
3414 // Look ahead to see if it is a label
3415 t = peek(&token);
3416 if (t->value == TOKcolon)
3417 { // It's a label
3418 label = token.ident;
3419 labelloc = this->loc;
3420 nextToken();
3421 nextToken();
3422 continue;
3425 goto Ldefault;
3427 case TOKrcurly:
3428 if (toklist || label)
3430 error("asm statements must end in ';'");
3432 break;
3434 case TOKendline:
3435 case TOKsemicolon:
3436 s = NULL;
3437 if (toklist || label)
3438 { // Create AsmStatement from list of tokens we've saved
3439 s = new AsmStatement(this->loc, toklist);
3440 toklist = NULL;
3441 ptoklist = &toklist;
3442 if (label)
3443 { s = new LabelStatement(labelloc, label, s);
3444 label = NULL;
3446 statements->push(s);
3448 nextToken();
3449 continue;
3451 case TOKeof:
3452 /* { */
3453 error("matching '}' expected, not end of file");
3454 break;
3456 case TOKlparen:
3457 case TOKstring:
3458 // If the first token is a string or '(', parse as extended asm.
3459 if (! toklist)
3461 s = parseExtAsm(0);
3462 statements->push(s);
3463 continue;
3465 // ...else, drop through.
3467 default:
3468 Ldefault:
3469 *ptoklist = new Token();
3470 memcpy(*ptoklist, &token, sizeof(Token));
3471 ptoklist = &(*ptoklist)->next;
3472 *ptoklist = NULL;
3474 nextToken();
3475 continue;
3477 break;
3479 s = new CompoundStatement(loc, statements);
3480 nextToken();
3481 break;
3484 default:
3485 error("found '%s' instead of statement", token.toChars());
3486 goto Lerror;
3488 Lerror:
3489 while (token.value != TOKrcurly &&
3490 token.value != TOKsemicolon &&
3491 token.value != TOKeof)
3492 nextToken();
3493 if (token.value == TOKsemicolon)
3494 nextToken();
3495 s = NULL;
3496 break;
3499 return s;
3502 Statement *Parser::parseExtAsm(int expect_rparen)
3504 Expression * insnTemplate;
3505 Expressions * args = NULL;
3506 Array * argNames = NULL;
3507 Expressions * argConstraints = NULL;
3508 int nOutputArgs = 0;
3509 Expressions * clobbers = NULL;
3510 bool isInputPhase = false; // Output operands first, then input.
3512 insnTemplate = parseExpression();
3513 if (token.value == TOKrparen || token.value == TOKsemicolon)
3514 goto Ldone;
3515 check(TOKcolon);
3516 while (1) {
3517 Expression * arg = NULL;
3518 Identifier * name = NULL;
3519 Expression * constraint = NULL;
3521 switch (token.value)
3523 case TOKsemicolon:
3524 case TOKrparen:
3525 goto Ldone;
3527 case TOKcolon:
3528 nextToken();
3529 goto LnextPhase;
3531 case TOKeof:
3532 error("unterminated statement");
3534 case TOKlbracket:
3535 nextToken();
3536 if (token.value == TOKidentifier)
3538 name = token.ident;
3539 nextToken();
3541 else
3542 error("expected identifier after '['");
3543 check(TOKrbracket);
3544 // drop through
3545 default:
3546 constraint = parsePrimaryExp();
3547 if (constraint->op != TOKstring)
3548 error("expected constant string constraint for operand");
3549 arg = parseAssignExp();
3550 if (! args)
3552 args = new Expressions;
3553 argConstraints = new Expressions;
3554 argNames = new Array;
3556 args->push(arg);
3557 argNames->push(name);
3558 argConstraints->push(constraint);
3559 if (! isInputPhase)
3560 nOutputArgs++;
3562 if (token.value == TOKcomma)
3563 nextToken();
3564 break;
3566 continue;
3567 LnextPhase:
3568 if (! isInputPhase)
3569 isInputPhase = true;
3570 else
3571 break;
3574 while (1)
3576 Expression * clobber;
3578 switch (token.value)
3580 case TOKsemicolon:
3581 case TOKrparen:
3582 goto Ldone;
3584 case TOKeof:
3585 error("unterminated statement");
3587 default:
3588 clobber = parseAssignExp();
3589 if (clobber->op != TOKstring)
3590 error("expected constant string constraint for clobber name");
3591 if (! clobbers)
3592 clobbers = new Expressions;
3593 clobbers->push(clobber);
3595 if (token.value == TOKcomma)
3596 nextToken();
3597 break;
3600 Ldone:
3601 if (expect_rparen)
3602 check(TOKrparen);
3603 else
3604 check(TOKsemicolon);
3606 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3607 argConstraints, nOutputArgs, clobbers);
3610 void Parser::optionalEndline() {
3611 while (token.value == TOKendline) {
3612 nextToken();
3616 void Parser::check(enum TOK value)
3618 check(loc, value);
3621 void Parser::check(Loc loc, enum TOK value)
3623 if (token.value != value)
3624 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3625 nextToken();
3628 void Parser::check(enum TOK value, char *string)
3630 if (token.value != value)
3631 error("found '%s' when expecting '%s' following '%s'",
3632 token.toChars(), Token::toChars(value), string);
3633 nextToken();
3636 char *Parser::endToken()
3638 return "semicolon";
3641 char *DltParser::endToken()
3643 return "newline";
3646 void Parser::checkLParen() { check(TOKlparen); }
3647 void Parser::checkRParen() { check(TOKrparen); }
3649 void DltParser::checkLParen() { }
3650 void DltParser::checkRParen() { }
3652 /************************************
3653 * Determine if the scanner is sitting on the start of a declaration.
3654 * Input:
3655 * needId 0 no identifier
3656 * 1 identifier optional
3657 * 2 must have identifier
3660 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3662 int haveId = 0;
3664 if (!isBasicType(&t))
3665 return FALSE;
3666 if (!isDeclarator(&t, &haveId, endtok))
3667 return FALSE;
3668 if ( needId == 1 ||
3669 (needId == 0 && !haveId) ||
3670 (needId == 2 && haveId))
3671 { if (pt)
3672 *pt = t;
3673 return TRUE;
3675 else
3676 return FALSE;
3679 int Parser::isBasicType(Token **pt)
3681 // This code parallels parseBasicType()
3682 Token *t = *pt;
3683 Token *t2;
3684 int parens;
3686 switch (t->value)
3688 CASE_BASIC_TYPES:
3689 t = peek(t);
3690 break;
3692 case TOKidentifier:
3693 t = peek(t);
3694 if (t->value == TOKnot)
3696 goto L4;
3698 goto L3;
3699 while (1)
3702 t = peek(t);
3704 if (t->value == TOKdot)
3706 Ldot:
3707 t = peek(t);
3708 if (t->value != TOKidentifier)
3709 goto Lfalse;
3710 t = peek(t);
3711 if (t->value != TOKnot)
3712 goto L3;
3714 t = peek(t);
3715 if (t->value != TOKlparen)
3716 goto Lfalse;
3717 if (!skipParens(t, &t))
3718 goto Lfalse;
3720 else
3721 break;
3723 break;
3725 case TOKdot:
3726 goto Ldot;
3728 case TOKtypeof:
3729 /* typeof(exp).identifier...
3731 t = peek(t);
3732 if (t->value != TOKlparen)
3733 goto Lfalse;
3734 if (!skipParens(t, &t))
3735 goto Lfalse;
3736 goto L2;
3738 default:
3739 goto Lfalse;
3741 *pt = t;
3742 return TRUE;
3744 Lfalse:
3745 return FALSE;
3748 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3749 { // This code parallels parseDeclarator()
3750 Token *t = *pt;
3751 int parens;
3753 //printf("Parser::isDeclarator()\n");
3754 //t->print();
3755 if (t->value == TOKassign)
3756 return FALSE;
3758 while (1)
3760 parens = FALSE;
3761 switch (t->value)
3763 case TOKquestion:
3764 case TOKmul:
3765 case TOKand:
3766 t = peek(t);
3767 continue;
3769 case TOKlbracket:
3770 t = peek(t);
3771 if (t->value == TOKrbracket)
3773 t = peek(t);
3775 else if (isDeclaration(t, 0, TOKrbracket, &t))
3776 { // It's an associative array declaration
3777 t = peek(t);
3779 else
3781 // [ expression ]
3782 // [ expression .. expression ]
3783 if (!isExpression(&t))
3784 return FALSE;
3785 if (t->value == TOKslice)
3786 { t = peek(t);
3787 if (!isExpression(&t))
3788 return FALSE;
3790 if (t->value != TOKrbracket)
3791 return FALSE;
3792 t = peek(t);
3794 continue;
3796 case TOKidentifier:
3797 if (*haveId)
3798 return FALSE;
3799 *haveId = TRUE;
3800 t = peek(t);
3801 break;
3803 case TOKlparen:
3804 t = peek(t);
3806 if (t->value == TOKrparen)
3807 return FALSE; // () is not a declarator
3809 /* Regard ( identifier ) as not a declarator
3810 * BUG: what about ( *identifier ) in
3811 * f(*p)(x);
3812 * where f is a class instance with overloaded () ?
3813 * Should we just disallow C-style function pointer declarations?
3815 if (t->value == TOKidentifier)
3816 { Token *t2 = peek(t);
3817 if (t2->value == TOKrparen)
3818 return FALSE;
3822 if (!isDeclarator(&t, haveId, TOKrparen))
3823 return FALSE;
3824 t = peek(t);
3825 parens = TRUE;
3826 break;
3828 case TOKdelegate:
3829 case TOKfunction:
3830 t = peek(t);
3831 if (!isParameters(&t))
3832 return FALSE;
3833 continue;
3835 break;
3838 while (1)
3840 switch (t->value)
3842 #if CARRAYDECL
3843 case TOKlbracket:
3844 parens = FALSE;
3845 t = peek(t);
3846 if (t->value == TOKrbracket)
3848 t = peek(t);
3850 else if (isDeclaration(t, 0, TOKrbracket, &t))
3851 { // It's an associative array declaration
3852 t = peek(t);
3854 else
3856 // [ expression ]
3857 if (!isExpression(&t))
3858 return FALSE;
3859 if (t->value != TOKrbracket)
3860 return FALSE;
3861 t = peek(t);
3863 continue;
3864 #endif
3866 case TOKlparen:
3867 parens = FALSE;
3868 if (!isParameters(&t))
3869 return FALSE;
3870 continue;
3872 // Valid tokens that follow a declaration
3873 case TOKrparen:
3874 case TOKrbracket:
3875 case TOKassign:
3876 case TOKcomma:
3877 case TOKendline:
3878 case TOKsemicolon:
3879 case TOKlcurly:
3880 case TOKin:
3881 // The !parens is to disallow unnecessary parentheses
3882 if (!parens && (endtok == TOKreserved || endtok == t->value))
3883 { *pt = t;
3884 return TRUE;
3886 return FALSE;
3888 default:
3889 return FALSE;
3895 int Parser::isParameters(Token **pt)
3896 { // This code parallels parseParameters()
3897 Token *t = *pt;
3898 int tmp;
3900 //printf("isParameters()\n");
3901 if (t->value != TOKlparen)
3902 return FALSE;
3904 t = peek(t);
3905 while (1)
3907 switch (t->value)
3909 case TOKrparen:
3910 break;
3912 case TOKdotdotdot:
3913 t = peek(t);
3914 break;
3916 case TOKin:
3917 case TOKout:
3918 case TOKinout:
3919 case TOKref:
3920 case TOKlazy:
3921 t = peek(t);
3922 default:
3923 if (!isBasicType(&t))
3924 return FALSE;
3925 tmp = FALSE;
3926 if (t->value != TOKdotdotdot &&
3927 !isDeclarator(&t, &tmp, TOKreserved))
3928 return FALSE;
3929 if (t->value == TOKassign)
3930 { t = peek(t);
3931 if (!isExpression(&t))
3932 return FALSE;
3934 if (t->value == TOKdotdotdot)
3936 t = peek(t);
3937 break;
3939 if (t->value == TOKcomma)
3940 { t = peek(t);
3941 continue;
3943 break;
3945 break;
3947 if (t->value != TOKrparen)
3948 return FALSE;
3949 t = peek(t);
3950 *pt = t;
3951 return TRUE;
3954 int Parser::isExpression(Token **pt)
3956 // This is supposed to determine if something is an expression.
3957 // What it actually does is scan until a closing right bracket
3958 // is found.
3960 Token *t = *pt;
3961 int brnest = 0;
3962 int panest = 0;
3964 for (;; t = peek(t))
3966 switch (t->value)
3968 case TOKlbracket:
3969 brnest++;
3970 continue;
3972 case TOKrbracket:
3973 if (--brnest >= 0)
3974 continue;
3975 break;
3977 case TOKlparen:
3978 panest++;
3979 continue;
3981 case TOKcomma:
3982 if (brnest || panest)
3983 continue;
3984 break;
3986 case TOKrparen:
3987 if (--panest >= 0)
3988 continue;
3989 break;
3991 case TOKslice:
3992 if (brnest)
3993 continue;
3994 break;
3996 case TOKeof:
3997 return FALSE;
3999 default:
4000 continue;
4002 break;
4005 *pt = t;
4006 return TRUE;
4009 /**********************************************
4010 * Skip over
4011 * instance foo.bar(parameters...)
4012 * Output:
4013 * if (pt), *pt is set to the token following the closing )
4014 * Returns:
4015 * 1 it's valid instance syntax
4016 * 0 invalid instance syntax
4019 int Parser::isTemplateInstance(Token *t, Token **pt)
4021 t = peek(t);
4022 if (t->value != TOKdot)
4024 if (t->value != TOKidentifier)
4025 goto Lfalse;
4026 t = peek(t);
4028 while (t->value == TOKdot)
4030 t = peek(t);
4031 if (t->value != TOKidentifier)
4032 goto Lfalse;
4033 t = peek(t);
4035 if (t->value != TOKlparen)
4036 goto Lfalse;
4038 // Skip over the template arguments
4039 while (1)
4041 while (1)
4043 t = peek(t);
4044 switch (t->value)
4046 case TOKlparen:
4047 if (!skipParens(t, &t))
4048 goto Lfalse;
4049 continue;
4050 case TOKrparen:
4051 break;
4052 case TOKcomma:
4053 break;
4054 case TOKeof:
4055 case TOKsemicolon:
4056 goto Lfalse;
4057 default:
4058 continue;
4060 break;
4063 if (t->value != TOKcomma)
4064 break;
4066 if (t->value != TOKrparen)
4067 goto Lfalse;
4068 t = peek(t);
4069 if (pt)
4070 *pt = t;
4071 return 1;
4073 Lfalse:
4074 return 0;
4077 /*******************************************
4078 * Skip parens, brackets.
4079 * Input:
4080 * t is on opening (
4081 * Output:
4082 * *pt is set to closing token, which is ')' on success
4083 * Returns:
4084 * !=0 successful
4085 * 0 some parsing error
4088 int Parser::skipParens(Token *t, Token **pt)
4090 int parens = 0;
4092 while (1)
4094 switch (t->value)
4096 case TOKlparen:
4097 parens++;
4098 break;
4100 case TOKrparen:
4101 parens--;
4102 if (parens < 0)
4103 goto Lfalse;
4104 if (parens == 0)
4105 goto Ldone;
4106 break;
4108 case TOKeof:
4109 case TOKsemicolon:
4110 goto Lfalse;
4112 default:
4113 break;
4115 t = peek(t);
4118 Ldone:
4119 if (*pt)
4120 *pt = t;
4121 return 1;
4123 Lfalse:
4124 return 0;
4127 /********************************* Expression Parser ***************************/
4129 Expression *Parser::parsePrimaryExp()
4130 { Expression *e;
4131 Type *t;
4132 Identifier *id;
4133 enum TOK save;
4134 Loc loc = this->loc;
4136 switch (token.value)
4138 case TOKidentifier:
4139 id = token.ident;
4140 nextToken();
4141 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4142 { // identifier!(template-argument-list)
4143 TemplateInstance *tempinst;
4145 tempinst = new TemplateInstance(loc, id);
4146 nextToken();
4147 tempinst->tiargs = parseTemplateArgumentList();
4148 e = new ScopeExp(loc, tempinst);
4150 else
4151 e = new IdentifierExp(loc, id);
4152 break;
4154 case TOKdollar:
4155 if (!inBrackets)
4156 error("'$' is valid only inside [] of index or slice");
4157 e = new DollarExp(loc);
4158 nextToken();
4159 break;
4161 case TOKdot:
4162 // Signal global scope '.' operator with "" identifier
4163 e = new IdentifierExp(loc, Id::empty);
4164 break;
4166 case TOKthis:
4167 e = new ThisExp(loc);
4168 nextToken();
4169 break;
4171 case TOKsuper:
4172 e = new SuperExp(loc);
4173 nextToken();
4174 break;
4176 case TOKint32v:
4177 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
4178 nextToken();
4179 break;
4181 case TOKuns32v:
4182 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
4183 nextToken();
4184 break;
4186 case TOKint64v:
4187 e = new IntegerExp(loc, token.int64value, Type::tint64);
4188 nextToken();
4189 break;
4191 case TOKuns64v:
4192 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
4193 nextToken();
4194 break;
4196 case TOKfloat32v:
4197 e = new RealExp(loc, token.float80value, Type::tfloat32);
4198 nextToken();
4199 break;
4201 case TOKfloat64v:
4202 e = new RealExp(loc, token.float80value, Type::tfloat64);
4203 nextToken();
4204 break;
4206 case TOKfloat80v:
4207 e = new RealExp(loc, token.float80value, Type::tfloat80);
4208 nextToken();
4209 break;
4211 case TOKimaginary32v:
4212 e = new RealExp(loc, token.float80value, Type::timaginary32);
4213 nextToken();
4214 break;
4216 case TOKimaginary64v:
4217 e = new RealExp(loc, token.float80value, Type::timaginary64);
4218 nextToken();
4219 break;
4221 case TOKimaginary80v:
4222 e = new RealExp(loc, token.float80value, Type::timaginary80);
4223 nextToken();
4224 break;
4226 case TOKnull:
4227 e = new NullExp(loc);
4228 nextToken();
4229 break;
4231 case TOKtrue:
4232 e = new IntegerExp(loc, 1, Type::tbool);
4233 nextToken();
4234 break;
4236 case TOKfalse:
4237 e = new IntegerExp(loc, 0, Type::tbool);
4238 nextToken();
4239 break;
4241 case TOKcharv:
4242 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
4243 nextToken();
4244 break;
4246 case TOKwcharv:
4247 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
4248 nextToken();
4249 break;
4251 case TOKdcharv:
4252 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
4253 nextToken();
4254 break;
4256 case TOKstring:
4257 { unsigned char *s;
4258 unsigned len;
4259 unsigned char postfix;
4261 // cat adjacent strings
4262 s = token.ustring;
4263 len = token.len;
4264 postfix = token.postfix;
4265 while (1)
4267 nextToken();
4268 if (token.value == TOKstring)
4269 { unsigned len1;
4270 unsigned len2;
4271 unsigned char *s2;
4273 if (token.postfix)
4274 { if (token.postfix != postfix)
4275 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4276 postfix = token.postfix;
4279 len1 = len;
4280 len2 = token.len;
4281 len = len1 + len2;
4282 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4283 memcpy(s2, s, len1 * sizeof(unsigned char));
4284 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4285 s = s2;
4287 else
4288 break;
4290 e = new StringExp(loc, s, len, postfix);
4291 break;
4294 CASE_BASIC_TYPES_X(t):
4295 nextToken();
4297 check(TOKdot, t->toChars());
4298 if (token.value != TOKidentifier)
4299 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4300 goto Lerr;
4302 e = new TypeDotIdExp(loc, t, token.ident);
4303 nextToken();
4304 break;
4306 case TOKtypeof:
4307 { Expression *exp;
4309 nextToken();
4310 check(TOKlparen);
4311 exp = parseExpression();
4312 check(TOKrparen);
4313 t = new TypeTypeof(loc, exp);
4314 if (token.value == TOKdot)
4315 goto L1;
4316 e = new TypeExp(loc, t);
4317 break;
4320 case TOKtypeid:
4321 { Type *t;
4323 nextToken();
4324 check(TOKlparen, "typeid");
4325 t = parseBasicType();
4326 t = parseDeclarator(t,NULL); // ( type )
4327 check(TOKrparen);
4328 e = new TypeidExp(loc, t);
4329 break;
4332 case TOKis:
4333 { Type *targ;
4334 Identifier *ident = NULL;
4335 Type *tspec = NULL;
4336 enum TOK tok = TOKreserved;
4337 enum TOK tok2 = TOKreserved;
4338 Loc loc = this->loc;
4340 nextToken();
4341 if (token.value == TOKlparen)
4343 nextToken();
4344 targ = parseBasicType();
4345 targ = parseDeclarator(targ, &ident);
4346 if (token.value == TOKcolon || token.value == TOKequal)
4348 tok = token.value;
4349 nextToken();
4350 if (tok == TOKequal &&
4351 (token.value == TOKtypedef ||
4352 token.value == TOKstruct ||
4353 token.value == TOKunion ||
4354 token.value == TOKclass ||
4355 token.value == TOKsuper ||
4356 token.value == TOKenum ||
4357 token.value == TOKinterface ||
4358 token.value == TOKfunction ||
4359 token.value == TOKdelegate ||
4360 token.value == TOKreturn))
4362 tok2 = token.value;
4363 nextToken();
4365 else
4367 tspec = parseBasicType();
4368 tspec = parseDeclarator(tspec, NULL);
4371 check(TOKrparen);
4373 else
4374 { error("(type identifier : specialization) expected following is");
4375 goto Lerr;
4377 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4378 break;
4381 case TOKassert:
4382 { Expression *msg = NULL;
4384 nextToken();
4386 checkLParen();
4387 e = parseAssignExp();
4388 if (token.value == (dltSyntax ? TOKelse : TOKcomma))
4389 { nextToken();
4390 msg = parseAssignExp();
4392 checkRParen();
4394 e = new AssertExp(loc, e, msg);
4395 break;
4398 case TOKmixin:
4400 nextToken();
4401 check(TOKlparen, "mixin");
4402 e = parseAssignExp();
4403 check(TOKrparen);
4404 e = new CompileExp(loc, e);
4405 break;
4408 case TOKimport:
4410 nextToken();
4411 check(TOKlparen, "import");
4412 e = parseAssignExp();
4413 check(TOKrparen);
4414 e = new FileExp(loc, e);
4415 break;
4418 case TOKlparen:
4419 if (peekPastParen(&token)->value == TOKlcurly)
4420 { // (arguments) { statements... }
4421 save = TOKdelegate;
4422 goto case_delegate;
4424 // ( expression )
4425 nextToken();
4426 e = parseExpression();
4427 check(loc, TOKrparen);
4428 break;
4430 case TOKlbracket:
4431 { /* Parse array literals and associative array literals:
4432 * [ value, value, value ... ]
4433 * [ key:value, key:value, key:value ... ]
4435 Expressions *values = new Expressions();
4436 Expressions *keys = NULL;
4438 nextToken();
4439 if (token.value != TOKrbracket)
4441 while (1)
4443 Expression *e = parseAssignExp();
4444 if (token.value == TOKcolon && (keys || values->dim == 0))
4445 { nextToken();
4446 if (!keys)
4447 keys = new Expressions();
4448 keys->push(e);
4449 e = parseAssignExp();
4451 else if (keys)
4452 { error("'key:value' expected for associative array literal");
4453 delete keys;
4454 keys = NULL;
4456 values->push(e);
4457 if (token.value == TOKrbracket)
4458 break;
4459 check(TOKcomma);
4462 check(TOKrbracket);
4464 if (keys)
4465 e = new AssocArrayLiteralExp(loc, keys, values);
4466 else
4467 e = new ArrayLiteralExp(loc, values);
4468 break;
4471 case TOKlcurly:
4472 // { statements... }
4473 save = TOKdelegate;
4474 goto case_delegate;
4476 case TOKfunction:
4477 case TOKdelegate:
4478 save = token.value;
4479 nextToken();
4480 case_delegate:
4482 /* function type(parameters) { body }
4483 * delegate type(parameters) { body }
4485 Arguments *arguments;
4486 int varargs;
4487 FuncLiteralDeclaration *fd;
4488 Type *t;
4490 if (token.value == TOKlcurly)
4492 t = NULL;
4493 varargs = 0;
4494 arguments = new Arguments();
4496 else
4498 if (token.value == TOKlparen)
4499 t = NULL;
4500 else
4502 t = parseBasicType();
4503 t = parseBasicType2(t); // function return type
4505 arguments = parseParameters(&varargs);
4507 t = new TypeFunction(arguments, t, varargs, linkage);
4508 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4509 parseContracts(fd);
4510 e = new FuncExp(loc, fd);
4511 break;
4514 default:
4515 error("expression expected, not '%s'", token.toChars());
4516 Lerr:
4517 // Anything for e, as long as it's not NULL
4518 e = new IntegerExp(loc, 0, Type::tint32);
4519 nextToken();
4520 break;
4522 return parsePostExp(e);
4525 Expression *Parser::parsePostExp(Expression *e)
4527 Loc loc;
4529 while (1)
4531 loc = this->loc;
4532 switch (token.value)
4534 case TOKdot:
4535 nextToken();
4536 if (token.value == TOKidentifier)
4537 { Identifier *id = token.ident;
4539 nextToken();
4540 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4541 { // identifier!(template-argument-list)
4542 TemplateInstance *tempinst;
4544 tempinst = new TemplateInstance(loc, id);
4545 nextToken();
4546 tempinst->tiargs = parseTemplateArgumentList();
4547 e = new DotTemplateInstanceExp(loc, e, tempinst);
4549 else
4550 e = new DotIdExp(loc, e, id);
4551 continue;
4553 else if (token.value == TOKnew)
4555 e = parseNewExp(e);
4556 continue;
4558 else
4559 error("identifier expected following '.', not '%s'", token.toChars());
4560 break;
4562 case TOKplusplus:
4563 e = new PostExp(TOKplusplus, loc, e);
4564 break;
4566 case TOKminusminus:
4567 e = new PostExp(TOKminusminus, loc, e);
4568 break;
4570 case TOKlparen:
4571 e = new CallExp(loc, e, parseArguments());
4572 continue;
4574 case TOKlbracket:
4575 { // array dereferences:
4576 // array[index]
4577 // array[]
4578 // array[lwr .. upr]
4579 Expression *index;
4580 Expression *upr;
4582 inBrackets++;
4583 nextToken();
4584 if (token.value == TOKrbracket)
4585 { // array[]
4586 e = new SliceExp(loc, e, NULL, NULL);
4587 nextToken();
4589 else
4591 index = parseAssignExp();
4592 if (token.value == TOKslice)
4593 { // array[lwr .. upr]
4594 nextToken();
4595 upr = parseAssignExp();
4596 e = new SliceExp(loc, e, index, upr);
4598 else
4599 { // array[index, i2, i3, i4, ...]
4600 Expressions *arguments = new Expressions();
4601 arguments->push(index);
4602 if (token.value == TOKcomma)
4604 nextToken();
4605 while (1)
4606 { Expression *arg;
4608 arg = parseAssignExp();
4609 arguments->push(arg);
4610 if (token.value == TOKrbracket)
4611 break;
4612 check(TOKcomma);
4615 e = new ArrayExp(loc, e, arguments);
4617 check(TOKrbracket);
4618 inBrackets--;
4620 continue;
4623 default:
4624 return e;
4626 nextToken();
4630 Expression *Parser::parseUnaryExp()
4631 { Expression *e;
4632 Loc loc = this->loc;
4634 switch (token.value)
4636 case TOKand:
4637 nextToken();
4638 e = parseUnaryExp();
4639 e = new AddrExp(loc, e);
4640 break;
4642 case TOKplusplus:
4643 nextToken();
4644 e = parseUnaryExp();
4645 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4646 break;
4648 case TOKminusminus:
4649 nextToken();
4650 e = parseUnaryExp();
4651 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4652 break;
4654 case TOKmul:
4655 nextToken();
4656 e = parseUnaryExp();
4657 e = new PtrExp(loc, e);
4658 break;
4660 case TOKmin:
4661 nextToken();
4662 e = parseUnaryExp();
4663 e = new NegExp(loc, e);
4664 break;
4666 case TOKadd:
4667 nextToken();
4668 e = parseUnaryExp();
4669 e = new UAddExp(loc, e);
4670 break;
4672 case TOKnot:
4673 nextToken();
4674 e = parseUnaryExp();
4675 e = new NotExp(loc, e);
4676 break;
4678 case TOKtilde:
4679 nextToken();
4680 e = parseUnaryExp();
4681 e = new ComExp(loc, e);
4682 break;
4684 case TOKdelete:
4685 nextToken();
4686 e = parseUnaryExp();
4687 e = new DeleteExp(loc, e);
4688 break;
4690 case TOKnew:
4691 e = parseNewExp(NULL);
4692 break;
4694 case TOKcast: // cast(type) expression
4695 { Type *t;
4697 nextToken();
4698 check(TOKlparen);
4699 t = parseBasicType();
4700 t = parseDeclarator(t,NULL); // ( type )
4701 check(TOKrparen);
4703 e = parseUnaryExp();
4704 e = new CastExp(loc, e, t);
4705 break;
4708 case TOKlparen:
4709 { Token *tk;
4711 tk = peek(&token);
4712 #if CCASTSYNTAX
4713 // If cast
4714 if (isDeclaration(tk, 0, TOKrparen, &tk))
4716 tk = peek(tk); // skip over right parenthesis
4717 switch (tk->value)
4719 case TOKdot:
4720 case TOKplusplus:
4721 case TOKminusminus:
4722 case TOKnot:
4723 case TOKdelete:
4724 case TOKnew:
4725 case TOKlparen:
4726 case TOKidentifier:
4727 case TOKthis:
4728 case TOKsuper:
4729 case TOKint32v:
4730 case TOKuns32v:
4731 case TOKint64v:
4732 case TOKuns64v:
4733 case TOKfloat32v:
4734 case TOKfloat64v:
4735 case TOKfloat80v:
4736 case TOKimaginary32v:
4737 case TOKimaginary64v:
4738 case TOKimaginary80v:
4739 case TOKnull:
4740 case TOKtrue:
4741 case TOKfalse:
4742 case TOKcharv:
4743 case TOKwcharv:
4744 case TOKdcharv:
4745 case TOKstring:
4746 #if 0
4747 case TOKtilde:
4748 case TOKand:
4749 case TOKmul:
4750 case TOKmin:
4751 case TOKadd:
4752 #endif
4753 case TOKfunction:
4754 case TOKdelegate:
4755 case TOKtypeof:
4756 CASE_BASIC_TYPES: // (type)int.size
4757 { // (type) una_exp
4758 Type *t;
4760 nextToken();
4761 t = parseBasicType();
4762 t = parseDeclarator(t,NULL);
4763 check(TOKrparen);
4765 // if .identifier
4766 if (token.value == TOKdot)
4768 nextToken();
4769 if (token.value != TOKidentifier)
4770 { error("Identifier expected following (type).");
4771 return NULL;
4773 e = new TypeDotIdExp(loc, t, token.ident);
4774 nextToken();
4775 e = parsePostExp(e);
4777 else
4779 e = parseUnaryExp();
4780 e = new CastExp(loc, e, t);
4781 error("C style cast illegal, use %s", e->toChars());
4783 return e;
4787 #endif
4788 e = parsePrimaryExp();
4789 break;
4791 default:
4792 e = parsePrimaryExp();
4793 break;
4795 assert(e);
4796 return e;
4799 Expression *Parser::parseMulExp()
4800 { Expression *e;
4801 Expression *e2;
4802 Loc loc = this->loc;
4804 e = parseUnaryExp();
4805 while (1)
4807 switch (token.value)
4809 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4810 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4811 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4813 default:
4814 break;
4816 break;
4818 return e;
4821 Expression *Parser::parseAddExp()
4822 { Expression *e;
4823 Expression *e2;
4824 Loc loc = this->loc;
4826 e = parseMulExp();
4827 while (1)
4829 switch (token.value)
4831 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4832 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4833 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4835 default:
4836 break;
4838 break;
4840 return e;
4843 Expression *Parser::parseShiftExp()
4844 { Expression *e;
4845 Expression *e2;
4846 Loc loc = this->loc;
4848 e = parseAddExp();
4849 while (1)
4851 switch (token.value)
4853 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4854 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4855 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4857 default:
4858 break;
4860 break;
4862 return e;
4865 Expression *Parser::parseRelExp()
4866 { Expression *e;
4867 Expression *e2;
4868 enum TOK op;
4869 Loc loc = this->loc;
4871 e = parseShiftExp();
4872 while (1)
4874 switch (token.value)
4876 case TOKlt:
4877 case TOKle:
4878 case TOKgt:
4879 case TOKge:
4880 case TOKunord:
4881 case TOKlg:
4882 case TOKleg:
4883 case TOKule:
4884 case TOKul:
4885 case TOKuge:
4886 case TOKug:
4887 case TOKue:
4888 op = token.value;
4889 nextToken();
4890 e2 = parseShiftExp();
4891 e = new CmpExp(op, loc, e, e2);
4892 continue;
4894 case TOKin:
4895 nextToken();
4896 e2 = parseShiftExp();
4897 e = new InExp(loc, e, e2);
4898 continue;
4900 default:
4901 break;
4903 break;
4905 return e;
4908 Expression *Parser::parseEqualExp()
4909 { Expression *e;
4910 Expression *e2;
4911 Token *t;
4912 Loc loc = this->loc;
4914 e = parseRelExp();
4915 while (1)
4916 { enum TOK value = token.value;
4918 switch (value)
4920 case TOKequal:
4921 case TOKnotequal:
4922 nextToken();
4923 e2 = parseRelExp();
4924 e = new EqualExp(value, loc, e, e2);
4925 continue;
4927 case TOKidentity:
4928 error("'===' is no longer legal, use 'is' instead");
4929 goto L1;
4931 case TOKnotidentity:
4932 error("'!==' is no longer legal, use '!is' instead");
4933 goto L1;
4935 case TOKis:
4936 value = TOKidentity;
4937 goto L1;
4939 case TOKnot:
4940 // Attempt to identify '!is'
4941 t = peek(&token);
4942 if (t->value != TOKis)
4943 break;
4944 nextToken();
4945 value = TOKnotidentity;
4946 goto L1;
4949 nextToken();
4950 e2 = parseRelExp();
4951 e = new IdentityExp(value, loc, e, e2);
4952 continue;
4954 default:
4955 break;
4957 break;
4959 return e;
4962 Expression *Parser::parseCmpExp()
4963 { Expression *e;
4964 Expression *e2;
4965 Token *t;
4966 Loc loc = this->loc;
4968 e = parseShiftExp();
4969 enum TOK op = token.value;
4971 switch (op)
4973 case TOKequal:
4974 case TOKnotequal:
4975 nextToken();
4976 e2 = parseShiftExp();
4977 e = new EqualExp(op, loc, e, e2);
4978 break;
4980 case TOKis:
4981 op = TOKidentity;
4982 goto L1;
4984 case TOKnot:
4985 // Attempt to identify '!is'
4986 t = peek(&token);
4987 if (t->value != TOKis)
4988 break;
4989 nextToken();
4990 op = TOKnotidentity;
4991 goto L1;
4994 nextToken();
4995 e2 = parseShiftExp();
4996 e = new IdentityExp(op, loc, e, e2);
4997 break;
4999 case TOKlt:
5000 case TOKle:
5001 case TOKgt:
5002 case TOKge:
5003 case TOKunord:
5004 case TOKlg:
5005 case TOKleg:
5006 case TOKule:
5007 case TOKul:
5008 case TOKuge:
5009 case TOKug:
5010 case TOKue:
5011 nextToken();
5012 e2 = parseShiftExp();
5013 e = new CmpExp(op, loc, e, e2);
5014 break;
5016 case TOKin:
5017 nextToken();
5018 e2 = parseShiftExp();
5019 e = new InExp(loc, e, e2);
5020 break;
5022 default:
5023 break;
5025 return e;
5028 Expression *Parser::parseAndExp()
5029 { Expression *e;
5030 Expression *e2;
5031 Loc loc = this->loc;
5033 if (global.params.Dversion == 1)
5035 e = parseEqualExp();
5036 while (token.value == TOKand)
5038 nextToken();
5039 e2 = parseEqualExp();
5040 e = new AndExp(loc,e,e2);
5041 loc = this->loc;
5044 else
5046 e = parseCmpExp();
5047 while (token.value == TOKand)
5049 nextToken();
5050 e2 = parseCmpExp();
5051 e = new AndExp(loc,e,e2);
5052 loc = this->loc;
5055 return e;
5058 Expression *Parser::parseXorExp()
5059 { Expression *e;
5060 Expression *e2;
5061 Loc loc = this->loc;
5063 e = parseAndExp();
5064 while (token.value == TOKxor)
5066 nextToken();
5067 e2 = parseAndExp();
5068 e = new XorExp(loc, e, e2);
5070 return e;
5073 Expression *Parser::parseOrExp()
5074 { Expression *e;
5075 Expression *e2;
5076 Loc loc = this->loc;
5078 e = parseXorExp();
5079 while (token.value == TOKor)
5081 nextToken();
5082 e2 = parseXorExp();
5083 e = new OrExp(loc, e, e2);
5085 return e;
5088 Expression *Parser::parseAndAndExp()
5089 { Expression *e;
5090 Expression *e2;
5091 Loc loc = this->loc;
5093 e = parseOrExp();
5094 while (token.value == TOKandand)
5096 nextToken();
5097 e2 = parseOrExp();
5098 e = new AndAndExp(loc, e, e2);
5100 return e;
5103 Expression *Parser::parseOrOrExp()
5104 { Expression *e;
5105 Expression *e2;
5106 Loc loc = this->loc;
5108 e = parseAndAndExp();
5109 while (token.value == TOKoror)
5111 nextToken();
5112 e2 = parseAndAndExp();
5113 e = new OrOrExp(loc, e, e2);
5115 return e;
5118 Expression *Parser::parseCondExp()
5119 { Expression *e;
5120 Expression *e1;
5121 Expression *e2;
5122 Loc loc = this->loc;
5124 e = parseOrOrExp();
5125 if (token.value == TOKquestion)
5127 nextToken();
5128 e1 = parseExpression();
5129 check(TOKcolon);
5130 e2 = parseCondExp();
5131 e = new CondExp(loc, e, e1, e2);
5133 return e;
5136 Expression *DltParser::parseCondExp()
5137 { Expression *e;
5138 Expression *e1;
5139 Expression *e2;
5140 Loc loc = this->loc;
5142 e = parseOrOrExp();
5143 if (token.value == TOKif)
5145 nextToken();
5146 e1 = parseExpression();
5147 check(TOKelse);
5148 e2 = parseCondExp();
5149 e = new CondExp(loc, e1, e, e2);
5151 return e;
5154 Expression *Parser::parseAssignExp()
5155 { Expression *e;
5156 Expression *e2;
5157 Loc loc;
5159 e = parseCondExp();
5160 while (1)
5162 loc = this->loc;
5163 switch (token.value)
5165 #define X(tok,ector) \
5166 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5168 X(TOKassign, AssignExp);
5169 X(TOKaddass, AddAssignExp);
5170 X(TOKminass, MinAssignExp);
5171 X(TOKmulass, MulAssignExp);
5172 X(TOKdivass, DivAssignExp);
5173 X(TOKmodass, ModAssignExp);
5174 X(TOKandass, AndAssignExp);
5175 X(TOKorass, OrAssignExp);
5176 X(TOKxorass, XorAssignExp);
5177 X(TOKshlass, ShlAssignExp);
5178 X(TOKshrass, ShrAssignExp);
5179 X(TOKushrass, UshrAssignExp);
5180 X(TOKcatass, CatAssignExp);
5182 #undef X
5183 default:
5184 break;
5186 break;
5188 return e;
5191 Expression *Parser::parseExpression()
5192 { Expression *e;
5193 Expression *e2;
5194 Loc loc = this->loc;
5196 //printf("Parser::parseExpression()\n");
5197 e = parseAssignExp();
5198 while (token.value == TOKcomma)
5200 nextToken();
5201 e2 = parseAssignExp();
5202 e = new CommaExp(loc, e, e2);
5203 loc = this->loc;
5205 return e;
5209 /*************************
5210 * Collect argument list.
5211 * Assume current token is '(' or '['.
5214 Expressions *Parser::parseArguments()
5215 { // function call
5216 Expressions *arguments;
5217 Expression *arg;
5218 enum TOK endtok;
5220 arguments = new Expressions();
5221 if (token.value == TOKlbracket)
5222 endtok = TOKrbracket;
5223 else
5224 endtok = TOKrparen;
5227 nextToken();
5228 if (token.value != endtok)
5230 while (1)
5232 arg = parseAssignExp();
5233 arguments->push(arg);
5234 if (token.value == endtok)
5235 break;
5236 check(TOKcomma);
5239 check(endtok);
5241 return arguments;
5244 /*******************************************
5247 Expression *Parser::parseNewExp(Expression *thisexp)
5248 { Type *t;
5249 Expressions *newargs;
5250 Expressions *arguments = NULL;
5251 Expression *e;
5252 Loc loc = this->loc;
5254 nextToken();
5255 newargs = NULL;
5256 if (token.value == TOKlparen)
5258 newargs = parseArguments();
5261 // An anonymous nested class starts with "class"
5262 if (token.value == TOKclass)
5264 nextToken();
5265 if (token.value == TOKlparen)
5266 arguments = parseArguments();
5268 BaseClasses *baseclasses = NULL;
5269 if (token.value != TOKlcurly)
5270 baseclasses = parseBaseClasses();
5272 Identifier *id = NULL;
5273 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
5275 if (token.value != TOKlcurly)
5276 { error("{ members } expected for anonymous class");
5277 cd->members = NULL;
5279 else
5281 nextToken();
5282 Array *decl = parseDeclDefs(0);
5283 if (token.value != TOKrcurly)
5284 error("class member expected");
5285 nextToken();
5286 cd->members = decl;
5289 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
5291 return e;
5294 #if LTORARRAYDECL
5295 t = parseBasicType();
5296 t = parseBasicType2(t);
5297 if (t->ty == Taarray)
5299 Type *index = ((TypeAArray *)t)->index;
5301 Expression *e = index->toExpression();
5302 if (e)
5303 { arguments = new Expressions();
5304 arguments->push(e);
5305 t = new TypeDArray(t->next);
5307 else
5309 error("need size of rightmost array, not type %s", index->toChars());
5310 return new NullExp(loc);
5313 else if (t->ty == Tsarray)
5315 TypeSArray *tsa = (TypeSArray *)t;
5316 Expression *e = tsa->dim;
5318 arguments = new Expressions();
5319 arguments->push(e);
5320 t = new TypeDArray(t->next);
5322 else if (token.value == TOKlparen)
5324 arguments = parseArguments();
5326 #else
5327 t = parseBasicType();
5328 while (token.value == TOKmul)
5329 { t = new TypePointer(t);
5330 nextToken();
5332 if (token.value == TOKlbracket)
5334 Expression *e;
5336 nextToken();
5337 e = parseAssignExp();
5338 arguments = new Array();
5339 arguments->push(e);
5340 check(TOKrbracket);
5341 t = parseDeclarator(t, NULL);
5342 t = new TypeDArray(t);
5344 else if (token.value == TOKlparen)
5345 arguments = parseArguments();
5346 #endif
5347 e = new NewExp(loc, thisexp, newargs, t, arguments);
5348 return e;
5351 /**********************************************
5354 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5356 s->addComment(combineComments(blockComment, token.lineComment));
5360 /********************************* ***************************/