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
= NULL
;
1173 if (token
.value
== (dltSyntax
? TOKextends
: TOKcolon
))
1176 baseclasses
= parseBaseClasses();
1177 if (token
.value
!= startBlockTok
)
1178 error("members expected");
1181 if (tok
== TOKclass
)
1182 a
= new ClassDeclaration(loc
, id
, baseclasses
);
1184 a
= new InterfaceDeclaration(loc
, id
, baseclasses
);
1190 a
= new StructDeclaration(loc
, id
);
1197 a
= new UnionDeclaration(loc
, id
);
1206 if (a
&& token
.value
== (dltSyntax
? TOKendline
: TOKsemicolon
))
1209 else if (token
.value
== startBlockTok
)
1211 //printf("aggregate definition\n");
1214 Array
*decl
= parseDeclDefs(0);
1215 if (token
.value
!= TOKrcurly
)
1216 error("end-of-block expected following member declarations in aggregate");
1220 /* Anonymous structs/unions are more like attributes.
1222 return new AnonDeclaration(loc
, anon
- 1, decl
);
1229 error("%s expected following aggregate declaration", Token::toChars(startBlockTok
));
1230 a
= new StructDeclaration(loc
, NULL
);
1235 TemplateDeclaration
*tempdecl
;
1237 // Wrap a template around the aggregate declaration
1238 decldefs
= new Array();
1240 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
1247 /*******************************************
1250 BaseClasses
*Parser::parseBaseClasses()
1252 enum PROT protection
= PROTpublic
;
1253 BaseClasses
*baseclasses
= new BaseClasses();
1255 for (; 1; nextToken())
1257 switch (token
.value
)
1262 protection
= PROTprivate
;
1265 protection
= PROTpackage
;
1268 protection
= PROTprotected
;
1271 protection
= PROTpublic
;
1274 error("base classes expected instead of %s", token
.toChars());
1277 BaseClass
*b
= new BaseClass(parseBasicType(), protection
);
1278 baseclasses
->push(b
);
1279 if (token
.value
!= TOKcomma
)
1281 protection
= PROTpublic
;
1286 /**************************************
1287 * Parse a TemplateDeclaration.
1290 TemplateDeclaration
*Parser::parseTemplateDeclaration()
1292 TemplateDeclaration
*tempdecl
;
1294 TemplateParameters
*tpl
;
1296 Loc loc
= this->loc
;
1299 if (token
.value
!= TOKidentifier
)
1300 { error("TemplateIdentifier expected following template");
1305 tpl
= parseTemplateParameterList();
1309 if (token
.value
!= startBlockTok
)
1310 { error("members of template declaration expected");
1316 decldefs
= parseDeclDefs(0);
1317 if (token
.value
!= TOKrcurly
)
1318 { error("template member expected");
1324 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
1331 /******************************************
1332 * Parse template parameter list.
1335 TemplateParameters
*Parser::parseTemplateParameterList()
1337 TemplateParameters
*tpl
= new TemplateParameters();
1339 if (token
.value
!= TOKlparen
)
1340 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1345 // Get array of TemplateParameters
1346 if (token
.value
!= TOKrparen
)
1347 { int isvariadic
= 0;
1350 { TemplateParameter
*tp
;
1351 Identifier
*tp_ident
= NULL
;
1352 Type
*tp_spectype
= NULL
;
1353 Type
*tp_valtype
= NULL
;
1354 Type
*tp_defaulttype
= NULL
;
1355 Expression
*tp_specvalue
= NULL
;
1356 Expression
*tp_defaultvalue
= NULL
;
1359 // Get TemplateParameter
1361 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1363 if (token
.value
== TOKalias
)
1366 if (token
.value
!= TOKidentifier
)
1367 { error("Identifier expected for template parameter");
1370 tp_ident
= token
.ident
;
1372 if (token
.value
== TOKcolon
) // : Type
1375 tp_spectype
= parseBasicType();
1376 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1378 if (token
.value
== TOKassign
) // = Type
1381 tp_defaulttype
= parseBasicType();
1382 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1384 tp
= new TemplateAliasParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1386 else if (t
->value
== TOKcolon
|| t
->value
== TOKassign
||
1387 t
->value
== TOKcomma
|| t
->value
== TOKrparen
)
1389 if (token
.value
!= TOKidentifier
)
1390 { error("Identifier expected for template parameter");
1393 tp_ident
= token
.ident
;
1395 if (token
.value
== TOKcolon
) // : Type
1398 tp_spectype
= parseBasicType();
1399 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1401 if (token
.value
== TOKassign
) // = Type
1404 tp_defaulttype
= parseBasicType();
1405 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1407 tp
= new TemplateTypeParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1409 else if (token
.value
== TOKidentifier
&& t
->value
== TOKdotdotdot
)
1412 error("variadic template parameter must be last");
1414 tp_ident
= token
.ident
;
1417 tp
= new TemplateTupleParameter(loc
, tp_ident
);
1421 tp_valtype
= parseBasicType();
1422 tp_valtype
= parseDeclarator(tp_valtype
, &tp_ident
);
1425 error("no identifier for template value parameter");
1426 tp_ident
= new Identifier("error", TOKidentifier
);
1428 if (token
.value
== TOKcolon
) // : CondExpression
1431 tp_specvalue
= parseCondExp();
1433 if (token
.value
== TOKassign
) // = CondExpression
1436 tp_defaultvalue
= parseCondExp();
1438 tp
= new TemplateValueParameter(loc
, tp_ident
, tp_valtype
, tp_specvalue
, tp_defaultvalue
);
1441 if (token
.value
!= TOKcomma
)
1451 /******************************************
1452 * Parse template mixin.
1455 * mixin a.b.c!(args).Foo!(args);
1456 * mixin Foo!(args) identifier;
1457 * mixin typeof(expr).identifier!(args);
1460 Dsymbol
*Parser::parseMixin()
1468 //printf("parseMixin()\n");
1471 if (token
.value
== TOKdot
)
1477 if (token
.value
== TOKtypeof
)
1482 exp
= parseExpression();
1484 tqual
= new TypeTypeof(loc
, exp
);
1487 if (token
.value
!= TOKidentifier
)
1489 error("identifier expected, not %s", token
.toChars());
1496 idents
= new Array();
1500 if (token
.value
== TOKnot
)
1503 tiargs
= parseTemplateArgumentList();
1506 if (token
.value
!= TOKdot
)
1510 { TemplateInstance
*tempinst
= new TemplateInstance(loc
, id
);
1511 tempinst
->tiargs
= tiargs
;
1512 id
= (Identifier
*)tempinst
;
1518 if (token
.value
!= TOKidentifier
)
1519 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1527 if (token
.value
== TOKidentifier
)
1535 tm
= new TemplateMixin(loc
, id
, tqual
, idents
, tiargs
);
1536 if (token
.value
!= TOKsemicolon
)
1537 error("';' expected after mixin");
1546 /******************************************
1547 * Parse template argument list.
1549 * current token is opening '('
1551 * current token is one after closing ')'
1554 Objects
*Parser::parseTemplateArgumentList()
1556 //printf("Parser::parseTemplateArgumentList()\n");
1557 Objects
*tiargs
= new Objects();
1558 if (token
.value
!= TOKlparen
)
1559 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1564 // Get TemplateArgumentList
1565 if (token
.value
!= TOKrparen
)
1569 // See if it is an Expression or a Type
1570 if (isDeclaration(&token
, 0, TOKreserved
, NULL
))
1574 // Get TemplateArgument
1575 ta
= parseBasicType();
1576 ta
= parseDeclarator(ta
, NULL
);
1583 ea
= parseAssignExp();
1586 if (token
.value
!= TOKcomma
)
1591 check(TOKrparen
, "template argument list");
1595 Import
*Parser::parseImport(Array
*decldefs
, int isstatic
)
1598 Identifier
*aliasid
= NULL
;
1602 //printf("Parser::parseImport()\n");
1607 if (token
.value
!= TOKidentifier
)
1608 { error("Identifier expected following import");
1616 if (!aliasid
&& token
.value
== TOKassign
)
1621 while (token
.value
== TOKdot
)
1627 if (token
.value
!= TOKidentifier
)
1628 { error("Identifier expected following package");
1635 s
= new Import(loc
, a
, token
.ident
, aliasid
, isstatic
);
1639 * : alias=name, alias=name;
1642 if (token
.value
== TOKcolon
)
1651 if (dltSyntax
&& token
.value
== TOKrcurly
)
1653 if (token
.value
!= TOKidentifier
)
1654 { error("Identifier expected following :");
1657 alias
= token
.ident
;
1659 if (token
.value
== TOKassign
)
1662 if (token
.value
!= TOKidentifier
)
1663 { error("Identifier expected following %s=", alias
->toChars());
1673 s
->addAlias(name
, alias
);
1674 if (token
.value
!= TOKcomma
&& token
.value
!= TOKendline
)
1688 } while (token
.value
== TOKcomma
);
1690 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
1694 error("%s expected", endToken());
1701 Type
*Parser::parseBasicType()
1705 TemplateInstance
*tempinst
;
1707 //printf("parseBasicType()\n");
1708 switch (token
.value
)
1710 CASE_BASIC_TYPES_X(t
):
1717 if (token
.value
== TOKnot
)
1720 tempinst
= new TemplateInstance(loc
, id
);
1721 tempinst
->tiargs
= parseTemplateArgumentList();
1722 tid
= new TypeInstance(loc
, tempinst
);
1726 tid
= new TypeIdentifier(loc
, id
);
1728 while (token
.value
== TOKdot
)
1730 if (token
.value
!= TOKidentifier
)
1731 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1736 if (token
.value
== TOKnot
)
1739 tempinst
= new TemplateInstance(loc
, id
);
1740 tempinst
->tiargs
= parseTemplateArgumentList();
1741 tid
->addIdent((Identifier
*)tempinst
);
1758 exp
= parseExpression();
1760 tid
= new TypeTypeof(loc
, exp
);
1765 error("basic type expected, not %s", token
.toChars());
1772 Type
*Parser::parseBasicType2(Type
*t
)
1777 //printf("parseBasicType2()\n");
1780 switch (token
.value
)
1783 t
= new TypePointer(t
);
1789 // Handle []. Make sure things like
1791 // is (array[1] of array[3] of int)
1793 if (token
.value
== TOKrbracket
)
1795 t
= new TypeDArray(t
); // []
1798 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1799 { // It's an associative array declaration
1802 //printf("it's an associative array\n");
1803 index
= parseBasicType();
1804 index
= parseDeclarator(index
, NULL
); // [ type ]
1805 t
= new TypeAArray(t
, index
);
1810 //printf("it's [expression]\n");
1812 Expression
*e
= parseExpression(); // [ expression ]
1813 if (token
.value
== TOKslice
)
1817 e2
= parseExpression(); // [ exp .. exp ]
1818 t
= new TypeSlice(t
, e
, e2
);
1821 t
= new TypeSArray(t
,e
);
1827 // Handle []. Make sure things like
1829 // is (array[3] of array[1] of int)
1831 while (token
.value
== TOKlbracket
)
1834 if (token
.value
== TOKrbracket
)
1836 ta
= new TypeDArray(t
); // []
1839 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1840 { // It's an associative array declaration
1843 //printf("it's an associative array\n");
1844 index
= parseBasicType();
1845 index
= parseDeclarator(index
, NULL
); // [ type ]
1847 ta
= new TypeAArray(t
, index
);
1851 //printf("it's [expression]\n");
1852 Expression
*e
= parseExpression(); // [ expression ]
1853 ta
= new TypeSArray(t
,e
);
1857 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1867 { // Handle delegate declaration:
1868 // t delegate(parameter list)
1869 // t function(parameter list)
1870 Arguments
*arguments
;
1872 enum TOK save
= token
.value
;
1875 arguments
= parseParameters(&varargs
);
1876 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1877 if (save
== TOKdelegate
)
1878 t
= new TypeDelegate(t
);
1880 t
= new TypePointer(t
); // pointer to function
1890 error("Type %s cannot be null; ? is pointless", old
->toChars());
1894 // fall-through to default
1907 // Don't wrap it yet, because that confuses resolve()
1908 ((TypeIdentifier
*) ts
)->maybe
= 1;
1911 // TypeMaybe will unwrap itself later if this isn't a nullable type
1920 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1924 //printf("parseDeclarator(tpl = %p)\n", tpl);
1925 t
= parseBasicType2(t
);
1927 switch (token
.value
)
1932 *pident
= token
.ident
;
1934 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1941 ts
= parseDeclarator(t
, pident
);
1952 switch (token
.value
)
1956 { // This is the old C-style post [] syntax.
1958 if (token
.value
== TOKrbracket
)
1960 ta
= new TypeDArray(t
); // []
1963 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1964 { // It's an associative array declaration
1967 //printf("it's an associative array\n");
1968 index
= parseBasicType();
1969 index
= parseDeclarator(index
, NULL
); // [ type ]
1971 ta
= new TypeAArray(t
, index
);
1975 //printf("it's [expression]\n");
1976 Expression
*e
= parseExpression(); // [ expression ]
1977 ta
= new TypeSArray(t
, e
);
1981 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1988 { Arguments
*arguments
;
1993 /* Look ahead to see if this is (...)(...),
1994 * i.e. a function template declaration
1996 if (peekPastParen(&token
)->value
== TOKlparen
)
1997 { // It's a function template declaration
1998 //printf("function template declaration\n");
2000 // Gather template parameter list
2001 *tpl
= parseTemplateParameterList();
2005 arguments
= parseParameters(&varargs
);
2006 Type
*ta
= new TypeFunction(arguments
, t
, varargs
, linkage
);
2008 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
2020 /**********************************
2021 * Return array of Declaration *'s.
2024 Array
*Parser::parseDeclarations()
2026 enum STC storage_class
;
2034 unsigned char *comment
= token
.blockComment
;
2035 enum LINK link
= linkage
;
2037 //printf("parseDeclarations()\n");
2038 switch (token
.value
)
2051 storage_class
= STCundefined
;
2054 switch (token
.value
)
2056 case TOKconst
: stc
= STCconst
; goto L1
;
2057 case TOKstatic
: stc
= STCstatic
; goto L1
;
2058 case TOKfinal
: stc
= STCfinal
; goto L1
;
2059 case TOKauto
: stc
= STCauto
; goto L1
;
2060 case TOKscope
: stc
= STCscope
; goto L1
;
2061 case TOKoverride
: stc
= STCoverride
; goto L1
;
2062 case TOKabstract
: stc
= STCabstract
; goto L1
;
2063 case TOKsynchronized
: stc
= STCsynchronized
; goto L1
;
2064 case TOKdeprecated
: stc
= STCdeprecated
; goto L1
;
2066 if (storage_class
& stc
)
2067 error("redundant storage class '%s'", token
.toChars());
2068 storage_class
= (STC
) (storage_class
| stc
);
2073 if (peek(&token
)->value
!= TOKlparen
)
2078 link
= parseLinkage();
2089 /* Look for auto initializers:
2090 * storage_class identifier = initializer;
2092 while (storage_class
&&
2093 token
.value
== TOKidentifier
&&
2094 peek(&token
)->value
== TOKassign
)
2096 ident
= token
.ident
;
2099 Initializer
*init
= parseInitializer();
2100 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
2101 v
->storage_class
= storage_class
;
2103 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
2106 addComment(v
, comment
);
2108 else if (token
.value
== TOKcomma
)
2111 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
2113 error("Identifier expected following comma");
2119 error("%s expected following auto declaration, not '%s'", endToken(), token
.toChars());
2123 if (token
.value
== TOKclass
)
2124 { AggregateDeclaration
*s
;
2126 s
= (AggregateDeclaration
*)parseAggregate();
2127 s
->storage_class
|= storage_class
;
2129 addComment(s
, comment
);
2133 ts
= parseBasicType();
2134 ts
= parseBasicType2(ts
);
2139 Loc loc
= this->loc
;
2140 TemplateParameters
*tpl
= NULL
;
2143 t
= parseDeclarator(ts
, &ident
, &tpl
);
2147 else if (t
!= tfirst
)
2148 error("multiple declarations must have the same type, not %s and %s",
2149 tfirst
->toChars(), t
->toChars());
2151 error("no identifier for declarator %s", t
->toChars());
2153 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2159 /* Unwrap maybe qualifiers from aliases.
2160 * Otherwise, it thinks we're aliasing types when we're not.
2162 if (t
->ty
== Tmaybe
) {
2168 if (token
.value
== TOKassign
)
2171 init
= parseInitializer();
2173 if (tok
== TOKtypedef
)
2174 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2177 error("alias cannot have initializer");
2178 v
= new AliasDeclaration(loc
, ident
, t
);
2180 v
->storage_class
= storage_class
;
2181 if (link
== linkage
)
2185 Array
*ax
= new Array();
2187 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2190 switch (token
.value
)
2191 { case TOKsemicolon
:
2194 addComment(v
, comment
);
2199 addComment(v
, comment
);
2203 error("%s expected to close %s declaration", endToken(), Token::toChars(tok
));
2207 else if (t
->ty
== Tfunction
)
2208 { FuncDeclaration
*f
;
2211 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2212 addComment(f
, comment
);
2214 addComment(f
, NULL
);
2215 if (link
== linkage
)
2221 Array
*ax
= new Array();
2223 s
= new LinkDeclaration(link
, ax
);
2225 if (tpl
) // it's a function template
2227 TemplateDeclaration
*tempdecl
;
2229 // Wrap a template around the aggregate declaration
2230 decldefs
= new Array();
2232 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
, dltSyntax
);
2235 addComment(s
, comment
);
2239 { VarDeclaration
*v
;
2243 if (token
.value
== TOKassign
)
2246 init
= parseInitializer();
2248 v
= new VarDeclaration(loc
, t
, ident
, init
);
2249 v
->storage_class
= storage_class
;
2250 if (link
== linkage
)
2254 Array
*ax
= new Array();
2256 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2259 switch (token
.value
)
2260 { case TOKsemicolon
:
2263 addComment(v
, comment
);
2268 addComment(v
, comment
);
2272 error("%s expected, not '%s'", endToken(), token
.toChars());
2281 /*****************************************
2282 * Parse contracts following function declaration.
2285 void Parser::parseContracts(FuncDeclaration
*f
)
2288 enum LINK linksave
= linkage
;
2290 // The following is irrelevant, as it is overridden by sc->linkage in
2291 // TypeFunction::semantic
2292 linkage
= LINKd
; // nested functions have D linkage
2294 switch (token
.value
)
2298 if (token
.value
!= startBlockTok
)
2299 error("use %s to start a new block", Token::toChars(startBlockTok
));
2300 if (f
->frequire
|| f
->fensure
)
2301 error("missing body { ... } after in or out");
2302 f
->fbody
= parseStatement(PSsemi
| PScolon
);
2308 f
->fbody
= parseStatement(PScurly
);
2314 error("unexpected semi-colon after function declaration");
2317 if (f
->frequire
|| f
->fensure
)
2318 error("missing body { ... } after in or out");
2322 #if 0 // Do we want this for function declarations, so we can do:
2323 // int x, y, foo(), z;
2329 #if 0 // Dumped feature
2332 f
->fthrows
= new Array();
2337 tb
= parseBasicType();
2338 f
->fthrows
->push(tb
);
2339 if (token
.value
== TOKcomma
)
2352 error("redundant 'in' statement");
2353 f
->frequire
= parseStatement(PScurly
| PSscope
);
2357 // parse: out (identifier) { statement }
2359 if (token
.value
!= startBlockTok
)
2362 if (token
.value
!= TOKidentifier
)
2363 error("(identifier) following 'out' expected, not %s", token
.toChars());
2364 f
->outId
= token
.ident
;
2369 error("redundant 'out' statement");
2370 f
->fensure
= parseStatement(PScurly
| PSscope
);
2374 error("%s expected following function declaration", endToken());
2380 /*****************************************
2383 Initializer
*Parser::parseInitializer()
2385 StructInitializer
*is
;
2386 ArrayInitializer
*ia
;
2392 Loc loc
= this->loc
;
2396 switch (token
.value
)
2399 /* Scan ahead to see if it is a struct initializer or
2400 * a function literal.
2401 * If it contains a ';', it is a function literal.
2402 * Treat { } as a struct initializer.
2405 for (t
= peek(&token
); 1; t
= peek(t
))
2431 is
= new StructInitializer(loc
);
2436 switch (token
.value
)
2440 error("comma expected separating field initializers");
2442 if (t
->value
== TOKcolon
)
2446 nextToken(); // skip over ':'
2451 value
= parseInitializer();
2452 is
->addInit(id
, value
);
2461 case TOKrcurly
: // allow trailing comma's
2466 error("found EOF instead of initializer");
2470 value
= parseInitializer();
2471 is
->addInit(NULL
, value
);
2474 //error("found '%s' instead of field initializer", token.toChars());
2482 ia
= new ArrayInitializer(loc
);
2487 switch (token
.value
)
2491 { error("comma expected separating array initializers, not %s", token
.toChars());
2495 e
= parseAssignExp();
2498 if (token
.value
== TOKcolon
)
2501 value
= parseInitializer();
2504 { value
= new ExpInitializer(e
->loc
, e
);
2507 ia
->addInit(e
, value
);
2514 error("comma expected separating array initializers, not %s", token
.toChars());
2515 value
= parseInitializer();
2516 ia
->addInit(NULL
, value
);
2525 case TOKrbracket
: // allow trailing comma's
2530 error("found '%s' instead of array initializer", token
.toChars());
2539 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
|| t
->value
== TOKendline
)
2542 return new VoidInitializer(loc
);
2548 e
= parseAssignExp();
2549 ie
= new ExpInitializer(loc
, e
);
2554 Statement
*Parser::logStatement(int level
) {
2556 if (token
.value
!= TOKlparen
)
2557 error(loc
, "found '%s' when expecting '('", token
.toChars());
2558 return new LogStatement(loc
, level
, parseArguments());
2561 /*****************************************
2566 Statement
*DltParser::parseStatement(int flags
)
2569 if (flags
& (PScolon
| PSscope
))
2571 return Parser::parseStatement(flags
);
2574 Statement
*Parser::parseStatement(int flags
)
2577 Condition
*condition
;
2579 Statement
*elsebody
;
2580 Loc loc
= this->loc
;
2582 //printf("parseStatement()\n");
2584 if ((flags
& PScurly
) && token
.value
!= startBlockTok
)
2585 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2587 int tok
= token
.value
;
2589 switch (token
.value
)
2594 // Need to look ahead to see if it is a declaration, label, or expression
2596 if (t
->value
== TOKcolon
)
2600 ident
= token
.ident
;
2603 s
= parseStatement(PSsemi
);
2604 s
= new LabelStatement(loc
, ident
, s
);
2608 // fallthrough to TOKdot
2611 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2627 case TOKimaginary32v
:
2628 case TOKimaginary64v
:
2629 case TOKimaginary80v
:
2654 exp
= parseExpression();
2656 check(TOKsemicolon
, "statement");
2657 s
= new ExpStatement(loc
, exp
);
2662 { // Look ahead to see if it's static assert() or static if()
2666 if (t
->value
== TOKassert
)
2669 s
= new StaticAssertStatement(parseStaticAssert());
2672 if (t
->value
== TOKif
)
2675 condition
= parseStaticIfCondition();
2679 error("no static variables in Delight");
2695 a
= parseDeclarations();
2698 Statements
*as
= new Statements();
2699 as
->reserve(a
->dim
);
2700 for (int i
= 0; i
< a
->dim
; i
++)
2702 Dsymbol
*d
= (Dsymbol
*)a
->data
[i
];
2703 s
= new DeclarationStatement(loc
, d
);
2706 s
= new CompoundStatement(loc
, as
);
2708 else if (a
->dim
== 1)
2710 Dsymbol
*d
= (Dsymbol
*)a
->data
[0];
2711 s
= new DeclarationStatement(loc
, d
);
2715 if (flags
& PSscope
)
2716 s
= new ScopeStatement(loc
, s
);
2726 d
= parseAggregate();
2727 s
= new DeclarationStatement(loc
, d
);
2735 s
= new DeclarationStatement(loc
, d
);
2741 if (t
->value
== TOKlparen
)
2744 check(TOKlparen
, "mixin");
2745 Expression
*e
= parseAssignExp();
2747 check(TOKsemicolon
);
2748 s
= new CompileStatement(loc
, e
);
2751 Dsymbol
*d
= parseMixin();
2752 s
= new DeclarationStatement(loc
, d
);
2758 { Statements
*statements
;
2760 if (token
.value
!= startBlockTok
)
2761 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2765 statements
= new Statements();
2766 while (token
.value
!= TOKrcurly
)
2768 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2772 s
= new CompoundStatement(loc
, statements
);
2773 if (flags
& (PSscope
| PScurlyscope
))
2774 s
= new ScopeStatement(loc
, s
);
2779 case TOKlog_error
: s
= logStatement(LogStatement::Error
); break;
2780 case TOKlog_warning
: s
= logStatement(LogStatement::Warn
); break;
2781 case TOKlog_info
: s
= logStatement(LogStatement::Info
); break;
2782 case TOKlog_trace
: s
= logStatement(LogStatement::Trace
); break;
2785 { Expression
*condition
;
2790 condition
= parseExpression();
2792 body
= parseStatement(PSscope
);
2793 s
= new WhileStatement(loc
, condition
, body
);
2798 if (!(flags
& PSsemi
))
2799 error("use '{ }' for an empty statement, not a ';'");
2801 s
= new ExpStatement(loc
, NULL
);
2806 Expression
*condition
;
2809 body
= parseStatement(PSscope
);
2812 condition
= parseExpression();
2814 s
= new DoStatement(loc
, body
, condition
);
2821 Expression
*condition
;
2822 Expression
*increment
;
2827 if (token
.value
== TOKlparen
) {
2828 /* for (init; cond; incr): ... */
2830 if (token
.value
== TOKsemicolon
)
2835 { init
= parseStatement(0);
2837 if (token
.value
== TOKsemicolon
)
2844 condition
= parseExpression();
2845 check(TOKsemicolon
, "for condition");
2847 if (token
.value
== TOKrparen
)
2852 { increment
= parseExpression();
2855 body
= parseStatement(PSscope
);
2856 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2858 s
= new ScopeStatement(loc
, s
);
2859 } else if (dltSyntax
)
2866 case TOKforeach_reverse
:
2868 /* for var in seq: ... */
2869 /* for index, var in seq: ... */
2870 Arguments
*arguments
;
2875 enum TOK op
= (TOK
) tok
;
2882 TOK inTok
= dltSyntax
? TOKin
: TOKsemicolon
;
2884 arguments
= new Arguments();
2889 Identifier
*ai
= NULL
;
2891 unsigned storageClass
;
2894 storageClass
= STCin
;
2895 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2896 { storageClass
= STCref
;
2899 if (token
.value
== TOKidentifier
)
2901 Token
*t
= peek(&token
);
2902 if (t
->value
== TOKcomma
|| t
->value
== inTok
)
2904 at
= NULL
; // infer argument type
2909 tb
= parseBasicType();
2910 at
= parseDeclarator(tb
, &ai
);
2912 error("no identifier for declarator %s", at
->toChars());
2914 a
= new Argument(storageClass
, at
, ai
, NULL
);
2916 if (token
.value
== TOKcomma
)
2925 aggr
= parseExpression();
2929 if (token
.value
== TOKreversed
) {
2930 op
= TOKforeach_reverse
;
2937 body
= parseStatement(PScolon
);
2938 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2943 { Argument
*arg
= NULL
;
2944 Expression
*condition
;
2946 Statement
*elsebody
;
2951 if (token
.value
== TOKauto
)
2954 if (token
.value
== TOKidentifier
)
2956 Token
*t
= peek(&token
);
2957 if (t
->value
== TOKassign
)
2959 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2964 { error("= expected following auto identifier");
2969 { error("identifier expected following auto");
2973 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
2979 tb
= parseBasicType();
2980 at
= parseDeclarator(tb
, &ai
);
2982 arg
= new Argument(STCin
, at
, ai
, NULL
);
2985 // Check for " ident;"
2986 else if (token
.value
== TOKidentifier
&& !dltSyntax
)
2988 Token
*t
= peek(&token
);
2989 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2991 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2994 if (1 || !global
.params
.useDeprecated
)
2995 error("if (v; e) is deprecated, use if (auto v = e)");
2999 condition
= parseExpression();
3001 ifbody
= parseStatement(PSscope
);
3002 if (token
.value
== TOKelse
)
3007 if (token
.value
== TOKcolon
) {
3008 elsebody
= parseStatement(PSscope
);
3009 } else if (token
.value
== TOKif
) {
3010 elsebody
= parseStatement(0);
3012 error("Expected 'else:' or 'else if', not 'else %s'", token
.toChars());
3017 elsebody
= parseStatement(PSscope
);
3021 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
3026 if (peek(&token
)->value
!= TOKlparen
)
3027 goto Ldeclaration
; // scope used as storage class
3030 if (token
.value
!= TOKidentifier
)
3031 { error("scope identifier expected");
3035 { TOK t
= TOKon_scope_exit
;
3036 Identifier
*id
= token
.ident
;
3039 t
= TOKon_scope_exit
;
3040 else if (id
== Id::failure
)
3041 t
= TOKon_scope_failure
;
3042 else if (id
== Id::success
)
3043 t
= TOKon_scope_success
;
3045 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
3048 Statement
*st
= parseStatement(PScolon
| PScurlyscope
);
3049 s
= new OnScopeStatement(loc
, t
, st
);
3055 condition
= parseDebugCondition();
3060 condition
= parseVersionCondition();
3064 if (dltSyntax
&& token
.value
!= TOKcolon
)
3065 error("expected colon after condition, not '%s'", token
.toChars());
3066 ifbody
= parseStatement(PScolon
/*PSsemi*/);
3068 if (token
.value
== TOKelse
)
3071 elsebody
= parseStatement(PScolon
/*PSsemi*/);
3073 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
3077 { Identifier
*ident
;
3078 Expressions
*args
= NULL
;
3083 if (token
.value
!= TOKidentifier
)
3084 { error("pragma(identifier expected");
3087 ident
= token
.ident
;
3089 if (token
.value
== TOKcomma
)
3090 args
= parseArguments(); // pragma(identifier, args...);
3092 check(TOKrparen
); // pragma(identifier);
3093 if (token
.value
== TOKsemicolon
)
3098 body
= parseStatement(PSsemi
| PScolon
);
3099 s
= new PragmaStatement(loc
, ident
, args
, body
);
3104 { Expression
*condition
;
3109 condition
= parseExpression();
3111 body
= parseStatement(PSscope
| PScolon
);
3112 s
= new SwitchStatement(loc
, condition
, body
);
3118 Statements
*statements
;
3119 Array cases
; // array of Expression's
3124 exp
= parseAssignExp();
3126 if (token
.value
!= TOKcomma
)
3132 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3138 statements
= new Statements();
3139 while (token
.value
!= TOKcase
&&
3140 token
.value
!= TOKdefault
&&
3141 token
.value
!= TOKrcurly
)
3143 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3145 s
= new CompoundStatement(loc
, statements
);
3148 s
= new ScopeStatement(loc
, s
);
3150 // Keep cases in order by building the case statements backwards
3151 for (int i
= cases
.dim
; i
; i
--)
3153 exp
= (Expression
*)cases
.data
[i
- 1];
3154 s
= new CaseStatement(loc
, exp
, s
);
3161 Statements
*statements
;
3167 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3173 statements
= new Statements();
3174 while (token
.value
!= TOKcase
&&
3175 token
.value
!= TOKdefault
&&
3176 token
.value
!= TOKrcurly
)
3178 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3180 s
= new CompoundStatement(loc
, statements
);
3183 s
= new ScopeStatement(loc
, s
);
3184 s
= new DefaultStatement(loc
, s
);
3192 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
3195 exp
= parseExpression();
3198 check(TOKsemicolon
, "return statement");
3199 else if (token
.value
!= TOKendline
) {
3200 error("Expected end-of-line after return statement, but found '%s'", token
.toChars());
3203 s
= new ReturnStatement(loc
, exp
);
3208 { Identifier
*ident
;
3211 if (token
.value
== TOKidentifier
)
3212 { ident
= token
.ident
;
3217 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3218 error("expected %s after break, not '%s'", endToken(), token
.toChars());
3222 s
= new BreakStatement(loc
, ident
);
3227 { Identifier
*ident
;
3230 if (token
.value
== TOKidentifier
)
3231 { ident
= token
.ident
;
3236 check(TOKsemicolon
, "continue statement");
3237 s
= new ContinueStatement(loc
, ident
);
3242 { Identifier
*ident
;
3245 if (token
.value
== TOKdefault
)
3248 s
= new GotoDefaultStatement(loc
);
3250 else if (token
.value
== TOKcase
)
3252 Expression
*exp
= NULL
;
3255 if (token
.value
!= TOKsemicolon
)
3256 exp
= parseExpression();
3257 s
= new GotoCaseStatement(loc
, exp
);
3261 if (token
.value
!= TOKidentifier
)
3262 { error("Identifier expected following goto");
3266 { ident
= token
.ident
;
3269 s
= new GotoStatement(loc
, ident
);
3271 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3272 error("expected %s after goto statement, not '%s'", endToken(), token
.toChars());
3277 case TOKsynchronized
:
3282 if (token
.value
== TOKlparen
)
3285 exp
= parseExpression();
3290 body
= parseStatement(PSscope
);
3291 s
= new SynchronizedStatement(loc
, exp
, body
);
3301 exp
= parseExpression();
3303 body
= parseStatement(PSscope
);
3304 s
= new WithStatement(loc
, exp
, body
);
3310 Array
*catches
= NULL
;
3311 Statement
*finalbody
= NULL
;
3314 body
= parseStatement(PSscope
);
3315 while (token
.value
== TOKcatch
)
3321 Loc loc
= this->loc
;
3324 if (token
.value
== startBlockTok
)
3332 t
= parseBasicType();
3334 t
= parseDeclarator(t
, &id
);
3337 handler
= parseStatement(PScolon
);
3338 c
= new Catch(loc
, t
, id
, handler
);
3340 catches
= new Array();
3344 if (token
.value
== TOKfinally
)
3346 finalbody
= parseStatement(PScolon
);
3350 if (!catches
&& !finalbody
)
3351 error("catch or finally expected following try");
3354 s
= new TryCatchStatement(loc
, body
, catches
);
3356 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3365 exp
= parseExpression();
3366 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3367 error("%s expected after throw statement, not '%s'", endToken(), token
.toChars());
3371 s
= new ThrowStatement(loc
, exp
);
3377 s
= parseStatement(PSsemi
| PScurlyscope
);
3378 s
= new VolatileStatement(loc
, s
);
3382 { Statements
*statements
;
3388 // Parse the asm block into a sequence of AsmStatements,
3389 // each AsmStatement is one instruction.
3390 // Separate out labels.
3391 // Defer parsing of AsmStatements until semantic processing.
3394 #if GDC_EXTENDED_ASM_SYNTAX
3395 if (token
.value
== TOKlparen
)
3402 check(startBlockTok
);
3404 ptoklist
= &toklist
;
3406 statements
= new Statements();
3409 switch (token
.value
)
3414 // Look ahead to see if it is a label
3416 if (t
->value
== TOKcolon
)
3418 label
= token
.ident
;
3419 labelloc
= this->loc
;
3428 if (toklist
|| label
)
3430 error("asm statements must end in ';'");
3437 if (toklist
|| label
)
3438 { // Create AsmStatement from list of tokens we've saved
3439 s
= new AsmStatement(this->loc
, toklist
);
3441 ptoklist
= &toklist
;
3443 { s
= new LabelStatement(labelloc
, label
, s
);
3446 statements
->push(s
);
3453 error("matching '}' expected, not end of file");
3458 // If the first token is a string or '(', parse as extended asm.
3462 statements
->push(s
);
3465 // ...else, drop through.
3469 *ptoklist
= new Token();
3470 memcpy(*ptoklist
, &token
, sizeof(Token
));
3471 ptoklist
= &(*ptoklist
)->next
;
3479 s
= new CompoundStatement(loc
, statements
);
3485 error("found '%s' instead of statement", token
.toChars());
3489 while (token
.value
!= TOKrcurly
&&
3490 token
.value
!= TOKsemicolon
&&
3491 token
.value
!= TOKeof
)
3493 if (token
.value
== TOKsemicolon
)
3502 Statement
*Parser::parseExtAsm(int expect_rparen
)
3504 Expression
* insnTemplate
;
3505 Expressions
* args
= NULL
;
3506 Array
* argNames
= NULL
;
3507 Expressions
* argConstraints
= NULL
;
3508 int nOutputArgs
= 0;
3509 Expressions
* clobbers
= NULL
;
3510 bool isInputPhase
= false; // Output operands first, then input.
3512 insnTemplate
= parseExpression();
3513 if (token
.value
== TOKrparen
|| token
.value
== TOKsemicolon
)
3517 Expression
* arg
= NULL
;
3518 Identifier
* name
= NULL
;
3519 Expression
* constraint
= NULL
;
3521 switch (token
.value
)
3532 error("unterminated statement");
3536 if (token
.value
== TOKidentifier
)
3542 error("expected identifier after '['");
3546 constraint
= parsePrimaryExp();
3547 if (constraint
->op
!= TOKstring
)
3548 error("expected constant string constraint for operand");
3549 arg
= parseAssignExp();
3552 args
= new Expressions
;
3553 argConstraints
= new Expressions
;
3554 argNames
= new Array
;
3557 argNames
->push(name
);
3558 argConstraints
->push(constraint
);
3562 if (token
.value
== TOKcomma
)
3569 isInputPhase
= true;
3576 Expression
* clobber
;
3578 switch (token
.value
)
3585 error("unterminated statement");
3588 clobber
= parseAssignExp();
3589 if (clobber
->op
!= TOKstring
)
3590 error("expected constant string constraint for clobber name");
3592 clobbers
= new Expressions
;
3593 clobbers
->push(clobber
);
3595 if (token
.value
== TOKcomma
)
3604 check(TOKsemicolon
);
3606 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3607 argConstraints
, nOutputArgs
, clobbers
);
3610 void Parser::optionalEndline() {
3611 while (token
.value
== TOKendline
) {
3616 void Parser::check(enum TOK value
)
3621 void Parser::check(Loc loc
, enum TOK value
)
3623 if (token
.value
!= value
)
3624 error(loc
, "found '%s' when expecting '%s'", token
.toChars(), Token::toChars(value
));
3628 void Parser::check(enum TOK value
, char *string
)
3630 if (token
.value
!= value
)
3631 error("found '%s' when expecting '%s' following '%s'",
3632 token
.toChars(), Token::toChars(value
), string
);
3636 char *Parser::endToken()
3641 char *DltParser::endToken()
3646 void Parser::checkLParen() { check(TOKlparen
); }
3647 void Parser::checkRParen() { check(TOKrparen
); }
3649 void DltParser::checkLParen() { }
3650 void DltParser::checkRParen() { }
3652 /************************************
3653 * Determine if the scanner is sitting on the start of a declaration.
3655 * needId 0 no identifier
3656 * 1 identifier optional
3657 * 2 must have identifier
3660 int Parser::isDeclaration(Token
*t
, int needId
, enum TOK endtok
, Token
**pt
)
3664 if (!isBasicType(&t
))
3666 if (!isDeclarator(&t
, &haveId
, endtok
))
3669 (needId
== 0 && !haveId
) ||
3670 (needId
== 2 && haveId
))
3679 int Parser::isBasicType(Token
**pt
)
3681 // This code parallels parseBasicType()
3694 if (t
->value
== TOKnot
)
3704 if (t
->value
== TOKdot
)
3708 if (t
->value
!= TOKidentifier
)
3711 if (t
->value
!= TOKnot
)
3715 if (t
->value
!= TOKlparen
)
3717 if (!skipParens(t
, &t
))
3729 /* typeof(exp).identifier...
3732 if (t
->value
!= TOKlparen
)
3734 if (!skipParens(t
, &t
))
3748 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3749 { // This code parallels parseDeclarator()
3753 //printf("Parser::isDeclarator()\n");
3755 if (t
->value
== TOKassign
)
3771 if (t
->value
== TOKrbracket
)
3775 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3776 { // It's an associative array declaration
3782 // [ expression .. expression ]
3783 if (!isExpression(&t
))
3785 if (t
->value
== TOKslice
)
3787 if (!isExpression(&t
))
3790 if (t
->value
!= TOKrbracket
)
3806 if (t
->value
== TOKrparen
)
3807 return FALSE
; // () is not a declarator
3809 /* Regard ( identifier ) as not a declarator
3810 * BUG: what about ( *identifier ) in
3812 * where f is a class instance with overloaded () ?
3813 * Should we just disallow C-style function pointer declarations?
3815 if (t
->value
== TOKidentifier
)
3816 { Token
*t2
= peek(t
);
3817 if (t2
->value
== TOKrparen
)
3822 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3831 if (!isParameters(&t
))
3846 if (t
->value
== TOKrbracket
)
3850 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3851 { // It's an associative array declaration
3857 if (!isExpression(&t
))
3859 if (t
->value
!= TOKrbracket
)
3868 if (!isParameters(&t
))
3872 // Valid tokens that follow a declaration
3881 // The !parens is to disallow unnecessary parentheses
3882 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3895 int Parser::isParameters(Token
**pt
)
3896 { // This code parallels parseParameters()
3900 //printf("isParameters()\n");
3901 if (t
->value
!= TOKlparen
)
3923 if (!isBasicType(&t
))
3926 if (t
->value
!= TOKdotdotdot
&&
3927 !isDeclarator(&t
, &tmp
, TOKreserved
))
3929 if (t
->value
== TOKassign
)
3931 if (!isExpression(&t
))
3934 if (t
->value
== TOKdotdotdot
)
3939 if (t
->value
== TOKcomma
)
3947 if (t
->value
!= TOKrparen
)
3954 int Parser::isExpression(Token
**pt
)
3956 // This is supposed to determine if something is an expression.
3957 // What it actually does is scan until a closing right bracket
3964 for (;; t
= peek(t
))
3982 if (brnest
|| panest
)
4009 /**********************************************
4011 * instance foo.bar(parameters...)
4013 * if (pt), *pt is set to the token following the closing )
4015 * 1 it's valid instance syntax
4016 * 0 invalid instance syntax
4019 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
4022 if (t
->value
!= TOKdot
)
4024 if (t
->value
!= TOKidentifier
)
4028 while (t
->value
== TOKdot
)
4031 if (t
->value
!= TOKidentifier
)
4035 if (t
->value
!= TOKlparen
)
4038 // Skip over the template arguments
4047 if (!skipParens(t
, &t
))
4063 if (t
->value
!= TOKcomma
)
4066 if (t
->value
!= TOKrparen
)
4077 /*******************************************
4078 * Skip parens, brackets.
4082 * *pt is set to closing token, which is ')' on success
4085 * 0 some parsing error
4088 int Parser::skipParens(Token
*t
, Token
**pt
)
4127 /********************************* Expression Parser ***************************/
4129 Expression
*Parser::parsePrimaryExp()
4134 Loc loc
= this->loc
;
4136 switch (token
.value
)
4141 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4142 { // identifier!(template-argument-list)
4143 TemplateInstance
*tempinst
;
4145 tempinst
= new TemplateInstance(loc
, id
);
4147 tempinst
->tiargs
= parseTemplateArgumentList();
4148 e
= new ScopeExp(loc
, tempinst
);
4151 e
= new IdentifierExp(loc
, id
);
4156 error("'$' is valid only inside [] of index or slice");
4157 e
= new DollarExp(loc
);
4162 // Signal global scope '.' operator with "" identifier
4163 e
= new IdentifierExp(loc
, Id::empty
);
4167 e
= new ThisExp(loc
);
4172 e
= new SuperExp(loc
);
4177 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
4182 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
4187 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
4192 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
4197 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
4202 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
4207 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
4211 case TOKimaginary32v
:
4212 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
4216 case TOKimaginary64v
:
4217 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
4221 case TOKimaginary80v
:
4222 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
4227 e
= new NullExp(loc
);
4232 e
= new IntegerExp(loc
, 1, Type::tbool
);
4237 e
= new IntegerExp(loc
, 0, Type::tbool
);
4242 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
4247 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
4252 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
4259 unsigned char postfix
;
4261 // cat adjacent strings
4264 postfix
= token
.postfix
;
4268 if (token
.value
== TOKstring
)
4274 { if (token
.postfix
!= postfix
)
4275 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4276 postfix
= token
.postfix
;
4282 s2
= (unsigned char *)mem
.malloc((len
+ 1) * sizeof(unsigned char));
4283 memcpy(s2
, s
, len1
* sizeof(unsigned char));
4284 memcpy(s2
+ len1
, token
.ustring
, (len2
+ 1) * sizeof(unsigned char));
4290 e
= new StringExp(loc
, s
, len
, postfix
);
4294 CASE_BASIC_TYPES_X(t
):
4297 check(TOKdot
, t
->toChars());
4298 if (token
.value
!= TOKidentifier
)
4299 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4302 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4311 exp
= parseExpression();
4313 t
= new TypeTypeof(loc
, exp
);
4314 if (token
.value
== TOKdot
)
4316 e
= new TypeExp(loc
, t
);
4324 check(TOKlparen
, "typeid");
4325 t
= parseBasicType();
4326 t
= parseDeclarator(t
,NULL
); // ( type )
4328 e
= new TypeidExp(loc
, t
);
4334 Identifier
*ident
= NULL
;
4336 enum TOK tok
= TOKreserved
;
4337 enum TOK tok2
= TOKreserved
;
4338 Loc loc
= this->loc
;
4341 if (token
.value
== TOKlparen
)
4344 targ
= parseBasicType();
4345 targ
= parseDeclarator(targ
, &ident
);
4346 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
4350 if (tok
== TOKequal
&&
4351 (token
.value
== TOKtypedef
||
4352 token
.value
== TOKstruct
||
4353 token
.value
== TOKunion
||
4354 token
.value
== TOKclass
||
4355 token
.value
== TOKsuper
||
4356 token
.value
== TOKenum
||
4357 token
.value
== TOKinterface
||
4358 token
.value
== TOKfunction
||
4359 token
.value
== TOKdelegate
||
4360 token
.value
== TOKreturn
))
4367 tspec
= parseBasicType();
4368 tspec
= parseDeclarator(tspec
, NULL
);
4374 { error("(type identifier : specialization) expected following is");
4377 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4382 { Expression
*msg
= NULL
;
4387 e
= parseAssignExp();
4388 if (token
.value
== (dltSyntax
? TOKelse
: TOKcomma
))
4390 msg
= parseAssignExp();
4394 e
= new AssertExp(loc
, e
, msg
);
4401 check(TOKlparen
, "mixin");
4402 e
= parseAssignExp();
4404 e
= new CompileExp(loc
, e
);
4411 check(TOKlparen
, "import");
4412 e
= parseAssignExp();
4414 e
= new FileExp(loc
, e
);
4419 if (peekPastParen(&token
)->value
== TOKlcurly
)
4420 { // (arguments) { statements... }
4426 e
= parseExpression();
4427 check(loc
, TOKrparen
);
4431 { /* Parse array literals and associative array literals:
4432 * [ value, value, value ... ]
4433 * [ key:value, key:value, key:value ... ]
4435 Expressions
*values
= new Expressions();
4436 Expressions
*keys
= NULL
;
4439 if (token
.value
!= TOKrbracket
)
4443 Expression
*e
= parseAssignExp();
4444 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4447 keys
= new Expressions();
4449 e
= parseAssignExp();
4452 { error("'key:value' expected for associative array literal");
4457 if (token
.value
== TOKrbracket
)
4465 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4467 e
= new ArrayLiteralExp(loc
, values
);
4472 // { statements... }
4482 /* function type(parameters) { body }
4483 * delegate type(parameters) { body }
4485 Arguments
*arguments
;
4487 FuncLiteralDeclaration
*fd
;
4490 if (token
.value
== TOKlcurly
)
4494 arguments
= new Arguments();
4498 if (token
.value
== TOKlparen
)
4502 t
= parseBasicType();
4503 t
= parseBasicType2(t
); // function return type
4505 arguments
= parseParameters(&varargs
);
4507 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
4508 fd
= new FuncLiteralDeclaration(loc
, 0, t
, save
, NULL
);
4510 e
= new FuncExp(loc
, fd
);
4515 error("expression expected, not '%s'", token
.toChars());
4517 // Anything for e, as long as it's not NULL
4518 e
= new IntegerExp(loc
, 0, Type::tint32
);
4522 return parsePostExp(e
);
4525 Expression
*Parser::parsePostExp(Expression
*e
)
4532 switch (token
.value
)
4536 if (token
.value
== TOKidentifier
)
4537 { Identifier
*id
= token
.ident
;
4540 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4541 { // identifier!(template-argument-list)
4542 TemplateInstance
*tempinst
;
4544 tempinst
= new TemplateInstance(loc
, id
);
4546 tempinst
->tiargs
= parseTemplateArgumentList();
4547 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4550 e
= new DotIdExp(loc
, e
, id
);
4553 else if (token
.value
== TOKnew
)
4559 error("identifier expected following '.', not '%s'", token
.toChars());
4563 e
= new PostExp(TOKplusplus
, loc
, e
);
4567 e
= new PostExp(TOKminusminus
, loc
, e
);
4571 e
= new CallExp(loc
, e
, parseArguments());
4575 { // array dereferences:
4578 // array[lwr .. upr]
4584 if (token
.value
== TOKrbracket
)
4586 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4591 index
= parseAssignExp();
4592 if (token
.value
== TOKslice
)
4593 { // array[lwr .. upr]
4595 upr
= parseAssignExp();
4596 e
= new SliceExp(loc
, e
, index
, upr
);
4599 { // array[index, i2, i3, i4, ...]
4600 Expressions
*arguments
= new Expressions();
4601 arguments
->push(index
);
4602 if (token
.value
== TOKcomma
)
4608 arg
= parseAssignExp();
4609 arguments
->push(arg
);
4610 if (token
.value
== TOKrbracket
)
4615 e
= new ArrayExp(loc
, e
, arguments
);
4630 Expression
*Parser::parseUnaryExp()
4632 Loc loc
= this->loc
;
4634 switch (token
.value
)
4638 e
= parseUnaryExp();
4639 e
= new AddrExp(loc
, e
);
4644 e
= parseUnaryExp();
4645 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4650 e
= parseUnaryExp();
4651 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4656 e
= parseUnaryExp();
4657 e
= new PtrExp(loc
, e
);
4662 e
= parseUnaryExp();
4663 e
= new NegExp(loc
, e
);
4668 e
= parseUnaryExp();
4669 e
= new UAddExp(loc
, e
);
4674 e
= parseUnaryExp();
4675 e
= new NotExp(loc
, e
);
4680 e
= parseUnaryExp();
4681 e
= new ComExp(loc
, e
);
4686 e
= parseUnaryExp();
4687 e
= new DeleteExp(loc
, e
);
4691 e
= parseNewExp(NULL
);
4694 case TOKcast
: // cast(type) expression
4699 t
= parseBasicType();
4700 t
= parseDeclarator(t
,NULL
); // ( type )
4703 e
= parseUnaryExp();
4704 e
= new CastExp(loc
, e
, t
);
4714 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4716 tk
= peek(tk
); // skip over right parenthesis
4736 case TOKimaginary32v
:
4737 case TOKimaginary64v
:
4738 case TOKimaginary80v
:
4756 CASE_BASIC_TYPES
: // (type)int.size
4761 t
= parseBasicType();
4762 t
= parseDeclarator(t
,NULL
);
4766 if (token
.value
== TOKdot
)
4769 if (token
.value
!= TOKidentifier
)
4770 { error("Identifier expected following (type).");
4773 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4775 e
= parsePostExp(e
);
4779 e
= parseUnaryExp();
4780 e
= new CastExp(loc
, e
, t
);
4781 error("C style cast illegal, use %s", e
->toChars());
4788 e
= parsePrimaryExp();
4792 e
= parsePrimaryExp();
4799 Expression
*Parser::parseMulExp()
4802 Loc loc
= this->loc
;
4804 e
= parseUnaryExp();
4807 switch (token
.value
)
4809 case TOKmul
: nextToken(); e2
= parseUnaryExp(); e
= new MulExp(loc
,e
,e2
); continue;
4810 case TOKdiv
: nextToken(); e2
= parseUnaryExp(); e
= new DivExp(loc
,e
,e2
); continue;
4811 case TOKmod
: nextToken(); e2
= parseUnaryExp(); e
= new ModExp(loc
,e
,e2
); continue;
4821 Expression
*Parser::parseAddExp()
4824 Loc loc
= this->loc
;
4829 switch (token
.value
)
4831 case TOKadd
: nextToken(); e2
= parseMulExp(); e
= new AddExp(loc
,e
,e2
); continue;
4832 case TOKmin
: nextToken(); e2
= parseMulExp(); e
= new MinExp(loc
,e
,e2
); continue;
4833 case TOKtilde
: nextToken(); e2
= parseMulExp(); e
= new CatExp(loc
,e
,e2
); continue;
4843 Expression
*Parser::parseShiftExp()
4846 Loc loc
= this->loc
;
4851 switch (token
.value
)
4853 case TOKshl
: nextToken(); e2
= parseAddExp(); e
= new ShlExp(loc
,e
,e2
); continue;
4854 case TOKshr
: nextToken(); e2
= parseAddExp(); e
= new ShrExp(loc
,e
,e2
); continue;
4855 case TOKushr
: nextToken(); e2
= parseAddExp(); e
= new UshrExp(loc
,e
,e2
); continue;
4865 Expression
*Parser::parseRelExp()
4869 Loc loc
= this->loc
;
4871 e
= parseShiftExp();
4874 switch (token
.value
)
4890 e2
= parseShiftExp();
4891 e
= new CmpExp(op
, loc
, e
, e2
);
4896 e2
= parseShiftExp();
4897 e
= new InExp(loc
, e
, e2
);
4908 Expression
*Parser::parseEqualExp()
4912 Loc loc
= this->loc
;
4916 { enum TOK value
= token
.value
;
4924 e
= new EqualExp(value
, loc
, e
, e2
);
4928 error("'===' is no longer legal, use 'is' instead");
4931 case TOKnotidentity
:
4932 error("'!==' is no longer legal, use '!is' instead");
4936 value
= TOKidentity
;
4940 // Attempt to identify '!is'
4942 if (t
->value
!= TOKis
)
4945 value
= TOKnotidentity
;
4951 e
= new IdentityExp(value
, loc
, e
, e2
);
4962 Expression
*Parser::parseCmpExp()
4966 Loc loc
= this->loc
;
4968 e
= parseShiftExp();
4969 enum TOK op
= token
.value
;
4976 e2
= parseShiftExp();
4977 e
= new EqualExp(op
, loc
, e
, e2
);
4985 // Attempt to identify '!is'
4987 if (t
->value
!= TOKis
)
4990 op
= TOKnotidentity
;
4995 e2
= parseShiftExp();
4996 e
= new IdentityExp(op
, loc
, e
, e2
);
5012 e2
= parseShiftExp();
5013 e
= new CmpExp(op
, loc
, e
, e2
);
5018 e2
= parseShiftExp();
5019 e
= new InExp(loc
, e
, e2
);
5028 Expression
*Parser::parseAndExp()
5031 Loc loc
= this->loc
;
5033 if (global
.params
.Dversion
== 1)
5035 e
= parseEqualExp();
5036 while (token
.value
== TOKand
)
5039 e2
= parseEqualExp();
5040 e
= new AndExp(loc
,e
,e2
);
5047 while (token
.value
== TOKand
)
5051 e
= new AndExp(loc
,e
,e2
);
5058 Expression
*Parser::parseXorExp()
5061 Loc loc
= this->loc
;
5064 while (token
.value
== TOKxor
)
5068 e
= new XorExp(loc
, e
, e2
);
5073 Expression
*Parser::parseOrExp()
5076 Loc loc
= this->loc
;
5079 while (token
.value
== TOKor
)
5083 e
= new OrExp(loc
, e
, e2
);
5088 Expression
*Parser::parseAndAndExp()
5091 Loc loc
= this->loc
;
5094 while (token
.value
== TOKandand
)
5098 e
= new AndAndExp(loc
, e
, e2
);
5103 Expression
*Parser::parseOrOrExp()
5106 Loc loc
= this->loc
;
5108 e
= parseAndAndExp();
5109 while (token
.value
== TOKoror
)
5112 e2
= parseAndAndExp();
5113 e
= new OrOrExp(loc
, e
, e2
);
5118 Expression
*Parser::parseCondExp()
5122 Loc loc
= this->loc
;
5125 if (token
.value
== TOKquestion
)
5128 e1
= parseExpression();
5130 e2
= parseCondExp();
5131 e
= new CondExp(loc
, e
, e1
, e2
);
5136 Expression
*DltParser::parseCondExp()
5140 Loc loc
= this->loc
;
5143 if (token
.value
== TOKif
)
5146 e1
= parseExpression();
5148 e2
= parseCondExp();
5149 e
= new CondExp(loc
, e1
, e
, e2
);
5154 Expression
*Parser::parseAssignExp()
5163 switch (token
.value
)
5165 #define X(tok,ector) \
5166 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5168 X(TOKassign
, AssignExp
);
5169 X(TOKaddass
, AddAssignExp
);
5170 X(TOKminass
, MinAssignExp
);
5171 X(TOKmulass
, MulAssignExp
);
5172 X(TOKdivass
, DivAssignExp
);
5173 X(TOKmodass
, ModAssignExp
);
5174 X(TOKandass
, AndAssignExp
);
5175 X(TOKorass
, OrAssignExp
);
5176 X(TOKxorass
, XorAssignExp
);
5177 X(TOKshlass
, ShlAssignExp
);
5178 X(TOKshrass
, ShrAssignExp
);
5179 X(TOKushrass
, UshrAssignExp
);
5180 X(TOKcatass
, CatAssignExp
);
5191 Expression
*Parser::parseExpression()
5194 Loc loc
= this->loc
;
5196 //printf("Parser::parseExpression()\n");
5197 e
= parseAssignExp();
5198 while (token
.value
== TOKcomma
)
5201 e2
= parseAssignExp();
5202 e
= new CommaExp(loc
, e
, e2
);
5209 /*************************
5210 * Collect argument list.
5211 * Assume current token is '(' or '['.
5214 Expressions
*Parser::parseArguments()
5216 Expressions
*arguments
;
5220 arguments
= new Expressions();
5221 if (token
.value
== TOKlbracket
)
5222 endtok
= TOKrbracket
;
5228 if (token
.value
!= endtok
)
5232 arg
= parseAssignExp();
5233 arguments
->push(arg
);
5234 if (token
.value
== endtok
)
5244 /*******************************************
5247 Expression
*Parser::parseNewExp(Expression
*thisexp
)
5249 Expressions
*newargs
;
5250 Expressions
*arguments
= NULL
;
5252 Loc loc
= this->loc
;
5256 if (token
.value
== TOKlparen
)
5258 newargs
= parseArguments();
5261 // An anonymous nested class starts with "class"
5262 if (token
.value
== TOKclass
)
5265 if (token
.value
== TOKlparen
)
5266 arguments
= parseArguments();
5268 BaseClasses
*baseclasses
= NULL
;
5269 if (token
.value
!= TOKlcurly
)
5270 baseclasses
= parseBaseClasses();
5272 Identifier
*id
= NULL
;
5273 ClassDeclaration
*cd
= new ClassDeclaration(loc
, id
, baseclasses
);
5275 if (token
.value
!= TOKlcurly
)
5276 { error("{ members } expected for anonymous class");
5282 Array
*decl
= parseDeclDefs(0);
5283 if (token
.value
!= TOKrcurly
)
5284 error("class member expected");
5289 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
5295 t
= parseBasicType();
5296 t
= parseBasicType2(t
);
5297 if (t
->ty
== Taarray
)
5299 Type
*index
= ((TypeAArray
*)t
)->index
;
5301 Expression
*e
= index
->toExpression();
5303 { arguments
= new Expressions();
5305 t
= new TypeDArray(t
->next
);
5309 error("need size of rightmost array, not type %s", index
->toChars());
5310 return new NullExp(loc
);
5313 else if (t
->ty
== Tsarray
)
5315 TypeSArray
*tsa
= (TypeSArray
*)t
;
5316 Expression
*e
= tsa
->dim
;
5318 arguments
= new Expressions();
5320 t
= new TypeDArray(t
->next
);
5322 else if (token
.value
== TOKlparen
)
5324 arguments
= parseArguments();
5327 t
= parseBasicType();
5328 while (token
.value
== TOKmul
)
5329 { t
= new TypePointer(t
);
5332 if (token
.value
== TOKlbracket
)
5337 e
= parseAssignExp();
5338 arguments
= new Array();
5341 t
= parseDeclarator(t
, NULL
);
5342 t
= new TypeDArray(t
);
5344 else if (token
.value
== TOKlparen
)
5345 arguments
= parseArguments();
5347 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5351 /**********************************************
5354 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5356 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5360 /********************************* ***************************/