2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
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
28 #include "staticassert.h"
29 #include "expression.h"
30 #include "statement.h"
34 #include "declaration.h"
35 #include "aggregate.h"
40 #include "d-dmd-gcc.h"
43 // How multiple declarations are parsed.
52 // Support C cast syntax:
56 // Support C array declarations, such as
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");
70 dltNormalMode
= FALSE
;
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()
89 // ModuleDeclation leads off
91 if (token
.value
== TOKmodule
)
93 unsigned char *comment
= token
.blockComment
;
96 if (token
.value
!= TOKidentifier
)
97 { error("Identifier expected following module");
107 if (dltSyntax
&& id
== Id::dlt
)
108 dltNormalMode
= FALSE
;
110 while (nextToken() == TOKdot
)
116 if (token
.value
!= TOKidentifier
)
117 { error("Identifier expected following package");
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());
130 addComment(mod
, comment
);
134 decldefs
= parseDeclDefs(0);
135 if (token
.value
!= TOKeof
)
136 { error("unrecognized declaration '%s'", token
.toChars());
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());
156 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKeof
)
162 Array
*Parser::parseDeclDefs(int once
)
169 Condition
*condition
;
170 unsigned char *comment
;
172 //printf("Parser::parseDeclDefs()\n");
173 decldefs
= new Array();
176 comment
= token
.blockComment
;
190 s
= parseAggregate();
194 s
= parseImport(decldefs
, 0);
198 s
= (Dsymbol
*)parseTemplateDeclaration();
202 { Loc loc
= this->loc
;
203 if (peek(&token
)->value
== TOKlparen
)
206 check(TOKlparen
, "mixin");
207 Expression
*e
= parseAssignExp();
210 s
= new CompileDeclaration(loc
, e
);
224 a
= parseDeclarations();
238 s
= parseInvariant();
240 if (peek(&token
)->value
== TOKlcurly
)
241 s
= parseInvariant();
268 if (token
.value
== TOKthis
)
270 s
= parseStaticCtor();
272 error("no static constructors in Delight");
274 else if (token
.value
== TOKtilde
)
276 s
= parseStaticDtor();
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();
286 if (token
.value
== TOKelse
)
288 aelse
= parseBlock();
290 s
= new StaticIfDeclaration(condition
, a
, aelse
);
293 else if (token
.value
== TOKimport
)
295 s
= parseImport(decldefs
, 1);
300 error("no static variables in Delight");
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
;
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;
337 /* Look for auto initializers:
338 * storage_class identifier = initializer;
340 if (token
.value
== TOKidentifier
&&
341 peek(&token
)->value
== TOKassign
)
345 Identifier
*ident
= token
.ident
;
348 Initializer
*init
= parseInitializer();
349 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
350 v
->storage_class
= stc
;
352 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
356 else if (token
.value
== TOKcomma
)
359 if (token
.value
== TOKidentifier
&&
360 peek(&token
)->value
== TOKassign
)
363 addComment(s
, comment
);
367 error("Identifier expected following comma");
370 error("%s expected following declaration, not '%s'", endToken(), token
.toChars());
376 s
= new StorageClassDeclaration(stc
, a
);
381 if (peek(&token
)->value
!= TOKlparen
)
386 enum LINK linksave
= linkage
;
387 linkage
= parseLinkage();
389 s
= new LinkDeclaration(linkage
, a
);
393 error("access to external symbols can be done only by dlt.* modules");
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
;
405 s
= new ProtDeclaration(prot
, a
);
413 if (token
.value
== TOKlparen
)
416 if (token
.value
== TOKint32v
)
417 n
= (unsigned)token
.uns64value
;
419 { error("integer expected, not %s", token
.toChars());
426 n
= global
.structalign
; // default
429 s
= new AlignDeclaration(n
, a
);
435 Expressions
*args
= NULL
;
439 if (token
.value
!= TOKidentifier
)
440 { error("pragma(identifier expected");
445 if (token
.value
== TOKcomma
)
446 args
= parseArguments(); // pragma(identifier, args...)
448 check(TOKrparen
); // pragma(identifier)
450 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
455 a
= parseDeclDefs(0);
460 s
= new PragmaDeclaration(loc
, ident
, args
, a
);
466 if (token
.value
== TOKassign
)
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
);
474 { error("identifier or integer expected, not %s", token
.toChars());
478 if (token
.value
!= TOKsemicolon
)
479 error("semicolon expected");
484 condition
= parseDebugCondition();
489 if (token
.value
== TOKassign
)
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
);
497 { error("identifier or integer expected, not %s", token
.toChars());
501 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
)
502 error("%s expected after version assignment", endToken());
506 condition
= parseVersionCondition();
512 if (token
.value
== TOKelse
)
514 aelse
= parseBlock();
516 s
= new ConditionalDeclaration(condition
, a
, aelse
);
519 case TOKsemicolon
: // empty declaration
524 error("Declaration expected, not '%s'",token
.toChars());
526 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
&& token
.value
!= TOKeof
)
534 addComment(s
, comment
);
541 /********************************************
542 * Parse declarations after an align, protection, or extern decl.
545 Array
*Parser::parseBlock()
550 //printf("Parser::parseBlock()\n");
554 error("declaration expected following attribute, not ';'");
560 a
= parseDeclDefs(0);
561 if (token
.value
!= TOKrcurly
)
563 error("matching '}' expected, not %s", token
.toChars());
574 a
= parseDeclDefs(0); // grab declarations up to closing curly bracket
579 a
= parseDeclDefs(1);
585 Array
*DltParser::parseBlock()
595 error("declaration expected following attribute, not %s", token
.toChars());
601 a
= parseDeclDefs(0);
602 if (token
.value
!= TOKrcurly
)
604 error("matching end-of-block expected, not %s", token
.toChars());
611 a
= parseDeclDefs(1);
617 /**********************************
618 * Parse a static assertion.
621 StaticAssert
*Parser::parseStaticAssert()
625 Expression
*msg
= NULL
;
627 //printf("parseStaticAssert()\n");
630 exp
= parseAssignExp();
631 if (token
.value
== TOKcomma
)
633 msg
= parseAssignExp();
636 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
) {
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
;
653 assert(token
.value
== TOKlparen
);
655 if (token
.value
== TOKidentifier
)
656 { Identifier
*id
= token
.ident
;
659 if (id
== Id::Windows
)
661 else if (id
== Id::Pascal
)
663 else if (id
== Id::D
)
665 else if (id
== Id::C
)
668 if (token
.value
== TOKplusplus
)
673 else if (id
== Id::System
)
676 link
= d_gcc_is_target_win32() ? LINKwindows
: LINKc
;
687 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
693 link
= LINKd
; // default
699 /**************************************
700 * Parse a debug conditional
703 Condition
*Parser::parseDebugCondition()
707 if (token
.value
== TOKlparen
)
711 Identifier
*id
= NULL
;
713 if (token
.value
== TOKidentifier
)
715 else if (token
.value
== TOKint32v
)
716 level
= (unsigned)token
.uns64value
;
718 error("identifier or integer expected, not %s", token
.toChars());
721 c
= new DebugCondition(mod
, level
, id
);
722 if (dltSyntax
&& token
.value
!= TOKcolon
)
723 error("expected colon after debug(), not '%s'", token
.toChars());
725 if (dltSyntax
&& token
.value
!= TOKcolon
)
726 error("expected ':' or '(' after 'debug', not '%s'", token
.toChars());
727 c
= new DebugCondition(mod
, 1, NULL
);
733 /**************************************
734 * Parse a version conditional
737 Condition
*Parser::parseVersionCondition()
741 Identifier
*id
= NULL
;
743 if (token
.value
== TOKlparen
)
746 if (token
.value
== TOKidentifier
)
748 else if (token
.value
== TOKint32v
)
749 level
= (unsigned)token
.uns64value
;
753 * even though unittest is a keyword
755 else if (token
.value
== TOKunittest
)
756 id
= Lexer::idPool(Token::toChars(TOKunittest
));
759 error("identifier or integer expected, not %s", token
.toChars());
765 error("(condition) expected following version");
766 c
= new VersionCondition(mod
, level
, id
);
771 /***********************************************
772 * static if (expression)
778 Condition
*Parser::parseStaticIfCondition()
780 Condition
*condition
;
787 exp
= parseAssignExp();
790 condition
= new StaticIfCondition(loc
, exp
);
795 /*****************************************
796 * Parse a constructor definition:
797 * this(arguments) { body }
798 * Current token is 'this'.
801 CtorDeclaration
*Parser::parseCtor()
804 Arguments
*arguments
;
809 arguments
= parseParameters(&varargs
);
810 f
= new CtorDeclaration(loc
, 0, arguments
, varargs
);
815 /*****************************************
816 * Parse a destructor definition:
818 * Current token is '~'.
821 DtorDeclaration
*Parser::parseDtor()
831 f
= new DtorDeclaration(loc
, 0);
836 /*****************************************
837 * Parse a static constructor definition:
838 * static this() { body }
839 * Current token is 'this'.
842 StaticCtorDeclaration
*Parser::parseStaticCtor()
844 StaticCtorDeclaration
*f
;
851 f
= new StaticCtorDeclaration(loc
, 0);
856 /*****************************************
857 * Parse a static destructor definition:
858 * static ~this() { body }
859 * Current token is '~'.
862 StaticDtorDeclaration
*Parser::parseStaticDtor()
864 StaticDtorDeclaration
*f
;
872 f
= new StaticDtorDeclaration(loc
, 0);
877 /*****************************************
878 * Parse an invariant definition:
880 * Current token is 'invariant'.
883 InvariantDeclaration
*Parser::parseInvariant()
885 InvariantDeclaration
*f
;
889 if (token
.value
== TOKlparen
) // optional ()
895 f
= new InvariantDeclaration(loc
, 0);
896 f
->fbody
= parseStatement(PScurly
);
900 /*****************************************
901 * Parse a unittest definition:
903 * Current token is 'unittest'.
906 UnitTestDeclaration
*Parser::parseUnitTest()
908 UnitTestDeclaration
*f
;
914 body
= parseStatement(PScurly
);
916 f
= new UnitTestDeclaration(loc
, this->loc
);
921 /*****************************************
922 * Parse a new definition:
923 * new(arguments) { body }
924 * Current token is 'new'.
927 NewDeclaration
*Parser::parseNew()
930 Arguments
*arguments
;
935 arguments
= parseParameters(&varargs
);
936 f
= new NewDeclaration(loc
, 0, arguments
, varargs
);
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
;
955 arguments
= parseParameters(&varargs
);
957 error("... not allowed in delete function parameter list");
958 f
= new DeleteDeclaration(loc
, 0, arguments
);
963 /**********************************************
964 * Parse parameter list.
967 Arguments
*Parser::parseParameters(int *pvarargs
)
969 Arguments
*arguments
= new Arguments();
979 unsigned storageClass
;
983 storageClass
= STCin
; // parameter is "in" by default
995 storageClass
= STCin
;
1000 storageClass
= STCout
;
1006 storageClass
= STCref
;
1011 storageClass
= STClazy
;
1017 tb
= parseBasicType();
1018 at
= parseDeclarator(tb
, &ai
);
1020 if (token
.value
== TOKassign
) // = defaultArg
1022 ae
= parseAssignExp();
1027 error("default argument expected for %s",
1028 ai
? ai
->toChars() : at
->toChars());
1030 if (token
.value
== TOKdotdotdot
)
1035 if (storageClass
& (STCout
| STCref
))
1036 error("variadic argument cannot be out or ref");
1038 a
= new Argument(storageClass
, at
, ai
, ae
);
1043 a
= new Argument(storageClass
, at
, ai
, ae
);
1045 if (token
.value
== TOKcomma
)
1054 *pvarargs
= varargs
;
1059 /*************************************
1062 EnumDeclaration
*Parser::parseEnum()
1063 { EnumDeclaration
*e
;
1066 Loc loc
= this->loc
;
1068 //printf("Parser::parseEnum()\n");
1070 if (token
.value
== TOKidentifier
)
1077 if (token
.value
== (dltSyntax
? TOKextends
: TOKcolon
))
1080 t
= parseBasicType();
1085 e
= new EnumDeclaration(loc
, id
, t
);
1086 if (token
.value
== TOKsemicolon
&& id
)
1088 else if (token
.value
== startBlockTok
)
1090 //printf("enum definition\n");
1091 e
->members
= new Array();
1093 unsigned char *comment
= token
.blockComment
;
1095 while (token
.value
!= TOKrcurly
)
1097 if (token
.value
== TOKidentifier
)
1103 ident
= token
.ident
;
1106 if (token
.value
== TOKassign
)
1109 value
= parseAssignExp();
1111 em
= new EnumMember(loc
, ident
, value
);
1112 e
->members
->push(em
);
1114 if (token
.value
== TOKrcurly
)
1117 { addComment(em
, comment
);
1122 addComment(em
, comment
);
1123 comment
= token
.blockComment
;
1126 { error("enum member expected");
1133 error("enum declaration is invalid");
1138 Dsymbol
*Parser::parseAggregate()
1139 { AggregateDeclaration
*a
= NULL
;
1143 TemplateParameters
*tpl
= NULL
;
1145 //printf("Parser::parseAggregate()\n");
1148 if (token
.value
!= TOKidentifier
)
1155 if (token
.value
== TOKlparen
)
1156 { // Class template declaration.
1158 // Gather template parameter list
1159 tpl
= parseTemplateParameterList();
1163 Loc loc
= this->loc
;
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
);
1180 a
= new InterfaceDeclaration(loc
, id
, baseclasses
);
1186 a
= new StructDeclaration(loc
, id
);
1193 a
= new UnionDeclaration(loc
, id
);
1202 if (a
&& token
.value
== (dltSyntax
? TOKendline
: TOKsemicolon
))
1205 else if (token
.value
== startBlockTok
)
1207 //printf("aggregate definition\n");
1210 Array
*decl
= parseDeclDefs(0);
1211 if (token
.value
!= TOKrcurly
)
1212 error("end-of-block expected following member declarations in aggregate");
1216 /* Anonymous structs/unions are more like attributes.
1218 return new AnonDeclaration(loc
, anon
- 1, decl
);
1225 error("%s expected following aggregate declaration", Token::toChars(startBlockTok
));
1226 a
= new StructDeclaration(loc
, NULL
);
1231 TemplateDeclaration
*tempdecl
;
1233 // Wrap a template around the aggregate declaration
1234 decldefs
= new Array();
1236 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
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
1255 if (token
.value
== TOKextends
)
1257 else if (token
.value
== TOKimplements
)
1262 if (token
.value
== TOKcolon
)
1270 BaseClasses
*baseclasses
= new BaseClasses();
1272 for (; 1; nextToken())
1274 switch (token
.value
)
1279 protection
= PROTprivate
;
1282 protection
= PROTpackage
;
1285 protection
= PROTprotected
;
1288 protection
= PROTpublic
;
1291 error("base classes expected instead of %s", token
.toChars());
1294 BaseClass
*b
= new BaseClass(parseBasicType(), protection
);
1295 baseclasses
->push(b
);
1297 protection
= PROTpublic
;
1299 switch (token
.value
) {
1304 error("extends part must come before implements");
1306 error("only one extends is permitted");
1312 error("separate implemented interfaces with commas");
1320 /**************************************
1321 * Parse a TemplateDeclaration.
1324 TemplateDeclaration
*Parser::parseTemplateDeclaration()
1326 TemplateDeclaration
*tempdecl
;
1328 TemplateParameters
*tpl
;
1330 Loc loc
= this->loc
;
1333 if (token
.value
!= TOKidentifier
)
1334 { error("TemplateIdentifier expected following template");
1339 tpl
= parseTemplateParameterList();
1343 if (token
.value
!= startBlockTok
)
1344 { error("members of template declaration expected");
1350 decldefs
= parseDeclDefs(0);
1351 if (token
.value
!= TOKrcurly
)
1352 { error("template member expected");
1358 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
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");
1379 // Get array of TemplateParameters
1380 if (token
.value
!= TOKrparen
)
1381 { int isvariadic
= 0;
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
;
1393 // Get TemplateParameter
1395 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1397 if (token
.value
== TOKalias
)
1400 if (token
.value
!= TOKidentifier
)
1401 { error("Identifier expected for template parameter");
1404 tp_ident
= token
.ident
;
1406 if (token
.value
== TOKcolon
) // : Type
1409 tp_spectype
= parseBasicType();
1410 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1412 if (token
.value
== TOKassign
) // = Type
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
)
1423 if (token
.value
!= TOKidentifier
)
1424 { error("Identifier expected for template parameter");
1427 tp_ident
= token
.ident
;
1429 if (token
.value
== TOKcolon
) // : Type
1432 tp_spectype
= parseBasicType();
1433 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1435 if (token
.value
== TOKassign
) // = Type
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
)
1446 error("variadic template parameter must be last");
1448 tp_ident
= token
.ident
;
1451 tp
= new TemplateTupleParameter(loc
, tp_ident
);
1455 tp_valtype
= parseBasicType();
1456 tp_valtype
= parseDeclarator(tp_valtype
, &tp_ident
);
1459 error("no identifier for template value parameter");
1460 tp_ident
= new Identifier("error", TOKidentifier
);
1462 if (token
.value
== TOKcolon
) // : CondExpression
1465 tp_specvalue
= parseCondExp();
1467 if (token
.value
== TOKassign
) // = CondExpression
1470 tp_defaultvalue
= parseCondExp();
1472 tp
= new TemplateValueParameter(loc
, tp_ident
, tp_valtype
, tp_specvalue
, tp_defaultvalue
);
1475 if (token
.value
!= TOKcomma
)
1485 /******************************************
1486 * Parse template mixin.
1489 * mixin a.b.c!(args).Foo!(args);
1490 * mixin Foo!(args) identifier;
1491 * mixin typeof(expr).identifier!(args);
1494 Dsymbol
*Parser::parseMixin()
1502 //printf("parseMixin()\n");
1505 if (token
.value
== TOKdot
)
1511 if (token
.value
== TOKtypeof
)
1516 exp
= parseExpression();
1518 tqual
= new TypeTypeof(loc
, exp
);
1521 if (token
.value
!= TOKidentifier
)
1523 error("identifier expected, not %s", token
.toChars());
1530 idents
= new Array();
1534 if (token
.value
== TOKnot
)
1537 tiargs
= parseTemplateArgumentList();
1540 if (token
.value
!= TOKdot
)
1544 { TemplateInstance
*tempinst
= new TemplateInstance(loc
, id
);
1545 tempinst
->tiargs
= tiargs
;
1546 id
= (Identifier
*)tempinst
;
1552 if (token
.value
!= TOKidentifier
)
1553 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1561 if (token
.value
== TOKidentifier
)
1569 tm
= new TemplateMixin(loc
, id
, tqual
, idents
, tiargs
);
1570 if (token
.value
!= TOKsemicolon
)
1571 error("';' expected after mixin");
1580 /******************************************
1581 * Parse template argument list.
1583 * current token is opening '('
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");
1598 // Get TemplateArgumentList
1599 if (token
.value
!= TOKrparen
)
1603 // See if it is an Expression or a Type
1604 if (isDeclaration(&token
, 0, TOKreserved
, NULL
))
1608 // Get TemplateArgument
1609 ta
= parseBasicType();
1610 ta
= parseDeclarator(ta
, NULL
);
1617 ea
= parseAssignExp();
1620 if (token
.value
!= TOKcomma
)
1625 check(TOKrparen
, "template argument list");
1629 Import
*Parser::parseImport(Array
*decldefs
, int isstatic
)
1632 Identifier
*aliasid
= NULL
;
1636 //printf("Parser::parseImport()\n");
1641 if (token
.value
!= TOKidentifier
)
1642 { error("Identifier expected following import");
1650 if (!aliasid
&& token
.value
== TOKassign
)
1655 while (token
.value
== TOKdot
)
1661 if (token
.value
!= TOKidentifier
)
1662 { error("Identifier expected following package");
1669 s
= new Import(loc
, a
, token
.ident
, aliasid
, isstatic
);
1673 * : alias=name, alias=name;
1676 if (token
.value
== TOKcolon
)
1685 if (dltSyntax
&& token
.value
== TOKrcurly
)
1687 if (token
.value
!= TOKidentifier
)
1688 { error("Identifier expected following :");
1691 alias
= token
.ident
;
1693 if (token
.value
== TOKassign
)
1696 if (token
.value
!= TOKidentifier
)
1697 { error("Identifier expected following %s=", alias
->toChars());
1707 s
->addAlias(name
, alias
);
1708 if (token
.value
!= TOKcomma
&& token
.value
!= TOKendline
)
1722 } while (token
.value
== TOKcomma
);
1724 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
1728 error("%s expected", endToken());
1735 Type
*Parser::parseBasicType()
1739 TemplateInstance
*tempinst
;
1741 //printf("parseBasicType()\n");
1742 switch (token
.value
)
1744 CASE_BASIC_TYPES_X(t
):
1751 if (token
.value
== TOKnot
)
1754 tempinst
= new TemplateInstance(loc
, id
);
1755 tempinst
->tiargs
= parseTemplateArgumentList();
1756 tid
= new TypeInstance(loc
, tempinst
);
1760 tid
= new TypeIdentifier(loc
, id
);
1762 while (token
.value
== TOKdot
)
1764 if (token
.value
!= TOKidentifier
)
1765 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1770 if (token
.value
== TOKnot
)
1773 tempinst
= new TemplateInstance(loc
, id
);
1774 tempinst
->tiargs
= parseTemplateArgumentList();
1775 tid
->addIdent((Identifier
*)tempinst
);
1792 exp
= parseExpression();
1794 tid
= new TypeTypeof(loc
, exp
);
1799 error("basic type expected, not %s", token
.toChars());
1806 Type
*Parser::parseBasicType2(Type
*t
)
1811 //printf("parseBasicType2()\n");
1814 switch (token
.value
)
1817 t
= new TypePointer(t
);
1823 // Handle []. Make sure things like
1825 // is (array[1] of array[3] of int)
1827 if (token
.value
== TOKrbracket
)
1829 t
= new TypeDArray(t
); // []
1832 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1833 { // It's an associative array declaration
1836 //printf("it's an associative array\n");
1837 index
= parseBasicType();
1838 index
= parseDeclarator(index
, NULL
); // [ type ]
1839 t
= new TypeAArray(t
, index
);
1844 //printf("it's [expression]\n");
1846 Expression
*e
= parseExpression(); // [ expression ]
1847 if (token
.value
== TOKslice
)
1851 e2
= parseExpression(); // [ exp .. exp ]
1852 t
= new TypeSlice(t
, e
, e2
);
1855 t
= new TypeSArray(t
,e
);
1861 // Handle []. Make sure things like
1863 // is (array[3] of array[1] of int)
1865 while (token
.value
== TOKlbracket
)
1868 if (token
.value
== TOKrbracket
)
1870 ta
= new TypeDArray(t
); // []
1873 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1874 { // It's an associative array declaration
1877 //printf("it's an associative array\n");
1878 index
= parseBasicType();
1879 index
= parseDeclarator(index
, NULL
); // [ type ]
1881 ta
= new TypeAArray(t
, index
);
1885 //printf("it's [expression]\n");
1886 Expression
*e
= parseExpression(); // [ expression ]
1887 ta
= new TypeSArray(t
,e
);
1891 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1901 { // Handle delegate declaration:
1902 // t delegate(parameter list)
1903 // t function(parameter list)
1904 Arguments
*arguments
;
1906 enum TOK save
= token
.value
;
1909 arguments
= parseParameters(&varargs
);
1910 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1911 if (save
== TOKdelegate
)
1912 t
= new TypeDelegate(t
);
1914 t
= new TypePointer(t
); // pointer to function
1924 error("Type %s cannot be null; ? is pointless", old
->toChars());
1928 // fall-through to default
1941 // Don't wrap it yet, because that confuses resolve()
1942 ((TypeIdentifier
*) ts
)->maybe
= 1;
1945 // TypeMaybe will unwrap itself later if this isn't a nullable type
1954 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1958 //printf("parseDeclarator(tpl = %p)\n", tpl);
1959 t
= parseBasicType2(t
);
1961 switch (token
.value
)
1966 *pident
= token
.ident
;
1968 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1975 ts
= parseDeclarator(t
, pident
);
1986 switch (token
.value
)
1990 { // This is the old C-style post [] syntax.
1992 if (token
.value
== TOKrbracket
)
1994 ta
= new TypeDArray(t
); // []
1997 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1998 { // It's an associative array declaration
2001 //printf("it's an associative array\n");
2002 index
= parseBasicType();
2003 index
= parseDeclarator(index
, NULL
); // [ type ]
2005 ta
= new TypeAArray(t
, index
);
2009 //printf("it's [expression]\n");
2010 Expression
*e
= parseExpression(); // [ expression ]
2011 ta
= new TypeSArray(t
, e
);
2015 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
2022 { Arguments
*arguments
;
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
);
2042 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
2054 /**********************************
2055 * Return array of Declaration *'s.
2058 Array
*Parser::parseDeclarations()
2060 enum STC storage_class
;
2068 unsigned char *comment
= token
.blockComment
;
2069 enum LINK link
= linkage
;
2071 //printf("parseDeclarations()\n");
2072 switch (token
.value
)
2085 storage_class
= STCundefined
;
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
);
2107 if (peek(&token
)->value
!= TOKlparen
)
2112 link
= parseLinkage();
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
;
2133 Initializer
*init
= parseInitializer();
2134 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
2135 v
->storage_class
= storage_class
;
2137 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
2140 addComment(v
, comment
);
2142 else if (token
.value
== TOKcomma
)
2145 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
2147 error("Identifier expected following comma");
2153 error("%s expected following auto declaration, not '%s'", endToken(), token
.toChars());
2157 if (token
.value
== TOKclass
)
2158 { AggregateDeclaration
*s
;
2160 s
= (AggregateDeclaration
*)parseAggregate();
2161 s
->storage_class
|= storage_class
;
2163 addComment(s
, comment
);
2167 ts
= parseBasicType();
2168 ts
= parseBasicType2(ts
);
2173 Loc loc
= this->loc
;
2174 TemplateParameters
*tpl
= NULL
;
2177 t
= parseDeclarator(ts
, &ident
, &tpl
);
2181 else if (t
!= tfirst
)
2182 error("multiple declarations must have the same type, not %s and %s",
2183 tfirst
->toChars(), t
->toChars());
2185 error("no identifier for declarator %s", t
->toChars());
2187 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2193 /* Unwrap maybe qualifiers from aliases.
2194 * Otherwise, it thinks we're aliasing types when we're not.
2196 if (t
->ty
== Tmaybe
) {
2202 if (token
.value
== TOKassign
)
2205 init
= parseInitializer();
2207 if (tok
== TOKtypedef
)
2208 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2211 error("alias cannot have initializer");
2212 v
= new AliasDeclaration(loc
, ident
, t
);
2214 v
->storage_class
= storage_class
;
2215 if (link
== linkage
)
2219 Array
*ax
= new Array();
2221 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2224 switch (token
.value
)
2225 { case TOKsemicolon
:
2228 addComment(v
, comment
);
2233 addComment(v
, comment
);
2237 error("%s expected to close %s declaration", endToken(), Token::toChars(tok
));
2241 else if (t
->ty
== Tfunction
)
2242 { FuncDeclaration
*f
;
2245 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2246 addComment(f
, comment
);
2248 addComment(f
, NULL
);
2249 if (link
== linkage
)
2255 Array
*ax
= new Array();
2257 s
= new LinkDeclaration(link
, ax
);
2259 if (tpl
) // it's a function template
2261 TemplateDeclaration
*tempdecl
;
2263 // Wrap a template around the aggregate declaration
2264 decldefs
= new Array();
2266 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
, dltSyntax
);
2269 addComment(s
, comment
);
2273 { VarDeclaration
*v
;
2277 if (token
.value
== TOKassign
)
2280 init
= parseInitializer();
2282 v
= new VarDeclaration(loc
, t
, ident
, init
);
2283 v
->storage_class
= storage_class
;
2284 if (link
== linkage
)
2288 Array
*ax
= new Array();
2290 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2293 switch (token
.value
)
2297 addComment(v
, comment
);
2302 addComment(v
, comment
);
2306 addComment(v
, comment
);
2310 error("%s expected, not '%s'", endToken(), token
.toChars());
2319 /*****************************************
2320 * Parse contracts following function declaration.
2323 void Parser::parseContracts(FuncDeclaration
*f
)
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
)
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
);
2346 f
->fbody
= parseStatement(PScurly
);
2352 error("unexpected semi-colon after function declaration");
2355 if (f
->frequire
|| f
->fensure
)
2356 error("missing body { ... } after in or out");
2360 #if 0 // Do we want this for function declarations, so we can do:
2361 // int x, y, foo(), z;
2367 #if 0 // Dumped feature
2370 f
->fthrows
= new Array();
2375 tb
= parseBasicType();
2376 f
->fthrows
->push(tb
);
2377 if (token
.value
== TOKcomma
)
2390 error("redundant 'in' statement");
2391 f
->frequire
= parseStatement(PScurly
| PSscope
);
2395 // parse: out (identifier) { statement }
2397 if (token
.value
!= startBlockTok
)
2400 if (token
.value
!= TOKidentifier
)
2401 error("(identifier) following 'out' expected, not %s", token
.toChars());
2402 f
->outId
= token
.ident
;
2407 error("redundant 'out' statement");
2408 f
->fensure
= parseStatement(PScurly
| PSscope
);
2412 error("%s expected following function declaration", endToken());
2418 /*****************************************
2421 Initializer
*Parser::parseInitializer()
2423 StructInitializer
*is
;
2424 ArrayInitializer
*ia
;
2430 Loc loc
= this->loc
;
2434 switch (token
.value
)
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.
2443 for (t
= peek(&token
); 1; t
= peek(t
))
2469 is
= new StructInitializer(loc
);
2474 switch (token
.value
)
2478 error("comma expected separating field initializers");
2480 if (t
->value
== TOKcolon
)
2484 nextToken(); // skip over ':'
2489 value
= parseInitializer();
2490 is
->addInit(id
, value
);
2499 case TOKrcurly
: // allow trailing comma's
2504 error("found EOF instead of initializer");
2508 value
= parseInitializer();
2509 is
->addInit(NULL
, value
);
2512 //error("found '%s' instead of field initializer", token.toChars());
2520 ia
= new ArrayInitializer(loc
);
2525 switch (token
.value
)
2529 { error("comma expected separating array initializers, not %s", token
.toChars());
2533 e
= parseAssignExp();
2536 if (token
.value
== TOKcolon
)
2539 value
= parseInitializer();
2542 { value
= new ExpInitializer(e
->loc
, e
);
2545 ia
->addInit(e
, value
);
2552 error("comma expected separating array initializers, not %s", token
.toChars());
2553 value
= parseInitializer();
2554 ia
->addInit(NULL
, value
);
2563 case TOKrbracket
: // allow trailing comma's
2568 error("found '%s' instead of array initializer", token
.toChars());
2577 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
|| t
->value
== TOKendline
)
2580 return new VoidInitializer(loc
);
2586 e
= parseAssignExp();
2587 ie
= new ExpInitializer(loc
, e
);
2592 Statement
*Parser::logStatement(int level
) {
2594 if (token
.value
!= TOKlparen
)
2595 error(loc
, "found '%s' when expecting '('", token
.toChars());
2596 return new LogStatement(loc
, level
, parseArguments());
2599 /*****************************************
2604 Statement
*DltParser::parseStatement(int flags
)
2607 if (flags
& (PScolon
| PSscope
))
2609 return Parser::parseStatement(flags
);
2612 Statement
*Parser::parseStatement(int flags
)
2615 Condition
*condition
;
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
)
2632 // Need to look ahead to see if it is a declaration, label, or expression
2634 if (t
->value
== TOKcolon
)
2638 ident
= token
.ident
;
2641 s
= parseStatement(PSsemi
);
2642 s
= new LabelStatement(loc
, ident
, s
);
2646 // fallthrough to TOKdot
2649 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2665 case TOKimaginary32v
:
2666 case TOKimaginary64v
:
2667 case TOKimaginary80v
:
2692 exp
= parseExpression();
2694 check(TOKsemicolon
, "statement");
2695 s
= new ExpStatement(loc
, exp
);
2700 { // Look ahead to see if it's static assert() or static if()
2704 if (t
->value
== TOKassert
)
2707 s
= new StaticAssertStatement(parseStaticAssert());
2710 if (t
->value
== TOKif
)
2713 condition
= parseStaticIfCondition();
2717 error("no static variables in Delight");
2733 a
= parseDeclarations();
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
);
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
);
2753 if (flags
& PSscope
)
2754 s
= new ScopeStatement(loc
, s
);
2764 d
= parseAggregate();
2765 s
= new DeclarationStatement(loc
, d
);
2773 s
= new DeclarationStatement(loc
, d
);
2779 if (t
->value
== TOKlparen
)
2782 check(TOKlparen
, "mixin");
2783 Expression
*e
= parseAssignExp();
2785 check(TOKsemicolon
);
2786 s
= new CompileStatement(loc
, e
);
2789 Dsymbol
*d
= parseMixin();
2790 s
= new DeclarationStatement(loc
, d
);
2796 { Statements
*statements
;
2798 if (token
.value
!= startBlockTok
)
2799 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2803 statements
= new Statements();
2804 while (token
.value
!= TOKrcurly
)
2806 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2810 s
= new CompoundStatement(loc
, statements
);
2811 if (flags
& (PSscope
| PScurlyscope
))
2812 s
= new ScopeStatement(loc
, s
);
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;
2823 { Expression
*condition
;
2828 condition
= parseExpression();
2830 body
= parseStatement(PSscope
);
2831 s
= new WhileStatement(loc
, condition
, body
);
2836 if (!(flags
& PSsemi
))
2837 error("use '{ }' for an empty statement, not a ';'");
2839 s
= new ExpStatement(loc
, NULL
);
2844 Expression
*condition
;
2847 body
= parseStatement(PSscope
);
2850 condition
= parseExpression();
2852 s
= new DoStatement(loc
, body
, condition
);
2859 Expression
*condition
;
2860 Expression
*increment
;
2865 if (token
.value
== TOKlparen
) {
2866 /* for (init; cond; incr): ... */
2868 if (token
.value
== TOKsemicolon
)
2873 { init
= parseStatement(0);
2875 check(TOKsemicolon
);
2877 if (token
.value
== TOKsemicolon
)
2884 condition
= parseExpression();
2885 check(TOKsemicolon
, "for condition");
2887 if (token
.value
== TOKrparen
)
2892 { increment
= parseExpression();
2895 body
= parseStatement(PSscope
);
2896 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2898 s
= new ScopeStatement(loc
, s
);
2899 } else if (dltSyntax
)
2906 case TOKforeach_reverse
:
2908 /* for var in seq: ... */
2909 /* for index, var in seq: ... */
2910 Arguments
*arguments
;
2915 enum TOK op
= (TOK
) tok
;
2922 TOK inTok
= dltSyntax
? TOKin
: TOKsemicolon
;
2924 arguments
= new Arguments();
2929 Identifier
*ai
= NULL
;
2931 unsigned storageClass
;
2934 storageClass
= STCin
;
2935 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2936 { storageClass
= STCref
;
2939 if (token
.value
== TOKidentifier
)
2941 Token
*t
= peek(&token
);
2942 if (t
->value
== TOKcomma
|| t
->value
== inTok
)
2944 at
= NULL
; // infer argument type
2949 tb
= parseBasicType();
2950 at
= parseDeclarator(tb
, &ai
);
2952 error("no identifier for declarator %s", at
->toChars());
2954 a
= new Argument(storageClass
, at
, ai
, NULL
);
2956 if (token
.value
== TOKcomma
)
2965 aggr
= parseExpression();
2969 if (token
.value
== TOKreversed
) {
2970 op
= TOKforeach_reverse
;
2977 body
= parseStatement(PScolon
);
2978 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2983 { Argument
*arg
= NULL
;
2984 Expression
*condition
;
2986 Statement
*elsebody
;
2991 if (token
.value
== TOKauto
)
2994 if (token
.value
== TOKidentifier
)
2996 Token
*t
= peek(&token
);
2997 if (t
->value
== TOKassign
)
2999 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
3004 { error("= expected following auto identifier");
3009 { error("identifier expected following auto");
3013 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
3019 tb
= parseBasicType();
3020 at
= parseDeclarator(tb
, &ai
);
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
);
3034 if (1 || !global
.params
.useDeprecated
)
3035 error("if (v; e) is deprecated, use if (auto v = e)");
3039 condition
= parseExpression();
3041 ifbody
= parseStatement(PSscope
);
3042 if (token
.value
== TOKelse
)
3047 if (token
.value
== TOKcolon
) {
3048 elsebody
= parseStatement(PSscope
);
3049 } else if (token
.value
== TOKif
) {
3050 elsebody
= parseStatement(0);
3052 error("Expected 'else:' or 'else if', not 'else %s'", token
.toChars());
3057 elsebody
= parseStatement(PSscope
);
3061 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
3066 if (peek(&token
)->value
!= TOKlparen
)
3067 goto Ldeclaration
; // scope used as storage class
3070 if (token
.value
!= TOKidentifier
)
3071 { error("scope identifier expected");
3075 { TOK t
= TOKon_scope_exit
;
3076 Identifier
*id
= token
.ident
;
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
;
3085 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
3088 Statement
*st
= parseStatement(PScolon
| PScurlyscope
);
3089 s
= new OnScopeStatement(loc
, t
, st
);
3095 condition
= parseDebugCondition();
3100 condition
= parseVersionCondition();
3104 if (dltSyntax
&& token
.value
!= TOKcolon
)
3105 error("expected colon after condition, not '%s'", token
.toChars());
3106 ifbody
= parseStatement(PScolon
/*PSsemi*/);
3108 if (token
.value
== TOKelse
)
3111 elsebody
= parseStatement(PScolon
/*PSsemi*/);
3113 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
3117 { Identifier
*ident
;
3118 Expressions
*args
= NULL
;
3123 if (token
.value
!= TOKidentifier
)
3124 { error("pragma(identifier expected");
3127 ident
= token
.ident
;
3129 if (token
.value
== TOKcomma
)
3130 args
= parseArguments(); // pragma(identifier, args...);
3132 check(TOKrparen
); // pragma(identifier);
3133 if (token
.value
== TOKsemicolon
)
3138 body
= parseStatement(PSsemi
| PScolon
);
3139 s
= new PragmaStatement(loc
, ident
, args
, body
);
3144 { Expression
*condition
;
3149 condition
= parseExpression();
3151 body
= parseStatement(PSscope
| PScolon
);
3152 s
= new SwitchStatement(loc
, condition
, body
);
3158 Statements
*statements
;
3159 Array cases
; // array of Expression's
3164 exp
= parseAssignExp();
3166 if (token
.value
!= TOKcomma
)
3172 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
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
);
3201 Statements
*statements
;
3207 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
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
);
3232 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
3235 exp
= parseExpression();
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
);
3248 { Identifier
*ident
;
3251 if (token
.value
== TOKidentifier
)
3252 { ident
= token
.ident
;
3257 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3258 error("expected %s after break, not '%s'", endToken(), token
.toChars());
3262 s
= new BreakStatement(loc
, ident
);
3267 { Identifier
*ident
;
3270 if (token
.value
== TOKidentifier
)
3271 { ident
= token
.ident
;
3276 check(TOKsemicolon
, "continue statement");
3277 s
= new ContinueStatement(loc
, ident
);
3282 { Identifier
*ident
;
3285 if (token
.value
== TOKdefault
)
3288 s
= new GotoDefaultStatement(loc
);
3290 else if (token
.value
== TOKcase
)
3292 Expression
*exp
= NULL
;
3295 if (token
.value
!= TOKsemicolon
)
3296 exp
= parseExpression();
3297 s
= new GotoCaseStatement(loc
, exp
);
3301 if (token
.value
!= TOKidentifier
)
3302 { error("Identifier expected following goto");
3306 { ident
= token
.ident
;
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());
3317 case TOKsynchronized
:
3322 if (token
.value
== TOKlparen
)
3325 exp
= parseExpression();
3330 body
= parseStatement(PSscope
);
3331 s
= new SynchronizedStatement(loc
, exp
, body
);
3341 exp
= parseExpression();
3343 body
= parseStatement(PSscope
);
3344 s
= new WithStatement(loc
, exp
, body
);
3350 Array
*catches
= NULL
;
3351 Statement
*finalbody
= NULL
;
3354 body
= parseStatement(PSscope
);
3355 while (token
.value
== TOKcatch
)
3361 Loc loc
= this->loc
;
3364 if (token
.value
== startBlockTok
)
3372 t
= parseBasicType();
3374 t
= parseDeclarator(t
, &id
);
3377 handler
= parseStatement(PScolon
);
3378 c
= new Catch(loc
, t
, id
, handler
);
3380 catches
= new Array();
3384 if (token
.value
== TOKfinally
)
3386 finalbody
= parseStatement(PScolon
);
3390 if (!catches
&& !finalbody
)
3391 error("catch or finally expected following try");
3394 s
= new TryCatchStatement(loc
, body
, catches
);
3396 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3405 exp
= parseExpression();
3406 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3407 error("%s expected after throw statement, not '%s'", endToken(), token
.toChars());
3411 s
= new ThrowStatement(loc
, exp
);
3417 s
= parseStatement(PSsemi
| PScurlyscope
);
3418 s
= new VolatileStatement(loc
, s
);
3422 { Statements
*statements
;
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.
3434 #if GDC_EXTENDED_ASM_SYNTAX
3435 if (token
.value
== TOKlparen
)
3442 check(startBlockTok
);
3444 ptoklist
= &toklist
;
3446 statements
= new Statements();
3449 switch (token
.value
)
3454 // Look ahead to see if it is a label
3456 if (t
->value
== TOKcolon
)
3458 label
= token
.ident
;
3459 labelloc
= this->loc
;
3468 if (toklist
|| label
)
3470 error("asm statements must end in ';'");
3477 if (toklist
|| label
)
3478 { // Create AsmStatement from list of tokens we've saved
3479 s
= new AsmStatement(this->loc
, toklist
);
3481 ptoklist
= &toklist
;
3483 { s
= new LabelStatement(labelloc
, label
, s
);
3486 statements
->push(s
);
3493 error("matching '}' expected, not end of file");
3498 // If the first token is a string or '(', parse as extended asm.
3502 statements
->push(s
);
3505 // ...else, drop through.
3509 *ptoklist
= new Token();
3510 memcpy(*ptoklist
, &token
, sizeof(Token
));
3511 ptoklist
= &(*ptoklist
)->next
;
3519 s
= new CompoundStatement(loc
, statements
);
3525 error("found '%s' instead of statement", token
.toChars());
3529 while (token
.value
!= TOKrcurly
&&
3530 token
.value
!= TOKsemicolon
&&
3531 token
.value
!= TOKeof
)
3533 if (token
.value
== TOKsemicolon
)
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
)
3557 Expression
* arg
= NULL
;
3558 Identifier
* name
= NULL
;
3559 Expression
* constraint
= NULL
;
3561 switch (token
.value
)
3572 error("unterminated statement");
3576 if (token
.value
== TOKidentifier
)
3582 error("expected identifier after '['");
3586 constraint
= parsePrimaryExp();
3587 if (constraint
->op
!= TOKstring
)
3588 error("expected constant string constraint for operand");
3589 arg
= parseAssignExp();
3592 args
= new Expressions
;
3593 argConstraints
= new Expressions
;
3594 argNames
= new Array
;
3597 argNames
->push(name
);
3598 argConstraints
->push(constraint
);
3602 if (token
.value
== TOKcomma
)
3609 isInputPhase
= true;
3616 Expression
* clobber
;
3618 switch (token
.value
)
3625 error("unterminated statement");
3628 clobber
= parseAssignExp();
3629 if (clobber
->op
!= TOKstring
)
3630 error("expected constant string constraint for clobber name");
3632 clobbers
= new Expressions
;
3633 clobbers
->push(clobber
);
3635 if (token
.value
== TOKcomma
)
3644 check(TOKsemicolon
);
3646 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3647 argConstraints
, nOutputArgs
, clobbers
);
3650 void Parser::optionalEndline() {
3651 while (token
.value
== TOKendline
) {
3656 void Parser::check(enum TOK 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
));
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
);
3676 char *Parser::endToken()
3681 char *DltParser::endToken()
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.
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
)
3704 if (!isBasicType(&t
))
3706 if (!isDeclarator(&t
, &haveId
, endtok
))
3709 (needId
== 0 && !haveId
) ||
3710 (needId
== 2 && haveId
))
3719 int Parser::isBasicType(Token
**pt
)
3721 // This code parallels parseBasicType()
3734 if (t
->value
== TOKnot
)
3744 if (t
->value
== TOKdot
)
3748 if (t
->value
!= TOKidentifier
)
3751 if (t
->value
!= TOKnot
)
3755 if (t
->value
!= TOKlparen
)
3757 if (!skipParens(t
, &t
))
3769 /* typeof(exp).identifier...
3772 if (t
->value
!= TOKlparen
)
3774 if (!skipParens(t
, &t
))
3788 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3789 { // This code parallels parseDeclarator()
3793 //printf("Parser::isDeclarator()\n");
3795 if (t
->value
== TOKassign
)
3811 if (t
->value
== TOKrbracket
)
3815 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3816 { // It's an associative array declaration
3822 // [ expression .. expression ]
3823 if (!isExpression(&t
))
3825 if (t
->value
== TOKslice
)
3827 if (!isExpression(&t
))
3830 if (t
->value
!= TOKrbracket
)
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
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
)
3862 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3871 if (!isParameters(&t
))
3886 if (t
->value
== TOKrbracket
)
3890 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3891 { // It's an associative array declaration
3897 if (!isExpression(&t
))
3899 if (t
->value
!= TOKrbracket
)
3908 if (!isParameters(&t
))
3912 // Valid tokens that follow a declaration
3921 // The !parens is to disallow unnecessary parentheses
3922 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3935 int Parser::isParameters(Token
**pt
)
3936 { // This code parallels parseParameters()
3940 //printf("isParameters()\n");
3941 if (t
->value
!= TOKlparen
)
3963 if (!isBasicType(&t
))
3966 if (t
->value
!= TOKdotdotdot
&&
3967 !isDeclarator(&t
, &tmp
, TOKreserved
))
3969 if (t
->value
== TOKassign
)
3971 if (!isExpression(&t
))
3974 if (t
->value
== TOKdotdotdot
)
3979 if (t
->value
== TOKcomma
)
3987 if (t
->value
!= TOKrparen
)
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
4004 for (;; t
= peek(t
))
4022 if (brnest
|| panest
)
4049 /**********************************************
4051 * instance foo.bar(parameters...)
4053 * if (pt), *pt is set to the token following the closing )
4055 * 1 it's valid instance syntax
4056 * 0 invalid instance syntax
4059 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
4062 if (t
->value
!= TOKdot
)
4064 if (t
->value
!= TOKidentifier
)
4068 while (t
->value
== TOKdot
)
4071 if (t
->value
!= TOKidentifier
)
4075 if (t
->value
!= TOKlparen
)
4078 // Skip over the template arguments
4087 if (!skipParens(t
, &t
))
4103 if (t
->value
!= TOKcomma
)
4106 if (t
->value
!= TOKrparen
)
4117 /*******************************************
4118 * Skip parens, brackets.
4122 * *pt is set to closing token, which is ')' on success
4125 * 0 some parsing error
4128 int Parser::skipParens(Token
*t
, Token
**pt
)
4167 /********************************* Expression Parser ***************************/
4169 Expression
*Parser::parsePrimaryExp()
4174 Loc loc
= this->loc
;
4176 switch (token
.value
)
4181 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4182 { // identifier!(template-argument-list)
4183 TemplateInstance
*tempinst
;
4185 tempinst
= new TemplateInstance(loc
, id
);
4187 tempinst
->tiargs
= parseTemplateArgumentList();
4188 e
= new ScopeExp(loc
, tempinst
);
4191 e
= new IdentifierExp(loc
, id
);
4196 error("'$' is valid only inside [] of index or slice");
4197 e
= new DollarExp(loc
);
4202 // Signal global scope '.' operator with "" identifier
4203 e
= new IdentifierExp(loc
, Id::empty
);
4207 e
= new ThisExp(loc
);
4212 e
= new SuperExp(loc
);
4217 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
4222 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
4227 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
4232 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
4237 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
4242 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
4247 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
4251 case TOKimaginary32v
:
4252 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
4256 case TOKimaginary64v
:
4257 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
4261 case TOKimaginary80v
:
4262 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
4267 e
= new NullExp(loc
);
4272 e
= new IntegerExp(loc
, 1, Type::tbool
);
4277 e
= new IntegerExp(loc
, 0, Type::tbool
);
4282 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
4287 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
4292 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
4299 unsigned char postfix
;
4301 // cat adjacent strings
4304 postfix
= token
.postfix
;
4308 if (token
.value
== TOKstring
)
4314 { if (token
.postfix
!= postfix
)
4315 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4316 postfix
= token
.postfix
;
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));
4330 e
= new StringExp(loc
, s
, len
, postfix
);
4334 CASE_BASIC_TYPES_X(t
):
4337 check(TOKdot
, t
->toChars());
4338 if (token
.value
!= TOKidentifier
)
4339 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4342 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4351 exp
= parseExpression();
4353 t
= new TypeTypeof(loc
, exp
);
4354 if (token
.value
== TOKdot
)
4356 e
= new TypeExp(loc
, t
);
4364 check(TOKlparen
, "typeid");
4365 t
= parseBasicType();
4366 t
= parseDeclarator(t
,NULL
); // ( type )
4368 e
= new TypeidExp(loc
, t
);
4374 Identifier
*ident
= NULL
;
4376 enum TOK tok
= TOKreserved
;
4377 enum TOK tok2
= TOKreserved
;
4378 Loc loc
= this->loc
;
4381 if (token
.value
== TOKlparen
)
4384 targ
= parseBasicType();
4385 targ
= parseDeclarator(targ
, &ident
);
4386 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
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
))
4407 tspec
= parseBasicType();
4408 tspec
= parseDeclarator(tspec
, NULL
);
4414 { error("(type identifier : specialization) expected following is");
4417 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4422 { Expression
*msg
= NULL
;
4427 e
= parseAssignExp();
4428 if (token
.value
== (dltSyntax
? TOKelse
: TOKcomma
))
4430 msg
= parseAssignExp();
4434 e
= new AssertExp(loc
, e
, msg
);
4441 check(TOKlparen
, "mixin");
4442 e
= parseAssignExp();
4444 e
= new CompileExp(loc
, e
);
4451 check(TOKlparen
, "import");
4452 e
= parseAssignExp();
4454 e
= new FileExp(loc
, e
);
4459 if (peekPastParen(&token
)->value
== TOKlcurly
)
4460 { // (arguments) { statements... }
4466 e
= parseExpression();
4467 check(loc
, TOKrparen
);
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
;
4479 if (token
.value
!= TOKrbracket
)
4483 Expression
*e
= parseAssignExp();
4484 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4487 keys
= new Expressions();
4489 e
= parseAssignExp();
4492 { error("'key:value' expected for associative array literal");
4497 if (token
.value
== TOKrbracket
)
4505 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4507 e
= new ArrayLiteralExp(loc
, values
);
4512 // { statements... }
4522 /* function type(parameters) { body }
4523 * delegate type(parameters) { body }
4525 Arguments
*arguments
;
4527 FuncLiteralDeclaration
*fd
;
4530 if (token
.value
== TOKlcurly
)
4534 arguments
= new Arguments();
4538 if (token
.value
== TOKlparen
)
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
);
4550 e
= new FuncExp(loc
, fd
);
4555 error("expression expected, not '%s'", token
.toChars());
4557 // Anything for e, as long as it's not NULL
4558 e
= new IntegerExp(loc
, 0, Type::tint32
);
4562 return parsePostExp(e
);
4565 Expression
*Parser::parsePostExp(Expression
*e
)
4572 switch (token
.value
)
4576 if (token
.value
== TOKidentifier
)
4577 { Identifier
*id
= token
.ident
;
4580 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4581 { // identifier!(template-argument-list)
4582 TemplateInstance
*tempinst
;
4584 tempinst
= new TemplateInstance(loc
, id
);
4586 tempinst
->tiargs
= parseTemplateArgumentList();
4587 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4590 e
= new DotIdExp(loc
, e
, id
);
4593 else if (token
.value
== TOKnew
)
4599 error("identifier expected following '.', not '%s'", token
.toChars());
4603 e
= new PostExp(TOKplusplus
, loc
, e
);
4607 e
= new PostExp(TOKminusminus
, loc
, e
);
4611 e
= new CallExp(loc
, e
, parseArguments());
4615 { // array dereferences:
4618 // array[lwr .. upr]
4624 if (token
.value
== TOKrbracket
)
4626 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4631 index
= parseAssignExp();
4632 if (token
.value
== TOKslice
)
4633 { // array[lwr .. upr]
4635 upr
= parseAssignExp();
4636 e
= new SliceExp(loc
, e
, index
, upr
);
4639 { // array[index, i2, i3, i4, ...]
4640 Expressions
*arguments
= new Expressions();
4641 arguments
->push(index
);
4642 if (token
.value
== TOKcomma
)
4648 arg
= parseAssignExp();
4649 arguments
->push(arg
);
4650 if (token
.value
== TOKrbracket
)
4655 e
= new ArrayExp(loc
, e
, arguments
);
4670 Expression
*Parser::parseUnaryExp()
4672 Loc loc
= this->loc
;
4674 switch (token
.value
)
4678 e
= parseUnaryExp();
4679 e
= new AddrExp(loc
, e
);
4684 e
= parseUnaryExp();
4685 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4690 e
= parseUnaryExp();
4691 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4696 e
= parseUnaryExp();
4697 e
= new PtrExp(loc
, e
);
4702 e
= parseUnaryExp();
4703 e
= new NegExp(loc
, e
);
4708 e
= parseUnaryExp();
4709 e
= new UAddExp(loc
, e
);
4714 e
= parseUnaryExp();
4715 e
= new NotExp(loc
, e
);
4720 e
= parseUnaryExp();
4721 e
= new ComExp(loc
, e
);
4726 e
= parseUnaryExp();
4727 e
= new DeleteExp(loc
, e
);
4731 e
= parseNewExp(NULL
);
4734 case TOKcast
: // cast(type) expression
4739 t
= parseBasicType();
4740 t
= parseDeclarator(t
,NULL
); // ( type )
4743 e
= parseUnaryExp();
4744 e
= new CastExp(loc
, e
, t
);
4754 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4756 tk
= peek(tk
); // skip over right parenthesis
4776 case TOKimaginary32v
:
4777 case TOKimaginary64v
:
4778 case TOKimaginary80v
:
4796 CASE_BASIC_TYPES
: // (type)int.size
4801 t
= parseBasicType();
4802 t
= parseDeclarator(t
,NULL
);
4806 if (token
.value
== TOKdot
)
4809 if (token
.value
!= TOKidentifier
)
4810 { error("Identifier expected following (type).");
4813 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4815 e
= parsePostExp(e
);
4819 e
= parseUnaryExp();
4820 e
= new CastExp(loc
, e
, t
);
4821 error("C style cast illegal, use %s", e
->toChars());
4828 e
= parsePrimaryExp();
4832 e
= parsePrimaryExp();
4839 Expression
*Parser::parseMulExp()
4842 Loc loc
= this->loc
;
4844 e
= parseUnaryExp();
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;
4861 Expression
*Parser::parseAddExp()
4864 Loc loc
= this->loc
;
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;
4883 Expression
*Parser::parseShiftExp()
4886 Loc loc
= this->loc
;
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;
4905 Expression
*Parser::parseRelExp()
4909 Loc loc
= this->loc
;
4911 e
= parseShiftExp();
4914 switch (token
.value
)
4930 e2
= parseShiftExp();
4931 e
= new CmpExp(op
, loc
, e
, e2
);
4936 e2
= parseShiftExp();
4937 e
= new InExp(loc
, e
, e2
);
4948 Expression
*Parser::parseEqualExp()
4952 Loc loc
= this->loc
;
4956 { enum TOK value
= token
.value
;
4964 e
= new EqualExp(value
, loc
, e
, e2
);
4968 error("'===' is no longer legal, use 'is' instead");
4971 case TOKnotidentity
:
4972 error("'!==' is no longer legal, use '!is' instead");
4976 value
= TOKidentity
;
4980 // Attempt to identify '!is'
4982 if (t
->value
!= TOKis
)
4985 value
= TOKnotidentity
;
4991 e
= new IdentityExp(value
, loc
, e
, e2
);
5002 Expression
*Parser::parseCmpExp()
5006 Loc loc
= this->loc
;
5008 e
= parseShiftExp();
5009 enum TOK op
= token
.value
;
5016 e2
= parseShiftExp();
5017 e
= new EqualExp(op
, loc
, e
, e2
);
5025 // Attempt to identify '!is'
5027 if (t
->value
!= TOKis
)
5030 op
= TOKnotidentity
;
5035 e2
= parseShiftExp();
5036 e
= new IdentityExp(op
, loc
, e
, e2
);
5052 e2
= parseShiftExp();
5053 e
= new CmpExp(op
, loc
, e
, e2
);
5058 e2
= parseShiftExp();
5059 e
= new InExp(loc
, e
, e2
);
5068 Expression
*Parser::parseAndExp()
5071 Loc loc
= this->loc
;
5073 if (global
.params
.Dversion
== 1)
5075 e
= parseEqualExp();
5076 while (token
.value
== TOKand
)
5079 e2
= parseEqualExp();
5080 e
= new AndExp(loc
,e
,e2
);
5087 while (token
.value
== TOKand
)
5091 e
= new AndExp(loc
,e
,e2
);
5098 Expression
*Parser::parseXorExp()
5101 Loc loc
= this->loc
;
5104 while (token
.value
== TOKxor
)
5108 e
= new XorExp(loc
, e
, e2
);
5113 Expression
*Parser::parseOrExp()
5116 Loc loc
= this->loc
;
5119 while (token
.value
== TOKor
)
5123 e
= new OrExp(loc
, e
, e2
);
5128 Expression
*Parser::parseAndAndExp()
5131 Loc loc
= this->loc
;
5134 while (token
.value
== TOKandand
)
5138 e
= new AndAndExp(loc
, e
, e2
);
5143 Expression
*Parser::parseOrOrExp()
5146 Loc loc
= this->loc
;
5148 e
= parseAndAndExp();
5149 while (token
.value
== TOKoror
)
5152 e2
= parseAndAndExp();
5153 e
= new OrOrExp(loc
, e
, e2
);
5158 Expression
*Parser::parseCondExp()
5162 Loc loc
= this->loc
;
5165 if (token
.value
== TOKquestion
)
5168 e1
= parseExpression();
5170 e2
= parseCondExp();
5171 e
= new CondExp(loc
, e
, e1
, e2
);
5176 Expression
*DltParser::parseCondExp()
5180 Loc loc
= this->loc
;
5183 if (token
.value
== TOKif
)
5186 e1
= parseExpression();
5188 e2
= parseCondExp();
5189 e
= new CondExp(loc
, e1
, e
, e2
);
5194 Expression
*Parser::parseAssignExp()
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
);
5231 Expression
*Parser::parseExpression()
5234 Loc loc
= this->loc
;
5236 //printf("Parser::parseExpression()\n");
5237 e
= parseAssignExp();
5238 while (token
.value
== TOKcomma
)
5241 e2
= parseAssignExp();
5242 e
= new CommaExp(loc
, e
, e2
);
5249 /*************************
5250 * Collect argument list.
5251 * Assume current token is '(' or '['.
5254 Expressions
*Parser::parseArguments()
5256 Expressions
*arguments
;
5260 arguments
= new Expressions();
5261 if (token
.value
== TOKlbracket
)
5262 endtok
= TOKrbracket
;
5268 if (token
.value
!= endtok
)
5272 arg
= parseAssignExp();
5273 arguments
->push(arg
);
5274 if (token
.value
== endtok
)
5284 /*******************************************
5287 Expression
*Parser::parseNewExp(Expression
*thisexp
)
5289 Expressions
*newargs
;
5290 Expressions
*arguments
= NULL
;
5292 Loc loc
= this->loc
;
5296 if (token
.value
== TOKlparen
)
5298 newargs
= parseArguments();
5301 // An anonymous nested class starts with "class"
5302 if (token
.value
== TOKclass
)
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");
5322 Array
*decl
= parseDeclDefs(0);
5323 if (token
.value
!= TOKrcurly
)
5324 error("class member expected");
5329 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
5335 t
= parseBasicType();
5336 t
= parseBasicType2(t
);
5337 if (t
->ty
== Taarray
)
5339 Type
*index
= ((TypeAArray
*)t
)->index
;
5341 Expression
*e
= index
->toExpression();
5343 { arguments
= new Expressions();
5345 t
= new TypeDArray(t
->next
);
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();
5360 t
= new TypeDArray(t
->next
);
5362 else if (token
.value
== TOKlparen
)
5364 arguments
= parseArguments();
5367 t
= parseBasicType();
5368 while (token
.value
== TOKmul
)
5369 { t
= new TypePointer(t
);
5372 if (token
.value
== TOKlbracket
)
5377 e
= parseAssignExp();
5378 arguments
= new Array();
5381 t
= parseDeclarator(t
, NULL
);
5382 t
= new TypeDArray(t
);
5384 else if (token
.value
== TOKlparen
)
5385 arguments
= parseArguments();
5387 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5391 /**********************************************
5394 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5396 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5400 /********************************* ***************************/