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");
72 startBlockTok
= TOKlcurly
;
73 //nextToken(); // start up the scanner
76 DltParser::DltParser(Module
*module
, unsigned char *base
, unsigned length
, int doDocComment
)
77 : Parser(module
, base
, length
, doDocComment
)
79 //printf("DltParser::DltParser(%s)\n", module->ident->string);
80 startBlockTok
= TOKcolon
;
83 Array
*Parser::parseModule()
87 // ModuleDeclation leads off
89 if (token
.value
== TOKmodule
)
91 unsigned char *comment
= token
.blockComment
;
94 if (token
.value
!= TOKidentifier
)
95 { error("Identifier expected following module");
104 while (nextToken() == TOKdot
)
110 if (token
.value
!= TOKidentifier
)
111 { error("Identifier expected following package");
117 md
= new ModuleDeclaration(a
, id
);
119 TOK end
= dltSyntax
? TOKendline
: TOKsemicolon
;
120 if (token
.value
!= end
)
121 error("%s expected following module declaration instead of %s", Token::toChars(end
), token
.toChars());
124 addComment(mod
, comment
);
128 decldefs
= parseDeclDefs(0);
129 if (token
.value
!= TOKeof
)
130 { error("unrecognized declaration '%s'", token
.toChars());
136 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKeof
)
142 Array
*Parser::parseDeclDefs(int once
)
149 Condition
*condition
;
150 unsigned char *comment
;
152 //printf("Parser::parseDeclDefs()\n");
153 decldefs
= new Array();
156 comment
= token
.blockComment
;
170 s
= parseAggregate();
174 s
= parseImport(decldefs
, 0);
178 s
= (Dsymbol
*)parseTemplateDeclaration();
182 { Loc loc
= this->loc
;
183 if (peek(&token
)->value
== TOKlparen
)
186 check(TOKlparen
, "mixin");
187 Expression
*e
= parseAssignExp();
190 s
= new CompileDeclaration(loc
, e
);
204 a
= parseDeclarations();
218 s
= parseInvariant();
220 if (peek(&token
)->value
== TOKlcurly
)
221 s
= parseInvariant();
248 if (token
.value
== TOKthis
)
249 s
= parseStaticCtor();
250 else if (token
.value
== TOKtilde
)
251 s
= parseStaticDtor();
252 else if (token
.value
== TOKassert
)
253 s
= parseStaticAssert();
254 else if (token
.value
== TOKif
)
255 { condition
= parseStaticIfCondition();
258 if (token
.value
== TOKelse
)
260 aelse
= parseBlock();
262 s
= new StaticIfDeclaration(condition
, a
, aelse
);
265 else if (token
.value
== TOKimport
)
267 s
= parseImport(decldefs
, 1);
280 case TOKconst
: stc
= STCconst
; goto Lstc
;
281 case TOKfinal
: stc
= STCfinal
; goto Lstc
;
282 case TOKauto
: stc
= STCauto
; goto Lstc
;
283 case TOKscope
: stc
= STCscope
; goto Lstc
;
284 case TOKoverride
: stc
= STCoverride
; goto Lstc
;
285 case TOKabstract
: stc
= STCabstract
; goto Lstc
;
286 case TOKsynchronized
: stc
= STCsynchronized
; goto Lstc
;
287 case TOKdeprecated
: stc
= STCdeprecated
; goto Lstc
;
294 case TOKconst
: stc
|= STCconst
; goto Lstc
;
295 case TOKfinal
: stc
|= STCfinal
; goto Lstc
;
296 case TOKauto
: stc
|= STCauto
; goto Lstc
;
297 case TOKscope
: stc
|= STCscope
; goto Lstc
;
298 case TOKoverride
: stc
|= STCoverride
; goto Lstc
;
299 case TOKabstract
: stc
|= STCabstract
; goto Lstc
;
300 case TOKsynchronized
: stc
|= STCsynchronized
; goto Lstc
;
301 case TOKdeprecated
: stc
|= STCdeprecated
; goto Lstc
;
302 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
307 /* Look for auto initializers:
308 * storage_class identifier = initializer;
310 if (token
.value
== TOKidentifier
&&
311 peek(&token
)->value
== TOKassign
)
315 Identifier
*ident
= token
.ident
;
318 Initializer
*init
= parseInitializer();
319 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
320 v
->storage_class
= stc
;
322 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
326 else if (token
.value
== TOKcomma
)
329 if (token
.value
== TOKidentifier
&&
330 peek(&token
)->value
== TOKassign
)
333 addComment(s
, comment
);
337 error("Identifier expected following comma");
340 error("%s expected following declaration, not '%s'", endToken(), token
.toChars());
346 s
= new StorageClassDeclaration(stc
, a
);
351 if (peek(&token
)->value
!= TOKlparen
)
356 enum LINK linksave
= linkage
;
357 linkage
= parseLinkage();
359 s
= new LinkDeclaration(linkage
, a
);
363 case TOKprivate
: prot
= PROTprivate
; goto Lprot
;
364 case TOKpackage
: prot
= PROTpackage
; goto Lprot
;
365 case TOKprotected
: prot
= PROTprotected
; goto Lprot
;
366 case TOKpublic
: prot
= PROTpublic
; goto Lprot
;
367 case TOKexport
: prot
= PROTexport
; goto Lprot
;
372 s
= new ProtDeclaration(prot
, a
);
380 if (token
.value
== TOKlparen
)
383 if (token
.value
== TOKint32v
)
384 n
= (unsigned)token
.uns64value
;
386 { error("integer expected, not %s", token
.toChars());
393 n
= global
.structalign
; // default
396 s
= new AlignDeclaration(n
, a
);
402 Expressions
*args
= NULL
;
406 if (token
.value
!= TOKidentifier
)
407 { error("pragma(identifier expected");
412 if (token
.value
== TOKcomma
)
413 args
= parseArguments(); // pragma(identifier, args...)
415 check(TOKrparen
); // pragma(identifier)
417 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
422 a
= parseDeclDefs(0);
427 s
= new PragmaDeclaration(loc
, ident
, args
, a
);
433 if (token
.value
== TOKassign
)
436 if (token
.value
== TOKidentifier
)
437 s
= new DebugSymbol(loc
, token
.ident
);
438 else if (token
.value
== TOKint32v
)
439 s
= new DebugSymbol(loc
, (unsigned)token
.uns64value
);
441 { error("identifier or integer expected, not %s", token
.toChars());
445 if (token
.value
!= TOKsemicolon
)
446 error("semicolon expected");
451 condition
= parseDebugCondition();
456 if (token
.value
== TOKassign
)
459 if (token
.value
== TOKidentifier
)
460 s
= new VersionSymbol(loc
, token
.ident
);
461 else if (token
.value
== TOKint32v
)
462 s
= new VersionSymbol(loc
, (unsigned)token
.uns64value
);
464 { error("identifier or integer expected, not %s", token
.toChars());
468 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
)
469 error("%s expected after version assignment", endToken());
473 condition
= parseVersionCondition();
479 if (token
.value
== TOKelse
)
481 aelse
= parseBlock();
483 s
= new ConditionalDeclaration(condition
, a
, aelse
);
486 case TOKsemicolon
: // empty declaration
491 error("Declaration expected, not '%s'",token
.toChars());
493 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
&& token
.value
!= TOKeof
)
501 addComment(s
, comment
);
508 /********************************************
509 * Parse declarations after an align, protection, or extern decl.
512 Array
*Parser::parseBlock()
517 //printf("Parser::parseBlock()\n");
521 error("declaration expected following attribute, not ';'");
527 a
= parseDeclDefs(0);
528 if (token
.value
!= TOKrcurly
)
530 error("matching '}' expected, not %s", token
.toChars());
541 a
= parseDeclDefs(0); // grab declarations up to closing curly bracket
546 a
= parseDeclDefs(1);
552 Array
*DltParser::parseBlock()
562 error("declaration expected following attribute, not %s", token
.toChars());
568 a
= parseDeclDefs(0);
569 if (token
.value
!= TOKrcurly
)
571 error("matching end-of-block expected, not %s", token
.toChars());
578 a
= parseDeclDefs(1);
584 /**********************************
585 * Parse a static assertion.
588 StaticAssert
*Parser::parseStaticAssert()
592 Expression
*msg
= NULL
;
594 //printf("parseStaticAssert()\n");
597 exp
= parseAssignExp();
598 if (token
.value
== TOKcomma
)
600 msg
= parseAssignExp();
603 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
) {
605 return new StaticAssert(loc
, exp
, msg
);
607 error("expected %s after static assert", endToken());
611 /***********************************
612 * Parse extern (linkage)
613 * The parser is on the 'extern' token.
616 enum LINK
Parser::parseLinkage()
618 enum LINK link
= LINKdefault
;
620 assert(token
.value
== TOKlparen
);
622 if (token
.value
== TOKidentifier
)
623 { Identifier
*id
= token
.ident
;
626 if (id
== Id::Windows
)
628 else if (id
== Id::Pascal
)
630 else if (id
== Id::D
)
632 else if (id
== Id::C
)
635 if (token
.value
== TOKplusplus
)
640 else if (id
== Id::System
)
643 link
= d_gcc_is_target_win32() ? LINKwindows
: LINKc
;
654 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
660 link
= LINKd
; // default
666 /**************************************
667 * Parse a debug conditional
670 Condition
*Parser::parseDebugCondition()
674 if (token
.value
== TOKlparen
)
678 Identifier
*id
= NULL
;
680 if (token
.value
== TOKidentifier
)
682 else if (token
.value
== TOKint32v
)
683 level
= (unsigned)token
.uns64value
;
685 error("identifier or integer expected, not %s", token
.toChars());
688 c
= new DebugCondition(mod
, level
, id
);
689 if (dltSyntax
&& token
.value
!= TOKcolon
)
690 error("expected colon after debug(), not '%s'", token
.toChars());
692 if (dltSyntax
&& token
.value
!= TOKcolon
)
693 error("expected ':' or '(' after 'debug', not '%s'", token
.toChars());
694 c
= new DebugCondition(mod
, 1, NULL
);
700 /**************************************
701 * Parse a version conditional
704 Condition
*Parser::parseVersionCondition()
708 Identifier
*id
= NULL
;
710 if (token
.value
== TOKlparen
)
713 if (token
.value
== TOKidentifier
)
715 else if (token
.value
== TOKint32v
)
716 level
= (unsigned)token
.uns64value
;
720 * even though unittest is a keyword
722 else if (token
.value
== TOKunittest
)
723 id
= Lexer::idPool(Token::toChars(TOKunittest
));
726 error("identifier or integer expected, not %s", token
.toChars());
732 error("(condition) expected following version");
733 c
= new VersionCondition(mod
, level
, id
);
738 /***********************************************
739 * static if (expression)
745 Condition
*Parser::parseStaticIfCondition()
747 Condition
*condition
;
754 exp
= parseAssignExp();
757 condition
= new StaticIfCondition(loc
, exp
);
762 /*****************************************
763 * Parse a constructor definition:
764 * this(arguments) { body }
765 * Current token is 'this'.
768 CtorDeclaration
*Parser::parseCtor()
771 Arguments
*arguments
;
776 arguments
= parseParameters(&varargs
);
777 f
= new CtorDeclaration(loc
, 0, arguments
, varargs
);
782 /*****************************************
783 * Parse a destructor definition:
785 * Current token is '~'.
788 DtorDeclaration
*Parser::parseDtor()
798 f
= new DtorDeclaration(loc
, 0);
803 /*****************************************
804 * Parse a static constructor definition:
805 * static this() { body }
806 * Current token is 'this'.
809 StaticCtorDeclaration
*Parser::parseStaticCtor()
811 StaticCtorDeclaration
*f
;
818 f
= new StaticCtorDeclaration(loc
, 0);
823 /*****************************************
824 * Parse a static destructor definition:
825 * static ~this() { body }
826 * Current token is '~'.
829 StaticDtorDeclaration
*Parser::parseStaticDtor()
831 StaticDtorDeclaration
*f
;
839 f
= new StaticDtorDeclaration(loc
, 0);
844 /*****************************************
845 * Parse an invariant definition:
847 * Current token is 'invariant'.
850 InvariantDeclaration
*Parser::parseInvariant()
852 InvariantDeclaration
*f
;
856 if (token
.value
== TOKlparen
) // optional ()
862 f
= new InvariantDeclaration(loc
, 0);
863 f
->fbody
= parseStatement(PScurly
);
867 /*****************************************
868 * Parse a unittest definition:
870 * Current token is 'unittest'.
873 UnitTestDeclaration
*Parser::parseUnitTest()
875 UnitTestDeclaration
*f
;
881 body
= parseStatement(PScurly
);
883 f
= new UnitTestDeclaration(loc
, this->loc
);
888 /*****************************************
889 * Parse a new definition:
890 * new(arguments) { body }
891 * Current token is 'new'.
894 NewDeclaration
*Parser::parseNew()
897 Arguments
*arguments
;
902 arguments
= parseParameters(&varargs
);
903 f
= new NewDeclaration(loc
, 0, arguments
, varargs
);
908 /*****************************************
909 * Parse a delete definition:
910 * delete(arguments) { body }
911 * Current token is 'delete'.
914 DeleteDeclaration
*Parser::parseDelete()
916 DeleteDeclaration
*f
;
917 Arguments
*arguments
;
922 arguments
= parseParameters(&varargs
);
924 error("... not allowed in delete function parameter list");
925 f
= new DeleteDeclaration(loc
, 0, arguments
);
930 /**********************************************
931 * Parse parameter list.
934 Arguments
*Parser::parseParameters(int *pvarargs
)
936 Arguments
*arguments
= new Arguments();
946 unsigned storageClass
;
950 storageClass
= STCin
; // parameter is "in" by default
962 storageClass
= STCin
;
967 storageClass
= STCout
;
973 storageClass
= STCref
;
978 storageClass
= STClazy
;
984 tb
= parseBasicType();
985 at
= parseDeclarator(tb
, &ai
);
987 if (token
.value
== TOKassign
) // = defaultArg
989 ae
= parseAssignExp();
994 error("default argument expected for %s",
995 ai
? ai
->toChars() : at
->toChars());
997 if (token
.value
== TOKdotdotdot
)
1002 if (storageClass
& (STCout
| STCref
))
1003 error("variadic argument cannot be out or ref");
1005 a
= new Argument(storageClass
, at
, ai
, ae
);
1010 a
= new Argument(storageClass
, at
, ai
, ae
);
1012 if (token
.value
== TOKcomma
)
1021 *pvarargs
= varargs
;
1026 /*************************************
1029 EnumDeclaration
*Parser::parseEnum()
1030 { EnumDeclaration
*e
;
1033 Loc loc
= this->loc
;
1035 //printf("Parser::parseEnum()\n");
1037 if (token
.value
== TOKidentifier
)
1044 if (token
.value
== (dltSyntax
? TOKextends
: TOKcolon
))
1047 t
= parseBasicType();
1052 e
= new EnumDeclaration(loc
, id
, t
);
1053 if (token
.value
== TOKsemicolon
&& id
)
1055 else if (token
.value
== startBlockTok
)
1057 //printf("enum definition\n");
1058 e
->members
= new Array();
1060 unsigned char *comment
= token
.blockComment
;
1062 while (token
.value
!= TOKrcurly
)
1064 if (token
.value
== TOKidentifier
)
1070 ident
= token
.ident
;
1073 if (token
.value
== TOKassign
)
1076 value
= parseAssignExp();
1078 em
= new EnumMember(loc
, ident
, value
);
1079 e
->members
->push(em
);
1081 if (token
.value
== TOKrcurly
)
1084 { addComment(em
, comment
);
1089 addComment(em
, comment
);
1090 comment
= token
.blockComment
;
1093 { error("enum member expected");
1100 error("enum declaration is invalid");
1105 Dsymbol
*Parser::parseAggregate()
1106 { AggregateDeclaration
*a
= NULL
;
1110 TemplateParameters
*tpl
= NULL
;
1112 //printf("Parser::parseAggregate()\n");
1115 if (token
.value
!= TOKidentifier
)
1122 if (token
.value
== TOKlparen
)
1123 { // Class template declaration.
1125 // Gather template parameter list
1126 tpl
= parseTemplateParameterList();
1130 Loc loc
= this->loc
;
1136 error("anonymous classes not allowed");
1138 // Collect base class(es)
1139 BaseClasses
*baseclasses
= NULL
;
1140 if (token
.value
== (dltSyntax
? TOKextends
: TOKcolon
))
1143 baseclasses
= parseBaseClasses();
1144 if (token
.value
!= startBlockTok
)
1145 error("members expected");
1148 if (tok
== TOKclass
)
1149 a
= new ClassDeclaration(loc
, id
, baseclasses
);
1151 a
= new InterfaceDeclaration(loc
, id
, baseclasses
);
1157 a
= new StructDeclaration(loc
, id
);
1164 a
= new UnionDeclaration(loc
, id
);
1173 if (a
&& token
.value
== (dltSyntax
? TOKendline
: TOKsemicolon
))
1176 else if (token
.value
== startBlockTok
)
1178 //printf("aggregate definition\n");
1181 Array
*decl
= parseDeclDefs(0);
1182 if (token
.value
!= TOKrcurly
)
1183 error("end-of-block expected following member declarations in aggregate");
1187 /* Anonymous structs/unions are more like attributes.
1189 return new AnonDeclaration(loc
, anon
- 1, decl
);
1196 error("%s expected following aggregate declaration", Token::toChars(startBlockTok
));
1197 a
= new StructDeclaration(loc
, NULL
);
1202 TemplateDeclaration
*tempdecl
;
1204 // Wrap a template around the aggregate declaration
1205 decldefs
= new Array();
1207 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
1214 /*******************************************
1217 BaseClasses
*Parser::parseBaseClasses()
1219 enum PROT protection
= PROTpublic
;
1220 BaseClasses
*baseclasses
= new BaseClasses();
1222 for (; 1; nextToken())
1224 switch (token
.value
)
1229 protection
= PROTprivate
;
1232 protection
= PROTpackage
;
1235 protection
= PROTprotected
;
1238 protection
= PROTpublic
;
1241 error("base classes expected instead of %s", token
.toChars());
1244 BaseClass
*b
= new BaseClass(parseBasicType(), protection
);
1245 baseclasses
->push(b
);
1246 if (token
.value
!= TOKcomma
)
1248 protection
= PROTpublic
;
1253 /**************************************
1254 * Parse a TemplateDeclaration.
1257 TemplateDeclaration
*Parser::parseTemplateDeclaration()
1259 TemplateDeclaration
*tempdecl
;
1261 TemplateParameters
*tpl
;
1263 Loc loc
= this->loc
;
1266 if (token
.value
!= TOKidentifier
)
1267 { error("TemplateIdentifier expected following template");
1272 tpl
= parseTemplateParameterList();
1276 if (token
.value
!= startBlockTok
)
1277 { error("members of template declaration expected");
1283 decldefs
= parseDeclDefs(0);
1284 if (token
.value
!= TOKrcurly
)
1285 { error("template member expected");
1291 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
, dltSyntax
);
1298 /******************************************
1299 * Parse template parameter list.
1302 TemplateParameters
*Parser::parseTemplateParameterList()
1304 TemplateParameters
*tpl
= new TemplateParameters();
1306 if (token
.value
!= TOKlparen
)
1307 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1312 // Get array of TemplateParameters
1313 if (token
.value
!= TOKrparen
)
1314 { int isvariadic
= 0;
1317 { TemplateParameter
*tp
;
1318 Identifier
*tp_ident
= NULL
;
1319 Type
*tp_spectype
= NULL
;
1320 Type
*tp_valtype
= NULL
;
1321 Type
*tp_defaulttype
= NULL
;
1322 Expression
*tp_specvalue
= NULL
;
1323 Expression
*tp_defaultvalue
= NULL
;
1326 // Get TemplateParameter
1328 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1330 if (token
.value
== TOKalias
)
1333 if (token
.value
!= TOKidentifier
)
1334 { error("Identifier expected for template parameter");
1337 tp_ident
= token
.ident
;
1339 if (token
.value
== TOKcolon
) // : Type
1342 tp_spectype
= parseBasicType();
1343 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1345 if (token
.value
== TOKassign
) // = Type
1348 tp_defaulttype
= parseBasicType();
1349 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1351 tp
= new TemplateAliasParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1353 else if (t
->value
== TOKcolon
|| t
->value
== TOKassign
||
1354 t
->value
== TOKcomma
|| t
->value
== TOKrparen
)
1356 if (token
.value
!= TOKidentifier
)
1357 { error("Identifier expected for template parameter");
1360 tp_ident
= token
.ident
;
1362 if (token
.value
== TOKcolon
) // : Type
1365 tp_spectype
= parseBasicType();
1366 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1368 if (token
.value
== TOKassign
) // = Type
1371 tp_defaulttype
= parseBasicType();
1372 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1374 tp
= new TemplateTypeParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1376 else if (token
.value
== TOKidentifier
&& t
->value
== TOKdotdotdot
)
1379 error("variadic template parameter must be last");
1381 tp_ident
= token
.ident
;
1384 tp
= new TemplateTupleParameter(loc
, tp_ident
);
1388 tp_valtype
= parseBasicType();
1389 tp_valtype
= parseDeclarator(tp_valtype
, &tp_ident
);
1392 error("no identifier for template value parameter");
1393 tp_ident
= new Identifier("error", TOKidentifier
);
1395 if (token
.value
== TOKcolon
) // : CondExpression
1398 tp_specvalue
= parseCondExp();
1400 if (token
.value
== TOKassign
) // = CondExpression
1403 tp_defaultvalue
= parseCondExp();
1405 tp
= new TemplateValueParameter(loc
, tp_ident
, tp_valtype
, tp_specvalue
, tp_defaultvalue
);
1408 if (token
.value
!= TOKcomma
)
1418 /******************************************
1419 * Parse template mixin.
1422 * mixin a.b.c!(args).Foo!(args);
1423 * mixin Foo!(args) identifier;
1424 * mixin typeof(expr).identifier!(args);
1427 Dsymbol
*Parser::parseMixin()
1435 //printf("parseMixin()\n");
1438 if (token
.value
== TOKdot
)
1444 if (token
.value
== TOKtypeof
)
1449 exp
= parseExpression();
1451 tqual
= new TypeTypeof(loc
, exp
);
1454 if (token
.value
!= TOKidentifier
)
1456 error("identifier expected, not %s", token
.toChars());
1463 idents
= new Array();
1467 if (token
.value
== TOKnot
)
1470 tiargs
= parseTemplateArgumentList();
1473 if (token
.value
!= TOKdot
)
1477 { TemplateInstance
*tempinst
= new TemplateInstance(loc
, id
);
1478 tempinst
->tiargs
= tiargs
;
1479 id
= (Identifier
*)tempinst
;
1485 if (token
.value
!= TOKidentifier
)
1486 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1494 if (token
.value
== TOKidentifier
)
1502 tm
= new TemplateMixin(loc
, id
, tqual
, idents
, tiargs
);
1503 if (token
.value
!= TOKsemicolon
)
1504 error("';' expected after mixin");
1513 /******************************************
1514 * Parse template argument list.
1516 * current token is opening '('
1518 * current token is one after closing ')'
1521 Objects
*Parser::parseTemplateArgumentList()
1523 //printf("Parser::parseTemplateArgumentList()\n");
1524 Objects
*tiargs
= new Objects();
1525 if (token
.value
!= TOKlparen
)
1526 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1531 // Get TemplateArgumentList
1532 if (token
.value
!= TOKrparen
)
1536 // See if it is an Expression or a Type
1537 if (isDeclaration(&token
, 0, TOKreserved
, NULL
))
1541 // Get TemplateArgument
1542 ta
= parseBasicType();
1543 ta
= parseDeclarator(ta
, NULL
);
1550 ea
= parseAssignExp();
1553 if (token
.value
!= TOKcomma
)
1558 check(TOKrparen
, "template argument list");
1562 Import
*Parser::parseImport(Array
*decldefs
, int isstatic
)
1565 Identifier
*aliasid
= NULL
;
1569 //printf("Parser::parseImport()\n");
1574 if (token
.value
!= TOKidentifier
)
1575 { error("Identifier expected following import");
1583 if (!aliasid
&& token
.value
== TOKassign
)
1588 while (token
.value
== TOKdot
)
1594 if (token
.value
!= TOKidentifier
)
1595 { error("Identifier expected following package");
1602 s
= new Import(loc
, a
, token
.ident
, aliasid
, isstatic
);
1606 * : alias=name, alias=name;
1609 if (token
.value
== TOKcolon
)
1618 if (dltSyntax
&& token
.value
== TOKrcurly
)
1620 if (token
.value
!= TOKidentifier
)
1621 { error("Identifier expected following :");
1624 alias
= token
.ident
;
1626 if (token
.value
== TOKassign
)
1629 if (token
.value
!= TOKidentifier
)
1630 { error("Identifier expected following %s=", alias
->toChars());
1640 s
->addAlias(name
, alias
);
1641 if (token
.value
!= TOKcomma
&& token
.value
!= TOKendline
)
1655 } while (token
.value
== TOKcomma
);
1657 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
1661 error("%s expected", endToken());
1668 Type
*Parser::parseBasicType()
1672 TemplateInstance
*tempinst
;
1674 //printf("parseBasicType()\n");
1675 switch (token
.value
)
1677 CASE_BASIC_TYPES_X(t
):
1684 if (token
.value
== TOKnot
)
1687 tempinst
= new TemplateInstance(loc
, id
);
1688 tempinst
->tiargs
= parseTemplateArgumentList();
1689 tid
= new TypeInstance(loc
, tempinst
);
1693 tid
= new TypeIdentifier(loc
, id
);
1695 while (token
.value
== TOKdot
)
1697 if (token
.value
!= TOKidentifier
)
1698 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1703 if (token
.value
== TOKnot
)
1706 tempinst
= new TemplateInstance(loc
, id
);
1707 tempinst
->tiargs
= parseTemplateArgumentList();
1708 tid
->addIdent((Identifier
*)tempinst
);
1725 exp
= parseExpression();
1727 tid
= new TypeTypeof(loc
, exp
);
1732 error("basic type expected, not %s", token
.toChars());
1739 Type
*Parser::parseBasicType2(Type
*t
)
1744 //printf("parseBasicType2()\n");
1747 switch (token
.value
)
1750 t
= new TypePointer(t
);
1756 // Handle []. Make sure things like
1758 // is (array[1] of array[3] of int)
1760 if (token
.value
== TOKrbracket
)
1762 t
= new TypeDArray(t
); // []
1765 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1766 { // It's an associative array declaration
1769 //printf("it's an associative array\n");
1770 index
= parseBasicType();
1771 index
= parseDeclarator(index
, NULL
); // [ type ]
1772 if (index
->ty
== Tmaybe
&& !dltSyntax
)
1774 // This might be an expression. Remove the
1775 // maybe, so that D can try to resolve it as
1776 // a variable instead.
1777 index
= index
->next
;
1779 t
= new TypeAArray(t
, index
);
1784 //printf("it's [expression]\n");
1786 Expression
*e
= parseExpression(); // [ expression ]
1787 if (token
.value
== TOKslice
)
1791 e2
= parseExpression(); // [ exp .. exp ]
1792 t
= new TypeSlice(t
, e
, e2
);
1795 t
= new TypeSArray(t
,e
);
1801 // Handle []. Make sure things like
1803 // is (array[3] of array[1] of int)
1805 while (token
.value
== TOKlbracket
)
1808 if (token
.value
== TOKrbracket
)
1810 ta
= new TypeDArray(t
); // []
1813 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1814 { // It's an associative array declaration
1817 //printf("it's an associative array\n");
1818 index
= parseBasicType();
1819 index
= parseDeclarator(index
, NULL
); // [ type ]
1821 ta
= new TypeAArray(t
, index
);
1825 //printf("it's [expression]\n");
1826 Expression
*e
= parseExpression(); // [ expression ]
1827 ta
= new TypeSArray(t
,e
);
1831 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1841 { // Handle delegate declaration:
1842 // t delegate(parameter list)
1843 // t function(parameter list)
1844 Arguments
*arguments
;
1846 enum TOK save
= token
.value
;
1849 arguments
= parseParameters(&varargs
);
1850 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1851 if (save
== TOKdelegate
)
1852 t
= new TypeDelegate(t
);
1854 t
= new TypePointer(t
); // pointer to function
1865 // fall-through to default
1879 // TypeMaybe will unwrap itself later if this isn't a nullable type
1888 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1892 //printf("parseDeclarator(tpl = %p)\n", tpl);
1893 t
= parseBasicType2(t
);
1895 switch (token
.value
)
1900 *pident
= token
.ident
;
1902 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1909 ts
= parseDeclarator(t
, pident
);
1920 switch (token
.value
)
1924 { // This is the old C-style post [] syntax.
1926 if (token
.value
== TOKrbracket
)
1928 ta
= new TypeDArray(t
); // []
1931 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1932 { // It's an associative array declaration
1935 //printf("it's an associative array\n");
1936 index
= parseBasicType();
1937 index
= parseDeclarator(index
, NULL
); // [ type ]
1939 ta
= new TypeAArray(t
, index
);
1943 //printf("it's [expression]\n");
1944 Expression
*e
= parseExpression(); // [ expression ]
1945 ta
= new TypeSArray(t
, e
);
1949 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1956 { Arguments
*arguments
;
1961 /* Look ahead to see if this is (...)(...),
1962 * i.e. a function template declaration
1964 if (peekPastParen(&token
)->value
== TOKlparen
)
1965 { // It's a function template declaration
1966 //printf("function template declaration\n");
1968 // Gather template parameter list
1969 *tpl
= parseTemplateParameterList();
1973 arguments
= parseParameters(&varargs
);
1974 Type
*ta
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1976 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1988 /**********************************
1989 * Return array of Declaration *'s.
1992 Array
*Parser::parseDeclarations()
1994 enum STC storage_class
;
2002 unsigned char *comment
= token
.blockComment
;
2003 enum LINK link
= linkage
;
2005 //printf("parseDeclarations()\n");
2006 switch (token
.value
)
2019 storage_class
= STCundefined
;
2022 switch (token
.value
)
2024 case TOKconst
: stc
= STCconst
; goto L1
;
2025 case TOKstatic
: stc
= STCstatic
; goto L1
;
2026 case TOKfinal
: stc
= STCfinal
; goto L1
;
2027 case TOKauto
: stc
= STCauto
; goto L1
;
2028 case TOKscope
: stc
= STCscope
; goto L1
;
2029 case TOKoverride
: stc
= STCoverride
; goto L1
;
2030 case TOKabstract
: stc
= STCabstract
; goto L1
;
2031 case TOKsynchronized
: stc
= STCsynchronized
; goto L1
;
2032 case TOKdeprecated
: stc
= STCdeprecated
; goto L1
;
2034 if (storage_class
& stc
)
2035 error("redundant storage class '%s'", token
.toChars());
2036 storage_class
= (STC
) (storage_class
| stc
);
2041 if (peek(&token
)->value
!= TOKlparen
)
2046 link
= parseLinkage();
2057 /* Look for auto initializers:
2058 * storage_class identifier = initializer;
2060 while (storage_class
&&
2061 token
.value
== TOKidentifier
&&
2062 peek(&token
)->value
== TOKassign
)
2064 ident
= token
.ident
;
2067 Initializer
*init
= parseInitializer();
2068 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
2069 v
->storage_class
= storage_class
;
2071 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
2074 addComment(v
, comment
);
2076 else if (token
.value
== TOKcomma
)
2079 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
2081 error("Identifier expected following comma");
2087 error("%s expected following auto declaration, not '%s'", endToken(), token
.toChars());
2091 if (token
.value
== TOKclass
)
2092 { AggregateDeclaration
*s
;
2094 s
= (AggregateDeclaration
*)parseAggregate();
2095 s
->storage_class
|= storage_class
;
2097 addComment(s
, comment
);
2101 ts
= parseBasicType();
2102 ts
= parseBasicType2(ts
);
2107 Loc loc
= this->loc
;
2108 TemplateParameters
*tpl
= NULL
;
2111 t
= parseDeclarator(ts
, &ident
, &tpl
);
2115 else if (t
!= tfirst
)
2116 error("multiple declarations must have the same type, not %s and %s",
2117 tfirst
->toChars(), t
->toChars());
2119 error("no identifier for declarator %s", t
->toChars());
2121 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2127 /* Unwrap maybe qualifiers from aliases.
2128 * Otherwise, it thinks we're aliasing types when we're not.
2130 if (t
->ty
== Tmaybe
) {
2136 if (token
.value
== TOKassign
)
2139 init
= parseInitializer();
2141 if (tok
== TOKtypedef
)
2142 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2145 error("alias cannot have initializer");
2146 v
= new AliasDeclaration(loc
, ident
, t
);
2148 v
->storage_class
= storage_class
;
2149 if (link
== linkage
)
2153 Array
*ax
= new Array();
2155 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2158 switch (token
.value
)
2159 { case TOKsemicolon
:
2162 addComment(v
, comment
);
2167 addComment(v
, comment
);
2171 error("%s expected to close %s declaration", endToken(), Token::toChars(tok
));
2175 else if (t
->ty
== Tfunction
)
2176 { FuncDeclaration
*f
;
2179 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2180 addComment(f
, comment
);
2182 addComment(f
, NULL
);
2183 if (link
== linkage
)
2189 Array
*ax
= new Array();
2191 s
= new LinkDeclaration(link
, ax
);
2193 if (tpl
) // it's a function template
2195 TemplateDeclaration
*tempdecl
;
2197 // Wrap a template around the aggregate declaration
2198 decldefs
= new Array();
2200 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
, dltSyntax
);
2203 addComment(s
, comment
);
2207 { VarDeclaration
*v
;
2211 if (token
.value
== TOKassign
)
2214 init
= parseInitializer();
2216 v
= new VarDeclaration(loc
, t
, ident
, init
);
2217 v
->storage_class
= storage_class
;
2218 if (link
== linkage
)
2222 Array
*ax
= new Array();
2224 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2227 switch (token
.value
)
2228 { case TOKsemicolon
:
2231 addComment(v
, comment
);
2236 addComment(v
, comment
);
2240 error("%s expected, not '%s'", endToken(), token
.toChars());
2249 /*****************************************
2250 * Parse contracts following function declaration.
2253 void Parser::parseContracts(FuncDeclaration
*f
)
2256 enum LINK linksave
= linkage
;
2258 // The following is irrelevant, as it is overridden by sc->linkage in
2259 // TypeFunction::semantic
2260 linkage
= LINKd
; // nested functions have D linkage
2262 switch (token
.value
)
2266 if (token
.value
!= startBlockTok
)
2267 error("use %s to start a new block", Token::toChars(startBlockTok
));
2268 if (f
->frequire
|| f
->fensure
)
2269 error("missing body { ... } after in or out");
2270 f
->fbody
= parseStatement(PSsemi
| PScolon
);
2276 f
->fbody
= parseStatement(PScurly
);
2282 error("unexpected semi-colon after function declaration");
2285 if (f
->frequire
|| f
->fensure
)
2286 error("missing body { ... } after in or out");
2290 #if 0 // Do we want this for function declarations, so we can do:
2291 // int x, y, foo(), z;
2297 #if 0 // Dumped feature
2300 f
->fthrows
= new Array();
2305 tb
= parseBasicType();
2306 f
->fthrows
->push(tb
);
2307 if (token
.value
== TOKcomma
)
2320 error("redundant 'in' statement");
2321 f
->frequire
= parseStatement(PScurly
| PSscope
);
2325 // parse: out (identifier) { statement }
2327 if (token
.value
!= startBlockTok
)
2330 if (token
.value
!= TOKidentifier
)
2331 error("(identifier) following 'out' expected, not %s", token
.toChars());
2332 f
->outId
= token
.ident
;
2337 error("redundant 'out' statement");
2338 f
->fensure
= parseStatement(PScurly
| PSscope
);
2342 error("%s expected following function declaration", endToken());
2348 /*****************************************
2351 Initializer
*Parser::parseInitializer()
2353 StructInitializer
*is
;
2354 ArrayInitializer
*ia
;
2360 Loc loc
= this->loc
;
2364 switch (token
.value
)
2367 /* Scan ahead to see if it is a struct initializer or
2368 * a function literal.
2369 * If it contains a ';', it is a function literal.
2370 * Treat { } as a struct initializer.
2373 for (t
= peek(&token
); 1; t
= peek(t
))
2399 is
= new StructInitializer(loc
);
2404 switch (token
.value
)
2408 error("comma expected separating field initializers");
2410 if (t
->value
== TOKcolon
)
2414 nextToken(); // skip over ':'
2419 value
= parseInitializer();
2420 is
->addInit(id
, value
);
2429 case TOKrcurly
: // allow trailing comma's
2434 error("found EOF instead of initializer");
2438 value
= parseInitializer();
2439 is
->addInit(NULL
, value
);
2442 //error("found '%s' instead of field initializer", token.toChars());
2450 ia
= new ArrayInitializer(loc
);
2455 switch (token
.value
)
2459 { error("comma expected separating array initializers, not %s", token
.toChars());
2463 e
= parseAssignExp();
2466 if (token
.value
== TOKcolon
)
2469 value
= parseInitializer();
2472 { value
= new ExpInitializer(e
->loc
, e
);
2475 ia
->addInit(e
, value
);
2482 error("comma expected separating array initializers, not %s", token
.toChars());
2483 value
= parseInitializer();
2484 ia
->addInit(NULL
, value
);
2493 case TOKrbracket
: // allow trailing comma's
2498 error("found '%s' instead of array initializer", token
.toChars());
2507 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
|| t
->value
== TOKendline
)
2510 return new VoidInitializer(loc
);
2516 e
= parseAssignExp();
2517 ie
= new ExpInitializer(loc
, e
);
2522 Statement
*Parser::logStatement(int level
) {
2524 if (token
.value
!= TOKlparen
)
2525 error(loc
, "found '%s' when expecting '('", token
.toChars());
2526 return new LogStatement(loc
, level
, parseArguments());
2529 /*****************************************
2534 Statement
*DltParser::parseStatement(int flags
)
2537 if (flags
& (PScolon
| PSscope
))
2539 return Parser::parseStatement(flags
);
2542 Statement
*Parser::parseStatement(int flags
)
2545 Condition
*condition
;
2547 Statement
*elsebody
;
2548 Loc loc
= this->loc
;
2550 //printf("parseStatement()\n");
2552 if ((flags
& PScurly
) && token
.value
!= startBlockTok
)
2553 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2555 int tok
= token
.value
;
2557 switch (token
.value
)
2562 // Need to look ahead to see if it is a declaration, label, or expression
2564 if (t
->value
== TOKcolon
)
2568 ident
= token
.ident
;
2571 s
= parseStatement(PSsemi
);
2572 s
= new LabelStatement(loc
, ident
, s
);
2576 // fallthrough to TOKdot
2579 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2595 case TOKimaginary32v
:
2596 case TOKimaginary64v
:
2597 case TOKimaginary80v
:
2622 exp
= parseExpression();
2624 check(TOKsemicolon
, "statement");
2625 s
= new ExpStatement(loc
, exp
);
2630 { // Look ahead to see if it's static assert() or static if()
2634 if (t
->value
== TOKassert
)
2637 s
= new StaticAssertStatement(parseStaticAssert());
2640 if (t
->value
== TOKif
)
2643 condition
= parseStaticIfCondition();
2661 a
= parseDeclarations();
2664 Statements
*as
= new Statements();
2665 as
->reserve(a
->dim
);
2666 for (int i
= 0; i
< a
->dim
; i
++)
2668 Dsymbol
*d
= (Dsymbol
*)a
->data
[i
];
2669 s
= new DeclarationStatement(loc
, d
);
2672 s
= new CompoundStatement(loc
, as
);
2674 else if (a
->dim
== 1)
2676 Dsymbol
*d
= (Dsymbol
*)a
->data
[0];
2677 s
= new DeclarationStatement(loc
, d
);
2681 if (flags
& PSscope
)
2682 s
= new ScopeStatement(loc
, s
);
2692 d
= parseAggregate();
2693 s
= new DeclarationStatement(loc
, d
);
2701 s
= new DeclarationStatement(loc
, d
);
2707 if (t
->value
== TOKlparen
)
2710 check(TOKlparen
, "mixin");
2711 Expression
*e
= parseAssignExp();
2713 check(TOKsemicolon
);
2714 s
= new CompileStatement(loc
, e
);
2717 Dsymbol
*d
= parseMixin();
2718 s
= new DeclarationStatement(loc
, d
);
2724 { Statements
*statements
;
2726 if (token
.value
!= startBlockTok
)
2727 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2731 statements
= new Statements();
2732 while (token
.value
!= TOKrcurly
)
2734 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2738 s
= new CompoundStatement(loc
, statements
);
2739 if (flags
& (PSscope
| PScurlyscope
))
2740 s
= new ScopeStatement(loc
, s
);
2745 case TOKlog_error
: s
= logStatement(LogStatement::Error
); break;
2746 case TOKlog_warning
: s
= logStatement(LogStatement::Warn
); break;
2747 case TOKlog_info
: s
= logStatement(LogStatement::Info
); break;
2748 case TOKlog_trace
: s
= logStatement(LogStatement::Trace
); break;
2751 { Expression
*condition
;
2756 condition
= parseExpression();
2758 body
= parseStatement(PSscope
);
2759 s
= new WhileStatement(loc
, condition
, body
);
2764 if (!(flags
& PSsemi
))
2765 error("use '{ }' for an empty statement, not a ';'");
2767 s
= new ExpStatement(loc
, NULL
);
2772 Expression
*condition
;
2775 body
= parseStatement(PSscope
);
2778 condition
= parseExpression();
2780 s
= new DoStatement(loc
, body
, condition
);
2787 Expression
*condition
;
2788 Expression
*increment
;
2793 if (token
.value
== TOKlparen
) {
2794 /* for (init; cond; incr): ... */
2796 if (token
.value
== TOKsemicolon
)
2801 { init
= parseStatement(0);
2803 if (token
.value
== TOKsemicolon
)
2810 condition
= parseExpression();
2811 check(TOKsemicolon
, "for condition");
2813 if (token
.value
== TOKrparen
)
2818 { increment
= parseExpression();
2821 body
= parseStatement(PSscope
);
2822 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2824 s
= new ScopeStatement(loc
, s
);
2825 } else if (dltSyntax
)
2832 case TOKforeach_reverse
:
2834 /* for var in seq: ... */
2835 /* for index, var in seq: ... */
2836 Arguments
*arguments
;
2841 enum TOK op
= (TOK
) tok
;
2848 TOK inTok
= dltSyntax
? TOKin
: TOKsemicolon
;
2850 arguments
= new Arguments();
2855 Identifier
*ai
= NULL
;
2857 unsigned storageClass
;
2860 storageClass
= STCin
;
2861 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2862 { storageClass
= STCref
;
2865 if (token
.value
== TOKidentifier
)
2867 Token
*t
= peek(&token
);
2868 if (t
->value
== TOKcomma
|| t
->value
== inTok
)
2870 at
= NULL
; // infer argument type
2875 tb
= parseBasicType();
2876 at
= parseDeclarator(tb
, &ai
);
2878 error("no identifier for declarator %s", at
->toChars());
2880 a
= new Argument(storageClass
, at
, ai
, NULL
);
2882 if (token
.value
== TOKcomma
)
2891 aggr
= parseExpression();
2895 if (token
.value
== TOKreversed
) {
2896 op
= TOKforeach_reverse
;
2903 body
= parseStatement(PScolon
);
2904 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2909 { Argument
*arg
= NULL
;
2910 Expression
*condition
;
2912 Statement
*elsebody
;
2917 if (token
.value
== TOKauto
)
2920 if (token
.value
== TOKidentifier
)
2922 Token
*t
= peek(&token
);
2923 if (t
->value
== TOKassign
)
2925 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2930 { error("= expected following auto identifier");
2935 { error("identifier expected following auto");
2939 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
2945 tb
= parseBasicType();
2946 at
= parseDeclarator(tb
, &ai
);
2948 arg
= new Argument(STCin
, at
, ai
, NULL
);
2951 // Check for " ident;"
2952 else if (token
.value
== TOKidentifier
&& !dltSyntax
)
2954 Token
*t
= peek(&token
);
2955 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2957 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2960 if (1 || !global
.params
.useDeprecated
)
2961 error("if (v; e) is deprecated, use if (auto v = e)");
2965 condition
= parseExpression();
2967 ifbody
= parseStatement(PSscope
);
2968 if (token
.value
== TOKelse
)
2973 if (token
.value
== TOKcolon
) {
2974 elsebody
= parseStatement(PSscope
);
2975 } else if (token
.value
== TOKif
) {
2976 elsebody
= parseStatement(0);
2978 error("Expected 'else:' or 'else if', not 'else %s'", token
.toChars());
2983 elsebody
= parseStatement(PSscope
);
2987 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
2992 if (peek(&token
)->value
!= TOKlparen
)
2993 goto Ldeclaration
; // scope used as storage class
2996 if (token
.value
!= TOKidentifier
)
2997 { error("scope identifier expected");
3001 { TOK t
= TOKon_scope_exit
;
3002 Identifier
*id
= token
.ident
;
3005 t
= TOKon_scope_exit
;
3006 else if (id
== Id::failure
)
3007 t
= TOKon_scope_failure
;
3008 else if (id
== Id::success
)
3009 t
= TOKon_scope_success
;
3011 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
3014 Statement
*st
= parseStatement(PScolon
| PScurlyscope
);
3015 s
= new OnScopeStatement(loc
, t
, st
);
3021 condition
= parseDebugCondition();
3026 condition
= parseVersionCondition();
3030 if (dltSyntax
&& token
.value
!= TOKcolon
)
3031 error("expected colon after condition, not '%s'", token
.toChars());
3032 ifbody
= parseStatement(PScolon
/*PSsemi*/);
3034 if (token
.value
== TOKelse
)
3037 elsebody
= parseStatement(PScolon
/*PSsemi*/);
3039 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
3043 { Identifier
*ident
;
3044 Expressions
*args
= NULL
;
3049 if (token
.value
!= TOKidentifier
)
3050 { error("pragma(identifier expected");
3053 ident
= token
.ident
;
3055 if (token
.value
== TOKcomma
)
3056 args
= parseArguments(); // pragma(identifier, args...);
3058 check(TOKrparen
); // pragma(identifier);
3059 if (token
.value
== TOKsemicolon
)
3064 body
= parseStatement(PSsemi
| PScolon
);
3065 s
= new PragmaStatement(loc
, ident
, args
, body
);
3070 { Expression
*condition
;
3075 condition
= parseExpression();
3077 body
= parseStatement(PSscope
| PScolon
);
3078 s
= new SwitchStatement(loc
, condition
, body
);
3084 Statements
*statements
;
3085 Array cases
; // array of Expression's
3090 exp
= parseAssignExp();
3092 if (token
.value
!= TOKcomma
)
3098 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3104 statements
= new Statements();
3105 while (token
.value
!= TOKcase
&&
3106 token
.value
!= TOKdefault
&&
3107 token
.value
!= TOKrcurly
)
3109 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3111 s
= new CompoundStatement(loc
, statements
);
3114 s
= new ScopeStatement(loc
, s
);
3116 // Keep cases in order by building the case statements backwards
3117 for (int i
= cases
.dim
; i
; i
--)
3119 exp
= (Expression
*)cases
.data
[i
- 1];
3120 s
= new CaseStatement(loc
, exp
, s
);
3127 Statements
*statements
;
3133 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3139 statements
= new Statements();
3140 while (token
.value
!= TOKcase
&&
3141 token
.value
!= TOKdefault
&&
3142 token
.value
!= TOKrcurly
)
3144 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3146 s
= new CompoundStatement(loc
, statements
);
3149 s
= new ScopeStatement(loc
, s
);
3150 s
= new DefaultStatement(loc
, s
);
3158 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
3161 exp
= parseExpression();
3164 check(TOKsemicolon
, "return statement");
3165 else if (token
.value
!= TOKendline
) {
3166 error("Expected end-of-line after return statement, but found '%s'", token
.toChars());
3169 s
= new ReturnStatement(loc
, exp
);
3174 { Identifier
*ident
;
3177 if (token
.value
== TOKidentifier
)
3178 { ident
= token
.ident
;
3183 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3184 error("expected %s after break, not '%s'", endToken(), token
.toChars());
3188 s
= new BreakStatement(loc
, ident
);
3193 { Identifier
*ident
;
3196 if (token
.value
== TOKidentifier
)
3197 { ident
= token
.ident
;
3202 check(TOKsemicolon
, "continue statement");
3203 s
= new ContinueStatement(loc
, ident
);
3208 { Identifier
*ident
;
3211 if (token
.value
== TOKdefault
)
3214 s
= new GotoDefaultStatement(loc
);
3216 else if (token
.value
== TOKcase
)
3218 Expression
*exp
= NULL
;
3221 if (token
.value
!= TOKsemicolon
)
3222 exp
= parseExpression();
3223 s
= new GotoCaseStatement(loc
, exp
);
3227 if (token
.value
!= TOKidentifier
)
3228 { error("Identifier expected following goto");
3232 { ident
= token
.ident
;
3235 s
= new GotoStatement(loc
, ident
);
3237 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3238 error("expected %s after goto statement, not '%s'", endToken(), token
.toChars());
3243 case TOKsynchronized
:
3248 if (token
.value
== TOKlparen
)
3251 exp
= parseExpression();
3256 body
= parseStatement(PSscope
);
3257 s
= new SynchronizedStatement(loc
, exp
, body
);
3267 exp
= parseExpression();
3269 body
= parseStatement(PSscope
);
3270 s
= new WithStatement(loc
, exp
, body
);
3276 Array
*catches
= NULL
;
3277 Statement
*finalbody
= NULL
;
3280 body
= parseStatement(PSscope
);
3281 while (token
.value
== TOKcatch
)
3287 Loc loc
= this->loc
;
3290 if (token
.value
== startBlockTok
)
3298 t
= parseBasicType();
3300 t
= parseDeclarator(t
, &id
);
3303 handler
= parseStatement(PScolon
);
3304 c
= new Catch(loc
, t
, id
, handler
);
3306 catches
= new Array();
3310 if (token
.value
== TOKfinally
)
3312 finalbody
= parseStatement(PScolon
);
3316 if (!catches
&& !finalbody
)
3317 error("catch or finally expected following try");
3320 s
= new TryCatchStatement(loc
, body
, catches
);
3322 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3331 exp
= parseExpression();
3332 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3333 error("%s expected after throw statement, not '%s'", endToken(), token
.toChars());
3337 s
= new ThrowStatement(loc
, exp
);
3343 s
= parseStatement(PSsemi
| PScurlyscope
);
3344 s
= new VolatileStatement(loc
, s
);
3348 { Statements
*statements
;
3354 // Parse the asm block into a sequence of AsmStatements,
3355 // each AsmStatement is one instruction.
3356 // Separate out labels.
3357 // Defer parsing of AsmStatements until semantic processing.
3360 #if GDC_EXTENDED_ASM_SYNTAX
3361 if (token
.value
== TOKlparen
)
3368 check(startBlockTok
);
3370 ptoklist
= &toklist
;
3372 statements
= new Statements();
3375 switch (token
.value
)
3380 // Look ahead to see if it is a label
3382 if (t
->value
== TOKcolon
)
3384 label
= token
.ident
;
3385 labelloc
= this->loc
;
3394 if (toklist
|| label
)
3396 error("asm statements must end in ';'");
3403 if (toklist
|| label
)
3404 { // Create AsmStatement from list of tokens we've saved
3405 s
= new AsmStatement(this->loc
, toklist
);
3407 ptoklist
= &toklist
;
3409 { s
= new LabelStatement(labelloc
, label
, s
);
3412 statements
->push(s
);
3419 error("matching '}' expected, not end of file");
3424 // If the first token is a string or '(', parse as extended asm.
3428 statements
->push(s
);
3431 // ...else, drop through.
3435 *ptoklist
= new Token();
3436 memcpy(*ptoklist
, &token
, sizeof(Token
));
3437 ptoklist
= &(*ptoklist
)->next
;
3445 s
= new CompoundStatement(loc
, statements
);
3451 error("found '%s' instead of statement", token
.toChars());
3455 while (token
.value
!= TOKrcurly
&&
3456 token
.value
!= TOKsemicolon
&&
3457 token
.value
!= TOKeof
)
3459 if (token
.value
== TOKsemicolon
)
3468 Statement
*Parser::parseExtAsm(int expect_rparen
)
3470 Expression
* insnTemplate
;
3471 Expressions
* args
= NULL
;
3472 Array
* argNames
= NULL
;
3473 Expressions
* argConstraints
= NULL
;
3474 int nOutputArgs
= 0;
3475 Expressions
* clobbers
= NULL
;
3476 bool isInputPhase
= false; // Output operands first, then input.
3478 insnTemplate
= parseExpression();
3479 if (token
.value
== TOKrparen
|| token
.value
== TOKsemicolon
)
3483 Expression
* arg
= NULL
;
3484 Identifier
* name
= NULL
;
3485 Expression
* constraint
= NULL
;
3487 switch (token
.value
)
3498 error("unterminated statement");
3502 if (token
.value
== TOKidentifier
)
3508 error("expected identifier after '['");
3512 constraint
= parsePrimaryExp();
3513 if (constraint
->op
!= TOKstring
)
3514 error("expected constant string constraint for operand");
3515 arg
= parseAssignExp();
3518 args
= new Expressions
;
3519 argConstraints
= new Expressions
;
3520 argNames
= new Array
;
3523 argNames
->push(name
);
3524 argConstraints
->push(constraint
);
3528 if (token
.value
== TOKcomma
)
3535 isInputPhase
= true;
3542 Expression
* clobber
;
3544 switch (token
.value
)
3551 error("unterminated statement");
3554 clobber
= parseAssignExp();
3555 if (clobber
->op
!= TOKstring
)
3556 error("expected constant string constraint for clobber name");
3558 clobbers
= new Expressions
;
3559 clobbers
->push(clobber
);
3561 if (token
.value
== TOKcomma
)
3570 check(TOKsemicolon
);
3572 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3573 argConstraints
, nOutputArgs
, clobbers
);
3576 void Parser::optionalEndline() {
3577 while (token
.value
== TOKendline
) {
3582 void Parser::check(enum TOK value
)
3587 void Parser::check(Loc loc
, enum TOK value
)
3589 if (token
.value
!= value
)
3590 error(loc
, "found '%s' when expecting '%s'", token
.toChars(), Token::toChars(value
));
3594 void Parser::check(enum TOK value
, char *string
)
3596 if (token
.value
!= value
)
3597 error("found '%s' when expecting '%s' following '%s'",
3598 token
.toChars(), Token::toChars(value
), string
);
3602 char *Parser::endToken()
3607 char *DltParser::endToken()
3612 void Parser::checkLParen() { check(TOKlparen
); }
3613 void Parser::checkRParen() { check(TOKrparen
); }
3615 void DltParser::checkLParen() { }
3616 void DltParser::checkRParen() { }
3618 /************************************
3619 * Determine if the scanner is sitting on the start of a declaration.
3621 * needId 0 no identifier
3622 * 1 identifier optional
3623 * 2 must have identifier
3626 int Parser::isDeclaration(Token
*t
, int needId
, enum TOK endtok
, Token
**pt
)
3630 if (!isBasicType(&t
))
3632 if (!isDeclarator(&t
, &haveId
, endtok
))
3635 (needId
== 0 && !haveId
) ||
3636 (needId
== 2 && haveId
))
3645 int Parser::isBasicType(Token
**pt
)
3647 // This code parallels parseBasicType()
3660 if (t
->value
== TOKnot
)
3670 if (t
->value
== TOKdot
)
3674 if (t
->value
!= TOKidentifier
)
3677 if (t
->value
!= TOKnot
)
3681 if (t
->value
!= TOKlparen
)
3683 if (!skipParens(t
, &t
))
3695 /* typeof(exp).identifier...
3698 if (t
->value
!= TOKlparen
)
3700 if (!skipParens(t
, &t
))
3714 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3715 { // This code parallels parseDeclarator()
3719 //printf("Parser::isDeclarator()\n");
3721 if (t
->value
== TOKassign
)
3737 if (t
->value
== TOKrbracket
)
3741 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3742 { // It's an associative array declaration
3748 // [ expression .. expression ]
3749 if (!isExpression(&t
))
3751 if (t
->value
== TOKslice
)
3753 if (!isExpression(&t
))
3756 if (t
->value
!= TOKrbracket
)
3772 if (t
->value
== TOKrparen
)
3773 return FALSE
; // () is not a declarator
3775 /* Regard ( identifier ) as not a declarator
3776 * BUG: what about ( *identifier ) in
3778 * where f is a class instance with overloaded () ?
3779 * Should we just disallow C-style function pointer declarations?
3781 if (t
->value
== TOKidentifier
)
3782 { Token
*t2
= peek(t
);
3783 if (t2
->value
== TOKrparen
)
3788 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3797 if (!isParameters(&t
))
3812 if (t
->value
== TOKrbracket
)
3816 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3817 { // It's an associative array declaration
3823 if (!isExpression(&t
))
3825 if (t
->value
!= TOKrbracket
)
3834 if (!isParameters(&t
))
3838 // Valid tokens that follow a declaration
3847 // The !parens is to disallow unnecessary parentheses
3848 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3861 int Parser::isParameters(Token
**pt
)
3862 { // This code parallels parseParameters()
3866 //printf("isParameters()\n");
3867 if (t
->value
!= TOKlparen
)
3889 if (!isBasicType(&t
))
3892 if (t
->value
!= TOKdotdotdot
&&
3893 !isDeclarator(&t
, &tmp
, TOKreserved
))
3895 if (t
->value
== TOKassign
)
3897 if (!isExpression(&t
))
3900 if (t
->value
== TOKdotdotdot
)
3905 if (t
->value
== TOKcomma
)
3913 if (t
->value
!= TOKrparen
)
3920 int Parser::isExpression(Token
**pt
)
3922 // This is supposed to determine if something is an expression.
3923 // What it actually does is scan until a closing right bracket
3930 for (;; t
= peek(t
))
3948 if (brnest
|| panest
)
3975 /**********************************************
3977 * instance foo.bar(parameters...)
3979 * if (pt), *pt is set to the token following the closing )
3981 * 1 it's valid instance syntax
3982 * 0 invalid instance syntax
3985 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
3988 if (t
->value
!= TOKdot
)
3990 if (t
->value
!= TOKidentifier
)
3994 while (t
->value
== TOKdot
)
3997 if (t
->value
!= TOKidentifier
)
4001 if (t
->value
!= TOKlparen
)
4004 // Skip over the template arguments
4013 if (!skipParens(t
, &t
))
4029 if (t
->value
!= TOKcomma
)
4032 if (t
->value
!= TOKrparen
)
4043 /*******************************************
4044 * Skip parens, brackets.
4048 * *pt is set to closing token, which is ')' on success
4051 * 0 some parsing error
4054 int Parser::skipParens(Token
*t
, Token
**pt
)
4093 /********************************* Expression Parser ***************************/
4095 Expression
*Parser::parsePrimaryExp()
4100 Loc loc
= this->loc
;
4102 switch (token
.value
)
4107 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4108 { // identifier!(template-argument-list)
4109 TemplateInstance
*tempinst
;
4111 tempinst
= new TemplateInstance(loc
, id
);
4113 tempinst
->tiargs
= parseTemplateArgumentList();
4114 e
= new ScopeExp(loc
, tempinst
);
4117 e
= new IdentifierExp(loc
, id
);
4122 error("'$' is valid only inside [] of index or slice");
4123 e
= new DollarExp(loc
);
4128 // Signal global scope '.' operator with "" identifier
4129 e
= new IdentifierExp(loc
, Id::empty
);
4133 e
= new ThisExp(loc
);
4138 e
= new SuperExp(loc
);
4143 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
4148 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
4153 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
4158 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
4163 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
4168 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
4173 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
4177 case TOKimaginary32v
:
4178 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
4182 case TOKimaginary64v
:
4183 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
4187 case TOKimaginary80v
:
4188 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
4193 e
= new NullExp(loc
);
4198 e
= new IntegerExp(loc
, 1, Type::tbool
);
4203 e
= new IntegerExp(loc
, 0, Type::tbool
);
4208 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
4213 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
4218 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
4225 unsigned char postfix
;
4227 // cat adjacent strings
4230 postfix
= token
.postfix
;
4234 if (token
.value
== TOKstring
)
4240 { if (token
.postfix
!= postfix
)
4241 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4242 postfix
= token
.postfix
;
4248 s2
= (unsigned char *)mem
.malloc((len
+ 1) * sizeof(unsigned char));
4249 memcpy(s2
, s
, len1
* sizeof(unsigned char));
4250 memcpy(s2
+ len1
, token
.ustring
, (len2
+ 1) * sizeof(unsigned char));
4256 e
= new StringExp(loc
, s
, len
, postfix
);
4260 CASE_BASIC_TYPES_X(t
):
4263 check(TOKdot
, t
->toChars());
4264 if (token
.value
!= TOKidentifier
)
4265 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4268 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4277 exp
= parseExpression();
4279 t
= new TypeTypeof(loc
, exp
);
4280 if (token
.value
== TOKdot
)
4282 e
= new TypeExp(loc
, t
);
4290 check(TOKlparen
, "typeid");
4291 t
= parseBasicType();
4292 t
= parseDeclarator(t
,NULL
); // ( type )
4294 e
= new TypeidExp(loc
, t
);
4300 Identifier
*ident
= NULL
;
4302 enum TOK tok
= TOKreserved
;
4303 enum TOK tok2
= TOKreserved
;
4304 Loc loc
= this->loc
;
4307 if (token
.value
== TOKlparen
)
4310 targ
= parseBasicType();
4311 targ
= parseDeclarator(targ
, &ident
);
4312 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
4316 if (tok
== TOKequal
&&
4317 (token
.value
== TOKtypedef
||
4318 token
.value
== TOKstruct
||
4319 token
.value
== TOKunion
||
4320 token
.value
== TOKclass
||
4321 token
.value
== TOKsuper
||
4322 token
.value
== TOKenum
||
4323 token
.value
== TOKinterface
||
4324 token
.value
== TOKfunction
||
4325 token
.value
== TOKdelegate
||
4326 token
.value
== TOKreturn
))
4333 tspec
= parseBasicType();
4334 tspec
= parseDeclarator(tspec
, NULL
);
4340 { error("(type identifier : specialization) expected following is");
4343 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4348 { Expression
*msg
= NULL
;
4353 e
= parseAssignExp();
4354 if (token
.value
== (dltSyntax
? TOKelse
: TOKcomma
))
4356 msg
= parseAssignExp();
4360 e
= new AssertExp(loc
, e
, msg
);
4367 check(TOKlparen
, "mixin");
4368 e
= parseAssignExp();
4370 e
= new CompileExp(loc
, e
);
4377 check(TOKlparen
, "import");
4378 e
= parseAssignExp();
4380 e
= new FileExp(loc
, e
);
4385 if (peekPastParen(&token
)->value
== TOKlcurly
)
4386 { // (arguments) { statements... }
4392 e
= parseExpression();
4393 check(loc
, TOKrparen
);
4397 { /* Parse array literals and associative array literals:
4398 * [ value, value, value ... ]
4399 * [ key:value, key:value, key:value ... ]
4401 Expressions
*values
= new Expressions();
4402 Expressions
*keys
= NULL
;
4405 if (token
.value
!= TOKrbracket
)
4409 Expression
*e
= parseAssignExp();
4410 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4413 keys
= new Expressions();
4415 e
= parseAssignExp();
4418 { error("'key:value' expected for associative array literal");
4423 if (token
.value
== TOKrbracket
)
4431 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4433 e
= new ArrayLiteralExp(loc
, values
);
4438 // { statements... }
4448 /* function type(parameters) { body }
4449 * delegate type(parameters) { body }
4451 Arguments
*arguments
;
4453 FuncLiteralDeclaration
*fd
;
4456 if (token
.value
== TOKlcurly
)
4460 arguments
= new Arguments();
4464 if (token
.value
== TOKlparen
)
4468 t
= parseBasicType();
4469 t
= parseBasicType2(t
); // function return type
4471 arguments
= parseParameters(&varargs
);
4473 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
4474 fd
= new FuncLiteralDeclaration(loc
, 0, t
, save
, NULL
);
4476 e
= new FuncExp(loc
, fd
);
4481 error("expression expected, not '%s'", token
.toChars());
4483 // Anything for e, as long as it's not NULL
4484 e
= new IntegerExp(loc
, 0, Type::tint32
);
4488 return parsePostExp(e
);
4491 Expression
*Parser::parsePostExp(Expression
*e
)
4498 switch (token
.value
)
4502 if (token
.value
== TOKidentifier
)
4503 { Identifier
*id
= token
.ident
;
4506 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4507 { // identifier!(template-argument-list)
4508 TemplateInstance
*tempinst
;
4510 tempinst
= new TemplateInstance(loc
, id
);
4512 tempinst
->tiargs
= parseTemplateArgumentList();
4513 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4516 e
= new DotIdExp(loc
, e
, id
);
4519 else if (token
.value
== TOKnew
)
4525 error("identifier expected following '.', not '%s'", token
.toChars());
4529 e
= new PostExp(TOKplusplus
, loc
, e
);
4533 e
= new PostExp(TOKminusminus
, loc
, e
);
4537 e
= new CallExp(loc
, e
, parseArguments());
4541 { // array dereferences:
4544 // array[lwr .. upr]
4550 if (token
.value
== TOKrbracket
)
4552 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4557 index
= parseAssignExp();
4558 if (token
.value
== TOKslice
)
4559 { // array[lwr .. upr]
4561 upr
= parseAssignExp();
4562 e
= new SliceExp(loc
, e
, index
, upr
);
4565 { // array[index, i2, i3, i4, ...]
4566 Expressions
*arguments
= new Expressions();
4567 arguments
->push(index
);
4568 if (token
.value
== TOKcomma
)
4574 arg
= parseAssignExp();
4575 arguments
->push(arg
);
4576 if (token
.value
== TOKrbracket
)
4581 e
= new ArrayExp(loc
, e
, arguments
);
4596 Expression
*Parser::parseUnaryExp()
4598 Loc loc
= this->loc
;
4600 switch (token
.value
)
4604 e
= parseUnaryExp();
4605 e
= new AddrExp(loc
, e
);
4610 e
= parseUnaryExp();
4611 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4616 e
= parseUnaryExp();
4617 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4622 e
= parseUnaryExp();
4623 e
= new PtrExp(loc
, e
);
4628 e
= parseUnaryExp();
4629 e
= new NegExp(loc
, e
);
4634 e
= parseUnaryExp();
4635 e
= new UAddExp(loc
, e
);
4640 e
= parseUnaryExp();
4641 e
= new NotExp(loc
, e
);
4646 e
= parseUnaryExp();
4647 e
= new ComExp(loc
, e
);
4652 e
= parseUnaryExp();
4653 e
= new DeleteExp(loc
, e
);
4657 e
= parseNewExp(NULL
);
4660 case TOKcast
: // cast(type) expression
4665 t
= parseBasicType();
4666 t
= parseDeclarator(t
,NULL
); // ( type )
4669 e
= parseUnaryExp();
4670 e
= new CastExp(loc
, e
, t
);
4680 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4682 tk
= peek(tk
); // skip over right parenthesis
4702 case TOKimaginary32v
:
4703 case TOKimaginary64v
:
4704 case TOKimaginary80v
:
4722 CASE_BASIC_TYPES
: // (type)int.size
4727 t
= parseBasicType();
4728 t
= parseDeclarator(t
,NULL
);
4732 if (token
.value
== TOKdot
)
4735 if (token
.value
!= TOKidentifier
)
4736 { error("Identifier expected following (type).");
4739 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4741 e
= parsePostExp(e
);
4745 e
= parseUnaryExp();
4746 e
= new CastExp(loc
, e
, t
);
4747 error("C style cast illegal, use %s", e
->toChars());
4754 e
= parsePrimaryExp();
4758 e
= parsePrimaryExp();
4765 Expression
*Parser::parseMulExp()
4768 Loc loc
= this->loc
;
4770 e
= parseUnaryExp();
4773 switch (token
.value
)
4775 case TOKmul
: nextToken(); e2
= parseUnaryExp(); e
= new MulExp(loc
,e
,e2
); continue;
4776 case TOKdiv
: nextToken(); e2
= parseUnaryExp(); e
= new DivExp(loc
,e
,e2
); continue;
4777 case TOKmod
: nextToken(); e2
= parseUnaryExp(); e
= new ModExp(loc
,e
,e2
); continue;
4787 Expression
*Parser::parseAddExp()
4790 Loc loc
= this->loc
;
4795 switch (token
.value
)
4797 case TOKadd
: nextToken(); e2
= parseMulExp(); e
= new AddExp(loc
,e
,e2
); continue;
4798 case TOKmin
: nextToken(); e2
= parseMulExp(); e
= new MinExp(loc
,e
,e2
); continue;
4799 case TOKtilde
: nextToken(); e2
= parseMulExp(); e
= new CatExp(loc
,e
,e2
); continue;
4809 Expression
*Parser::parseShiftExp()
4812 Loc loc
= this->loc
;
4817 switch (token
.value
)
4819 case TOKshl
: nextToken(); e2
= parseAddExp(); e
= new ShlExp(loc
,e
,e2
); continue;
4820 case TOKshr
: nextToken(); e2
= parseAddExp(); e
= new ShrExp(loc
,e
,e2
); continue;
4821 case TOKushr
: nextToken(); e2
= parseAddExp(); e
= new UshrExp(loc
,e
,e2
); continue;
4831 Expression
*Parser::parseRelExp()
4835 Loc loc
= this->loc
;
4837 e
= parseShiftExp();
4840 switch (token
.value
)
4856 e2
= parseShiftExp();
4857 e
= new CmpExp(op
, loc
, e
, e2
);
4862 e2
= parseShiftExp();
4863 e
= new InExp(loc
, e
, e2
);
4874 Expression
*Parser::parseEqualExp()
4878 Loc loc
= this->loc
;
4882 { enum TOK value
= token
.value
;
4890 e
= new EqualExp(value
, loc
, e
, e2
);
4894 error("'===' is no longer legal, use 'is' instead");
4897 case TOKnotidentity
:
4898 error("'!==' is no longer legal, use '!is' instead");
4902 value
= TOKidentity
;
4906 // Attempt to identify '!is'
4908 if (t
->value
!= TOKis
)
4911 value
= TOKnotidentity
;
4917 e
= new IdentityExp(value
, loc
, e
, e2
);
4928 Expression
*Parser::parseCmpExp()
4932 Loc loc
= this->loc
;
4934 e
= parseShiftExp();
4935 enum TOK op
= token
.value
;
4942 e2
= parseShiftExp();
4943 e
= new EqualExp(op
, loc
, e
, e2
);
4951 // Attempt to identify '!is'
4953 if (t
->value
!= TOKis
)
4956 op
= TOKnotidentity
;
4961 e2
= parseShiftExp();
4962 e
= new IdentityExp(op
, loc
, e
, e2
);
4978 e2
= parseShiftExp();
4979 e
= new CmpExp(op
, loc
, e
, e2
);
4984 e2
= parseShiftExp();
4985 e
= new InExp(loc
, e
, e2
);
4994 Expression
*Parser::parseAndExp()
4997 Loc loc
= this->loc
;
4999 if (global
.params
.Dversion
== 1)
5001 e
= parseEqualExp();
5002 while (token
.value
== TOKand
)
5005 e2
= parseEqualExp();
5006 e
= new AndExp(loc
,e
,e2
);
5013 while (token
.value
== TOKand
)
5017 e
= new AndExp(loc
,e
,e2
);
5024 Expression
*Parser::parseXorExp()
5027 Loc loc
= this->loc
;
5030 while (token
.value
== TOKxor
)
5034 e
= new XorExp(loc
, e
, e2
);
5039 Expression
*Parser::parseOrExp()
5042 Loc loc
= this->loc
;
5045 while (token
.value
== TOKor
)
5049 e
= new OrExp(loc
, e
, e2
);
5054 Expression
*Parser::parseAndAndExp()
5057 Loc loc
= this->loc
;
5060 while (token
.value
== TOKandand
)
5064 e
= new AndAndExp(loc
, e
, e2
);
5069 Expression
*Parser::parseOrOrExp()
5072 Loc loc
= this->loc
;
5074 e
= parseAndAndExp();
5075 while (token
.value
== TOKoror
)
5078 e2
= parseAndAndExp();
5079 e
= new OrOrExp(loc
, e
, e2
);
5084 Expression
*Parser::parseCondExp()
5088 Loc loc
= this->loc
;
5091 if (token
.value
== TOKquestion
)
5094 e1
= parseExpression();
5096 e2
= parseCondExp();
5097 e
= new CondExp(loc
, e
, e1
, e2
);
5102 Expression
*DltParser::parseCondExp()
5106 Loc loc
= this->loc
;
5109 if (token
.value
== TOKif
)
5112 e1
= parseExpression();
5114 e2
= parseCondExp();
5115 e
= new CondExp(loc
, e1
, e
, e2
);
5120 Expression
*Parser::parseAssignExp()
5129 switch (token
.value
)
5131 #define X(tok,ector) \
5132 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5134 X(TOKassign
, AssignExp
);
5135 X(TOKaddass
, AddAssignExp
);
5136 X(TOKminass
, MinAssignExp
);
5137 X(TOKmulass
, MulAssignExp
);
5138 X(TOKdivass
, DivAssignExp
);
5139 X(TOKmodass
, ModAssignExp
);
5140 X(TOKandass
, AndAssignExp
);
5141 X(TOKorass
, OrAssignExp
);
5142 X(TOKxorass
, XorAssignExp
);
5143 X(TOKshlass
, ShlAssignExp
);
5144 X(TOKshrass
, ShrAssignExp
);
5145 X(TOKushrass
, UshrAssignExp
);
5146 X(TOKcatass
, CatAssignExp
);
5157 Expression
*Parser::parseExpression()
5160 Loc loc
= this->loc
;
5162 //printf("Parser::parseExpression()\n");
5163 e
= parseAssignExp();
5164 while (token
.value
== TOKcomma
)
5167 e2
= parseAssignExp();
5168 e
= new CommaExp(loc
, e
, e2
);
5175 /*************************
5176 * Collect argument list.
5177 * Assume current token is '(' or '['.
5180 Expressions
*Parser::parseArguments()
5182 Expressions
*arguments
;
5186 arguments
= new Expressions();
5187 if (token
.value
== TOKlbracket
)
5188 endtok
= TOKrbracket
;
5194 if (token
.value
!= endtok
)
5198 arg
= parseAssignExp();
5199 arguments
->push(arg
);
5200 if (token
.value
== endtok
)
5210 /*******************************************
5213 Expression
*Parser::parseNewExp(Expression
*thisexp
)
5215 Expressions
*newargs
;
5216 Expressions
*arguments
= NULL
;
5218 Loc loc
= this->loc
;
5222 if (token
.value
== TOKlparen
)
5224 newargs
= parseArguments();
5227 // An anonymous nested class starts with "class"
5228 if (token
.value
== TOKclass
)
5231 if (token
.value
== TOKlparen
)
5232 arguments
= parseArguments();
5234 BaseClasses
*baseclasses
= NULL
;
5235 if (token
.value
!= TOKlcurly
)
5236 baseclasses
= parseBaseClasses();
5238 Identifier
*id
= NULL
;
5239 ClassDeclaration
*cd
= new ClassDeclaration(loc
, id
, baseclasses
);
5241 if (token
.value
!= TOKlcurly
)
5242 { error("{ members } expected for anonymous class");
5248 Array
*decl
= parseDeclDefs(0);
5249 if (token
.value
!= TOKrcurly
)
5250 error("class member expected");
5255 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
5261 t
= parseBasicType();
5262 t
= parseBasicType2(t
);
5263 if (t
->ty
== Taarray
)
5265 Type
*index
= ((TypeAArray
*)t
)->index
;
5267 Expression
*e
= index
->toExpression();
5269 { arguments
= new Expressions();
5271 t
= new TypeDArray(t
->next
);
5275 error("need size of rightmost array, not type %s", index
->toChars());
5276 return new NullExp(loc
);
5279 else if (t
->ty
== Tsarray
)
5281 TypeSArray
*tsa
= (TypeSArray
*)t
;
5282 Expression
*e
= tsa
->dim
;
5284 arguments
= new Expressions();
5286 t
= new TypeDArray(t
->next
);
5288 else if (token
.value
== TOKlparen
)
5290 arguments
= parseArguments();
5293 t
= parseBasicType();
5294 while (token
.value
== TOKmul
)
5295 { t
= new TypePointer(t
);
5298 if (token
.value
== TOKlbracket
)
5303 e
= parseAssignExp();
5304 arguments
= new Array();
5307 t
= parseDeclarator(t
, NULL
);
5308 t
= new TypeDArray(t
);
5310 else if (token
.value
== TOKlparen
)
5311 arguments
= parseArguments();
5313 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5317 /**********************************************
5320 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5322 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5326 /********************************* ***************************/