Fixed semi-colon parsing in C-style for loops
[delight/core.git] / dmd / parse.c
blobb907a6ceadb45fd3f9fa97e536e0e0389f8d1f35
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
17 #include <stdio.h>
18 #include <assert.h>
20 #include "mem.h"
21 #include "lexer.h"
22 #include "parse.h"
23 #include "init.h"
24 #include "attrib.h"
25 #include "cond.h"
26 #include "mtype.h"
27 #include "template.h"
28 #include "staticassert.h"
29 #include "expression.h"
30 #include "statement.h"
31 #include "module.h"
32 #include "dsymbol.h"
33 #include "import.h"
34 #include "declaration.h"
35 #include "aggregate.h"
36 #include "enum.h"
37 #include "id.h"
38 #include "version.h"
39 #ifdef IN_GCC
40 #include "d-dmd-gcc.h"
41 #endif
43 // How multiple declarations are parsed.
44 // If 1, treat as C.
45 // If 0, treat:
46 // int *p, i;
47 // as:
48 // int* p;
49 // int* i;
50 #define CDECLSYNTAX 0
52 // Support C cast syntax:
53 // (type)(expression)
54 #define CCASTSYNTAX 1
56 // Support C array declarations, such as
57 // int a[3][4];
58 #define CARRAYDECL 1
60 // Support left-to-right array declarations
61 #define LTORARRAYDECL 1
64 Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
65 : Lexer(module, base, 0, length, doDocComment, 0, module->isDltFile)
67 //printf("Parser::Parser()\n");
68 md = NULL;
69 linkage = LINKd;
70 dltNormalMode = FALSE;
71 endloc = 0;
72 inBrackets = 0;
73 startBlockTok = TOKlcurly;
74 //nextToken(); // start up the scanner
77 DltParser::DltParser(Module *module, unsigned char *base, unsigned length, int doDocComment)
78 : Parser(module, base, length, doDocComment)
80 //printf("DltParser::DltParser(%s)\n", module->ident->string);
81 startBlockTok = TOKcolon;
82 dltNormalMode = TRUE; // becomes false if we find a "module dlt.*"
85 Array *Parser::parseModule()
87 Array *decldefs;
89 // ModuleDeclation leads off
90 optionalEndline();
91 if (token.value == TOKmodule)
93 unsigned char *comment = token.blockComment;
95 nextToken();
96 if (token.value != TOKidentifier)
97 { error("Identifier expected following module");
98 goto Lerr;
100 else
102 Array *a = NULL;
103 Identifier *id;
105 id = token.ident;
107 if (dltSyntax && id == Id::dlt)
108 dltNormalMode = FALSE;
110 while (nextToken() == TOKdot)
112 if (!a)
113 a = new Array();
114 a->push(id);
115 nextToken();
116 if (token.value != TOKidentifier)
117 { error("Identifier expected following package");
118 goto Lerr;
120 id = token.ident;
123 md = new ModuleDeclaration(a, id);
125 TOK end = dltSyntax ? TOKendline : TOKsemicolon;
126 if (token.value != end)
127 error("%s expected following module declaration instead of %s", Token::toChars(end), token.toChars());
129 nextToken();
130 addComment(mod, comment);
134 decldefs = parseDeclDefs(0);
135 if (token.value != TOKeof)
136 { error("unrecognized declaration '%s'", token.toChars());
137 goto Lerr;
140 if (dltNormalMode)
142 // Check for global variables
143 for (int i = 0; i < decldefs->dim; i++)
145 Dsymbol *d = (Dsymbol *) decldefs->data[i];
146 if (d->isVarDeclaration()) {
147 error("no global variables (%s) allowed in Delight; "
148 "try const, or put it in a class", d->toChars());
153 return decldefs;
155 Lerr:
156 while (token.value != TOKsemicolon && token.value != TOKeof)
157 nextToken();
158 nextToken();
159 return new Array();
162 Array *Parser::parseDeclDefs(int once)
163 { Dsymbol *s;
164 Array *decldefs;
165 Array *a;
166 Array *aelse;
167 enum PROT prot;
168 unsigned stc;
169 Condition *condition;
170 unsigned char *comment;
172 //printf("Parser::parseDeclDefs()\n");
173 decldefs = new Array();
176 comment = token.blockComment;
177 switch (token.value)
179 case TOKendline:
180 nextToken();
181 continue;
182 case TOKenum:
183 s = parseEnum();
184 break;
186 case TOKstruct:
187 case TOKunion:
188 case TOKclass:
189 case TOKinterface:
190 s = parseAggregate();
191 break;
193 case TOKimport:
194 s = parseImport(decldefs, 0);
195 break;
197 case TOKtemplate:
198 s = (Dsymbol *)parseTemplateDeclaration();
199 break;
201 case TOKmixin:
202 { Loc loc = this->loc;
203 if (peek(&token)->value == TOKlparen)
204 { // mixin(string)
205 nextToken();
206 check(TOKlparen, "mixin");
207 Expression *e = parseAssignExp();
208 check(TOKrparen);
209 check(TOKsemicolon);
210 s = new CompileDeclaration(loc, e);
211 break;
213 s = parseMixin();
214 break;
217 CASE_BASIC_TYPES:
218 case TOKalias:
219 case TOKtypedef:
220 case TOKidentifier:
221 case TOKtypeof:
222 case TOKdot:
223 Ldeclaration:
224 a = parseDeclarations();
225 decldefs->append(a);
226 continue;
228 case TOKthis:
229 s = parseCtor();
230 break;
232 case TOKtilde:
233 s = parseDtor();
234 break;
236 case TOKinvariant:
237 #if 1
238 s = parseInvariant();
239 #else
240 if (peek(&token)->value == TOKlcurly)
241 s = parseInvariant();
242 else
244 stc = STCinvariant;
245 goto Lstc;
247 #endif
248 break;
250 case TOKunittest:
251 s = parseUnitTest();
252 break;
254 case TOKnew:
255 s = parseNew();
256 break;
258 case TOKdelete:
259 s = parseDelete();
260 break;
262 case TOKeof:
263 case TOKrcurly:
264 return decldefs;
266 case TOKstatic:
267 nextToken();
268 if (token.value == TOKthis)
270 s = parseStaticCtor();
271 if (dltNormalMode)
272 error("no static constructors in Delight");
274 else if (token.value == TOKtilde)
276 s = parseStaticDtor();
277 if (dltNormalMode)
278 error("no static destructors in Delight");
280 else if (token.value == TOKassert)
281 s = parseStaticAssert();
282 else if (token.value == TOKif)
283 { condition = parseStaticIfCondition();
284 a = parseBlock();
285 aelse = NULL;
286 if (token.value == TOKelse)
287 { nextToken();
288 aelse = parseBlock();
290 s = new StaticIfDeclaration(condition, a, aelse);
291 break;
293 else if (token.value == TOKimport)
295 s = parseImport(decldefs, 1);
297 else
298 { stc = STCstatic;
299 if (dltNormalMode)
300 error("no static variables in Delight");
301 goto Lstc2;
303 break;
305 case TOKin:
306 nextToken();
307 stc = STCin;
308 goto Lstc2;
310 case TOKconst: stc = STCconst; goto Lstc;
311 case TOKfinal: stc = STCfinal; goto Lstc;
312 case TOKauto: stc = STCauto; goto Lstc;
313 case TOKscope: stc = STCscope; goto Lstc;
314 case TOKoverride: stc = STCoverride; goto Lstc;
315 case TOKabstract: stc = STCabstract; goto Lstc;
316 case TOKsynchronized: stc = STCsynchronized; goto Lstc;
317 case TOKdeprecated: stc = STCdeprecated; goto Lstc;
319 Lstc:
320 nextToken();
321 Lstc2:
322 switch (token.value)
324 case TOKconst: stc |= STCconst; goto Lstc;
325 case TOKfinal: stc |= STCfinal; goto Lstc;
326 case TOKauto: stc |= STCauto; goto Lstc;
327 case TOKscope: stc |= STCscope; goto Lstc;
328 case TOKoverride: stc |= STCoverride; goto Lstc;
329 case TOKabstract: stc |= STCabstract; goto Lstc;
330 case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
331 case TOKdeprecated: stc |= STCdeprecated; goto Lstc;
332 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
333 default:
334 break;
337 /* Look for auto initializers:
338 * storage_class identifier = initializer;
340 if (token.value == TOKidentifier &&
341 peek(&token)->value == TOKassign)
343 while (1)
345 Identifier *ident = token.ident;
346 nextToken();
347 nextToken();
348 Initializer *init = parseInitializer();
349 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
350 v->storage_class = stc;
351 s = v;
352 if (token.value == TOKsemicolon || token.value == TOKendline)
354 nextToken();
356 else if (token.value == TOKcomma)
358 nextToken();
359 if (token.value == TOKidentifier &&
360 peek(&token)->value == TOKassign)
362 decldefs->push(s);
363 addComment(s, comment);
364 continue;
366 else
367 error("Identifier expected following comma");
369 else
370 error("%s expected following declaration, not '%s'", endToken(), token.toChars());
371 break;
374 else
375 { a = parseBlock();
376 s = new StorageClassDeclaration(stc, a);
378 break;
380 case TOKextern:
381 if (peek(&token)->value != TOKlparen)
382 { stc = STCextern;
383 goto Lstc;
386 enum LINK linksave = linkage;
387 linkage = parseLinkage();
388 a = parseBlock();
389 s = new LinkDeclaration(linkage, a);
390 linkage = linksave;
392 if (dltNormalMode)
393 error("access to external symbols can be done only by dlt.* modules");
394 break;
396 case TOKprivate: prot = PROTprivate; goto Lprot;
397 case TOKpackage: prot = PROTpackage; goto Lprot;
398 case TOKprotected: prot = PROTprotected; goto Lprot;
399 case TOKpublic: prot = PROTpublic; goto Lprot;
400 case TOKexport: prot = PROTexport; goto Lprot;
402 Lprot:
403 nextToken();
404 a = parseBlock();
405 s = new ProtDeclaration(prot, a);
406 break;
408 case TOKalign:
409 { unsigned n;
411 s = NULL;
412 nextToken();
413 if (token.value == TOKlparen)
415 nextToken();
416 if (token.value == TOKint32v)
417 n = (unsigned)token.uns64value;
418 else
419 { error("integer expected, not %s", token.toChars());
420 n = 1;
422 nextToken();
423 check(TOKrparen);
425 else
426 n = global.structalign; // default
428 a = parseBlock();
429 s = new AlignDeclaration(n, a);
430 break;
433 case TOKpragma:
434 { Identifier *ident;
435 Expressions *args = NULL;
437 nextToken();
438 check(TOKlparen);
439 if (token.value != TOKidentifier)
440 { error("pragma(identifier expected");
441 goto Lerror;
443 ident = token.ident;
444 nextToken();
445 if (token.value == TOKcomma)
446 args = parseArguments(); // pragma(identifier, args...)
447 else
448 check(TOKrparen); // pragma(identifier)
450 if (token.value == TOKsemicolon || token.value == TOKendline)
451 a = NULL;
452 else if (dltSyntax)
454 check(TOKcolon);
455 a = parseDeclDefs(0);
456 check(TOKrcurly);
458 else
459 a = parseBlock();
460 s = new PragmaDeclaration(loc, ident, args, a);
461 break;
464 case TOKdebug:
465 nextToken();
466 if (token.value == TOKassign)
468 nextToken();
469 if (token.value == TOKidentifier)
470 s = new DebugSymbol(loc, token.ident);
471 else if (token.value == TOKint32v)
472 s = new DebugSymbol(loc, (unsigned)token.uns64value);
473 else
474 { error("identifier or integer expected, not %s", token.toChars());
475 s = NULL;
477 nextToken();
478 if (token.value != TOKsemicolon)
479 error("semicolon expected");
480 nextToken();
481 break;
484 condition = parseDebugCondition();
485 goto Lcondition;
487 case TOKversion:
488 nextToken();
489 if (token.value == TOKassign)
491 nextToken();
492 if (token.value == TOKidentifier)
493 s = new VersionSymbol(loc, token.ident);
494 else if (token.value == TOKint32v)
495 s = new VersionSymbol(loc, (unsigned)token.uns64value);
496 else
497 { error("identifier or integer expected, not %s", token.toChars());
498 s = NULL;
500 nextToken();
501 if (token.value != TOKsemicolon && token.value != TOKendline)
502 error("%s expected after version assignment", endToken());
503 nextToken();
504 break;
506 condition = parseVersionCondition();
507 goto Lcondition;
509 Lcondition:
510 a = parseBlock();
511 aelse = NULL;
512 if (token.value == TOKelse)
513 { nextToken();
514 aelse = parseBlock();
516 s = new ConditionalDeclaration(condition, a, aelse);
517 break;
519 case TOKsemicolon: // empty declaration
520 nextToken();
521 continue;
523 default:
524 error("Declaration expected, not '%s'",token.toChars());
525 Lerror:
526 while (token.value != TOKsemicolon && token.value != TOKendline && token.value != TOKeof)
527 nextToken();
528 nextToken();
529 s = NULL;
530 continue;
532 if (s)
533 { decldefs->push(s);
534 addComment(s, comment);
536 } while (!once);
537 return decldefs;
541 /********************************************
542 * Parse declarations after an align, protection, or extern decl.
545 Array *Parser::parseBlock()
547 Array *a = NULL;
548 Dsymbol *s;
550 //printf("Parser::parseBlock()\n");
551 switch (token.value)
553 case TOKsemicolon:
554 error("declaration expected following attribute, not ';'");
555 nextToken();
556 break;
558 case TOKlcurly:
559 nextToken();
560 a = parseDeclDefs(0);
561 if (token.value != TOKrcurly)
562 { /* { */
563 error("matching '}' expected, not %s", token.toChars());
565 else
566 nextToken();
567 break;
569 case TOKcolon:
570 nextToken();
571 #if 0
572 a = NULL;
573 #else
574 a = parseDeclDefs(0); // grab declarations up to closing curly bracket
575 #endif
576 break;
578 default:
579 a = parseDeclDefs(1);
580 break;
582 return a;
585 Array *DltParser::parseBlock()
587 Array *a = NULL;
588 Dsymbol *s;
590 optionalEndline();
591 switch (token.value)
593 case TOKendline:
594 case TOKsemicolon:
595 error("declaration expected following attribute, not %s", token.toChars());
596 nextToken();
597 break;
599 case TOKcolon:
600 nextToken();
601 a = parseDeclDefs(0);
602 if (token.value != TOKrcurly)
604 error("matching end-of-block expected, not %s", token.toChars());
606 else
607 nextToken();
608 break;
610 default:
611 a = parseDeclDefs(1);
612 break;
614 return a;
617 /**********************************
618 * Parse a static assertion.
621 StaticAssert *Parser::parseStaticAssert()
623 Loc loc = this->loc;
624 Expression *exp;
625 Expression *msg = NULL;
627 //printf("parseStaticAssert()\n");
628 nextToken();
629 checkLParen();
630 exp = parseAssignExp();
631 if (token.value == TOKcomma)
632 { nextToken();
633 msg = parseAssignExp();
635 checkRParen();
636 if (token.value == TOKsemicolon || token.value == TOKendline) {
637 nextToken();
638 return new StaticAssert(loc, exp, msg);
640 error("expected %s after static assert", endToken());
644 /***********************************
645 * Parse extern (linkage)
646 * The parser is on the 'extern' token.
649 enum LINK Parser::parseLinkage()
651 enum LINK link = LINKdefault;
652 nextToken();
653 assert(token.value == TOKlparen);
654 nextToken();
655 if (token.value == TOKidentifier)
656 { Identifier *id = token.ident;
658 nextToken();
659 if (id == Id::Windows)
660 link = LINKwindows;
661 else if (id == Id::Pascal)
662 link = LINKpascal;
663 else if (id == Id::D)
664 link = LINKd;
665 else if (id == Id::C)
667 link = LINKc;
668 if (token.value == TOKplusplus)
669 { link = LINKcpp;
670 nextToken();
673 else if (id == Id::System)
675 #ifdef IN_GCC
676 link = d_gcc_is_target_win32() ? LINKwindows : LINKc;
677 #else
678 #if _WIN32
679 link = LINKwindows;
680 #else
681 link = LINKc;
682 #endif
683 #endif
685 else
687 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
688 link = LINKd;
691 else
693 link = LINKd; // default
695 check(TOKrparen);
696 return link;
699 /**************************************
700 * Parse a debug conditional
703 Condition *Parser::parseDebugCondition()
705 Condition *c;
707 if (token.value == TOKlparen)
709 nextToken();
710 unsigned level = 1;
711 Identifier *id = NULL;
713 if (token.value == TOKidentifier)
714 id = token.ident;
715 else if (token.value == TOKint32v)
716 level = (unsigned)token.uns64value;
717 else
718 error("identifier or integer expected, not %s", token.toChars());
719 nextToken();
720 check(TOKrparen);
721 c = new DebugCondition(mod, level, id);
722 if (dltSyntax && token.value != TOKcolon)
723 error("expected colon after debug(), not '%s'", token.toChars());
724 } else {
725 if (dltSyntax && token.value != TOKcolon)
726 error("expected ':' or '(' after 'debug', not '%s'", token.toChars());
727 c = new DebugCondition(mod, 1, NULL);
729 return c;
733 /**************************************
734 * Parse a version conditional
737 Condition *Parser::parseVersionCondition()
739 Condition *c;
740 unsigned level = 1;
741 Identifier *id = NULL;
743 if (token.value == TOKlparen)
745 nextToken();
746 if (token.value == TOKidentifier)
747 id = token.ident;
748 else if (token.value == TOKint32v)
749 level = (unsigned)token.uns64value;
750 #if V2
751 /* Allow:
752 * version (unittest)
753 * even though unittest is a keyword
755 else if (token.value == TOKunittest)
756 id = Lexer::idPool(Token::toChars(TOKunittest));
757 #endif
758 else
759 error("identifier or integer expected, not %s", token.toChars());
760 nextToken();
761 check(TOKrparen);
764 else
765 error("(condition) expected following version");
766 c = new VersionCondition(mod, level, id);
767 return c;
771 /***********************************************
772 * static if (expression)
773 * body
774 * else
775 * body
778 Condition *Parser::parseStaticIfCondition()
779 { Expression *exp;
780 Condition *condition;
781 Array *aif;
782 Array *aelse;
783 Loc loc = this->loc;
785 nextToken();
786 checkLParen();
787 exp = parseAssignExp();
788 checkRParen();
790 condition = new StaticIfCondition(loc, exp);
791 return condition;
795 /*****************************************
796 * Parse a constructor definition:
797 * this(arguments) { body }
798 * Current token is 'this'.
801 CtorDeclaration *Parser::parseCtor()
803 CtorDeclaration *f;
804 Arguments *arguments;
805 int varargs;
806 Loc loc = this->loc;
808 nextToken();
809 arguments = parseParameters(&varargs);
810 f = new CtorDeclaration(loc, 0, arguments, varargs);
811 parseContracts(f);
812 return f;
815 /*****************************************
816 * Parse a destructor definition:
817 * ~this() { body }
818 * Current token is '~'.
821 DtorDeclaration *Parser::parseDtor()
823 DtorDeclaration *f;
824 Loc loc = this->loc;
826 nextToken();
827 check(TOKthis);
828 check(TOKlparen);
829 check(TOKrparen);
831 f = new DtorDeclaration(loc, 0);
832 parseContracts(f);
833 return f;
836 /*****************************************
837 * Parse a static constructor definition:
838 * static this() { body }
839 * Current token is 'this'.
842 StaticCtorDeclaration *Parser::parseStaticCtor()
844 StaticCtorDeclaration *f;
845 Loc loc = this->loc;
847 nextToken();
848 check(TOKlparen);
849 check(TOKrparen);
851 f = new StaticCtorDeclaration(loc, 0);
852 parseContracts(f);
853 return f;
856 /*****************************************
857 * Parse a static destructor definition:
858 * static ~this() { body }
859 * Current token is '~'.
862 StaticDtorDeclaration *Parser::parseStaticDtor()
864 StaticDtorDeclaration *f;
865 Loc loc = this->loc;
867 nextToken();
868 check(TOKthis);
869 check(TOKlparen);
870 check(TOKrparen);
872 f = new StaticDtorDeclaration(loc, 0);
873 parseContracts(f);
874 return f;
877 /*****************************************
878 * Parse an invariant definition:
879 * invariant { body }
880 * Current token is 'invariant'.
883 InvariantDeclaration *Parser::parseInvariant()
885 InvariantDeclaration *f;
886 Loc loc = this->loc;
888 nextToken();
889 if (token.value == TOKlparen) // optional ()
891 nextToken();
892 check(TOKrparen);
895 f = new InvariantDeclaration(loc, 0);
896 f->fbody = parseStatement(PScurly);
897 return f;
900 /*****************************************
901 * Parse a unittest definition:
902 * unittest { body }
903 * Current token is 'unittest'.
906 UnitTestDeclaration *Parser::parseUnitTest()
908 UnitTestDeclaration *f;
909 Statement *body;
910 Loc loc = this->loc;
912 nextToken();
914 body = parseStatement(PScurly);
916 f = new UnitTestDeclaration(loc, this->loc);
917 f->fbody = body;
918 return f;
921 /*****************************************
922 * Parse a new definition:
923 * new(arguments) { body }
924 * Current token is 'new'.
927 NewDeclaration *Parser::parseNew()
929 NewDeclaration *f;
930 Arguments *arguments;
931 int varargs;
932 Loc loc = this->loc;
934 nextToken();
935 arguments = parseParameters(&varargs);
936 f = new NewDeclaration(loc, 0, arguments, varargs);
937 parseContracts(f);
938 return f;
941 /*****************************************
942 * Parse a delete definition:
943 * delete(arguments) { body }
944 * Current token is 'delete'.
947 DeleteDeclaration *Parser::parseDelete()
949 DeleteDeclaration *f;
950 Arguments *arguments;
951 int varargs;
952 Loc loc = this->loc;
954 nextToken();
955 arguments = parseParameters(&varargs);
956 if (varargs)
957 error("... not allowed in delete function parameter list");
958 f = new DeleteDeclaration(loc, 0, arguments);
959 parseContracts(f);
960 return f;
963 /**********************************************
964 * Parse parameter list.
967 Arguments *Parser::parseParameters(int *pvarargs)
969 Arguments *arguments = new Arguments();
970 int varargs = 0;
971 int hasdefault = 0;
973 check(TOKlparen);
974 while (1)
975 { Type *tb;
976 Identifier *ai;
977 Type *at;
978 Argument *a;
979 unsigned storageClass;
980 Expression *ae;
982 ai = NULL;
983 storageClass = STCin; // parameter is "in" by default
984 switch (token.value)
986 case TOKrparen:
987 break;
989 case TOKdotdotdot:
990 varargs = 1;
991 nextToken();
992 break;
994 case TOKin:
995 storageClass = STCin;
996 nextToken();
997 goto L1;
999 case TOKout:
1000 storageClass = STCout;
1001 nextToken();
1002 goto L1;
1004 case TOKinout:
1005 case TOKref:
1006 storageClass = STCref;
1007 nextToken();
1008 goto L1;
1010 case TOKlazy:
1011 storageClass = STClazy;
1012 nextToken();
1013 goto L1;
1015 default:
1017 tb = parseBasicType();
1018 at = parseDeclarator(tb, &ai);
1019 ae = NULL;
1020 if (token.value == TOKassign) // = defaultArg
1021 { nextToken();
1022 ae = parseAssignExp();
1023 hasdefault = 1;
1025 else
1026 { if (hasdefault)
1027 error("default argument expected for %s",
1028 ai ? ai->toChars() : at->toChars());
1030 if (token.value == TOKdotdotdot)
1031 { /* This is:
1032 * at ai ...
1035 if (storageClass & (STCout | STCref))
1036 error("variadic argument cannot be out or ref");
1037 varargs = 2;
1038 a = new Argument(storageClass, at, ai, ae);
1039 arguments->push(a);
1040 nextToken();
1041 break;
1043 a = new Argument(storageClass, at, ai, ae);
1044 arguments->push(a);
1045 if (token.value == TOKcomma)
1046 { nextToken();
1047 continue;
1049 break;
1051 break;
1053 check(TOKrparen);
1054 *pvarargs = varargs;
1055 return arguments;
1059 /*************************************
1062 EnumDeclaration *Parser::parseEnum()
1063 { EnumDeclaration *e;
1064 Identifier *id;
1065 Type *t;
1066 Loc loc = this->loc;
1068 //printf("Parser::parseEnum()\n");
1069 nextToken();
1070 if (token.value == TOKidentifier)
1071 { id = token.ident;
1072 nextToken();
1074 else
1075 id = NULL;
1077 if (token.value == (dltSyntax ? TOKextends : TOKcolon))
1079 nextToken();
1080 t = parseBasicType();
1082 else
1083 t = NULL;
1085 e = new EnumDeclaration(loc, id, t);
1086 if (token.value == TOKsemicolon && id)
1087 nextToken();
1088 else if (token.value == startBlockTok)
1090 //printf("enum definition\n");
1091 e->members = new Array();
1092 nextToken();
1093 unsigned char *comment = token.blockComment;
1094 optionalEndline();
1095 while (token.value != TOKrcurly)
1097 if (token.value == TOKidentifier)
1098 { EnumMember *em;
1099 Expression *value;
1100 Identifier *ident;
1102 loc = this->loc;
1103 ident = token.ident;
1104 value = NULL;
1105 nextToken();
1106 if (token.value == TOKassign)
1108 nextToken();
1109 value = parseAssignExp();
1111 em = new EnumMember(loc, ident, value);
1112 e->members->push(em);
1113 optionalEndline();
1114 if (token.value == TOKrcurly)
1116 else
1117 { addComment(em, comment);
1118 comment = NULL;
1119 check(TOKcomma);
1120 optionalEndline();
1122 addComment(em, comment);
1123 comment = token.blockComment;
1125 else
1126 { error("enum member expected");
1127 nextToken();
1130 nextToken();
1132 else
1133 error("enum declaration is invalid");
1135 return e;
1138 Dsymbol *Parser::parseAggregate()
1139 { AggregateDeclaration *a = NULL;
1140 int anon = 0;
1141 enum TOK tok;
1142 Identifier *id;
1143 TemplateParameters *tpl = NULL;
1145 //printf("Parser::parseAggregate()\n");
1146 tok = token.value;
1147 nextToken();
1148 if (token.value != TOKidentifier)
1149 { id = NULL;
1151 else
1152 { id = token.ident;
1153 nextToken();
1155 if (token.value == TOKlparen)
1156 { // Class template declaration.
1158 // Gather template parameter list
1159 tpl = parseTemplateParameterList();
1163 Loc loc = this->loc;
1164 switch (tok)
1165 { case TOKclass:
1166 case TOKinterface:
1168 if (!id)
1169 error("anonymous classes not allowed");
1171 // Collect base class(es)
1172 BaseClasses *baseclasses = 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 check(TOKsemicolon);
2786 s = new CompileStatement(loc, e);
2787 break;
2789 Dsymbol *d = parseMixin();
2790 s = new DeclarationStatement(loc, d);
2791 break;
2794 case TOKcolon:
2795 case TOKlcurly:
2796 { Statements *statements;
2798 if (token.value != startBlockTok)
2799 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok), token.toChars());
2801 nextToken();
2802 optionalEndline();
2803 statements = new Statements();
2804 while (token.value != TOKrcurly)
2806 statements->push(parseStatement(PSsemi | PScurlyscope));
2807 optionalEndline();
2809 endloc = this->loc;
2810 s = new CompoundStatement(loc, statements);
2811 if (flags & (PSscope | PScurlyscope))
2812 s = new ScopeStatement(loc, s);
2813 nextToken();
2814 break;
2817 case TOKlog_error: s = logStatement(LogStatement::Error); break;
2818 case TOKlog_warning: s = logStatement(LogStatement::Warn); break;
2819 case TOKlog_info: s = logStatement(LogStatement::Info); break;
2820 case TOKlog_trace: s = logStatement(LogStatement::Trace); break;
2822 case TOKwhile:
2823 { Expression *condition;
2824 Statement *body;
2826 nextToken();
2827 checkLParen();
2828 condition = parseExpression();
2829 checkRParen();
2830 body = parseStatement(PSscope);
2831 s = new WhileStatement(loc, condition, body);
2832 break;
2835 case TOKsemicolon:
2836 if (!(flags & PSsemi))
2837 error("use '{ }' for an empty statement, not a ';'");
2838 nextToken();
2839 s = new ExpStatement(loc, NULL);
2840 break;
2842 case TOKdo:
2843 { Statement *body;
2844 Expression *condition;
2846 nextToken();
2847 body = parseStatement(PSscope);
2848 check(TOKwhile);
2849 checkLParen();
2850 condition = parseExpression();
2851 checkRParen();
2852 s = new DoStatement(loc, body, condition);
2853 break;
2856 case TOKfor:
2858 Statement *init;
2859 Expression *condition;
2860 Expression *increment;
2861 Statement *body;
2863 nextToken();
2865 if (token.value == TOKlparen) {
2866 /* for (init; cond; incr): ... */
2867 nextToken();
2868 if (token.value == TOKsemicolon)
2869 { init = NULL;
2870 nextToken();
2872 else
2873 { init = parseStatement(0);
2874 if (dltSyntax)
2875 check(TOKsemicolon);
2877 if (token.value == TOKsemicolon)
2879 condition = NULL;
2880 nextToken();
2882 else
2884 condition = parseExpression();
2885 check(TOKsemicolon, "for condition");
2887 if (token.value == TOKrparen)
2888 { increment = NULL;
2889 nextToken();
2891 else
2892 { increment = parseExpression();
2893 check(TOKrparen);
2895 body = parseStatement(PSscope);
2896 s = new ForStatement(loc, init, condition, increment, body);
2897 if (init)
2898 s = new ScopeStatement(loc, s);
2899 } else if (dltSyntax)
2900 goto caseForeach;
2901 break;
2904 caseForeach:
2905 case TOKforeach:
2906 case TOKforeach_reverse:
2908 /* for var in seq: ... */
2909 /* for index, var in seq: ... */
2910 Arguments *arguments;
2912 Statement *d;
2913 Statement *body;
2914 Expression *aggr;
2915 enum TOK op = (TOK) tok;
2917 if (tok != TOKfor)
2918 nextToken();
2920 checkLParen();
2922 TOK inTok = dltSyntax ? TOKin : TOKsemicolon;
2924 arguments = new Arguments();
2926 while (1)
2928 Type *tb;
2929 Identifier *ai = NULL;
2930 Type *at;
2931 unsigned storageClass;
2932 Argument *a;
2934 storageClass = STCin;
2935 if (token.value == TOKinout || token.value == TOKref)
2936 { storageClass = STCref;
2937 nextToken();
2939 if (token.value == TOKidentifier)
2941 Token *t = peek(&token);
2942 if (t->value == TOKcomma || t->value == inTok)
2943 { ai = token.ident;
2944 at = NULL; // infer argument type
2945 nextToken();
2946 goto Larg;
2949 tb = parseBasicType();
2950 at = parseDeclarator(tb, &ai);
2951 if (!ai)
2952 error("no identifier for declarator %s", at->toChars());
2953 Larg:
2954 a = new Argument(storageClass, at, ai, NULL);
2955 arguments->push(a);
2956 if (token.value == TOKcomma)
2957 { nextToken();
2958 continue;
2960 break;
2963 check(inTok);
2965 aggr = parseExpression();
2966 checkRParen();
2968 if (dltSyntax) {
2969 if (token.value == TOKreversed) {
2970 op = TOKforeach_reverse;
2971 nextToken();
2972 } else {
2973 op = TOKforeach;
2977 body = parseStatement(PScolon);
2978 s = new ForeachStatement(loc, op, arguments, aggr, body);
2979 break;
2982 case TOKif:
2983 { Argument *arg = NULL;
2984 Expression *condition;
2985 Statement *ifbody;
2986 Statement *elsebody;
2988 nextToken();
2989 checkLParen();
2991 if (token.value == TOKauto)
2993 nextToken();
2994 if (token.value == TOKidentifier)
2996 Token *t = peek(&token);
2997 if (t->value == TOKassign)
2999 arg = new Argument(STCin, NULL, token.ident, NULL);
3000 nextToken();
3001 nextToken();
3003 else
3004 { error("= expected following auto identifier");
3005 goto Lerror;
3008 else
3009 { error("identifier expected following auto");
3010 goto Lerror;
3013 else if (isDeclaration(&token, 2, TOKassign, NULL))
3015 Type *tb;
3016 Type *at;
3017 Identifier *ai;
3019 tb = parseBasicType();
3020 at = parseDeclarator(tb, &ai);
3021 check(TOKassign);
3022 arg = new Argument(STCin, at, ai, NULL);
3025 // Check for " ident;"
3026 else if (token.value == TOKidentifier && !dltSyntax)
3028 Token *t = peek(&token);
3029 if (t->value == TOKcomma || t->value == TOKsemicolon)
3031 arg = new Argument(STCin, NULL, token.ident, NULL);
3032 nextToken();
3033 nextToken();
3034 if (1 || !global.params.useDeprecated)
3035 error("if (v; e) is deprecated, use if (auto v = e)");
3039 condition = parseExpression();
3040 checkRParen();
3041 ifbody = parseStatement(PSscope);
3042 if (token.value == TOKelse)
3044 nextToken();
3045 if (dltSyntax)
3047 if (token.value == TOKcolon) {
3048 elsebody = parseStatement(PSscope);
3049 } else if (token.value == TOKif) {
3050 elsebody = parseStatement(0);
3051 } else {
3052 error("Expected 'else:' or 'else if', not 'else %s'", token.toChars());
3053 elsebody = NULL;
3056 else
3057 elsebody = parseStatement(PSscope);
3059 else
3060 elsebody = NULL;
3061 s = new IfStatement(loc, arg, condition, ifbody, elsebody);
3062 break;
3065 case TOKscope:
3066 if (peek(&token)->value != TOKlparen)
3067 goto Ldeclaration; // scope used as storage class
3068 nextToken();
3069 check(TOKlparen);
3070 if (token.value != TOKidentifier)
3071 { error("scope identifier expected");
3072 goto Lerror;
3074 else
3075 { TOK t = TOKon_scope_exit;
3076 Identifier *id = token.ident;
3078 if (id == Id::exit)
3079 t = TOKon_scope_exit;
3080 else if (id == Id::failure)
3081 t = TOKon_scope_failure;
3082 else if (id == Id::success)
3083 t = TOKon_scope_success;
3084 else
3085 error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
3086 nextToken();
3087 check(TOKrparen);
3088 Statement *st = parseStatement(PScolon | PScurlyscope);
3089 s = new OnScopeStatement(loc, t, st);
3090 break;
3093 case TOKdebug:
3094 nextToken();
3095 condition = parseDebugCondition();
3096 goto Lcondition;
3098 case TOKversion:
3099 nextToken();
3100 condition = parseVersionCondition();
3101 goto Lcondition;
3103 Lcondition:
3104 if (dltSyntax && token.value != TOKcolon)
3105 error("expected colon after condition, not '%s'", token.toChars());
3106 ifbody = parseStatement(PScolon /*PSsemi*/);
3107 elsebody = NULL;
3108 if (token.value == TOKelse)
3110 nextToken();
3111 elsebody = parseStatement(PScolon /*PSsemi*/);
3113 s = new ConditionalStatement(loc, condition, ifbody, elsebody);
3114 break;
3116 case TOKpragma:
3117 { Identifier *ident;
3118 Expressions *args = NULL;
3119 Statement *body;
3121 nextToken();
3122 check(TOKlparen);
3123 if (token.value != TOKidentifier)
3124 { error("pragma(identifier expected");
3125 goto Lerror;
3127 ident = token.ident;
3128 nextToken();
3129 if (token.value == TOKcomma)
3130 args = parseArguments(); // pragma(identifier, args...);
3131 else
3132 check(TOKrparen); // pragma(identifier);
3133 if (token.value == TOKsemicolon)
3134 { nextToken();
3135 body = NULL;
3137 else
3138 body = parseStatement(PSsemi | PScolon);
3139 s = new PragmaStatement(loc, ident, args, body);
3140 break;
3143 case TOKswitch:
3144 { Expression *condition;
3145 Statement *body;
3147 nextToken();
3148 checkLParen();
3149 condition = parseExpression();
3150 checkRParen();
3151 body = parseStatement(PSscope | PScolon);
3152 s = new SwitchStatement(loc, condition, body);
3153 break;
3156 case TOKcase:
3157 { Expression *exp;
3158 Statements *statements;
3159 Array cases; // array of Expression's
3161 while (1)
3163 nextToken();
3164 exp = parseAssignExp();
3165 cases.push(exp);
3166 if (token.value != TOKcomma)
3167 break;
3170 if (dltSyntax)
3172 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3174 else
3176 check(TOKcolon);
3178 statements = new Statements();
3179 while (token.value != TOKcase &&
3180 token.value != TOKdefault &&
3181 token.value != TOKrcurly)
3183 statements->push(parseStatement(PSsemi | PScurlyscope));
3185 s = new CompoundStatement(loc, statements);
3188 s = new ScopeStatement(loc, s);
3190 // Keep cases in order by building the case statements backwards
3191 for (int i = cases.dim; i; i--)
3193 exp = (Expression *)cases.data[i - 1];
3194 s = new CaseStatement(loc, exp, s);
3196 break;
3199 case TOKdefault:
3201 Statements *statements;
3203 nextToken();
3205 if (dltSyntax)
3207 s = parseStatement(PSsemi | PScurlyscope | PScolon);
3209 else
3211 check(TOKcolon);
3213 statements = new Statements();
3214 while (token.value != TOKcase &&
3215 token.value != TOKdefault &&
3216 token.value != TOKrcurly)
3218 statements->push(parseStatement(PSsemi | PScurlyscope));
3220 s = new CompoundStatement(loc, statements);
3223 s = new ScopeStatement(loc, s);
3224 s = new DefaultStatement(loc, s);
3225 break;
3228 case TOKreturn:
3229 { Expression *exp;
3231 nextToken();
3232 if (token.value == TOKsemicolon || token.value == TOKendline)
3233 exp = NULL;
3234 else
3235 exp = parseExpression();
3237 if (!dltSyntax)
3238 check(TOKsemicolon, "return statement");
3239 else if (token.value != TOKendline) {
3240 error("Expected end-of-line after return statement, but found '%s'", token.toChars());
3243 s = new ReturnStatement(loc, exp);
3244 break;
3247 case TOKbreak:
3248 { Identifier *ident;
3250 nextToken();
3251 if (token.value == TOKidentifier)
3252 { ident = token.ident;
3253 nextToken();
3255 else
3256 ident = NULL;
3257 if (token.value != TOKsemicolon && token.value != TOKendline) {
3258 error("expected %s after break, not '%s'", endToken(), token.toChars());
3260 if (!dltSyntax)
3261 nextToken();
3262 s = new BreakStatement(loc, ident);
3263 break;
3266 case TOKcontinue:
3267 { Identifier *ident;
3269 nextToken();
3270 if (token.value == TOKidentifier)
3271 { ident = token.ident;
3272 nextToken();
3274 else
3275 ident = NULL;
3276 check(TOKsemicolon, "continue statement");
3277 s = new ContinueStatement(loc, ident);
3278 break;
3281 case TOKgoto:
3282 { Identifier *ident;
3284 nextToken();
3285 if (token.value == TOKdefault)
3287 nextToken();
3288 s = new GotoDefaultStatement(loc);
3290 else if (token.value == TOKcase)
3292 Expression *exp = NULL;
3294 nextToken();
3295 if (token.value != TOKsemicolon)
3296 exp = parseExpression();
3297 s = new GotoCaseStatement(loc, exp);
3299 else
3301 if (token.value != TOKidentifier)
3302 { error("Identifier expected following goto");
3303 ident = NULL;
3305 else
3306 { ident = token.ident;
3307 nextToken();
3309 s = new GotoStatement(loc, ident);
3311 if (token.value != TOKsemicolon && token.value != TOKendline) {
3312 error("expected %s after goto statement, not '%s'", endToken(), token.toChars());
3314 break;
3317 case TOKsynchronized:
3318 { Expression *exp;
3319 Statement *body;
3321 nextToken();
3322 if (token.value == TOKlparen)
3324 nextToken();
3325 exp = parseExpression();
3326 check(TOKrparen);
3328 else
3329 exp = NULL;
3330 body = parseStatement(PSscope);
3331 s = new SynchronizedStatement(loc, exp, body);
3332 break;
3335 case TOKwith:
3336 { Expression *exp;
3337 Statement *body;
3339 nextToken();
3340 check(TOKlparen);
3341 exp = parseExpression();
3342 check(TOKrparen);
3343 body = parseStatement(PSscope);
3344 s = new WithStatement(loc, exp, body);
3345 break;
3348 case TOKtry:
3349 { Statement *body;
3350 Array *catches = NULL;
3351 Statement *finalbody = NULL;
3353 nextToken();
3354 body = parseStatement(PSscope);
3355 while (token.value == TOKcatch)
3357 Statement *handler;
3358 Catch *c;
3359 Type *t;
3360 Identifier *id;
3361 Loc loc = this->loc;
3363 nextToken();
3364 if (token.value == startBlockTok)
3366 t = NULL;
3367 id = NULL;
3369 else
3371 check(TOKlparen);
3372 t = parseBasicType();
3373 id = NULL;
3374 t = parseDeclarator(t, &id);
3375 check(TOKrparen);
3377 handler = parseStatement(PScolon);
3378 c = new Catch(loc, t, id, handler);
3379 if (!catches)
3380 catches = new Array();
3381 catches->push(c);
3384 if (token.value == TOKfinally)
3385 { nextToken();
3386 finalbody = parseStatement(PScolon);
3389 s = body;
3390 if (!catches && !finalbody)
3391 error("catch or finally expected following try");
3392 else
3393 { if (catches)
3394 s = new TryCatchStatement(loc, body, catches);
3395 if (finalbody)
3396 s = new TryFinallyStatement(loc, s, finalbody);
3398 break;
3401 case TOKthrow:
3402 { Expression *exp;
3404 nextToken();
3405 exp = parseExpression();
3406 if (token.value != TOKsemicolon && token.value != TOKendline) {
3407 error("%s expected after throw statement, not '%s'", endToken(), token.toChars());
3409 if (!dltSyntax)
3410 nextToken();
3411 s = new ThrowStatement(loc, exp);
3412 break;
3415 case TOKvolatile:
3416 nextToken();
3417 s = parseStatement(PSsemi | PScurlyscope);
3418 s = new VolatileStatement(loc, s);
3419 break;
3421 case TOKasm:
3422 { Statements *statements;
3423 Identifier *label;
3424 Loc labelloc;
3425 Token *toklist;
3426 Token **ptoklist;
3428 // Parse the asm block into a sequence of AsmStatements,
3429 // each AsmStatement is one instruction.
3430 // Separate out labels.
3431 // Defer parsing of AsmStatements until semantic processing.
3433 nextToken();
3434 #if GDC_EXTENDED_ASM_SYNTAX
3435 if (token.value == TOKlparen)
3437 nextToken();
3438 s = parseExtAsm(1);
3439 break;
3441 #endif
3442 check(startBlockTok);
3443 toklist = NULL;
3444 ptoklist = &toklist;
3445 label = NULL;
3446 statements = new Statements();
3447 while (1)
3449 switch (token.value)
3451 case TOKidentifier:
3452 if (!toklist)
3454 // Look ahead to see if it is a label
3455 t = peek(&token);
3456 if (t->value == TOKcolon)
3457 { // It's a label
3458 label = token.ident;
3459 labelloc = this->loc;
3460 nextToken();
3461 nextToken();
3462 continue;
3465 goto Ldefault;
3467 case TOKrcurly:
3468 if (toklist || label)
3470 error("asm statements must end in ';'");
3472 break;
3474 case TOKendline:
3475 case TOKsemicolon:
3476 s = NULL;
3477 if (toklist || label)
3478 { // Create AsmStatement from list of tokens we've saved
3479 s = new AsmStatement(this->loc, toklist);
3480 toklist = NULL;
3481 ptoklist = &toklist;
3482 if (label)
3483 { s = new LabelStatement(labelloc, label, s);
3484 label = NULL;
3486 statements->push(s);
3488 nextToken();
3489 continue;
3491 case TOKeof:
3492 /* { */
3493 error("matching '}' expected, not end of file");
3494 break;
3496 case TOKlparen:
3497 case TOKstring:
3498 // If the first token is a string or '(', parse as extended asm.
3499 if (! toklist)
3501 s = parseExtAsm(0);
3502 statements->push(s);
3503 continue;
3505 // ...else, drop through.
3507 default:
3508 Ldefault:
3509 *ptoklist = new Token();
3510 memcpy(*ptoklist, &token, sizeof(Token));
3511 ptoklist = &(*ptoklist)->next;
3512 *ptoklist = NULL;
3514 nextToken();
3515 continue;
3517 break;
3519 s = new CompoundStatement(loc, statements);
3520 nextToken();
3521 break;
3524 default:
3525 error("found '%s' instead of statement", token.toChars());
3526 goto Lerror;
3528 Lerror:
3529 while (token.value != TOKrcurly &&
3530 token.value != TOKsemicolon &&
3531 token.value != TOKeof)
3532 nextToken();
3533 if (token.value == TOKsemicolon)
3534 nextToken();
3535 s = NULL;
3536 break;
3539 return s;
3542 Statement *Parser::parseExtAsm(int expect_rparen)
3544 Expression * insnTemplate;
3545 Expressions * args = NULL;
3546 Array * argNames = NULL;
3547 Expressions * argConstraints = NULL;
3548 int nOutputArgs = 0;
3549 Expressions * clobbers = NULL;
3550 bool isInputPhase = false; // Output operands first, then input.
3552 insnTemplate = parseExpression();
3553 if (token.value == TOKrparen || token.value == TOKsemicolon)
3554 goto Ldone;
3555 check(TOKcolon);
3556 while (1) {
3557 Expression * arg = NULL;
3558 Identifier * name = NULL;
3559 Expression * constraint = NULL;
3561 switch (token.value)
3563 case TOKsemicolon:
3564 case TOKrparen:
3565 goto Ldone;
3567 case TOKcolon:
3568 nextToken();
3569 goto LnextPhase;
3571 case TOKeof:
3572 error("unterminated statement");
3574 case TOKlbracket:
3575 nextToken();
3576 if (token.value == TOKidentifier)
3578 name = token.ident;
3579 nextToken();
3581 else
3582 error("expected identifier after '['");
3583 check(TOKrbracket);
3584 // drop through
3585 default:
3586 constraint = parsePrimaryExp();
3587 if (constraint->op != TOKstring)
3588 error("expected constant string constraint for operand");
3589 arg = parseAssignExp();
3590 if (! args)
3592 args = new Expressions;
3593 argConstraints = new Expressions;
3594 argNames = new Array;
3596 args->push(arg);
3597 argNames->push(name);
3598 argConstraints->push(constraint);
3599 if (! isInputPhase)
3600 nOutputArgs++;
3602 if (token.value == TOKcomma)
3603 nextToken();
3604 break;
3606 continue;
3607 LnextPhase:
3608 if (! isInputPhase)
3609 isInputPhase = true;
3610 else
3611 break;
3614 while (1)
3616 Expression * clobber;
3618 switch (token.value)
3620 case TOKsemicolon:
3621 case TOKrparen:
3622 goto Ldone;
3624 case TOKeof:
3625 error("unterminated statement");
3627 default:
3628 clobber = parseAssignExp();
3629 if (clobber->op != TOKstring)
3630 error("expected constant string constraint for clobber name");
3631 if (! clobbers)
3632 clobbers = new Expressions;
3633 clobbers->push(clobber);
3635 if (token.value == TOKcomma)
3636 nextToken();
3637 break;
3640 Ldone:
3641 if (expect_rparen)
3642 check(TOKrparen);
3643 else
3644 check(TOKsemicolon);
3646 return new ExtAsmStatement(loc, insnTemplate, args, argNames,
3647 argConstraints, nOutputArgs, clobbers);
3650 void Parser::optionalEndline() {
3651 while (token.value == TOKendline) {
3652 nextToken();
3656 void Parser::check(enum TOK value)
3658 check(loc, value);
3661 void Parser::check(Loc loc, enum TOK value)
3663 if (token.value != value)
3664 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
3665 nextToken();
3668 void Parser::check(enum TOK value, char *string)
3670 if (token.value != value)
3671 error("found '%s' when expecting '%s' following '%s'",
3672 token.toChars(), Token::toChars(value), string);
3673 nextToken();
3676 char *Parser::endToken()
3678 return "semicolon";
3681 char *DltParser::endToken()
3683 return "newline";
3686 void Parser::checkLParen() { check(TOKlparen); }
3687 void Parser::checkRParen() { check(TOKrparen); }
3689 void DltParser::checkLParen() { }
3690 void DltParser::checkRParen() { }
3692 /************************************
3693 * Determine if the scanner is sitting on the start of a declaration.
3694 * Input:
3695 * needId 0 no identifier
3696 * 1 identifier optional
3697 * 2 must have identifier
3700 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
3702 int haveId = 0;
3704 if (!isBasicType(&t))
3705 return FALSE;
3706 if (!isDeclarator(&t, &haveId, endtok))
3707 return FALSE;
3708 if ( needId == 1 ||
3709 (needId == 0 && !haveId) ||
3710 (needId == 2 && haveId))
3711 { if (pt)
3712 *pt = t;
3713 return TRUE;
3715 else
3716 return FALSE;
3719 int Parser::isBasicType(Token **pt)
3721 // This code parallels parseBasicType()
3722 Token *t = *pt;
3723 Token *t2;
3724 int parens;
3726 switch (t->value)
3728 CASE_BASIC_TYPES:
3729 t = peek(t);
3730 break;
3732 case TOKidentifier:
3733 t = peek(t);
3734 if (t->value == TOKnot)
3736 goto L4;
3738 goto L3;
3739 while (1)
3742 t = peek(t);
3744 if (t->value == TOKdot)
3746 Ldot:
3747 t = peek(t);
3748 if (t->value != TOKidentifier)
3749 goto Lfalse;
3750 t = peek(t);
3751 if (t->value != TOKnot)
3752 goto L3;
3754 t = peek(t);
3755 if (t->value != TOKlparen)
3756 goto Lfalse;
3757 if (!skipParens(t, &t))
3758 goto Lfalse;
3760 else
3761 break;
3763 break;
3765 case TOKdot:
3766 goto Ldot;
3768 case TOKtypeof:
3769 /* typeof(exp).identifier...
3771 t = peek(t);
3772 if (t->value != TOKlparen)
3773 goto Lfalse;
3774 if (!skipParens(t, &t))
3775 goto Lfalse;
3776 goto L2;
3778 default:
3779 goto Lfalse;
3781 *pt = t;
3782 return TRUE;
3784 Lfalse:
3785 return FALSE;
3788 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
3789 { // This code parallels parseDeclarator()
3790 Token *t = *pt;
3791 int parens;
3793 //printf("Parser::isDeclarator()\n");
3794 //t->print();
3795 if (t->value == TOKassign)
3796 return FALSE;
3798 while (1)
3800 parens = FALSE;
3801 switch (t->value)
3803 case TOKquestion:
3804 case TOKmul:
3805 case TOKand:
3806 t = peek(t);
3807 continue;
3809 case TOKlbracket:
3810 t = peek(t);
3811 if (t->value == TOKrbracket)
3813 t = peek(t);
3815 else if (isDeclaration(t, 0, TOKrbracket, &t))
3816 { // It's an associative array declaration
3817 t = peek(t);
3819 else
3821 // [ expression ]
3822 // [ expression .. expression ]
3823 if (!isExpression(&t))
3824 return FALSE;
3825 if (t->value == TOKslice)
3826 { t = peek(t);
3827 if (!isExpression(&t))
3828 return FALSE;
3830 if (t->value != TOKrbracket)
3831 return FALSE;
3832 t = peek(t);
3834 continue;
3836 case TOKidentifier:
3837 if (*haveId)
3838 return FALSE;
3839 *haveId = TRUE;
3840 t = peek(t);
3841 break;
3843 case TOKlparen:
3844 t = peek(t);
3846 if (t->value == TOKrparen)
3847 return FALSE; // () is not a declarator
3849 /* Regard ( identifier ) as not a declarator
3850 * BUG: what about ( *identifier ) in
3851 * f(*p)(x);
3852 * where f is a class instance with overloaded () ?
3853 * Should we just disallow C-style function pointer declarations?
3855 if (t->value == TOKidentifier)
3856 { Token *t2 = peek(t);
3857 if (t2->value == TOKrparen)
3858 return FALSE;
3862 if (!isDeclarator(&t, haveId, TOKrparen))
3863 return FALSE;
3864 t = peek(t);
3865 parens = TRUE;
3866 break;
3868 case TOKdelegate:
3869 case TOKfunction:
3870 t = peek(t);
3871 if (!isParameters(&t))
3872 return FALSE;
3873 continue;
3875 break;
3878 while (1)
3880 switch (t->value)
3882 #if CARRAYDECL
3883 case TOKlbracket:
3884 parens = FALSE;
3885 t = peek(t);
3886 if (t->value == TOKrbracket)
3888 t = peek(t);
3890 else if (isDeclaration(t, 0, TOKrbracket, &t))
3891 { // It's an associative array declaration
3892 t = peek(t);
3894 else
3896 // [ expression ]
3897 if (!isExpression(&t))
3898 return FALSE;
3899 if (t->value != TOKrbracket)
3900 return FALSE;
3901 t = peek(t);
3903 continue;
3904 #endif
3906 case TOKlparen:
3907 parens = FALSE;
3908 if (!isParameters(&t))
3909 return FALSE;
3910 continue;
3912 // Valid tokens that follow a declaration
3913 case TOKrparen:
3914 case TOKrbracket:
3915 case TOKassign:
3916 case TOKcomma:
3917 case TOKendline:
3918 case TOKsemicolon:
3919 case TOKlcurly:
3920 case TOKin:
3921 // The !parens is to disallow unnecessary parentheses
3922 if (!parens && (endtok == TOKreserved || endtok == t->value))
3923 { *pt = t;
3924 return TRUE;
3926 return FALSE;
3928 default:
3929 return FALSE;
3935 int Parser::isParameters(Token **pt)
3936 { // This code parallels parseParameters()
3937 Token *t = *pt;
3938 int tmp;
3940 //printf("isParameters()\n");
3941 if (t->value != TOKlparen)
3942 return FALSE;
3944 t = peek(t);
3945 while (1)
3947 switch (t->value)
3949 case TOKrparen:
3950 break;
3952 case TOKdotdotdot:
3953 t = peek(t);
3954 break;
3956 case TOKin:
3957 case TOKout:
3958 case TOKinout:
3959 case TOKref:
3960 case TOKlazy:
3961 t = peek(t);
3962 default:
3963 if (!isBasicType(&t))
3964 return FALSE;
3965 tmp = FALSE;
3966 if (t->value != TOKdotdotdot &&
3967 !isDeclarator(&t, &tmp, TOKreserved))
3968 return FALSE;
3969 if (t->value == TOKassign)
3970 { t = peek(t);
3971 if (!isExpression(&t))
3972 return FALSE;
3974 if (t->value == TOKdotdotdot)
3976 t = peek(t);
3977 break;
3979 if (t->value == TOKcomma)
3980 { t = peek(t);
3981 continue;
3983 break;
3985 break;
3987 if (t->value != TOKrparen)
3988 return FALSE;
3989 t = peek(t);
3990 *pt = t;
3991 return TRUE;
3994 int Parser::isExpression(Token **pt)
3996 // This is supposed to determine if something is an expression.
3997 // What it actually does is scan until a closing right bracket
3998 // is found.
4000 Token *t = *pt;
4001 int brnest = 0;
4002 int panest = 0;
4004 for (;; t = peek(t))
4006 switch (t->value)
4008 case TOKlbracket:
4009 brnest++;
4010 continue;
4012 case TOKrbracket:
4013 if (--brnest >= 0)
4014 continue;
4015 break;
4017 case TOKlparen:
4018 panest++;
4019 continue;
4021 case TOKcomma:
4022 if (brnest || panest)
4023 continue;
4024 break;
4026 case TOKrparen:
4027 if (--panest >= 0)
4028 continue;
4029 break;
4031 case TOKslice:
4032 if (brnest)
4033 continue;
4034 break;
4036 case TOKeof:
4037 return FALSE;
4039 default:
4040 continue;
4042 break;
4045 *pt = t;
4046 return TRUE;
4049 /**********************************************
4050 * Skip over
4051 * instance foo.bar(parameters...)
4052 * Output:
4053 * if (pt), *pt is set to the token following the closing )
4054 * Returns:
4055 * 1 it's valid instance syntax
4056 * 0 invalid instance syntax
4059 int Parser::isTemplateInstance(Token *t, Token **pt)
4061 t = peek(t);
4062 if (t->value != TOKdot)
4064 if (t->value != TOKidentifier)
4065 goto Lfalse;
4066 t = peek(t);
4068 while (t->value == TOKdot)
4070 t = peek(t);
4071 if (t->value != TOKidentifier)
4072 goto Lfalse;
4073 t = peek(t);
4075 if (t->value != TOKlparen)
4076 goto Lfalse;
4078 // Skip over the template arguments
4079 while (1)
4081 while (1)
4083 t = peek(t);
4084 switch (t->value)
4086 case TOKlparen:
4087 if (!skipParens(t, &t))
4088 goto Lfalse;
4089 continue;
4090 case TOKrparen:
4091 break;
4092 case TOKcomma:
4093 break;
4094 case TOKeof:
4095 case TOKsemicolon:
4096 goto Lfalse;
4097 default:
4098 continue;
4100 break;
4103 if (t->value != TOKcomma)
4104 break;
4106 if (t->value != TOKrparen)
4107 goto Lfalse;
4108 t = peek(t);
4109 if (pt)
4110 *pt = t;
4111 return 1;
4113 Lfalse:
4114 return 0;
4117 /*******************************************
4118 * Skip parens, brackets.
4119 * Input:
4120 * t is on opening (
4121 * Output:
4122 * *pt is set to closing token, which is ')' on success
4123 * Returns:
4124 * !=0 successful
4125 * 0 some parsing error
4128 int Parser::skipParens(Token *t, Token **pt)
4130 int parens = 0;
4132 while (1)
4134 switch (t->value)
4136 case TOKlparen:
4137 parens++;
4138 break;
4140 case TOKrparen:
4141 parens--;
4142 if (parens < 0)
4143 goto Lfalse;
4144 if (parens == 0)
4145 goto Ldone;
4146 break;
4148 case TOKeof:
4149 case TOKsemicolon:
4150 goto Lfalse;
4152 default:
4153 break;
4155 t = peek(t);
4158 Ldone:
4159 if (*pt)
4160 *pt = t;
4161 return 1;
4163 Lfalse:
4164 return 0;
4167 /********************************* Expression Parser ***************************/
4169 Expression *Parser::parsePrimaryExp()
4170 { Expression *e;
4171 Type *t;
4172 Identifier *id;
4173 enum TOK save;
4174 Loc loc = this->loc;
4176 switch (token.value)
4178 case TOKidentifier:
4179 id = token.ident;
4180 nextToken();
4181 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4182 { // identifier!(template-argument-list)
4183 TemplateInstance *tempinst;
4185 tempinst = new TemplateInstance(loc, id);
4186 nextToken();
4187 tempinst->tiargs = parseTemplateArgumentList();
4188 e = new ScopeExp(loc, tempinst);
4190 else
4191 e = new IdentifierExp(loc, id);
4192 break;
4194 case TOKdollar:
4195 if (!inBrackets)
4196 error("'$' is valid only inside [] of index or slice");
4197 e = new DollarExp(loc);
4198 nextToken();
4199 break;
4201 case TOKdot:
4202 // Signal global scope '.' operator with "" identifier
4203 e = new IdentifierExp(loc, Id::empty);
4204 break;
4206 case TOKthis:
4207 e = new ThisExp(loc);
4208 nextToken();
4209 break;
4211 case TOKsuper:
4212 e = new SuperExp(loc);
4213 nextToken();
4214 break;
4216 case TOKint32v:
4217 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
4218 nextToken();
4219 break;
4221 case TOKuns32v:
4222 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
4223 nextToken();
4224 break;
4226 case TOKint64v:
4227 e = new IntegerExp(loc, token.int64value, Type::tint64);
4228 nextToken();
4229 break;
4231 case TOKuns64v:
4232 e = new IntegerExp(loc, token.uns64value, Type::tuns64);
4233 nextToken();
4234 break;
4236 case TOKfloat32v:
4237 e = new RealExp(loc, token.float80value, Type::tfloat32);
4238 nextToken();
4239 break;
4241 case TOKfloat64v:
4242 e = new RealExp(loc, token.float80value, Type::tfloat64);
4243 nextToken();
4244 break;
4246 case TOKfloat80v:
4247 e = new RealExp(loc, token.float80value, Type::tfloat80);
4248 nextToken();
4249 break;
4251 case TOKimaginary32v:
4252 e = new RealExp(loc, token.float80value, Type::timaginary32);
4253 nextToken();
4254 break;
4256 case TOKimaginary64v:
4257 e = new RealExp(loc, token.float80value, Type::timaginary64);
4258 nextToken();
4259 break;
4261 case TOKimaginary80v:
4262 e = new RealExp(loc, token.float80value, Type::timaginary80);
4263 nextToken();
4264 break;
4266 case TOKnull:
4267 e = new NullExp(loc);
4268 nextToken();
4269 break;
4271 case TOKtrue:
4272 e = new IntegerExp(loc, 1, Type::tbool);
4273 nextToken();
4274 break;
4276 case TOKfalse:
4277 e = new IntegerExp(loc, 0, Type::tbool);
4278 nextToken();
4279 break;
4281 case TOKcharv:
4282 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar);
4283 nextToken();
4284 break;
4286 case TOKwcharv:
4287 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar);
4288 nextToken();
4289 break;
4291 case TOKdcharv:
4292 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
4293 nextToken();
4294 break;
4296 case TOKstring:
4297 { unsigned char *s;
4298 unsigned len;
4299 unsigned char postfix;
4301 // cat adjacent strings
4302 s = token.ustring;
4303 len = token.len;
4304 postfix = token.postfix;
4305 while (1)
4307 nextToken();
4308 if (token.value == TOKstring)
4309 { unsigned len1;
4310 unsigned len2;
4311 unsigned char *s2;
4313 if (token.postfix)
4314 { if (token.postfix != postfix)
4315 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
4316 postfix = token.postfix;
4319 len1 = len;
4320 len2 = token.len;
4321 len = len1 + len2;
4322 s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
4323 memcpy(s2, s, len1 * sizeof(unsigned char));
4324 memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
4325 s = s2;
4327 else
4328 break;
4330 e = new StringExp(loc, s, len, postfix);
4331 break;
4334 CASE_BASIC_TYPES_X(t):
4335 nextToken();
4337 check(TOKdot, t->toChars());
4338 if (token.value != TOKidentifier)
4339 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
4340 goto Lerr;
4342 e = new TypeDotIdExp(loc, t, token.ident);
4343 nextToken();
4344 break;
4346 case TOKtypeof:
4347 { Expression *exp;
4349 nextToken();
4350 check(TOKlparen);
4351 exp = parseExpression();
4352 check(TOKrparen);
4353 t = new TypeTypeof(loc, exp);
4354 if (token.value == TOKdot)
4355 goto L1;
4356 e = new TypeExp(loc, t);
4357 break;
4360 case TOKtypeid:
4361 { Type *t;
4363 nextToken();
4364 check(TOKlparen, "typeid");
4365 t = parseBasicType();
4366 t = parseDeclarator(t,NULL); // ( type )
4367 check(TOKrparen);
4368 e = new TypeidExp(loc, t);
4369 break;
4372 case TOKis:
4373 { Type *targ;
4374 Identifier *ident = NULL;
4375 Type *tspec = NULL;
4376 enum TOK tok = TOKreserved;
4377 enum TOK tok2 = TOKreserved;
4378 Loc loc = this->loc;
4380 nextToken();
4381 if (token.value == TOKlparen)
4383 nextToken();
4384 targ = parseBasicType();
4385 targ = parseDeclarator(targ, &ident);
4386 if (token.value == TOKcolon || token.value == TOKequal)
4388 tok = token.value;
4389 nextToken();
4390 if (tok == TOKequal &&
4391 (token.value == TOKtypedef ||
4392 token.value == TOKstruct ||
4393 token.value == TOKunion ||
4394 token.value == TOKclass ||
4395 token.value == TOKsuper ||
4396 token.value == TOKenum ||
4397 token.value == TOKinterface ||
4398 token.value == TOKfunction ||
4399 token.value == TOKdelegate ||
4400 token.value == TOKreturn))
4402 tok2 = token.value;
4403 nextToken();
4405 else
4407 tspec = parseBasicType();
4408 tspec = parseDeclarator(tspec, NULL);
4411 check(TOKrparen);
4413 else
4414 { error("(type identifier : specialization) expected following is");
4415 goto Lerr;
4417 e = new IsExp(loc, targ, ident, tok, tspec, tok2);
4418 break;
4421 case TOKassert:
4422 { Expression *msg = NULL;
4424 nextToken();
4426 checkLParen();
4427 e = parseAssignExp();
4428 if (token.value == (dltSyntax ? TOKelse : TOKcomma))
4429 { nextToken();
4430 msg = parseAssignExp();
4432 checkRParen();
4434 e = new AssertExp(loc, e, msg);
4435 break;
4438 case TOKmixin:
4440 nextToken();
4441 check(TOKlparen, "mixin");
4442 e = parseAssignExp();
4443 check(TOKrparen);
4444 e = new CompileExp(loc, e);
4445 break;
4448 case TOKimport:
4450 nextToken();
4451 check(TOKlparen, "import");
4452 e = parseAssignExp();
4453 check(TOKrparen);
4454 e = new FileExp(loc, e);
4455 break;
4458 case TOKlparen:
4459 if (peekPastParen(&token)->value == TOKlcurly)
4460 { // (arguments) { statements... }
4461 save = TOKdelegate;
4462 goto case_delegate;
4464 // ( expression )
4465 nextToken();
4466 e = parseExpression();
4467 check(loc, TOKrparen);
4468 break;
4470 case TOKlbracket:
4471 { /* Parse array literals and associative array literals:
4472 * [ value, value, value ... ]
4473 * [ key:value, key:value, key:value ... ]
4475 Expressions *values = new Expressions();
4476 Expressions *keys = NULL;
4478 nextToken();
4479 if (token.value != TOKrbracket)
4481 while (1)
4483 Expression *e = parseAssignExp();
4484 if (token.value == TOKcolon && (keys || values->dim == 0))
4485 { nextToken();
4486 if (!keys)
4487 keys = new Expressions();
4488 keys->push(e);
4489 e = parseAssignExp();
4491 else if (keys)
4492 { error("'key:value' expected for associative array literal");
4493 delete keys;
4494 keys = NULL;
4496 values->push(e);
4497 if (token.value == TOKrbracket)
4498 break;
4499 check(TOKcomma);
4502 check(TOKrbracket);
4504 if (keys)
4505 e = new AssocArrayLiteralExp(loc, keys, values);
4506 else
4507 e = new ArrayLiteralExp(loc, values);
4508 break;
4511 case TOKlcurly:
4512 // { statements... }
4513 save = TOKdelegate;
4514 goto case_delegate;
4516 case TOKfunction:
4517 case TOKdelegate:
4518 save = token.value;
4519 nextToken();
4520 case_delegate:
4522 /* function type(parameters) { body }
4523 * delegate type(parameters) { body }
4525 Arguments *arguments;
4526 int varargs;
4527 FuncLiteralDeclaration *fd;
4528 Type *t;
4530 if (token.value == TOKlcurly)
4532 t = NULL;
4533 varargs = 0;
4534 arguments = new Arguments();
4536 else
4538 if (token.value == TOKlparen)
4539 t = NULL;
4540 else
4542 t = parseBasicType();
4543 t = parseBasicType2(t); // function return type
4545 arguments = parseParameters(&varargs);
4547 t = new TypeFunction(arguments, t, varargs, linkage);
4548 fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
4549 parseContracts(fd);
4550 e = new FuncExp(loc, fd);
4551 break;
4554 default:
4555 error("expression expected, not '%s'", token.toChars());
4556 Lerr:
4557 // Anything for e, as long as it's not NULL
4558 e = new IntegerExp(loc, 0, Type::tint32);
4559 nextToken();
4560 break;
4562 return parsePostExp(e);
4565 Expression *Parser::parsePostExp(Expression *e)
4567 Loc loc;
4569 while (1)
4571 loc = this->loc;
4572 switch (token.value)
4574 case TOKdot:
4575 nextToken();
4576 if (token.value == TOKidentifier)
4577 { Identifier *id = token.ident;
4579 nextToken();
4580 if (token.value == TOKnot && peek(&token)->value == TOKlparen)
4581 { // identifier!(template-argument-list)
4582 TemplateInstance *tempinst;
4584 tempinst = new TemplateInstance(loc, id);
4585 nextToken();
4586 tempinst->tiargs = parseTemplateArgumentList();
4587 e = new DotTemplateInstanceExp(loc, e, tempinst);
4589 else
4590 e = new DotIdExp(loc, e, id);
4591 continue;
4593 else if (token.value == TOKnew)
4595 e = parseNewExp(e);
4596 continue;
4598 else
4599 error("identifier expected following '.', not '%s'", token.toChars());
4600 break;
4602 case TOKplusplus:
4603 e = new PostExp(TOKplusplus, loc, e);
4604 break;
4606 case TOKminusminus:
4607 e = new PostExp(TOKminusminus, loc, e);
4608 break;
4610 case TOKlparen:
4611 e = new CallExp(loc, e, parseArguments());
4612 continue;
4614 case TOKlbracket:
4615 { // array dereferences:
4616 // array[index]
4617 // array[]
4618 // array[lwr .. upr]
4619 Expression *index;
4620 Expression *upr;
4622 inBrackets++;
4623 nextToken();
4624 if (token.value == TOKrbracket)
4625 { // array[]
4626 e = new SliceExp(loc, e, NULL, NULL);
4627 nextToken();
4629 else
4631 index = parseAssignExp();
4632 if (token.value == TOKslice)
4633 { // array[lwr .. upr]
4634 nextToken();
4635 upr = parseAssignExp();
4636 e = new SliceExp(loc, e, index, upr);
4638 else
4639 { // array[index, i2, i3, i4, ...]
4640 Expressions *arguments = new Expressions();
4641 arguments->push(index);
4642 if (token.value == TOKcomma)
4644 nextToken();
4645 while (1)
4646 { Expression *arg;
4648 arg = parseAssignExp();
4649 arguments->push(arg);
4650 if (token.value == TOKrbracket)
4651 break;
4652 check(TOKcomma);
4655 e = new ArrayExp(loc, e, arguments);
4657 check(TOKrbracket);
4658 inBrackets--;
4660 continue;
4663 default:
4664 return e;
4666 nextToken();
4670 Expression *Parser::parseUnaryExp()
4671 { Expression *e;
4672 Loc loc = this->loc;
4674 switch (token.value)
4676 case TOKand:
4677 nextToken();
4678 e = parseUnaryExp();
4679 e = new AddrExp(loc, e);
4680 break;
4682 case TOKplusplus:
4683 nextToken();
4684 e = parseUnaryExp();
4685 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4686 break;
4688 case TOKminusminus:
4689 nextToken();
4690 e = parseUnaryExp();
4691 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
4692 break;
4694 case TOKmul:
4695 nextToken();
4696 e = parseUnaryExp();
4697 e = new PtrExp(loc, e);
4698 break;
4700 case TOKmin:
4701 nextToken();
4702 e = parseUnaryExp();
4703 e = new NegExp(loc, e);
4704 break;
4706 case TOKadd:
4707 nextToken();
4708 e = parseUnaryExp();
4709 e = new UAddExp(loc, e);
4710 break;
4712 case TOKnot:
4713 nextToken();
4714 e = parseUnaryExp();
4715 e = new NotExp(loc, e);
4716 break;
4718 case TOKtilde:
4719 nextToken();
4720 e = parseUnaryExp();
4721 e = new ComExp(loc, e);
4722 break;
4724 case TOKdelete:
4725 nextToken();
4726 e = parseUnaryExp();
4727 e = new DeleteExp(loc, e);
4728 break;
4730 case TOKnew:
4731 e = parseNewExp(NULL);
4732 break;
4734 case TOKcast: // cast(type) expression
4735 { Type *t;
4737 nextToken();
4738 check(TOKlparen);
4739 t = parseBasicType();
4740 t = parseDeclarator(t,NULL); // ( type )
4741 check(TOKrparen);
4743 e = parseUnaryExp();
4744 e = new CastExp(loc, e, t);
4745 break;
4748 case TOKlparen:
4749 { Token *tk;
4751 tk = peek(&token);
4752 #if CCASTSYNTAX
4753 // If cast
4754 if (isDeclaration(tk, 0, TOKrparen, &tk))
4756 tk = peek(tk); // skip over right parenthesis
4757 switch (tk->value)
4759 case TOKdot:
4760 case TOKplusplus:
4761 case TOKminusminus:
4762 case TOKnot:
4763 case TOKdelete:
4764 case TOKnew:
4765 case TOKlparen:
4766 case TOKidentifier:
4767 case TOKthis:
4768 case TOKsuper:
4769 case TOKint32v:
4770 case TOKuns32v:
4771 case TOKint64v:
4772 case TOKuns64v:
4773 case TOKfloat32v:
4774 case TOKfloat64v:
4775 case TOKfloat80v:
4776 case TOKimaginary32v:
4777 case TOKimaginary64v:
4778 case TOKimaginary80v:
4779 case TOKnull:
4780 case TOKtrue:
4781 case TOKfalse:
4782 case TOKcharv:
4783 case TOKwcharv:
4784 case TOKdcharv:
4785 case TOKstring:
4786 #if 0
4787 case TOKtilde:
4788 case TOKand:
4789 case TOKmul:
4790 case TOKmin:
4791 case TOKadd:
4792 #endif
4793 case TOKfunction:
4794 case TOKdelegate:
4795 case TOKtypeof:
4796 CASE_BASIC_TYPES: // (type)int.size
4797 { // (type) una_exp
4798 Type *t;
4800 nextToken();
4801 t = parseBasicType();
4802 t = parseDeclarator(t,NULL);
4803 check(TOKrparen);
4805 // if .identifier
4806 if (token.value == TOKdot)
4808 nextToken();
4809 if (token.value != TOKidentifier)
4810 { error("Identifier expected following (type).");
4811 return NULL;
4813 e = new TypeDotIdExp(loc, t, token.ident);
4814 nextToken();
4815 e = parsePostExp(e);
4817 else
4819 e = parseUnaryExp();
4820 e = new CastExp(loc, e, t);
4821 error("C style cast illegal, use %s", e->toChars());
4823 return e;
4827 #endif
4828 e = parsePrimaryExp();
4829 break;
4831 default:
4832 e = parsePrimaryExp();
4833 break;
4835 assert(e);
4836 return e;
4839 Expression *Parser::parseMulExp()
4840 { Expression *e;
4841 Expression *e2;
4842 Loc loc = this->loc;
4844 e = parseUnaryExp();
4845 while (1)
4847 switch (token.value)
4849 case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
4850 case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
4851 case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
4853 default:
4854 break;
4856 break;
4858 return e;
4861 Expression *Parser::parseAddExp()
4862 { Expression *e;
4863 Expression *e2;
4864 Loc loc = this->loc;
4866 e = parseMulExp();
4867 while (1)
4869 switch (token.value)
4871 case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
4872 case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
4873 case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
4875 default:
4876 break;
4878 break;
4880 return e;
4883 Expression *Parser::parseShiftExp()
4884 { Expression *e;
4885 Expression *e2;
4886 Loc loc = this->loc;
4888 e = parseAddExp();
4889 while (1)
4891 switch (token.value)
4893 case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue;
4894 case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue;
4895 case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
4897 default:
4898 break;
4900 break;
4902 return e;
4905 Expression *Parser::parseRelExp()
4906 { Expression *e;
4907 Expression *e2;
4908 enum TOK op;
4909 Loc loc = this->loc;
4911 e = parseShiftExp();
4912 while (1)
4914 switch (token.value)
4916 case TOKlt:
4917 case TOKle:
4918 case TOKgt:
4919 case TOKge:
4920 case TOKunord:
4921 case TOKlg:
4922 case TOKleg:
4923 case TOKule:
4924 case TOKul:
4925 case TOKuge:
4926 case TOKug:
4927 case TOKue:
4928 op = token.value;
4929 nextToken();
4930 e2 = parseShiftExp();
4931 e = new CmpExp(op, loc, e, e2);
4932 continue;
4934 case TOKin:
4935 nextToken();
4936 e2 = parseShiftExp();
4937 e = new InExp(loc, e, e2);
4938 continue;
4940 default:
4941 break;
4943 break;
4945 return e;
4948 Expression *Parser::parseEqualExp()
4949 { Expression *e;
4950 Expression *e2;
4951 Token *t;
4952 Loc loc = this->loc;
4954 e = parseRelExp();
4955 while (1)
4956 { enum TOK value = token.value;
4958 switch (value)
4960 case TOKequal:
4961 case TOKnotequal:
4962 nextToken();
4963 e2 = parseRelExp();
4964 e = new EqualExp(value, loc, e, e2);
4965 continue;
4967 case TOKidentity:
4968 error("'===' is no longer legal, use 'is' instead");
4969 goto L1;
4971 case TOKnotidentity:
4972 error("'!==' is no longer legal, use '!is' instead");
4973 goto L1;
4975 case TOKis:
4976 value = TOKidentity;
4977 goto L1;
4979 case TOKnot:
4980 // Attempt to identify '!is'
4981 t = peek(&token);
4982 if (t->value != TOKis)
4983 break;
4984 nextToken();
4985 value = TOKnotidentity;
4986 goto L1;
4989 nextToken();
4990 e2 = parseRelExp();
4991 e = new IdentityExp(value, loc, e, e2);
4992 continue;
4994 default:
4995 break;
4997 break;
4999 return e;
5002 Expression *Parser::parseCmpExp()
5003 { Expression *e;
5004 Expression *e2;
5005 Token *t;
5006 Loc loc = this->loc;
5008 e = parseShiftExp();
5009 enum TOK op = token.value;
5011 switch (op)
5013 case TOKequal:
5014 case TOKnotequal:
5015 nextToken();
5016 e2 = parseShiftExp();
5017 e = new EqualExp(op, loc, e, e2);
5018 break;
5020 case TOKis:
5021 op = TOKidentity;
5022 goto L1;
5024 case TOKnot:
5025 // Attempt to identify '!is'
5026 t = peek(&token);
5027 if (t->value != TOKis)
5028 break;
5029 nextToken();
5030 op = TOKnotidentity;
5031 goto L1;
5034 nextToken();
5035 e2 = parseShiftExp();
5036 e = new IdentityExp(op, loc, e, e2);
5037 break;
5039 case TOKlt:
5040 case TOKle:
5041 case TOKgt:
5042 case TOKge:
5043 case TOKunord:
5044 case TOKlg:
5045 case TOKleg:
5046 case TOKule:
5047 case TOKul:
5048 case TOKuge:
5049 case TOKug:
5050 case TOKue:
5051 nextToken();
5052 e2 = parseShiftExp();
5053 e = new CmpExp(op, loc, e, e2);
5054 break;
5056 case TOKin:
5057 nextToken();
5058 e2 = parseShiftExp();
5059 e = new InExp(loc, e, e2);
5060 break;
5062 default:
5063 break;
5065 return e;
5068 Expression *Parser::parseAndExp()
5069 { Expression *e;
5070 Expression *e2;
5071 Loc loc = this->loc;
5073 if (global.params.Dversion == 1)
5075 e = parseEqualExp();
5076 while (token.value == TOKand)
5078 nextToken();
5079 e2 = parseEqualExp();
5080 e = new AndExp(loc,e,e2);
5081 loc = this->loc;
5084 else
5086 e = parseCmpExp();
5087 while (token.value == TOKand)
5089 nextToken();
5090 e2 = parseCmpExp();
5091 e = new AndExp(loc,e,e2);
5092 loc = this->loc;
5095 return e;
5098 Expression *Parser::parseXorExp()
5099 { Expression *e;
5100 Expression *e2;
5101 Loc loc = this->loc;
5103 e = parseAndExp();
5104 while (token.value == TOKxor)
5106 nextToken();
5107 e2 = parseAndExp();
5108 e = new XorExp(loc, e, e2);
5110 return e;
5113 Expression *Parser::parseOrExp()
5114 { Expression *e;
5115 Expression *e2;
5116 Loc loc = this->loc;
5118 e = parseXorExp();
5119 while (token.value == TOKor)
5121 nextToken();
5122 e2 = parseXorExp();
5123 e = new OrExp(loc, e, e2);
5125 return e;
5128 Expression *Parser::parseAndAndExp()
5129 { Expression *e;
5130 Expression *e2;
5131 Loc loc = this->loc;
5133 e = parseOrExp();
5134 while (token.value == TOKandand)
5136 nextToken();
5137 e2 = parseOrExp();
5138 e = new AndAndExp(loc, e, e2);
5140 return e;
5143 Expression *Parser::parseOrOrExp()
5144 { Expression *e;
5145 Expression *e2;
5146 Loc loc = this->loc;
5148 e = parseAndAndExp();
5149 while (token.value == TOKoror)
5151 nextToken();
5152 e2 = parseAndAndExp();
5153 e = new OrOrExp(loc, e, e2);
5155 return e;
5158 Expression *Parser::parseCondExp()
5159 { Expression *e;
5160 Expression *e1;
5161 Expression *e2;
5162 Loc loc = this->loc;
5164 e = parseOrOrExp();
5165 if (token.value == TOKquestion)
5167 nextToken();
5168 e1 = parseExpression();
5169 check(TOKcolon);
5170 e2 = parseCondExp();
5171 e = new CondExp(loc, e, e1, e2);
5173 return e;
5176 Expression *DltParser::parseCondExp()
5177 { Expression *e;
5178 Expression *e1;
5179 Expression *e2;
5180 Loc loc = this->loc;
5182 e = parseOrOrExp();
5183 if (token.value == TOKif)
5185 nextToken();
5186 e1 = parseExpression();
5187 check(TOKelse);
5188 e2 = parseCondExp();
5189 e = new CondExp(loc, e1, e, e2);
5191 return e;
5194 Expression *Parser::parseAssignExp()
5195 { Expression *e;
5196 Expression *e2;
5197 Loc loc;
5199 e = parseCondExp();
5200 while (1)
5202 loc = this->loc;
5203 switch (token.value)
5205 #define X(tok,ector) \
5206 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5208 X(TOKassign, AssignExp);
5209 X(TOKaddass, AddAssignExp);
5210 X(TOKminass, MinAssignExp);
5211 X(TOKmulass, MulAssignExp);
5212 X(TOKdivass, DivAssignExp);
5213 X(TOKmodass, ModAssignExp);
5214 X(TOKandass, AndAssignExp);
5215 X(TOKorass, OrAssignExp);
5216 X(TOKxorass, XorAssignExp);
5217 X(TOKshlass, ShlAssignExp);
5218 X(TOKshrass, ShrAssignExp);
5219 X(TOKushrass, UshrAssignExp);
5220 X(TOKcatass, CatAssignExp);
5222 #undef X
5223 default:
5224 break;
5226 break;
5228 return e;
5231 Expression *Parser::parseExpression()
5232 { Expression *e;
5233 Expression *e2;
5234 Loc loc = this->loc;
5236 //printf("Parser::parseExpression()\n");
5237 e = parseAssignExp();
5238 while (token.value == TOKcomma)
5240 nextToken();
5241 e2 = parseAssignExp();
5242 e = new CommaExp(loc, e, e2);
5243 loc = this->loc;
5245 return e;
5249 /*************************
5250 * Collect argument list.
5251 * Assume current token is '(' or '['.
5254 Expressions *Parser::parseArguments()
5255 { // function call
5256 Expressions *arguments;
5257 Expression *arg;
5258 enum TOK endtok;
5260 arguments = new Expressions();
5261 if (token.value == TOKlbracket)
5262 endtok = TOKrbracket;
5263 else
5264 endtok = TOKrparen;
5267 nextToken();
5268 if (token.value != endtok)
5270 while (1)
5272 arg = parseAssignExp();
5273 arguments->push(arg);
5274 if (token.value == endtok)
5275 break;
5276 check(TOKcomma);
5279 check(endtok);
5281 return arguments;
5284 /*******************************************
5287 Expression *Parser::parseNewExp(Expression *thisexp)
5288 { Type *t;
5289 Expressions *newargs;
5290 Expressions *arguments = NULL;
5291 Expression *e;
5292 Loc loc = this->loc;
5294 nextToken();
5295 newargs = NULL;
5296 if (token.value == TOKlparen)
5298 newargs = parseArguments();
5301 // An anonymous nested class starts with "class"
5302 if (token.value == TOKclass)
5304 nextToken();
5305 if (token.value == TOKlparen)
5306 arguments = parseArguments();
5308 BaseClasses *baseclasses = NULL;
5309 if (token.value != TOKlcurly)
5310 baseclasses = parseBaseClasses();
5312 Identifier *id = NULL;
5313 ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
5315 if (token.value != TOKlcurly)
5316 { error("{ members } expected for anonymous class");
5317 cd->members = NULL;
5319 else
5321 nextToken();
5322 Array *decl = parseDeclDefs(0);
5323 if (token.value != TOKrcurly)
5324 error("class member expected");
5325 nextToken();
5326 cd->members = decl;
5329 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
5331 return e;
5334 #if LTORARRAYDECL
5335 t = parseBasicType();
5336 t = parseBasicType2(t);
5337 if (t->ty == Taarray)
5339 Type *index = ((TypeAArray *)t)->index;
5341 Expression *e = index->toExpression();
5342 if (e)
5343 { arguments = new Expressions();
5344 arguments->push(e);
5345 t = new TypeDArray(t->next);
5347 else
5349 error("need size of rightmost array, not type %s", index->toChars());
5350 return new NullExp(loc);
5353 else if (t->ty == Tsarray)
5355 TypeSArray *tsa = (TypeSArray *)t;
5356 Expression *e = tsa->dim;
5358 arguments = new Expressions();
5359 arguments->push(e);
5360 t = new TypeDArray(t->next);
5362 else if (token.value == TOKlparen)
5364 arguments = parseArguments();
5366 #else
5367 t = parseBasicType();
5368 while (token.value == TOKmul)
5369 { t = new TypePointer(t);
5370 nextToken();
5372 if (token.value == TOKlbracket)
5374 Expression *e;
5376 nextToken();
5377 e = parseAssignExp();
5378 arguments = new Array();
5379 arguments->push(e);
5380 check(TOKrbracket);
5381 t = parseDeclarator(t, NULL);
5382 t = new TypeDArray(t);
5384 else if (token.value == TOKlparen)
5385 arguments = parseArguments();
5386 #endif
5387 e = new NewExp(loc, thisexp, newargs, t, arguments);
5388 return e;
5391 /**********************************************
5394 void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
5396 s->addComment(combineComments(blockComment, token.lineComment));
5400 /********************************* ***************************/