Fixed parsing of mixin expressions.
[delight/core.git] / dmd / parse.c
blob5b0c407b9d02b2bde12bba1b9f2a5a4776db5a95
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 && token.value != TOKclass)
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 = parseBaseClasses();
1173 if (baseclasses && token.value != startBlockTok) {
1174 error("members expected");
1177 if (tok == TOKclass)
1178 a = new ClassDeclaration(loc, id, baseclasses);
1179 else
1180 a = new InterfaceDeclaration(loc, id, baseclasses);
1181 break;
1184 case TOKstruct:
1185 if (id)
1186 a = new StructDeclaration(loc, id);
1187 else
1188 anon = 1;
1189 break;
1191 case TOKunion:
1192 if (id)
1193 a = new UnionDeclaration(loc, id);
1194 else
1195 anon = 2;
1196 break;
1198 default:
1199 assert(0);
1200 break;
1202 if (a && token.value == (dltSyntax ? TOKendline : TOKsemicolon))
1203 { nextToken();
1205 else if (token.value == startBlockTok)
1207 //printf("aggregate definition\n");
1208 nextToken();
1209 optionalEndline();
1210 Array *decl = parseDeclDefs(0);
1211 if (token.value != TOKrcurly)
1212 error("end-of-block expected following member declarations in aggregate");
1213 nextToken();
1214 if (anon)
1216 /* Anonymous structs/unions are more like attributes.
1218 return new AnonDeclaration(loc, anon - 1, decl);
1220 else
1221 a->members = decl;
1223 else
1225 error("%s expected following aggregate declaration", Token::toChars(startBlockTok));
1226 a = new StructDeclaration(loc, NULL);
1229 if (tpl)
1230 { Array *decldefs;
1231 TemplateDeclaration *tempdecl;
1233 // Wrap a template around the aggregate declaration
1234 decldefs = new Array();
1235 decldefs->push(a);
1236 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs, dltSyntax);
1237 return tempdecl;
1240 return a;
1243 /*******************************************
1246 /* If current token is TOKcolon, TOKextends or TOKimplements, return
1247 * the bases. Otherwise, return null.
1249 BaseClasses *Parser::parseBaseClasses()
1251 enum PROT protection = PROTpublic;
1252 int type; // 1 = extends, 2 = implements, 3 = unknown
1254 if (dltSyntax) {
1255 if (token.value == TOKextends)
1256 type = 1;
1257 else if (token.value == TOKimplements)
1258 type = 2;
1259 else
1260 return NULL;
1261 } else {
1262 if (token.value == TOKcolon)
1263 type = 3;
1264 else
1265 return NULL;
1268 nextToken();
1270 BaseClasses *baseclasses = new BaseClasses();
1272 for (; 1; nextToken())
1274 switch (token.value)
1276 case TOKidentifier:
1277 break;
1278 case TOKprivate:
1279 protection = PROTprivate;
1280 continue;
1281 case TOKpackage:
1282 protection = PROTpackage;
1283 continue;
1284 case TOKprotected:
1285 protection = PROTprotected;
1286 continue;
1287 case TOKpublic:
1288 protection = PROTpublic;
1289 continue;
1290 default:
1291 error("base classes expected instead of %s", token.toChars());
1292 return NULL;
1294 BaseClass *b = new BaseClass(parseBasicType(), protection);
1295 baseclasses->push(b);
1297 protection = PROTpublic;
1299 switch (token.value) {
1300 case TOKcomma:
1301 continue;
1302 case TOKextends:
1303 if (type == 2)
1304 error("extends part must come before implements");
1305 else
1306 error("only one extends is permitted");
1307 continue;
1308 case TOKimplements:
1309 if (type == 1)
1310 type = 2;
1311 else
1312 error("separate implemented interfaces with commas");
1313 continue;
1315 break;
1317 return baseclasses;
1320 /**************************************
1321 * Parse a TemplateDeclaration.
1324 TemplateDeclaration *Parser::parseTemplateDeclaration()
1326 TemplateDeclaration *tempdecl;
1327 Identifier *id;
1328 TemplateParameters *tpl;
1329 Array *decldefs;
1330 Loc loc = this->loc;
1332 nextToken();
1333 if (token.value != TOKidentifier)
1334 { error("TemplateIdentifier expected following template");
1335 goto Lerr;
1337 id = token.ident;
1338 nextToken();
1339 tpl = parseTemplateParameterList();
1340 if (!tpl)
1341 goto Lerr;
1343 if (token.value != startBlockTok)
1344 { error("members of template declaration expected");
1345 goto Lerr;
1347 else
1349 nextToken();
1350 decldefs = parseDeclDefs(0);
1351 if (token.value != TOKrcurly)
1352 { error("template member expected");
1353 goto Lerr;
1355 nextToken();
1358 tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs, dltSyntax);
1359 return tempdecl;
1361 Lerr:
1362 return NULL;
1365 /******************************************
1366 * Parse template parameter list.
1369 TemplateParameters *Parser::parseTemplateParameterList()
1371 TemplateParameters *tpl = new TemplateParameters();
1373 if (token.value != TOKlparen)
1374 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1375 goto Lerr;
1377 nextToken();
1379 // Get array of TemplateParameters
1380 if (token.value != TOKrparen)
1381 { int isvariadic = 0;
1383 while (1)
1384 { TemplateParameter *tp;
1385 Identifier *tp_ident = NULL;
1386 Type *tp_spectype = NULL;
1387 Type *tp_valtype = NULL;
1388 Type *tp_defaulttype = NULL;
1389 Expression *tp_specvalue = NULL;
1390 Expression *tp_defaultvalue = NULL;
1391 Token *t;
1393 // Get TemplateParameter
1395 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1396 t = peek(&token);
1397 if (token.value == TOKalias)
1398 { // AliasParameter
1399 nextToken();
1400 if (token.value != TOKidentifier)
1401 { error("Identifier expected for template parameter");
1402 goto Lerr;
1404 tp_ident = token.ident;
1405 nextToken();
1406 if (token.value == TOKcolon) // : Type
1408 nextToken();
1409 tp_spectype = parseBasicType();
1410 tp_spectype = parseDeclarator(tp_spectype, NULL);
1412 if (token.value == TOKassign) // = Type
1414 nextToken();
1415 tp_defaulttype = parseBasicType();
1416 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1418 tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1420 else if (t->value == TOKcolon || t->value == TOKassign ||
1421 t->value == TOKcomma || t->value == TOKrparen)
1422 { // TypeParameter
1423 if (token.value != TOKidentifier)
1424 { error("Identifier expected for template parameter");
1425 goto Lerr;
1427 tp_ident = token.ident;
1428 nextToken();
1429 if (token.value == TOKcolon) // : Type
1431 nextToken();
1432 tp_spectype = parseBasicType();
1433 tp_spectype = parseDeclarator(tp_spectype, NULL);
1435 if (token.value == TOKassign) // = Type
1437 nextToken();
1438 tp_defaulttype = parseBasicType();
1439 tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
1441 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
1443 else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
1444 { // ident...
1445 if (isvariadic)
1446 error("variadic template parameter must be last");
1447 isvariadic = 1;
1448 tp_ident = token.ident;
1449 nextToken();
1450 nextToken();
1451 tp = new TemplateTupleParameter(loc, tp_ident);
1453 else
1454 { // ValueParameter
1455 tp_valtype = parseBasicType();
1456 tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
1457 if (!tp_ident)
1459 error("no identifier for template value parameter");
1460 tp_ident = new Identifier("error", TOKidentifier);
1462 if (token.value == TOKcolon) // : CondExpression
1464 nextToken();
1465 tp_specvalue = parseCondExp();
1467 if (token.value == TOKassign) // = CondExpression
1469 nextToken();
1470 tp_defaultvalue = parseCondExp();
1472 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
1474 tpl->push(tp);
1475 if (token.value != TOKcomma)
1476 break;
1477 nextToken();
1480 check(TOKrparen);
1481 Lerr:
1482 return tpl;
1485 /******************************************
1486 * Parse template mixin.
1487 * mixin Foo;
1488 * mixin Foo!(args);
1489 * mixin a.b.c!(args).Foo!(args);
1490 * mixin Foo!(args) identifier;
1491 * mixin typeof(expr).identifier!(args);
1494 Dsymbol *Parser::parseMixin()
1496 TemplateMixin *tm;
1497 Identifier *id;
1498 Type *tqual;
1499 Objects *tiargs;
1500 Array *idents;
1502 //printf("parseMixin()\n");
1503 nextToken();
1504 tqual = NULL;
1505 if (token.value == TOKdot)
1507 id = Id::empty;
1509 else
1511 if (token.value == TOKtypeof)
1512 { Expression *exp;
1514 nextToken();
1515 check(TOKlparen);
1516 exp = parseExpression();
1517 check(TOKrparen);
1518 tqual = new TypeTypeof(loc, exp);
1519 check(TOKdot);
1521 if (token.value != TOKidentifier)
1523 error("identifier expected, not %s", token.toChars());
1524 goto Lerr;
1526 id = token.ident;
1527 nextToken();
1530 idents = new Array();
1531 while (1)
1533 tiargs = NULL;
1534 if (token.value == TOKnot)
1536 nextToken();
1537 tiargs = parseTemplateArgumentList();
1540 if (token.value != TOKdot)
1541 break;
1543 if (tiargs)
1544 { TemplateInstance *tempinst = new TemplateInstance(loc, id);
1545 tempinst->tiargs = tiargs;
1546 id = (Identifier *)tempinst;
1547 tiargs = NULL;
1549 idents->push(id);
1551 nextToken();
1552 if (token.value != TOKidentifier)
1553 { error("identifier expected following '.' instead of '%s'", token.toChars());
1554 break;
1556 id = token.ident;
1557 nextToken();
1559 idents->push(id);
1561 if (token.value == TOKidentifier)
1563 id = token.ident;
1564 nextToken();
1566 else
1567 id = NULL;
1569 tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
1570 if (token.value != TOKsemicolon)
1571 error("';' expected after mixin");
1572 nextToken();
1574 return tm;
1576 Lerr:
1577 return NULL;
1580 /******************************************
1581 * Parse template argument list.
1582 * Input:
1583 * current token is opening '('
1584 * Output:
1585 * current token is one after closing ')'
1588 Objects *Parser::parseTemplateArgumentList()
1590 //printf("Parser::parseTemplateArgumentList()\n");
1591 Objects *tiargs = new Objects();
1592 if (token.value != TOKlparen)
1593 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1594 return tiargs;
1596 nextToken();
1598 // Get TemplateArgumentList
1599 if (token.value != TOKrparen)
1601 while (1)
1603 // See if it is an Expression or a Type
1604 if (isDeclaration(&token, 0, TOKreserved, NULL))
1605 { // Type
1606 Type *ta;
1608 // Get TemplateArgument
1609 ta = parseBasicType();
1610 ta = parseDeclarator(ta, NULL);
1611 tiargs->push(ta);
1613 else
1614 { // Expression
1615 Expression *ea;
1617 ea = parseAssignExp();
1618 tiargs->push(ea);
1620 if (token.value != TOKcomma)
1621 break;
1622 nextToken();
1625 check(TOKrparen, "template argument list");
1626 return tiargs;
1629 Import *Parser::parseImport(Array *decldefs, int isstatic)
1630 { Import *s;
1631 Identifier *id;
1632 Identifier *aliasid = NULL;
1633 Array *a;
1634 Loc loc;
1636 //printf("Parser::parseImport()\n");
1640 nextToken();
1641 if (token.value != TOKidentifier)
1642 { error("Identifier expected following import");
1643 break;
1646 loc = this->loc;
1647 a = NULL;
1648 id = token.ident;
1649 nextToken();
1650 if (!aliasid && token.value == TOKassign)
1652 aliasid = id;
1653 goto L1;
1655 while (token.value == TOKdot)
1657 if (!a)
1658 a = new Array();
1659 a->push(id);
1660 nextToken();
1661 if (token.value != TOKidentifier)
1662 { error("Identifier expected following package");
1663 break;
1665 id = token.ident;
1666 nextToken();
1669 s = new Import(loc, a, token.ident, aliasid, isstatic);
1670 decldefs->push(s);
1672 /* Look for
1673 * : alias=name, alias=name;
1674 * syntax.
1676 if (token.value == TOKcolon)
1678 nextToken();
1679 while (1)
1680 { Identifier *name;
1681 Identifier *alias;
1683 optionalEndline();
1685 if (dltSyntax && token.value == TOKrcurly)
1686 break;
1687 if (token.value != TOKidentifier)
1688 { error("Identifier expected following :");
1689 break;
1691 alias = token.ident;
1692 nextToken();
1693 if (token.value == TOKassign)
1695 nextToken();
1696 if (token.value != TOKidentifier)
1697 { error("Identifier expected following %s=", alias->toChars());
1698 break;
1700 name = token.ident;
1701 nextToken();
1703 else
1704 { name = alias;
1705 alias = NULL;
1707 s->addAlias(name, alias);
1708 if (token.value != TOKcomma && token.value != TOKendline)
1709 break;
1710 nextToken();
1712 if (dltSyntax)
1714 check(TOKrcurly);
1715 return NULL;
1717 else
1718 break;
1721 aliasid = NULL;
1722 } while (token.value == TOKcomma);
1724 if (token.value == TOKsemicolon || token.value == TOKendline)
1725 nextToken();
1726 else
1728 error("%s expected", endToken());
1729 nextToken();
1732 return NULL;
1735 Type *Parser::parseBasicType()
1736 { Type *t;
1737 Identifier *id;
1738 TypeQualified *tid;
1739 TemplateInstance *tempinst;
1741 //printf("parseBasicType()\n");
1742 switch (token.value)
1744 CASE_BASIC_TYPES_X(t):
1745 nextToken();
1746 break;
1748 case TOKidentifier:
1749 id = token.ident;
1750 nextToken();
1751 if (token.value == TOKnot)
1753 nextToken();
1754 tempinst = new TemplateInstance(loc, id);
1755 tempinst->tiargs = parseTemplateArgumentList();
1756 tid = new TypeInstance(loc, tempinst);
1757 goto Lident2;
1759 Lident:
1760 tid = new TypeIdentifier(loc, id);
1761 Lident2:
1762 while (token.value == TOKdot)
1763 { nextToken();
1764 if (token.value != TOKidentifier)
1765 { error("identifier expected following '.' instead of '%s'", token.toChars());
1766 break;
1768 id = token.ident;
1769 nextToken();
1770 if (token.value == TOKnot)
1772 nextToken();
1773 tempinst = new TemplateInstance(loc, id);
1774 tempinst->tiargs = parseTemplateArgumentList();
1775 tid->addIdent((Identifier *)tempinst);
1777 else
1778 tid->addIdent(id);
1780 t = tid;
1781 break;
1783 case TOKdot:
1784 id = Id::empty;
1785 goto Lident;
1787 case TOKtypeof:
1788 { Expression *exp;
1790 nextToken();
1791 check(TOKlparen);
1792 exp = parseExpression();
1793 check(TOKrparen);
1794 tid = new TypeTypeof(loc, exp);
1795 goto Lident2;
1798 default:
1799 error("basic type expected, not %s", token.toChars());
1800 t = Type::tint32;
1801 break;
1803 return t;
1806 Type *Parser::parseBasicType2(Type *t)
1808 Type *ts;
1809 Type *ta;
1811 //printf("parseBasicType2()\n");
1812 while (1)
1814 switch (token.value)
1816 case TOKmul:
1817 t = new TypePointer(t);
1818 nextToken();
1819 continue;
1821 case TOKlbracket:
1822 #if LTORARRAYDECL
1823 // Handle []. Make sure things like
1824 // int[3][1] a;
1825 // is (array[1] of array[3] of int)
1826 nextToken();
1827 if (token.value == TOKrbracket)
1829 t = new TypeDArray(t); // []
1830 nextToken();
1832 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1833 { // It's an associative array declaration
1834 Type *index;
1836 //printf("it's an associative array\n");
1837 index = parseBasicType();
1838 index = parseDeclarator(index, NULL); // [ type ]
1839 t = new TypeAArray(t, index);
1840 check(TOKrbracket);
1842 else
1844 //printf("it's [expression]\n");
1845 inBrackets++;
1846 Expression *e = parseExpression(); // [ expression ]
1847 if (token.value == TOKslice)
1848 { Expression *e2;
1850 nextToken();
1851 e2 = parseExpression(); // [ exp .. exp ]
1852 t = new TypeSlice(t, e, e2);
1854 else
1855 t = new TypeSArray(t,e);
1856 inBrackets--;
1857 check(TOKrbracket);
1859 continue;
1860 #else
1861 // Handle []. Make sure things like
1862 // int[3][1] a;
1863 // is (array[3] of array[1] of int)
1864 ts = t;
1865 while (token.value == TOKlbracket)
1867 nextToken();
1868 if (token.value == TOKrbracket)
1870 ta = new TypeDArray(t); // []
1871 nextToken();
1873 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1874 { // It's an associative array declaration
1875 Type *index;
1877 //printf("it's an associative array\n");
1878 index = parseBasicType();
1879 index = parseDeclarator(index, NULL); // [ type ]
1880 check(TOKrbracket);
1881 ta = new TypeAArray(t, index);
1883 else
1885 //printf("it's [expression]\n");
1886 Expression *e = parseExpression(); // [ expression ]
1887 ta = new TypeSArray(t,e);
1888 check(TOKrbracket);
1890 Type **pt;
1891 for (pt = &ts; *pt != t; pt = &(*pt)->next)
1893 *pt = ta;
1895 t = ts;
1896 continue;
1897 #endif
1899 case TOKdelegate:
1900 case TOKfunction:
1901 { // Handle delegate declaration:
1902 // t delegate(parameter list)
1903 // t function(parameter list)
1904 Arguments *arguments;
1905 int varargs;
1906 enum TOK save = token.value;
1908 nextToken();
1909 arguments = parseParameters(&varargs);
1910 t = new TypeFunction(arguments, t, varargs, linkage);
1911 if (save == TOKdelegate)
1912 t = new TypeDelegate(t);
1913 else
1914 t = new TypePointer(t); // pointer to function
1915 continue;
1918 case TOKquestion:
1919 if (dltSyntax)
1921 Type *old = t;
1922 t = t->maybe();
1923 if (t == old)
1924 error("Type %s cannot be null; ? is pointless", old->toChars());
1925 nextToken();
1926 continue;
1928 // fall-through to default
1930 default:
1931 ts = t;
1932 break;
1934 break;
1937 if (!dltSyntax)
1939 switch (ts->ty) {
1940 case Tident:
1941 // Don't wrap it yet, because that confuses resolve()
1942 ((TypeIdentifier *) ts)->maybe = 1;
1943 break;
1944 case Tpointer:
1945 // TypeMaybe will unwrap itself later if this isn't a nullable type
1946 ts = ts->maybe();
1947 break;
1951 return ts;
1954 Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
1955 { Type *ts;
1956 Type *ta;
1958 //printf("parseDeclarator(tpl = %p)\n", tpl);
1959 t = parseBasicType2(t);
1961 switch (token.value)
1964 case TOKidentifier:
1965 if (pident)
1966 *pident = token.ident;
1967 else
1968 error("unexpected identifer '%s' in declarator", token.ident->toChars());
1969 ts = t;
1970 nextToken();
1971 break;
1973 case TOKlparen:
1974 nextToken();
1975 ts = parseDeclarator(t, pident);
1976 check(TOKrparen);
1977 break;
1979 default:
1980 ts = t;
1981 break;
1984 while (1)
1986 switch (token.value)
1988 #if CARRAYDECL
1989 case TOKlbracket:
1990 { // This is the old C-style post [] syntax.
1991 nextToken();
1992 if (token.value == TOKrbracket)
1994 ta = new TypeDArray(t); // []
1995 nextToken();
1997 else if (isDeclaration(&token, 0, TOKrbracket, NULL))
1998 { // It's an associative array declaration
1999 Type *index;
2001 //printf("it's an associative array\n");
2002 index = parseBasicType();
2003 index = parseDeclarator(index, NULL); // [ type ]
2004 check(TOKrbracket);
2005 ta = new TypeAArray(t, index);
2007 else
2009 //printf("it's [expression]\n");
2010 Expression *e = parseExpression(); // [ expression ]
2011 ta = new TypeSArray(t, e);
2012 check(TOKrbracket);
2014 Type **pt;
2015 for (pt = &ts; *pt != t; pt = &(*pt)->next)
2017 *pt = ta;
2018 continue;
2020 #endif
2021 case TOKlparen:
2022 { Arguments *arguments;
2023 int varargs;
2025 if (tpl)
2027 /* Look ahead to see if this is (...)(...),
2028 * i.e. a function template declaration
2030 if (peekPastParen(&token)->value == TOKlparen)
2031 { // It's a function template declaration
2032 //printf("function template declaration\n");
2034 // Gather template parameter list
2035 *tpl = parseTemplateParameterList();
2039 arguments = parseParameters(&varargs);
2040 Type *ta = new TypeFunction(arguments, t, varargs, linkage);
2041 Type **pt;
2042 for (pt = &ts; *pt != t; pt = &(*pt)->next)
2044 *pt = ta;
2045 break;
2048 break;
2051 return ts;
2054 /**********************************
2055 * Return array of Declaration *'s.
2058 Array *Parser::parseDeclarations()
2060 enum STC storage_class;
2061 enum STC stc;
2062 Type *ts;
2063 Type *t;
2064 Type *tfirst;
2065 Identifier *ident;
2066 Array *a;
2067 enum TOK tok;
2068 unsigned char *comment = token.blockComment;
2069 enum LINK link = linkage;
2071 //printf("parseDeclarations()\n");
2072 switch (token.value)
2074 case TOKtypedef:
2075 case TOKalias:
2076 tok = token.value;
2077 nextToken();
2078 break;
2080 default:
2081 tok = TOKreserved;
2082 break;
2085 storage_class = STCundefined;
2086 while (1)
2088 switch (token.value)
2090 case TOKconst: stc = STCconst; goto L1;
2091 case TOKstatic: stc = STCstatic; goto L1;
2092 case TOKfinal: stc = STCfinal; goto L1;
2093 case TOKauto: stc = STCauto; goto L1;
2094 case TOKscope: stc = STCscope; goto L1;
2095 case TOKoverride: stc = STCoverride; goto L1;
2096 case TOKabstract: stc = STCabstract; goto L1;
2097 case TOKsynchronized: stc = STCsynchronized; goto L1;
2098 case TOKdeprecated: stc = STCdeprecated; goto L1;
2100 if (storage_class & stc)
2101 error("redundant storage class '%s'", token.toChars());
2102 storage_class = (STC) (storage_class | stc);
2103 nextToken();
2104 continue;
2106 case TOKextern:
2107 if (peek(&token)->value != TOKlparen)
2108 { stc = STCextern;
2109 goto L1;
2112 link = parseLinkage();
2113 continue;
2115 default:
2116 break;
2118 break;
2121 a = new Array();
2123 /* Look for auto initializers:
2124 * storage_class identifier = initializer;
2126 while (storage_class &&
2127 token.value == TOKidentifier &&
2128 peek(&token)->value == TOKassign)
2130 ident = token.ident;
2131 nextToken();
2132 nextToken();
2133 Initializer *init = parseInitializer();
2134 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
2135 v->storage_class = storage_class;
2136 a->push(v);
2137 if (token.value == TOKsemicolon || token.value == TOKendline)
2139 nextToken();
2140 addComment(v, comment);
2142 else if (token.value == TOKcomma)
2144 nextToken();
2145 if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
2147 error("Identifier expected following comma");
2149 else
2150 continue;
2152 else
2153 error("%s expected following auto declaration, not '%s'", endToken(), token.toChars());
2154 return a;
2157 if (token.value == TOKclass)
2158 { AggregateDeclaration *s;
2160 s = (AggregateDeclaration *)parseAggregate();
2161 s->storage_class |= storage_class;
2162 a->push(s);
2163 addComment(s, comment);
2164 return a;
2167 ts = parseBasicType();
2168 ts = parseBasicType2(ts);
2169 tfirst = NULL;
2171 while (1)
2173 Loc loc = this->loc;
2174 TemplateParameters *tpl = NULL;
2176 ident = NULL;
2177 t = parseDeclarator(ts, &ident, &tpl);
2178 assert(t);
2179 if (!tfirst)
2180 tfirst = t;
2181 else if (t != tfirst)
2182 error("multiple declarations must have the same type, not %s and %s",
2183 tfirst->toChars(), t->toChars());
2184 if (!ident)
2185 error("no identifier for declarator %s", t->toChars());
2187 if (tok == TOKtypedef || tok == TOKalias)
2188 { Declaration *v;
2189 Initializer *init;
2191 if (!dltSyntax)
2193 /* Unwrap maybe qualifiers from aliases.
2194 * Otherwise, it thinks we're aliasing types when we're not.
2196 if (t->ty == Tmaybe) {
2197 t = t->next;
2201 init = NULL;
2202 if (token.value == TOKassign)
2204 nextToken();
2205 init = parseInitializer();
2207 if (tok == TOKtypedef)
2208 v = new TypedefDeclaration(loc, ident, t, init);
2209 else
2210 { if (init)
2211 error("alias cannot have initializer");
2212 v = new AliasDeclaration(loc, ident, t);
2214 v->storage_class = storage_class;
2215 if (link == linkage)
2216 a->push(v);
2217 else
2219 Array *ax = new Array();
2220 ax->push(v);
2221 Dsymbol *s = new LinkDeclaration(link, ax);
2222 a->push(s);
2224 switch (token.value)
2225 { case TOKsemicolon:
2226 case TOKendline:
2227 nextToken();
2228 addComment(v, comment);
2229 break;
2231 case TOKcomma:
2232 nextToken();
2233 addComment(v, comment);
2234 continue;
2236 default:
2237 error("%s expected to close %s declaration", endToken(), Token::toChars(tok));
2238 break;
2241 else if (t->ty == Tfunction)
2242 { FuncDeclaration *f;
2243 Dsymbol *s;
2245 f = new FuncDeclaration(loc, 0, ident, storage_class, t);
2246 addComment(f, comment);
2247 parseContracts(f);
2248 addComment(f, NULL);
2249 if (link == linkage)
2251 s = f;
2253 else
2255 Array *ax = new Array();
2256 ax->push(f);
2257 s = new LinkDeclaration(link, ax);
2259 if (tpl) // it's a function template
2260 { Array *decldefs;
2261 TemplateDeclaration *tempdecl;
2263 // Wrap a template around the aggregate declaration
2264 decldefs = new Array();
2265 decldefs->push(s);
2266 tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs, dltSyntax);
2267 s = tempdecl;
2269 addComment(s, comment);
2270 a->push(s);
2272 else
2273 { VarDeclaration *v;
2274 Initializer *init;
2276 init = NULL;
2277 if (token.value == TOKassign)
2279 nextToken();
2280 init = parseInitializer();
2282 v = new VarDeclaration(loc, t, ident, init);
2283 v->storage_class = storage_class;
2284 if (link == linkage)
2285 a->push(v);
2286 else
2288 Array *ax = new Array();
2289 ax->push(v);
2290 Dsymbol *s = new LinkDeclaration(link, ax);
2291 a->push(s);
2293 switch (token.value)
2295 case TOKendline:
2296 nextToken();
2297 addComment(v, comment);
2298 break;
2299 case TOKsemicolon:
2300 if (!dltSyntax)
2301 nextToken();
2302 addComment(v, comment);
2303 break;
2304 case TOKcomma:
2305 nextToken();
2306 addComment(v, comment);
2307 continue;
2309 default:
2310 error("%s expected, not '%s'", endToken(), token.toChars());
2311 break;
2314 break;
2316 return a;
2319 /*****************************************
2320 * Parse contracts following function declaration.
2323 void Parser::parseContracts(FuncDeclaration *f)
2325 Type *tb;
2326 enum LINK linksave = linkage;
2328 // The following is irrelevant, as it is overridden by sc->linkage in
2329 // TypeFunction::semantic
2330 linkage = LINKd; // nested functions have D linkage
2332 switch (token.value)
2334 case TOKlcurly:
2335 case TOKcolon:
2336 if (token.value != startBlockTok)
2337 error("use %s to start a new block", Token::toChars(startBlockTok));
2338 if (f->frequire || f->fensure)
2339 error("missing body { ... } after in or out");
2340 f->fbody = parseStatement(PSsemi | PScolon);
2341 f->endloc = endloc;
2342 break;
2344 case TOKbody:
2345 nextToken();
2346 f->fbody = parseStatement(PScurly);
2347 f->endloc = endloc;
2348 break;
2350 case TOKsemicolon:
2351 if (dltSyntax)
2352 error("unexpected semi-colon after function declaration");
2353 // fall-through
2354 case TOKendline:
2355 if (f->frequire || f->fensure)
2356 error("missing body { ... } after in or out");
2357 nextToken();
2358 break;
2360 #if 0 // Do we want this for function declarations, so we can do:
2361 // int x, y, foo(), z;
2362 case TOKcomma:
2363 nextToken();
2364 continue;
2365 #endif
2367 #if 0 // Dumped feature
2368 case TOKthrow:
2369 if (!f->fthrows)
2370 f->fthrows = new Array();
2371 nextToken();
2372 check(TOKlparen);
2373 while (1)
2375 tb = parseBasicType();
2376 f->fthrows->push(tb);
2377 if (token.value == TOKcomma)
2378 { nextToken();
2379 continue;
2381 break;
2383 check(TOKrparen);
2384 goto L1;
2385 #endif
2387 case TOKin:
2388 nextToken();
2389 if (f->frequire)
2390 error("redundant 'in' statement");
2391 f->frequire = parseStatement(PScurly | PSscope);
2392 goto L1;
2394 case TOKout:
2395 // parse: out (identifier) { statement }
2396 nextToken();
2397 if (token.value != startBlockTok)
2399 check(TOKlparen);
2400 if (token.value != TOKidentifier)
2401 error("(identifier) following 'out' expected, not %s", token.toChars());
2402 f->outId = token.ident;
2403 nextToken();
2404 check(TOKrparen);
2406 if (f->fensure)
2407 error("redundant 'out' statement");
2408 f->fensure = parseStatement(PScurly | PSscope);
2409 goto L1;
2411 default:
2412 error("%s expected following function declaration", endToken());
2413 break;
2415 linkage = linksave;
2418 /*****************************************
2421 Initializer *Parser::parseInitializer()
2423 StructInitializer *is;
2424 ArrayInitializer *ia;
2425 ExpInitializer *ie;
2426 Expression *e;
2427 Identifier *id;
2428 Initializer *value;
2429 int comma;
2430 Loc loc = this->loc;
2431 Token *t;
2432 int braces;
2434 switch (token.value)
2436 case TOKlcurly:
2437 /* Scan ahead to see if it is a struct initializer or
2438 * a function literal.
2439 * If it contains a ';', it is a function literal.
2440 * Treat { } as a struct initializer.
2442 braces = 1;
2443 for (t = peek(&token); 1; t = peek(t))
2445 switch (t->value)
2447 case TOKsemicolon:
2448 case TOKreturn:
2449 goto Lexpression;
2451 case TOKlcurly:
2452 braces++;
2453 continue;
2455 case TOKrcurly:
2456 if (--braces == 0)
2457 break;
2458 continue;
2460 case TOKeof:
2461 break;
2463 default:
2464 continue;
2466 break;
2469 is = new StructInitializer(loc);
2470 nextToken();
2471 comma = 0;
2472 while (1)
2474 switch (token.value)
2476 case TOKidentifier:
2477 if (comma == 1)
2478 error("comma expected separating field initializers");
2479 t = peek(&token);
2480 if (t->value == TOKcolon)
2482 id = token.ident;
2483 nextToken();
2484 nextToken(); // skip over ':'
2486 else
2487 { id = NULL;
2489 value = parseInitializer();
2490 is->addInit(id, value);
2491 comma = 1;
2492 continue;
2494 case TOKcomma:
2495 nextToken();
2496 comma = 2;
2497 continue;
2499 case TOKrcurly: // allow trailing comma's
2500 nextToken();
2501 break;
2503 case TOKeof:
2504 error("found EOF instead of initializer");
2505 break;
2507 default:
2508 value = parseInitializer();
2509 is->addInit(NULL, value);
2510 comma = 1;
2511 continue;
2512 //error("found '%s' instead of field initializer", token.toChars());
2513 //break;
2515 break;
2517 return is;
2519 case TOKlbracket:
2520 ia = new ArrayInitializer(loc);
2521 nextToken();
2522 comma = 0;
2523 while (1)
2525 switch (token.value)
2527 default:
2528 if (comma == 1)
2529 { error("comma expected separating array initializers, not %s", token.toChars());
2530 nextToken();
2531 break;
2533 e = parseAssignExp();
2534 if (!e)
2535 break;
2536 if (token.value == TOKcolon)
2538 nextToken();
2539 value = parseInitializer();
2541 else
2542 { value = new ExpInitializer(e->loc, e);
2543 e = NULL;
2545 ia->addInit(e, value);
2546 comma = 1;
2547 continue;
2549 case TOKlcurly:
2550 case TOKlbracket:
2551 if (comma == 1)
2552 error("comma expected separating array initializers, not %s", token.toChars());
2553 value = parseInitializer();
2554 ia->addInit(NULL, value);
2555 comma = 1;
2556 continue;
2558 case TOKcomma:
2559 nextToken();
2560 comma = 2;
2561 continue;
2563 case TOKrbracket: // allow trailing comma's
2564 nextToken();
2565 break;
2567 case TOKeof:
2568 error("found '%s' instead of array initializer", token.toChars());
2569 break;
2571 break;
2573 return ia;
2575 case TOKvoid:
2576 t = peek(&token);
2577 if (t->value == TOKsemicolon || t->value == TOKcomma || t->value == TOKendline)
2579 nextToken();
2580 return new VoidInitializer(loc);
2582 goto Lexpression;
2584 default:
2585 Lexpression:
2586 e = parseAssignExp();
2587 ie = new ExpInitializer(loc, e);
2588 return ie;
2592 Statement *Parser::logStatement(int level) {
2593 nextToken();
2594 if (token.value != TOKlparen)
2595 error(loc, "found '%s' when expecting '('", token.toChars());
2596 return new LogStatement(loc, level, parseArguments());
2599 /*****************************************
2600 * Input:
2601 * flags PSxxxx
2604 Statement *DltParser::parseStatement(int flags)
2606 optionalEndline();
2607 if (flags & (PScolon | PSscope))
2608 flags |= PScurly;
2609 return Parser::parseStatement(flags);
2612 Statement *Parser::parseStatement(int flags)
2613 { Statement *s;
2614 Token *t;
2615 Condition *condition;
2616 Statement *ifbody;
2617 Statement *elsebody;
2618 Loc loc = this->loc;
2620 //printf("parseStatement()\n");
2622 if ((flags & PScurly) && token.value != startBlockTok)
2623 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2625 int tok = token.value;
2627 switch (token.value)
2629 case TOKidentifier:
2630 if (!dltSyntax)
2632 // Need to look ahead to see if it is a declaration, label, or expression
2633 t = peek(&token);
2634 if (t->value == TOKcolon)
2635 { // It's a label
2636 Identifier *ident;
2638 ident = token.ident;
2639 nextToken();
2640 nextToken();
2641 s = parseStatement(PSsemi);
2642 s = new LabelStatement(loc, ident, s);
2643 break;
2646 // fallthrough to TOKdot
2647 case TOKdot:
2648 case TOKtypeof:
2649 if (isDeclaration(&token, 2, TOKreserved, NULL))
2650 goto Ldeclaration;
2651 else
2652 goto Lexp;
2653 break;
2655 case TOKassert:
2656 case TOKthis:
2657 case TOKsuper:
2658 case TOKint32v:
2659 case TOKuns32v:
2660 case TOKint64v:
2661 case TOKuns64v:
2662 case TOKfloat32v:
2663 case TOKfloat64v:
2664 case TOKfloat80v:
2665 case TOKimaginary32v:
2666 case TOKimaginary64v:
2667 case TOKimaginary80v:
2668 case TOKcharv:
2669 case TOKwcharv:
2670 case TOKdcharv:
2671 case TOKnull:
2672 case TOKtrue:
2673 case TOKfalse:
2674 case TOKstring:
2675 case TOKlparen:
2676 case TOKcast:
2677 case TOKmul:
2678 case TOKmin:
2679 case TOKadd:
2680 case TOKplusplus:
2681 case TOKminusminus:
2682 case TOKnew:
2683 case TOKdelete:
2684 case TOKdelegate:
2685 case TOKfunction:
2686 case TOKtypeid:
2687 case TOKis:
2688 case TOKlbracket:
2689 Lexp:
2690 { Expression *exp;
2692 exp = parseExpression();
2693 if (!dltSyntax)
2694 check(TOKsemicolon, "statement");
2695 s = new ExpStatement(loc, exp);
2696 break;
2699 case TOKstatic:
2700 { // Look ahead to see if it's static assert() or static if()
2701 Token *t;
2703 t = peek(&token);
2704 if (t->value == TOKassert)
2706 nextToken();
2707 s = new StaticAssertStatement(parseStaticAssert());
2708 break;
2710 if (t->value == TOKif)
2712 nextToken();
2713 condition = parseStaticIfCondition();
2714 goto Lcondition;
2716 if (dltNormalMode)
2717 error("no static variables in Delight");
2718 goto Ldeclaration;
2721 CASE_BASIC_TYPES:
2722 case TOKtypedef:
2723 case TOKalias:
2724 case TOKconst:
2725 case TOKauto:
2726 case TOKextern:
2727 case TOKfinal:
2728 case TOKinvariant:
2729 // case TOKtypeof:
2730 Ldeclaration:
2731 { Array *a;
2733 a = parseDeclarations();
2734 if (a->dim > 1)
2736 Statements *as = new Statements();
2737 as->reserve(a->dim);
2738 for (int i = 0; i < a->dim; i++)
2740 Dsymbol *d = (Dsymbol *)a->data[i];
2741 s = new DeclarationStatement(loc, d);
2742 as->push(s);
2744 s = new CompoundStatement(loc, as);
2746 else if (a->dim == 1)
2748 Dsymbol *d = (Dsymbol *)a->data[0];
2749 s = new DeclarationStatement(loc, d);
2751 else
2752 assert(0);
2753 if (flags & PSscope)
2754 s = new ScopeStatement(loc, s);
2755 break;
2758 case TOKstruct:
2759 case TOKunion:
2760 case TOKclass:
2761 case TOKinterface:
2762 { Dsymbol *d;
2764 d = parseAggregate();
2765 s = new DeclarationStatement(loc, d);
2766 break;
2769 case TOKenum:
2770 { Dsymbol *d;
2772 d = parseEnum();
2773 s = new DeclarationStatement(loc, d);
2774 break;
2777 case TOKmixin:
2778 { t = peek(&token);
2779 if (t->value == TOKlparen)
2780 { // mixin(string)
2781 nextToken();
2782 check(TOKlparen, "mixin");
2783 Expression *e = parseAssignExp();
2784 check(TOKrparen);
2785 if (dltSyntax) {
2786 if (token.value != TOKsemicolon && token.value != TOKendline) {
2787 error("expected newline after mixin(), not '%s'", token.toChars());
2789 } else {
2790 check(TOKsemicolon);
2792 s = new CompileStatement(loc, e);
2793 break;
2795 Dsymbol *d = parseMixin();
2796 s = new DeclarationStatement(loc, d);
2797 break;
2800 case TOKcolon:
2801 case TOKlcurly:
2802 { Statements *statements;
2804 if (token.value != startBlockTok)
2805 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2807 nextToken();
2808 optionalEndline();
2809 statements = new Statements();
2810 while (token.value != TOKrcurly)
2812 statements->push(parseStatement(PSsemi | PScurlyscope));
2813 optionalEndline();
2815 endloc = this->loc;
2816 s = new CompoundStatement(loc, statements);
2817 if (flags & (PSscope | PScurlyscope))
2818 s = new ScopeStatement(loc, s);
2819 nextToken();
2820 break;
2823 case TOKlog_error: s = logStatement(LogStatement::Error); break;
2824 case TOKlog_warning: s = logStatement(LogStatement::Warn); break;
2825 case TOKlog_info: s = logStatement(LogStatement::Info); break;
2826 case TOKlog_trace: s = logStatement(LogStatement::Trace); break;
2828 case TOKwhile:
2829 { Expression *condition;
2830 Statement *body;
2832 nextToken();
2833 checkLParen();
2834 condition = parseExpression();
2835 checkRParen();
2836 body = parseStatement(PSscope);
2837 s = new WhileStatement(loc, condition, body);
2838 break;
2841 case TOKsemicolon:
2842 if (!(flags & PSsemi))
2843 error("use '{ }' for an empty statement, not a ';'");
2844 nextToken();
2845 s = new ExpStatement(loc, NULL);
2846 break;
2848 case TOKdo:
2849 { Statement *body;
2850 Expression *condition;
2852 nextToken();
2853 body = parseStatement(PSscope);
2854 check(TOKwhile);
2855 checkLParen();
2856 condition = parseExpression();
2857 checkRParen();
2858 s = new DoStatement(loc, body, condition);
2859 break;
2862 case TOKfor:
2864 Statement *init;
2865 Expression *condition;
2866 Expression *increment;
2867 Statement *body;
2869 nextToken();
2871 if (token.value == TOKlparen) {
2872 /* for (init; cond; incr): ... */
2873 nextToken();
2874 if (token.value == TOKsemicolon)
2875 { init = NULL;
2876 nextToken();
2878 else
2879 { init = parseStatement(0);
2880 if (dltSyntax)
2881 check(TOKsemicolon);
2883 if (token.value == TOKsemicolon)
2885 condition = NULL;
2886 nextToken();
2888 else
2890 condition = parseExpression();
2891 check(TOKsemicolon, "for condition");
2893 if (token.value == TOKrparen)
2894 { increment = NULL;
2895 nextToken();
2897 else
2898 { increment = parseExpression();
2899 check(TOKrparen);
2901 body = parseStatement(PSscope);
2902 s = new ForStatement(loc, init, condition, increment, body);
2903 if (init)
2904 s = new ScopeStatement(loc, s);
2905 } else if (dltSyntax)
2906 goto caseForeach;
2907 break;
2910 caseForeach:
2911 case TOKforeach:
2912 case TOKforeach_reverse:
2914 /* for var in seq: ... */
2915 /* for index, var in seq: ... */
2916 Arguments *arguments;
2918 Statement *d;
2919 Statement *body;
2920 Expression *aggr;
2921 enum TOK op = (TOK) tok;
2923 if (tok != TOKfor)
2924 nextToken();
2926 checkLParen();
2928 TOK inTok = dltSyntax ? TOKin : TOKsemicolon;
2930 arguments = new Arguments();
2932 while (1)
2934 Type *tb;
2935 Identifier *ai = NULL;
2936 Type *at;
2937 unsigned storageClass;
2938 Argument *a;
2940 storageClass = STCin;
2941 if (token.value == TOKinout || token.value == TOKref)
2942 { storageClass = STCref;
2943 nextToken();
2945 if (token.value == TOKidentifier)
2947 Token *t = peek(&token);
2948 if (t->value == TOKcomma || t->value == inTok)
2949 { ai = token.ident;
2950 at = NULL; // infer argument type
2951 nextToken();
2952 goto Larg;
2955 tb = parseBasicType();
2956 at = parseDeclarator(tb, &ai);
2957 if (!ai)
2958 error("no identifier for declarator %s", at->toChars());
2959 Larg:
2960 a = new Argument(storageClass, at, ai, NULL);
2961 arguments->push(a);
2962 if (token.value == TOKcomma)
2963 { nextToken();
2964 continue;
2966 break;
2969 check(inTok);
2971 aggr = parseExpression();
2972 checkRParen();
2974 if (dltSyntax) {
2975 if (token.value == TOKreversed) {
2976 op = TOKforeach_reverse;
2977 nextToken();
2978 } else {
2979 op = TOKforeach;
2983 body = parseStatement(PScolon);
2984 s = new ForeachStatement(loc, op, arguments, aggr, body);
2985 break;
2988 case TOKif:
2989 { Argument *arg = NULL;
2990 Expression *condition;
2991 Statement *ifbody;
2992 Statement *elsebody;
2994 nextToken();
2995 checkLParen();
2997 if (token.value == TOKauto)
2999 nextToken();
3000 if (token.value == TOKidentifier)
3002 Token *t = peek(&token);
3003 if (t->value == TOKassign)
3005 arg = new Argument(STCin, NULL, token.ident, NULL);
3006 nextToken();
3007 nextToken();
3009 else
3010 { error("= expected following auto identifier");
3011 goto Lerror;
3014 else
3015 { error("identifier expected following auto");
3016 goto Lerror;
3019 else if (isDeclaration(&token, 2, TOKassign, NULL))
3021 Type *tb;
3022 Type *at;
3023 Identifier *ai;
3025 tb = parseBasicType();
3026 at = parseDeclarator(tb, &ai);
3027 check(TOKassign);
3028 arg = new Argument(STCin, at, ai, NULL);
3031 // Check for " ident;"
3032 else if (token.value == TOKidentifier && !dltSyntax)
3034 Token *t = peek(&token);
3035 if (t->value == TOKcomma || t->value == TOKsemicolon)
3037 arg = new Argument(STCin, NULL, token.ident, NULL);
3038 nextToken();
3039 nextToken();
3040 if (1 || !global.params.useDeprecated)
3041 error("if (v; e) is deprecated, use if (auto v = e)");
3045 condition = parseExpression();
3046 checkRParen();
3047 ifbody = parseStatement(PSscope);
3048 if (token.value == TOKelse)
3050 nextToken();
3051 if (dltSyntax)
3053 if (token.value == TOKcolon) {
3054 elsebody = parseStatement(PSscope);
3055 } else if (token.value == TOKif) {
3056 elsebody = parseStatement(0);
3057 } else {
3058 error("Expected 'else:' or 'else if', not 'else %s'", token.toChars());
3059 elsebody = NULL;
3062 else
3063 elsebody = parseStatement(PSscope);
3065 else
3066 elsebody = NULL;
3067 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
3068 break;
3071 case TOKscope:
3072 if (peek(&token)->value != TOKlparen)
3073 goto Ldeclaration; // scope used as storage class
3074 nextToken();
3075 check(TOKlparen);
3076 if (token.value != TOKidentifier)
3077 { error("scope identifier expected");
3078 goto Lerror;
3080 else
3081 { TOK t = TOKon_scope_exit;
3082 Identifier *id = token.ident;
3084 if (id == Id::exit)
3085 t = TOKon_scope_exit;
3086 else if (id == Id::failure)
3087 t = TOKon_scope_failure;
3088 else if (id == Id::success)
3089 t = TOKon_scope_success;
3090 else
3091 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
3092 nextToken();
3093 check(TOKrparen);
3094 Statement *st = parseStatement(PScolon | PScurlyscope);
3095 s = new OnScopeStatement(loc, t, st);
3096 break;
3099 case TOKdebug:
3100 nextToken();
3101 condition = parseDebugCondition();
3102 goto Lcondition;
3104 case TOKversion:
3105 nextToken();
3106 condition = parseVersionCondition();
3107 goto Lcondition;
3109 Lcondition:
3110 if (dltSyntax && token.value != TOKcolon)
3111 error("expected colon after condition, not '%s'", token.toChars());
3112 ifbody = parseStatement(PScolon /*PSsemi*/);
3113 elsebody = NULL;
3114 if (token.value == TOKelse)
3116 nextToken();
3117 elsebody = parseStatement(PScolon /*PSsemi*/);
3119 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
3120 break;
3122 case TOKpragma:
3123 { Identifier *ident;
3124 Expressions *args = NULL;
3125 Statement *body;
3127 nextToken();
3128 check(TOKlparen);
3129 if (token.value != TOKidentifier)
3130 { error("pragma(identifier expected");
3131 goto Lerror;
3133 ident = token.ident;
3134 nextToken();
3135 if (token.value == TOKcomma)
3136 args = parseArguments(); // pragma(identifier, args...);
3137 else
3138 check(TOKrparen); // pragma(identifier);
3139 if (token.value == TOKsemicolon)
3140 { nextToken();
3141 body = NULL;
3143 else
3144 body = parseStatement(PSsemi | PScolon);
3145 s = new PragmaStatement(loc, ident, args, body);
3146 break;
3149 case TOKswitch:
3150 { Expression *condition;
3151 Statement *body;
3153 nextToken();
3154 checkLParen();
3155 condition = parseExpression();
3156 checkRParen();
3157 body = parseStatement(PSscope | PScolon);
3158 s = new SwitchStatement(loc, condition, body);
3159 break;
3162 case TOKcase:
3163 { Expression *exp;
3164 Statements *statements;
3165 Array cases; // array of Expression's
3167 while (1)
3169 nextToken();
3170 exp = parseAssignExp();
3171 cases.push(exp);
3172 if (token.value != TOKcomma)
3173 break;
3176 if (dltSyntax)
3178 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3180 else
3182 check(TOKcolon);
3184 statements = new Statements();
3185 while (token.value != TOKcase &&
3186 token.value != TOKdefault &&
3187 token.value != TOKrcurly)
3189 statements->push(parseStatement(PSsemi | PScurlyscope));
3191 s = new CompoundStatement(loc, statements);
3194 s = new ScopeStatement(loc, s);
3196 // Keep cases in order by building the case statements backwards
3197 for (int i = cases.dim; i; i--)
3199 exp = (Expression *)cases.data[i - 1];
3200 s = new CaseStatement(loc, exp, s);
3202 break;
3205 case TOKdefault:
3207 Statements *statements;
3209 nextToken();
3211 if (dltSyntax)
3213 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3215 else
3217 check(TOKcolon);
3219 statements = new Statements();
3220 while (token.value != TOKcase &&
3221 token.value != TOKdefault &&
3222 token.value != TOKrcurly)
3224 statements->push(parseStatement(PSsemi | PScurlyscope));
3226 s = new CompoundStatement(loc, statements);
3229 s = new ScopeStatement(loc, s);
3230 s = new DefaultStatement(loc, s);
3231 break;
3234 case TOKreturn:
3235 { Expression *exp;
3237 nextToken();
3238 if (token.value == TOKsemicolon || token.value == TOKendline)
3239 exp = NULL;
3240 else
3241 exp = parseExpression();
3243 if (!dltSyntax)
3244 check(TOKsemicolon, "return statement");
3245 else if (token.value != TOKendline) {
3246 error("Expected end-of-line after return statement, but found '%s'", token.toChars());
3249 s = new ReturnStatement(loc, exp);
3250 break;
3253 case TOKbreak:
3254 { Identifier *ident;
3256 nextToken();
3257 if (token.value == TOKidentifier)
3258 { ident = token.ident;
3259 nextToken();
3261 else
3262 ident = NULL;
3263 if (token.value != TOKsemicolon && token.value != TOKendline) {
3264 error("expected %s after break, not '%s'", endToken(), token.toChars());
3266 if (!dltSyntax)
3267 nextToken();
3268 s = new BreakStatement(loc, ident);
3269 break;
3272 case TOKcontinue:
3273 { Identifier *ident;
3275 nextToken();
3276 if (token.value == TOKidentifier)
3277 { ident = token.ident;
3278 nextToken();
3280 else
3281 ident = NULL;
3282 check(TOKsemicolon, "continue statement");
3283 s = new ContinueStatement(loc, ident);
3284 break;
3287 case TOKgoto:
3288 { Identifier *ident;
3290 nextToken();
3291 if (token.value == TOKdefault)
3293 nextToken();
3294 s = new GotoDefaultStatement(loc);
3296 else if (token.value == TOKcase)
3298 Expression *exp = NULL;
3300 nextToken();
3301 if (token.value != TOKsemicolon)
3302 exp = parseExpression();
3303 s = new GotoCaseStatement(loc, exp);
3305 else
3307 if (token.value != TOKidentifier)
3308 { error("Identifier expected following goto");
3309 ident = NULL;
3311 else
3312 { ident = token.ident;
3313 nextToken();
3315 s = new GotoStatement(loc, ident);
3317 if (token.value != TOKsemicolon && token.value != TOKendline) {
3318 error("expected %s after goto statement, not '%s'", endToken(), token.toChars());
3320 break;
3323 case TOKsynchronized:
3324 { Expression *exp;
3325 Statement *body;
3327 nextToken();
3328 if (token.value == TOKlparen)
3330 nextToken();
3331 exp = parseExpression();
3332 check(TOKrparen);
3334 else
3335 exp = NULL;
3336 body = parseStatement(PSscope);
3337 s = new SynchronizedStatement(loc, exp, body);
3338 break;
3341 case TOKwith:
3342 { Expression *exp;
3343 Statement *body;
3345 nextToken();
3346 check(TOKlparen);
3347 exp = parseExpression();
3348 check(TOKrparen);
3349 body = parseStatement(PSscope);
3350 s = new WithStatement(loc, exp, body);
3351 break;
3354 case TOKtry:
3355 { Statement *body;
3356 Array *catches = NULL;
3357 Statement *finalbody = NULL;
3359 nextToken();
3360 body = parseStatement(PSscope);
3361 while (token.value == TOKcatch)
3363 Statement *handler;
3364 Catch *c;
3365 Type *t;
3366 Identifier *id;
3367 Loc loc = this->loc;
3369 nextToken();
3370 if (token.value == startBlockTok)
3372 t = NULL;
3373 id = NULL;
3375 else
3377 check(TOKlparen);
3378 t = parseBasicType();
3379 id = NULL;
3380 t = parseDeclarator(t, &id);
3381 check(TOKrparen);
3383 handler = parseStatement(PScolon);
3384 c = new Catch(loc, t, id, handler);
3385 if (!catches)
3386 catches = new Array();
3387 catches->push(c);
3390 if (token.value == TOKfinally)
3391 { nextToken();
3392 finalbody = parseStatement(PScolon);
3395 s = body;
3396 if (!catches && !finalbody)
3397 error("catch or finally expected following try");
3398 else
3399 { if (catches)
3400 s = new TryCatchStatement(loc, body, catches);
3401 if (finalbody)
3402 s = new TryFinallyStatement(loc, s, finalbody);
3404 break;
3407 case TOKthrow:
3408 { Expression *exp;
3410 nextToken();
3411 exp = parseExpression();
3412 if (token.value != TOKsemicolon && token.value != TOKendline) {
3413 error("%s expected after throw statement, not '%s'", endToken(), token.toChars());
3415 if (!dltSyntax)
3416 nextToken();
3417 s = new ThrowStatement(loc, exp);
3418 break;
3421 case TOKvolatile:
3422 nextToken();
3423 s = parseStatement(PSsemi | PScurlyscope);
3424 s = new VolatileStatement(loc, s);
3425 break;
3427 case TOKasm:
3428 { Statements *statements;
3429 Identifier *label;
3430 Loc labelloc;
3431 Token *toklist;
3432 Token **ptoklist;
3434 // Parse the asm block into a sequence of AsmStatements,
3435 // each AsmStatement is one instruction.
3436 // Separate out labels.
3437 // Defer parsing of AsmStatements until semantic processing.
3439 nextToken();
3440 #if GDC_EXTENDED_ASM_SYNTAX
3441 if (token.value == TOKlparen)
3443 nextToken();
3444 s = parseExtAsm(1);
3445 break;
3447 #endif
3448 check(startBlockTok);
3449 toklist = NULL;
3450 ptoklist = &toklist;
3451 label = NULL;
3452 statements = new Statements();
3453 while (1)
3455 switch (token.value)
3457 case TOKidentifier:
3458 if (!toklist)
3460 // Look ahead to see if it is a label
3461 t = peek(&token);
3462 if (t->value == TOKcolon)
3463 { // It's a label
3464 label = token.ident;
3465 labelloc = this->loc;
3466 nextToken();
3467 nextToken();
3468 continue;
3471 goto Ldefault;
3473 case TOKrcurly:
3474 if (toklist || label)
3476 error("asm statements must end in ';'");
3478 break;
3480 case TOKendline:
3481 case TOKsemicolon:
3482 s = NULL;
3483 if (toklist || label)
3484 { // Create AsmStatement from list of tokens we've saved
3485 s = new AsmStatement(this->loc, toklist);
3486 toklist = NULL;
3487 ptoklist = &toklist;
3488 if (label)
3489 { s = new LabelStatement(labelloc, label, s);
3490 label = NULL;
3492 statements->push(s);
3494 nextToken();
3495 continue;
3497 case TOKeof:
3498 /* { */
3499 error("matching '}' expected, not end of file");
3500 break;
3502 case TOKlparen:
3503 case TOKstring:
3504 // If the first token is a string or '(', parse as extended asm.
3505 if (! toklist)
3507 s = parseExtAsm(0);
3508 statements->push(s);
3509 continue;
3511 // ...else, drop through.
3513 default:
3514 Ldefault:
3515 *ptoklist = new Token();
3516 memcpy(*ptoklist, &token, sizeof(Token));
3517 ptoklist = &(*ptoklist)->next;
3518 *ptoklist = NULL;
3520 nextToken();
3521 continue;
3523 break;
3525 s = new CompoundStatement(loc, statements);
3526 nextToken();
3527 break;
3530 default:
3531 error("found '%s' instead of statement", token.toChars());
3532 goto Lerror;
3534 Lerror:
3535 while (token.value != TOKrcurly &&
3536 token.value != TOKsemicolon &&
3537 token.value != TOKeof)
3538 nextToken();
3539 if (token.value == TOKsemicolon)
3540 nextToken();
3541 s = NULL;
3542 break;
3545 return s;
3548 Statement *Parser::parseExtAsm(int expect_rparen)
3550 Expression * insnTemplate;
3551 Expressions * args = NULL;
3552 Array * argNames = NULL;
3553 Expressions * argConstraints = NULL;
3554 int nOutputArgs = 0;
3555 Expressions * clobbers = NULL;
3556 bool isInputPhase = false; // Output operands first, then input.
3558 insnTemplate = parseExpression();
3559 if (token.value == TOKrparen || token.value == TOKsemicolon)
3560 goto Ldone;
3561 check(TOKcolon);
3562 while (1) {
3563 Expression * arg = NULL;
3564 Identifier * name = NULL;
3565 Expression * constraint = NULL;
3567 switch (token.value)
3569 case TOKsemicolon:
3570 case TOKrparen:
3571 goto Ldone;
3573 case TOKcolon:
3574 nextToken();
3575 goto LnextPhase;
3577 case TOKeof:
3578 error("unterminated statement");
3580 case TOKlbracket:
3581 nextToken();
3582 if (token.value == TOKidentifier)
3584 name = token.ident;
3585 nextToken();
3587 else
3588 error("expected identifier after '['");
3589 check(TOKrbracket);
3590 // drop through
3591 default:
3592 constraint = parsePrimaryExp();
3593 if (constraint->op != TOKstring)
3594 error("expected constant string constraint for operand");
3595 arg = parseAssignExp();
3596 if (! args)
3598 args = new Expressions;
3599 argConstraints = new Expressions;
3600 argNames = new Array;
3602 args->push(arg);
3603 argNames->push(name);
3604 argConstraints->push(constraint);
3605 if (! isInputPhase)
3606 nOutputArgs++;
3608 if (token.value == TOKcomma)
3609 nextToken();
3610 break;
3612 continue;
3613 LnextPhase:
3614 if (! isInputPhase)
3615 isInputPhase = true;
3616 else
3617 break;
3620 while (1)
3622 Expression * clobber;
3624 switch (token.value)
3626 case TOKsemicolon:
3627 case TOKrparen:
3628 goto Ldone;
3630 case TOKeof:
3631 error("unterminated statement");
3633 default:
3634 clobber = parseAssignExp();
3635 if (clobber->op != TOKstring)
3636 error("expected constant string constraint for clobber name");
3637 if (! clobbers)
3638 clobbers = new Expressions;
3639 clobbers->push(clobber);
3641 if (token.value == TOKcomma)
3642 nextToken();
3643 break;
3646 Ldone:
3647 if (expect_rparen)
3648 check(TOKrparen);
3649 else
3650 check(TOKsemicolon);
3652 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3653 argConstraints, nOutputArgs, clobbers);
3656 void Parser::optionalEndline() {
3657 while (token.value == TOKendline) {
3658 nextToken();
3662 void Parser::check(enum TOK value)
3664 check(loc, value);
3667 void Parser::check(Loc loc, enum TOK value)
3669 if (token.value != value)
3670 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3671 nextToken();
3674 void Parser::check(enum TOK value, char *string)
3676 if (token.value != value)
3677 error("found '%s' when expecting '%s' following '%s'",
3678 token.toChars(), Token::toChars(value), string);
3679 nextToken();
3682 char *Parser::endToken()
3684 return "semicolon";
3687 char *DltParser::endToken()
3689 return "newline";
3692 void Parser::checkLParen() { check(TOKlparen); }
3693 void Parser::checkRParen() { check(TOKrparen); }
3695 void DltParser::checkLParen() { }
3696 void DltParser::checkRParen() { }
3698 /************************************
3699 * Determine if the scanner is sitting on the start of a declaration.
3700 * Input:
3701 * needId 0 no identifier
3702 * 1 identifier optional
3703 * 2 must have identifier
3706 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3708 int haveId = 0;
3710 if (!isBasicType(&t))
3711 return FALSE;
3712 if (!isDeclarator(&t, &haveId, endtok))
3713 return FALSE;
3714 if ( needId == 1 ||
3715 (needId == 0 && !haveId) ||
3716 (needId == 2 && haveId))
3717 { if (pt)
3718 *pt = t;
3719 return TRUE;
3721 else
3722 return FALSE;
3725 int Parser::isBasicType(Token **pt)
3727 // This code parallels parseBasicType()
3728 Token *t = *pt;
3729 Token *t2;
3730 int parens;
3732 switch (t->value)
3734 CASE_BASIC_TYPES:
3735 t = peek(t);
3736 break;
3738 case TOKidentifier:
3739 t = peek(t);
3740 if (t->value == TOKnot)
3742 goto L4;
3744 goto L3;
3745 while (1)
3748 t = peek(t);
3750 if (t->value == TOKdot)
3752 Ldot:
3753 t = peek(t);
3754 if (t->value != TOKidentifier)
3755 goto Lfalse;
3756 t = peek(t);
3757 if (t->value != TOKnot)
3758 goto L3;
3760 t = peek(t);
3761 if (t->value != TOKlparen)
3762 goto Lfalse;
3763 if (!skipParens(t, &t))
3764 goto Lfalse;
3766 else
3767 break;
3769 break;
3771 case TOKdot:
3772 goto Ldot;
3774 case TOKtypeof:
3775 /* typeof(exp).identifier...
3777 t = peek(t);
3778 if (t->value != TOKlparen)
3779 goto Lfalse;
3780 if (!skipParens(t, &t))
3781 goto Lfalse;
3782 goto L2;
3784 default:
3785 goto Lfalse;
3787 *pt = t;
3788 return TRUE;
3790 Lfalse:
3791 return FALSE;
3794 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3795 { // This code parallels parseDeclarator()
3796 Token *t = *pt;
3797 int parens;
3799 //printf("Parser::isDeclarator()\n");
3800 //t->print();
3801 if (t->value == TOKassign)
3802 return FALSE;
3804 while (1)
3806 parens = FALSE;
3807 switch (t->value)
3809 case TOKquestion:
3810 case TOKmul:
3811 case TOKand:
3812 t = peek(t);
3813 continue;
3815 case TOKlbracket:
3816 t = peek(t);
3817 if (t->value == TOKrbracket)
3819 t = peek(t);
3821 else if (isDeclaration(t, 0, TOKrbracket, &t))
3822 { // It's an associative array declaration
3823 t = peek(t);
3825 else
3827 // [ expression ]
3828 // [ expression .. expression ]
3829 if (!isExpression(&t))
3830 return FALSE;
3831 if (t->value == TOKslice)
3832 { t = peek(t);
3833 if (!isExpression(&t))
3834 return FALSE;
3836 if (t->value != TOKrbracket)
3837 return FALSE;
3838 t = peek(t);
3840 continue;
3842 case TOKidentifier:
3843 if (*haveId)
3844 return FALSE;
3845 *haveId = TRUE;
3846 t = peek(t);
3847 break;
3849 case TOKlparen:
3850 t = peek(t);
3852 if (t->value == TOKrparen)
3853 return FALSE; // () is not a declarator
3855 /* Regard ( identifier ) as not a declarator
3856 * BUG: what about ( *identifier ) in
3857 * f(*p)(x);
3858 * where f is a class instance with overloaded () ?
3859 * Should we just disallow C-style function pointer declarations?
3861 if (t->value == TOKidentifier)
3862 { Token *t2 = peek(t);
3863 if (t2->value == TOKrparen)
3864 return FALSE;
3868 if (!isDeclarator(&t, haveId, TOKrparen))
3869 return FALSE;
3870 t = peek(t);
3871 parens = TRUE;
3872 break;
3874 case TOKdelegate:
3875 case TOKfunction:
3876 t = peek(t);
3877 if (!isParameters(&t))
3878 return FALSE;
3879 continue;
3881 break;
3884 while (1)
3886 switch (t->value)
3888 #if CARRAYDECL
3889 case TOKlbracket:
3890 parens = FALSE;
3891 t = peek(t);
3892 if (t->value == TOKrbracket)
3894 t = peek(t);
3896 else if (isDeclaration(t, 0, TOKrbracket, &t))
3897 { // It's an associative array declaration
3898 t = peek(t);
3900 else
3902 // [ expression ]
3903 if (!isExpression(&t))
3904 return FALSE;
3905 if (t->value != TOKrbracket)
3906 return FALSE;
3907 t = peek(t);
3909 continue;
3910 #endif
3912 case TOKlparen:
3913 parens = FALSE;
3914 if (!isParameters(&t))
3915 return FALSE;
3916 continue;
3918 // Valid tokens that follow a declaration
3919 case TOKrparen:
3920 case TOKrbracket:
3921 case TOKassign:
3922 case TOKcomma:
3923 case TOKendline:
3924 case TOKsemicolon:
3925 case TOKlcurly:
3926 case TOKin:
3927 // The !parens is to disallow unnecessary parentheses
3928 if (!parens && (endtok == TOKreserved || endtok == t->value))
3929 { *pt = t;
3930 return TRUE;
3932 return FALSE;
3934 default:
3935 return FALSE;
3941 int Parser::isParameters(Token **pt)
3942 { // This code parallels parseParameters()
3943 Token *t = *pt;
3944 int tmp;
3946 //printf("isParameters()\n");
3947 if (t->value != TOKlparen)
3948 return FALSE;
3950 t = peek(t);
3951 while (1)
3953 switch (t->value)
3955 case TOKrparen:
3956 break;
3958 case TOKdotdotdot:
3959 t = peek(t);
3960 break;
3962 case TOKin:
3963 case TOKout:
3964 case TOKinout:
3965 case TOKref:
3966 case TOKlazy:
3967 t = peek(t);
3968 default:
3969 if (!isBasicType(&t))
3970 return FALSE;
3971 tmp = FALSE;
3972 if (t->value != TOKdotdotdot &&
3973 !isDeclarator(&t, &tmp, TOKreserved))
3974 return FALSE;
3975 if (t->value == TOKassign)
3976 { t = peek(t);
3977 if (!isExpression(&t))
3978 return FALSE;
3980 if (t->value == TOKdotdotdot)
3982 t = peek(t);
3983 break;
3985 if (t->value == TOKcomma)
3986 { t = peek(t);
3987 continue;
3989 break;
3991 break;
3993 if (t->value != TOKrparen)
3994 return FALSE;
3995 t = peek(t);
3996 *pt = t;
3997 return TRUE;
4000 int Parser::isExpression(Token **pt)
4002 // This is supposed to determine if something is an expression.
4003 // What it actually does is scan until a closing right bracket
4004 // is found.
4006 Token *t = *pt;
4007 int brnest = 0;
4008 int panest = 0;
4010 for (;; t = peek(t))
4012 switch (t->value)
4014 case TOKlbracket:
4015 brnest++;
4016 continue;
4018 case TOKrbracket:
4019 if (--brnest >= 0)
4020 continue;
4021 break;
4023 case TOKlparen:
4024 panest++;
4025 continue;
4027 case TOKcomma:
4028 if (brnest || panest)
4029 continue;
4030 break;
4032 case TOKrparen:
4033 if (--panest >= 0)
4034 continue;
4035 break;
4037 case TOKslice:
4038 if (brnest)
4039 continue;
4040 break;
4042 case TOKeof:
4043 return FALSE;
4045 default:
4046 continue;
4048 break;
4051 *pt = t;
4052 return TRUE;
4055 /**********************************************
4056 * Skip over
4057 * instance foo.bar(parameters...)
4058 * Output:
4059 * if (pt), *pt is set to the token following the closing )
4060 * Returns:
4061 * 1 it's valid instance syntax
4062 * 0 invalid instance syntax
4065 int Parser::isTemplateInstance(Token *t, Token **pt)
4067 t = peek(t);
4068 if (t->value != TOKdot)
4070 if (t->value != TOKidentifier)
4071 goto Lfalse;
4072 t = peek(t);
4074 while (t->value == TOKdot)
4076 t = peek(t);
4077 if (t->value != TOKidentifier)
4078 goto Lfalse;
4079 t = peek(t);
4081 if (t->value != TOKlparen)
4082 goto Lfalse;
4084 // Skip over the template arguments
4085 while (1)
4087 while (1)
4089 t = peek(t);
4090 switch (t->value)
4092 case TOKlparen:
4093 if (!skipParens(t, &t))
4094 goto Lfalse;
4095 continue;
4096 case TOKrparen:
4097 break;
4098 case TOKcomma:
4099 break;
4100 case TOKeof:
4101 case TOKsemicolon:
4102 goto Lfalse;
4103 default:
4104 continue;
4106 break;
4109 if (t->value != TOKcomma)
4110 break;
4112 if (t->value != TOKrparen)
4113 goto Lfalse;
4114 t = peek(t);
4115 if (pt)
4116 *pt = t;
4117 return 1;
4119 Lfalse:
4120 return 0;
4123 /*******************************************
4124 * Skip parens, brackets.
4125 * Input:
4126 * t is on opening (
4127 * Output:
4128 * *pt is set to closing token, which is ')' on success
4129 * Returns:
4130 * !=0 successful
4131 * 0 some parsing error
4134 int Parser::skipParens(Token *t, Token **pt)
4136 int parens = 0;
4138 while (1)
4140 switch (t->value)
4142 case TOKlparen:
4143 parens++;
4144 break;
4146 case TOKrparen:
4147 parens--;
4148 if (parens < 0)
4149 goto Lfalse;
4150 if (parens == 0)
4151 goto Ldone;
4152 break;
4154 case TOKeof:
4155 case TOKsemicolon:
4156 goto Lfalse;
4158 default:
4159 break;
4161 t = peek(t);
4164 Ldone:
4165 if (*pt)
4166 *pt = t;
4167 return 1;
4169 Lfalse:
4170 return 0;
4173 /********************************* Expression Parser ***************************/
4175 Expression *Parser::parsePrimaryExp()
4176 { Expression *e;
4177 Type *t;
4178 Identifier *id;
4179 enum TOK save;
4180 Loc loc = this->loc;
4182 switch (token.value)
4184 case TOKidentifier:
4185 id = token.ident;
4186 nextToken();
4187 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4188 { // identifier!(template-argument-list)
4189 TemplateInstance *tempinst;
4191 tempinst = new TemplateInstance(loc, id);
4192 nextToken();
4193 tempinst->tiargs = parseTemplateArgumentList();
4194 e = new ScopeExp(loc, tempinst);
4196 else
4197 e = new IdentifierExp(loc, id);
4198 break;
4200 case TOKdollar:
4201 if (!inBrackets)
4202 error("'$' is valid only inside [] of index or slice");
4203 e = new DollarExp(loc);
4204 nextToken();
4205 break;
4207 case TOKdot:
4208 // Signal global scope '.' operator with "" identifier
4209 e = new IdentifierExp(loc, Id::empty);
4210 break;
4212 case TOKthis:
4213 e = new ThisExp(loc);
4214 nextToken();
4215 break;
4217 case TOKsuper:
4218 e = new SuperExp(loc);
4219 nextToken();
4220 break;
4222 case TOKint32v:
4223 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
4224 nextToken();
4225 break;
4227 case TOKuns32v:
4228 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
4229 nextToken();
4230 break;
4232 case TOKint64v:
4233 e = new IntegerExp(loc, token.int64value, Type::tint64);
4234 nextToken();
4235 break;
4237 case TOKuns64v:
4238 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
4239 nextToken();
4240 break;
4242 case TOKfloat32v:
4243 e = new RealExp(loc, token.float80value, Type::tfloat32);
4244 nextToken();
4245 break;
4247 case TOKfloat64v:
4248 e = new RealExp(loc, token.float80value, Type::tfloat64);
4249 nextToken();
4250 break;
4252 case TOKfloat80v:
4253 e = new RealExp(loc, token.float80value, Type::tfloat80);
4254 nextToken();
4255 break;
4257 case TOKimaginary32v:
4258 e = new RealExp(loc, token.float80value, Type::timaginary32);
4259 nextToken();
4260 break;
4262 case TOKimaginary64v:
4263 e = new RealExp(loc, token.float80value, Type::timaginary64);
4264 nextToken();
4265 break;
4267 case TOKimaginary80v:
4268 e = new RealExp(loc, token.float80value, Type::timaginary80);
4269 nextToken();
4270 break;
4272 case TOKnull:
4273 e = new NullExp(loc);
4274 nextToken();
4275 break;
4277 case TOKtrue:
4278 e = new IntegerExp(loc, 1, Type::tbool);
4279 nextToken();
4280 break;
4282 case TOKfalse:
4283 e = new IntegerExp(loc, 0, Type::tbool);
4284 nextToken();
4285 break;
4287 case TOKcharv:
4288 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
4289 nextToken();
4290 break;
4292 case TOKwcharv:
4293 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
4294 nextToken();
4295 break;
4297 case TOKdcharv:
4298 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
4299 nextToken();
4300 break;
4302 case TOKstring:
4303 { unsigned char *s;
4304 unsigned len;
4305 unsigned char postfix;
4307 // cat adjacent strings
4308 s = token.ustring;
4309 len = token.len;
4310 postfix = token.postfix;
4311 while (1)
4313 nextToken();
4314 if (token.value == TOKstring)
4315 { unsigned len1;
4316 unsigned len2;
4317 unsigned char *s2;
4319 if (token.postfix)
4320 { if (token.postfix != postfix)
4321 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4322 postfix = token.postfix;
4325 len1 = len;
4326 len2 = token.len;
4327 len = len1 + len2;
4328 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4329 memcpy(s2, s, len1 * sizeof(unsigned char));
4330 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4331 s = s2;
4333 else
4334 break;
4336 e = new StringExp(loc, s, len, postfix);
4337 break;
4340 CASE_BASIC_TYPES_X(t):
4341 nextToken();
4343 check(TOKdot, t->toChars());
4344 if (token.value != TOKidentifier)
4345 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4346 goto Lerr;
4348 e = new TypeDotIdExp(loc, t, token.ident);
4349 nextToken();
4350 break;
4352 case TOKtypeof:
4353 { Expression *exp;
4355 nextToken();
4356 check(TOKlparen);
4357 exp = parseExpression();
4358 check(TOKrparen);
4359 t = new TypeTypeof(loc, exp);
4360 if (token.value == TOKdot)
4361 goto L1;
4362 e = new TypeExp(loc, t);
4363 break;
4366 case TOKtypeid:
4367 { Type *t;
4369 nextToken();
4370 check(TOKlparen, "typeid");
4371 t = parseBasicType();
4372 t = parseDeclarator(t,NULL); // ( type )
4373 check(TOKrparen);
4374 e = new TypeidExp(loc, t);
4375 break;
4378 case TOKis:
4379 { Type *targ;
4380 Identifier *ident = NULL;
4381 Type *tspec = NULL;
4382 enum TOK tok = TOKreserved;
4383 enum TOK tok2 = TOKreserved;
4384 Loc loc = this->loc;
4386 nextToken();
4387 if (token.value == TOKlparen)
4389 nextToken();
4390 targ = parseBasicType();
4391 targ = parseDeclarator(targ, &ident);
4392 if (token.value == TOKcolon || token.value == TOKequal)
4394 tok = token.value;
4395 nextToken();
4396 if (tok == TOKequal &&
4397 (token.value == TOKtypedef ||
4398 token.value == TOKstruct ||
4399 token.value == TOKunion ||
4400 token.value == TOKclass ||
4401 token.value == TOKsuper ||
4402 token.value == TOKenum ||
4403 token.value == TOKinterface ||
4404 token.value == TOKfunction ||
4405 token.value == TOKdelegate ||
4406 token.value == TOKreturn))
4408 tok2 = token.value;
4409 nextToken();
4411 else
4413 tspec = parseBasicType();
4414 tspec = parseDeclarator(tspec, NULL);
4417 check(TOKrparen);
4419 else
4420 { error("(type identifier : specialization) expected following is");
4421 goto Lerr;
4423 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4424 break;
4427 case TOKassert:
4428 { Expression *msg = NULL;
4430 nextToken();
4432 checkLParen();
4433 e = parseAssignExp();
4434 if (token.value == (dltSyntax ? TOKelse : TOKcomma))
4435 { nextToken();
4436 msg = parseAssignExp();
4437 } else if (token.value == TOKcomma)
4438 error("Suspicious comma after assert; try 'else' instead");
4439 checkRParen();
4441 e = new AssertExp(loc, e, msg);
4442 break;
4445 case TOKmixin:
4447 nextToken();
4448 check(TOKlparen, "mixin");
4449 e = parseAssignExp();
4450 check(TOKrparen);
4451 e = new CompileExp(loc, e);
4452 break;
4455 case TOKimport:
4457 nextToken();
4458 check(TOKlparen, "import");
4459 e = parseAssignExp();
4460 check(TOKrparen);
4461 e = new FileExp(loc, e);
4462 break;
4465 case TOKlparen:
4466 if (peekPastParen(&token)->value == TOKlcurly)
4467 { // (arguments) { statements... }
4468 save = TOKdelegate;
4469 goto case_delegate;
4471 // ( expression )
4472 nextToken();
4473 e = parseExpression();
4474 check(loc, TOKrparen);
4475 break;
4477 case TOKlbracket:
4478 { /* Parse array literals and associative array literals:
4479 * [ value, value, value ... ]
4480 * [ key:value, key:value, key:value ... ]
4482 Expressions *values = new Expressions();
4483 Expressions *keys = NULL;
4485 nextToken();
4486 if (token.value != TOKrbracket)
4488 while (1)
4490 Expression *e = parseAssignExp();
4491 if (token.value == TOKcolon && (keys || values->dim == 0))
4492 { nextToken();
4493 if (!keys)
4494 keys = new Expressions();
4495 keys->push(e);
4496 e = parseAssignExp();
4498 else if (keys)
4499 { error("'key:value' expected for associative array literal");
4500 delete keys;
4501 keys = NULL;
4503 values->push(e);
4504 if (token.value == TOKrbracket)
4505 break;
4506 check(TOKcomma);
4509 check(TOKrbracket);
4511 if (keys)
4512 e = new AssocArrayLiteralExp(loc, keys, values);
4513 else
4514 e = new ArrayLiteralExp(loc, values);
4515 break;
4518 case TOKlcurly:
4519 // { statements... }
4520 save = TOKdelegate;
4521 goto case_delegate;
4523 case TOKfunction:
4524 case TOKdelegate:
4525 save = token.value;
4526 nextToken();
4527 case_delegate:
4529 /* function type(parameters) { body }
4530 * delegate type(parameters) { body }
4532 Arguments *arguments;
4533 int varargs;
4534 FuncLiteralDeclaration *fd;
4535 Type *t;
4537 if (token.value == TOKlcurly)
4539 t = NULL;
4540 varargs = 0;
4541 arguments = new Arguments();
4543 else
4545 if (token.value == TOKlparen)
4546 t = NULL;
4547 else
4549 t = parseBasicType();
4550 t = parseBasicType2(t); // function return type
4552 arguments = parseParameters(&varargs);
4554 t = new TypeFunction(arguments, t, varargs, linkage);
4555 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4556 parseContracts(fd);
4557 e = new FuncExp(loc, fd);
4558 break;
4561 default:
4562 error("expression expected, not '%s'", token.toChars());
4563 Lerr:
4564 // Anything for e, as long as it's not NULL
4565 e = new IntegerExp(loc, 0, Type::tint32);
4566 nextToken();
4567 break;
4569 return parsePostExp(e);
4572 Expression *Parser::parsePostExp(Expression *e)
4574 Loc loc;
4576 while (1)
4578 loc = this->loc;
4579 switch (token.value)
4581 case TOKdot:
4582 nextToken();
4583 if (token.value == TOKidentifier)
4584 { Identifier *id = token.ident;
4586 nextToken();
4587 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4588 { // identifier!(template-argument-list)
4589 TemplateInstance *tempinst;
4591 tempinst = new TemplateInstance(loc, id);
4592 nextToken();
4593 tempinst->tiargs = parseTemplateArgumentList();
4594 e = new DotTemplateInstanceExp(loc, e, tempinst);
4596 else
4597 e = new DotIdExp(loc, e, id);
4598 continue;
4600 else if (token.value == TOKnew)
4602 e = parseNewExp(e);
4603 continue;
4605 else
4606 error("identifier expected following '.', not '%s'", token.toChars());
4607 break;
4609 case TOKplusplus:
4610 e = new PostExp(TOKplusplus, loc, e);
4611 break;
4613 case TOKminusminus:
4614 e = new PostExp(TOKminusminus, loc, e);
4615 break;
4617 case TOKlparen:
4618 e = new CallExp(loc, e, parseArguments());
4619 continue;
4621 case TOKlbracket:
4622 { // array dereferences:
4623 // array[index]
4624 // array[]
4625 // array[lwr .. upr]
4626 Expression *index;
4627 Expression *upr;
4629 inBrackets++;
4630 nextToken();
4631 if (token.value == TOKrbracket)
4632 { // array[]
4633 e = new SliceExp(loc, e, NULL, NULL);
4634 nextToken();
4636 else
4638 index = parseAssignExp();
4639 if (token.value == TOKslice)
4640 { // array[lwr .. upr]
4641 nextToken();
4642 upr = parseAssignExp();
4643 e = new SliceExp(loc, e, index, upr);
4645 else
4646 { // array[index, i2, i3, i4, ...]
4647 Expressions *arguments = new Expressions();
4648 arguments->push(index);
4649 if (token.value == TOKcomma)
4651 nextToken();
4652 while (1)
4653 { Expression *arg;
4655 arg = parseAssignExp();
4656 arguments->push(arg);
4657 if (token.value == TOKrbracket)
4658 break;
4659 check(TOKcomma);
4662 e = new ArrayExp(loc, e, arguments);
4664 check(TOKrbracket);
4665 inBrackets--;
4667 continue;
4670 default:
4671 return e;
4673 nextToken();
4677 Expression *Parser::parseUnaryExp()
4678 { Expression *e;
4679 Loc loc = this->loc;
4681 switch (token.value)
4683 case TOKand:
4684 nextToken();
4685 e = parseUnaryExp();
4686 e = new AddrExp(loc, e);
4687 break;
4689 case TOKplusplus:
4690 nextToken();
4691 e = parseUnaryExp();
4692 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4693 break;
4695 case TOKminusminus:
4696 nextToken();
4697 e = parseUnaryExp();
4698 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4699 break;
4701 case TOKmul:
4702 nextToken();
4703 e = parseUnaryExp();
4704 e = new PtrExp(loc, e);
4705 break;
4707 case TOKmin:
4708 nextToken();
4709 e = parseUnaryExp();
4710 e = new NegExp(loc, e);
4711 break;
4713 case TOKadd:
4714 nextToken();
4715 e = parseUnaryExp();
4716 e = new UAddExp(loc, e);
4717 break;
4719 case TOKnot:
4720 nextToken();
4721 e = parseUnaryExp();
4722 e = new NotExp(loc, e);
4723 break;
4725 case TOKtilde:
4726 nextToken();
4727 e = parseUnaryExp();
4728 e = new ComExp(loc, e);
4729 break;
4731 case TOKdelete:
4732 nextToken();
4733 e = parseUnaryExp();
4734 e = new DeleteExp(loc, e);
4735 break;
4737 case TOKnew:
4738 e = parseNewExp(NULL);
4739 break;
4741 case TOKcast: // cast(type) expression
4742 { Type *t;
4744 nextToken();
4745 check(TOKlparen);
4746 t = parseBasicType();
4747 t = parseDeclarator(t,NULL); // ( type )
4748 check(TOKrparen);
4750 e = parseUnaryExp();
4751 e = new CastExp(loc, e, t);
4752 break;
4755 case TOKlparen:
4756 { Token *tk;
4758 tk = peek(&token);
4759 #if CCASTSYNTAX
4760 // If cast
4761 if (isDeclaration(tk, 0, TOKrparen, &tk))
4763 tk = peek(tk); // skip over right parenthesis
4764 switch (tk->value)
4766 case TOKdot:
4767 case TOKplusplus:
4768 case TOKminusminus:
4769 case TOKnot:
4770 case TOKdelete:
4771 case TOKnew:
4772 case TOKlparen:
4773 case TOKidentifier:
4774 case TOKthis:
4775 case TOKsuper:
4776 case TOKint32v:
4777 case TOKuns32v:
4778 case TOKint64v:
4779 case TOKuns64v:
4780 case TOKfloat32v:
4781 case TOKfloat64v:
4782 case TOKfloat80v:
4783 case TOKimaginary32v:
4784 case TOKimaginary64v:
4785 case TOKimaginary80v:
4786 case TOKnull:
4787 case TOKtrue:
4788 case TOKfalse:
4789 case TOKcharv:
4790 case TOKwcharv:
4791 case TOKdcharv:
4792 case TOKstring:
4793 #if 0
4794 case TOKtilde:
4795 case TOKand:
4796 case TOKmul:
4797 case TOKmin:
4798 case TOKadd:
4799 #endif
4800 case TOKfunction:
4801 case TOKdelegate:
4802 case TOKtypeof:
4803 CASE_BASIC_TYPES: // (type)int.size
4804 { // (type) una_exp
4805 Type *t;
4807 nextToken();
4808 t = parseBasicType();
4809 t = parseDeclarator(t,NULL);
4810 check(TOKrparen);
4812 // if .identifier
4813 if (token.value == TOKdot)
4815 nextToken();
4816 if (token.value != TOKidentifier)
4817 { error("Identifier expected following (type).");
4818 return NULL;
4820 e = new TypeDotIdExp(loc, t, token.ident);
4821 nextToken();
4822 e = parsePostExp(e);
4824 else
4826 e = parseUnaryExp();
4827 e = new CastExp(loc, e, t);
4828 error("C style cast illegal, use %s", e->toChars());
4830 return e;
4834 #endif
4835 e = parsePrimaryExp();
4836 break;
4838 default:
4839 e = parsePrimaryExp();
4840 break;
4842 assert(e);
4843 return e;
4846 Expression *Parser::parseMulExp()
4847 { Expression *e;
4848 Expression *e2;
4849 Loc loc = this->loc;
4851 e = parseUnaryExp();
4852 while (1)
4854 switch (token.value)
4856 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4857 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4858 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4860 default:
4861 break;
4863 break;
4865 return e;
4868 Expression *Parser::parseAddExp()
4869 { Expression *e;
4870 Expression *e2;
4871 Loc loc = this->loc;
4873 e = parseMulExp();
4874 while (1)
4876 switch (token.value)
4878 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4879 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4880 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4882 default:
4883 break;
4885 break;
4887 return e;
4890 Expression *Parser::parseShiftExp()
4891 { Expression *e;
4892 Expression *e2;
4893 Loc loc = this->loc;
4895 e = parseAddExp();
4896 while (1)
4898 switch (token.value)
4900 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4901 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4902 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4904 default:
4905 break;
4907 break;
4909 return e;
4912 Expression *Parser::parseRelExp()
4913 { Expression *e;
4914 Expression *e2;
4915 enum TOK op;
4916 Loc loc = this->loc;
4918 e = parseShiftExp();
4919 while (1)
4921 switch (token.value)
4923 case TOKlt:
4924 case TOKle:
4925 case TOKgt:
4926 case TOKge:
4927 case TOKunord:
4928 case TOKlg:
4929 case TOKleg:
4930 case TOKule:
4931 case TOKul:
4932 case TOKuge:
4933 case TOKug:
4934 case TOKue:
4935 op = token.value;
4936 nextToken();
4937 e2 = parseShiftExp();
4938 e = new CmpExp(op, loc, e, e2);
4939 continue;
4941 case TOKin:
4942 nextToken();
4943 e2 = parseShiftExp();
4944 e = new InExp(loc, e, e2);
4945 continue;
4947 default:
4948 break;
4950 break;
4952 return e;
4955 Expression *Parser::parseEqualExp()
4956 { Expression *e;
4957 Expression *e2;
4958 Token *t;
4959 Loc loc = this->loc;
4961 e = parseRelExp();
4962 while (1)
4963 { enum TOK value = token.value;
4965 switch (value)
4967 case TOKequal:
4968 case TOKnotequal:
4969 nextToken();
4970 e2 = parseRelExp();
4971 e = new EqualExp(value, loc, e, e2);
4972 continue;
4974 case TOKidentity:
4975 error("'===' is no longer legal, use 'is' instead");
4976 goto L1;
4978 case TOKnotidentity:
4979 error("'!==' is no longer legal, use '!is' instead");
4980 goto L1;
4982 case TOKis:
4983 value = TOKidentity;
4984 error("TOKis");
4985 if (dltSyntax)
4987 t = peek(&token);
4988 error("next: %s", t->toChars());
4989 if (t->value == TOKnot)
4991 // X is not Y
4992 value = TOKnotidentity;
4993 nextToken();
4996 goto L1;
4998 case TOKnot:
4999 // Attempt to identify '!is'
5000 t = peek(&token);
5001 if (t->value != TOKis)
5002 break;
5003 nextToken();
5004 value = TOKnotidentity;
5005 goto L1;
5008 nextToken();
5009 e2 = parseRelExp();
5010 e = new IdentityExp(value, loc, e, e2);
5011 continue;
5013 default:
5014 break;
5016 break;
5018 return e;
5021 Expression *Parser::parseCmpExp()
5022 { Expression *e;
5023 Expression *e2;
5024 Token *t;
5025 Loc loc = this->loc;
5027 e = parseShiftExp();
5028 enum TOK op = token.value;
5030 switch (op)
5032 case TOKequal:
5033 case TOKnotequal:
5034 nextToken();
5035 e2 = parseShiftExp();
5036 e = new EqualExp(op, loc, e, e2);
5037 break;
5039 case TOKis:
5040 op = TOKidentity;
5041 if (dltSyntax)
5043 t = peek(&token);
5044 if (t->value == TOKnot)
5046 // X is not Y
5047 op = TOKnotidentity;
5048 nextToken();
5051 goto L1;
5053 case TOKnot:
5054 // Attempt to identify '!is'
5055 t = peek(&token);
5056 if (t->value != TOKis)
5057 break;
5058 nextToken();
5059 op = TOKnotidentity;
5060 goto L1;
5063 nextToken();
5064 e2 = parseShiftExp();
5065 e = new IdentityExp(op, loc, e, e2);
5066 break;
5068 case TOKlt:
5069 case TOKle:
5070 case TOKgt:
5071 case TOKge:
5072 case TOKunord:
5073 case TOKlg:
5074 case TOKleg:
5075 case TOKule:
5076 case TOKul:
5077 case TOKuge:
5078 case TOKug:
5079 case TOKue:
5080 nextToken();
5081 e2 = parseShiftExp();
5082 e = new CmpExp(op, loc, e, e2);
5083 break;
5085 case TOKin:
5086 nextToken();
5087 e2 = parseShiftExp();
5088 e = new InExp(loc, e, e2);
5089 break;
5091 default:
5092 break;
5094 return e;
5097 Expression *Parser::parseAndExp()
5098 { Expression *e;
5099 Expression *e2;
5100 Loc loc = this->loc;
5102 if (global.params.Dversion == 1)
5104 e = parseEqualExp();
5105 while (token.value == TOKand)
5107 nextToken();
5108 e2 = parseEqualExp();
5109 e = new AndExp(loc,e,e2);
5110 loc = this->loc;
5113 else
5115 e = parseCmpExp();
5116 while (token.value == TOKand)
5118 nextToken();
5119 e2 = parseCmpExp();
5120 e = new AndExp(loc,e,e2);
5121 loc = this->loc;
5124 return e;
5127 Expression *Parser::parseXorExp()
5128 { Expression *e;
5129 Expression *e2;
5130 Loc loc = this->loc;
5132 e = parseAndExp();
5133 while (token.value == TOKxor)
5135 nextToken();
5136 e2 = parseAndExp();
5137 e = new XorExp(loc, e, e2);
5139 return e;
5142 Expression *Parser::parseOrExp()
5143 { Expression *e;
5144 Expression *e2;
5145 Loc loc = this->loc;
5147 e = parseXorExp();
5148 while (token.value == TOKor)
5150 nextToken();
5151 e2 = parseXorExp();
5152 e = new OrExp(loc, e, e2);
5154 return e;
5157 Expression *Parser::parseAndAndExp()
5158 { Expression *e;
5159 Expression *e2;
5160 Loc loc = this->loc;
5162 e = parseOrExp();
5163 while (token.value == TOKandand)
5165 nextToken();
5166 e2 = parseOrExp();
5167 e = new AndAndExp(loc, e, e2);
5169 return e;
5172 Expression *Parser::parseOrOrExp()
5173 { Expression *e;
5174 Expression *e2;
5175 Loc loc = this->loc;
5177 e = parseAndAndExp();
5178 while (token.value == TOKoror)
5180 nextToken();
5181 e2 = parseAndAndExp();
5182 e = new OrOrExp(loc, e, e2);
5184 return e;
5187 Expression *Parser::parseCondExp()
5188 { Expression *e;
5189 Expression *e1;
5190 Expression *e2;
5191 Loc loc = this->loc;
5193 e = parseOrOrExp();
5194 if (token.value == TOKquestion)
5196 nextToken();
5197 e1 = parseExpression();
5198 check(TOKcolon);
5199 e2 = parseCondExp();
5200 e = new CondExp(loc, e, e1, e2);
5202 return e;
5205 Expression *DltParser::parseCondExp()
5206 { Expression *e;
5207 Expression *e1;
5208 Expression *e2;
5209 Loc loc = this->loc;
5211 e = parseOrOrExp();
5212 if (token.value == TOKif)
5214 nextToken();
5215 e1 = parseExpression();
5216 check(TOKelse);
5217 e2 = parseCondExp();
5218 e = new CondExp(loc, e1, e, e2);
5220 return e;
5223 Expression *Parser::parseAssignExp()
5224 { Expression *e;
5225 Expression *e2;
5226 Loc loc;
5228 e = parseCondExp();
5229 while (1)
5231 loc = this->loc;
5232 switch (token.value)
5234 #define X(tok,ector) \
5235 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5237 X(TOKassign, AssignExp);
5238 X(TOKaddass, AddAssignExp);
5239 X(TOKminass, MinAssignExp);
5240 X(TOKmulass, MulAssignExp);
5241 X(TOKdivass, DivAssignExp);
5242 X(TOKmodass, ModAssignExp);
5243 X(TOKandass, AndAssignExp);
5244 X(TOKorass, OrAssignExp);
5245 X(TOKxorass, XorAssignExp);
5246 X(TOKshlass, ShlAssignExp);
5247 X(TOKshrass, ShrAssignExp);
5248 X(TOKushrass, UshrAssignExp);
5249 X(TOKcatass, CatAssignExp);
5251 #undef X
5252 default:
5253 break;
5255 break;
5257 return e;
5260 Expression *Parser::parseExpression()
5261 { Expression *e;
5262 Expression *e2;
5263 Loc loc = this->loc;
5265 //printf("Parser::parseExpression()\n");
5266 e = parseAssignExp();
5267 while (token.value == TOKcomma)
5269 nextToken();
5270 e2 = parseAssignExp();
5271 e = new CommaExp(loc, e, e2);
5272 loc = this->loc;
5274 return e;
5278 /*************************
5279 * Collect argument list.
5280 * Assume current token is '(' or '['.
5283 Expressions *Parser::parseArguments()
5284 { // function call
5285 Expressions *arguments;
5286 Expression *arg;
5287 enum TOK endtok;
5289 arguments = new Expressions();
5290 if (token.value == TOKlbracket)
5291 endtok = TOKrbracket;
5292 else
5293 endtok = TOKrparen;
5296 nextToken();
5297 if (token.value != endtok)
5299 while (1)
5301 arg = parseAssignExp();
5302 arguments->push(arg);
5303 if (token.value == endtok)
5304 break;
5305 check(TOKcomma);
5308 check(endtok);
5310 return arguments;
5313 /*******************************************
5316 Expression *Parser::parseNewExp(Expression *thisexp)
5317 { Type *t;
5318 Expressions *newargs;
5319 Expressions *arguments = NULL;
5320 Expression *e;
5321 Loc loc = this->loc;
5323 nextToken();
5324 newargs = NULL;
5325 if (token.value == TOKlparen)
5327 newargs = parseArguments();
5330 // An anonymous nested class starts with "class"
5331 if (token.value == TOKclass)
5333 nextToken();
5334 if (token.value == TOKlparen)
5335 arguments = parseArguments();
5337 BaseClasses *baseclasses = NULL;
5338 if (token.value != TOKlcurly)
5339 baseclasses = parseBaseClasses();
5341 Identifier *id = NULL;
5342 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
5344 if (token.value != TOKlcurly)
5345 { error("{ members } expected for anonymous class");
5346 cd->members = NULL;
5348 else
5350 nextToken();
5351 Array *decl = parseDeclDefs(0);
5352 if (token.value != TOKrcurly)
5353 error("class member expected");
5354 nextToken();
5355 cd->members = decl;
5358 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
5360 return e;
5363 #if LTORARRAYDECL
5364 t = parseBasicType();
5365 t = parseBasicType2(t);
5366 if (t->ty == Taarray)
5368 Type *index = ((TypeAArray *)t)->index;
5370 Expression *e = index->toExpression();
5371 if (e)
5372 { arguments = new Expressions();
5373 arguments->push(e);
5374 t = new TypeDArray(t->next);
5376 else
5378 error("need size of rightmost array, not type %s", index->toChars());
5379 return new NullExp(loc);
5382 else if (t->ty == Tsarray)
5384 TypeSArray *tsa = (TypeSArray *)t;
5385 Expression *e = tsa->dim;
5387 arguments = new Expressions();
5388 arguments->push(e);
5389 t = new TypeDArray(t->next);
5391 else if (token.value == TOKlparen)
5393 arguments = parseArguments();
5395 #else
5396 t = parseBasicType();
5397 while (token.value == TOKmul)
5398 { t = new TypePointer(t);
5399 nextToken();
5401 if (token.value == TOKlbracket)
5403 Expression *e;
5405 nextToken();
5406 e = parseAssignExp();
5407 arguments = new Array();
5408 arguments->push(e);
5409 check(TOKrbracket);
5410 t = parseDeclarator(t, NULL);
5411 t = new TypeDArray(t);
5413 else if (token.value == TOKlparen)
5414 arguments = parseArguments();
5415 #endif
5416 e = new NewExp(loc, thisexp, newargs, t, arguments);
5417 return e;
5420 /**********************************************
5423 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5425 s->addComment(combineComments(blockComment, token.lineComment));
5429 /********************************* ***************************/