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
);
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
);
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 t
= new TypeAArray(t
, index
);
1777 //printf("it's [expression]\n");
1779 Expression
*e
= parseExpression(); // [ expression ]
1780 if (token
.value
== TOKslice
)
1784 e2
= parseExpression(); // [ exp .. exp ]
1785 t
= new TypeSlice(t
, e
, e2
);
1788 t
= new TypeSArray(t
,e
);
1794 // Handle []. Make sure things like
1796 // is (array[3] of array[1] of int)
1798 while (token
.value
== TOKlbracket
)
1801 if (token
.value
== TOKrbracket
)
1803 ta
= new TypeDArray(t
); // []
1806 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1807 { // It's an associative array declaration
1810 //printf("it's an associative array\n");
1811 index
= parseBasicType();
1812 index
= parseDeclarator(index
, NULL
); // [ type ]
1814 ta
= new TypeAArray(t
, index
);
1818 //printf("it's [expression]\n");
1819 Expression
*e
= parseExpression(); // [ expression ]
1820 ta
= new TypeSArray(t
,e
);
1824 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1834 { // Handle delegate declaration:
1835 // t delegate(parameter list)
1836 // t function(parameter list)
1837 Arguments
*arguments
;
1839 enum TOK save
= token
.value
;
1842 arguments
= parseParameters(&varargs
);
1843 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1844 if (save
== TOKdelegate
)
1845 t
= new TypeDelegate(t
);
1847 t
= new TypePointer(t
); // pointer to function
1858 // fall-through to default
1872 // TypeMaybe will unwrap itself later if this isn't a nullable type
1881 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1885 //printf("parseDeclarator(tpl = %p)\n", tpl);
1886 t
= parseBasicType2(t
);
1888 switch (token
.value
)
1893 *pident
= token
.ident
;
1895 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1902 ts
= parseDeclarator(t
, pident
);
1913 switch (token
.value
)
1917 { // This is the old C-style post [] syntax.
1919 if (token
.value
== TOKrbracket
)
1921 ta
= new TypeDArray(t
); // []
1924 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1925 { // It's an associative array declaration
1928 //printf("it's an associative array\n");
1929 index
= parseBasicType();
1930 index
= parseDeclarator(index
, NULL
); // [ type ]
1932 ta
= new TypeAArray(t
, index
);
1936 //printf("it's [expression]\n");
1937 Expression
*e
= parseExpression(); // [ expression ]
1938 ta
= new TypeSArray(t
, e
);
1942 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1949 { Arguments
*arguments
;
1954 /* Look ahead to see if this is (...)(...),
1955 * i.e. a function template declaration
1957 if (peekPastParen(&token
)->value
== TOKlparen
)
1958 { // It's a function template declaration
1959 //printf("function template declaration\n");
1961 // Gather template parameter list
1962 *tpl
= parseTemplateParameterList();
1966 arguments
= parseParameters(&varargs
);
1967 Type
*ta
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1969 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1981 /**********************************
1982 * Return array of Declaration *'s.
1985 Array
*Parser::parseDeclarations()
1987 enum STC storage_class
;
1995 unsigned char *comment
= token
.blockComment
;
1996 enum LINK link
= linkage
;
1998 //printf("parseDeclarations()\n");
1999 switch (token
.value
)
2012 storage_class
= STCundefined
;
2015 switch (token
.value
)
2017 case TOKconst
: stc
= STCconst
; goto L1
;
2018 case TOKstatic
: stc
= STCstatic
; goto L1
;
2019 case TOKfinal
: stc
= STCfinal
; goto L1
;
2020 case TOKauto
: stc
= STCauto
; goto L1
;
2021 case TOKscope
: stc
= STCscope
; goto L1
;
2022 case TOKoverride
: stc
= STCoverride
; goto L1
;
2023 case TOKabstract
: stc
= STCabstract
; goto L1
;
2024 case TOKsynchronized
: stc
= STCsynchronized
; goto L1
;
2025 case TOKdeprecated
: stc
= STCdeprecated
; goto L1
;
2027 if (storage_class
& stc
)
2028 error("redundant storage class '%s'", token
.toChars());
2029 storage_class
= (STC
) (storage_class
| stc
);
2034 if (peek(&token
)->value
!= TOKlparen
)
2039 link
= parseLinkage();
2050 /* Look for auto initializers:
2051 * storage_class identifier = initializer;
2053 while (storage_class
&&
2054 token
.value
== TOKidentifier
&&
2055 peek(&token
)->value
== TOKassign
)
2057 ident
= token
.ident
;
2060 Initializer
*init
= parseInitializer();
2061 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
2062 v
->storage_class
= storage_class
;
2064 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
2067 addComment(v
, comment
);
2069 else if (token
.value
== TOKcomma
)
2072 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
2074 error("Identifier expected following comma");
2080 error("%s expected following auto declaration, not '%s'", endToken(), token
.toChars());
2084 if (token
.value
== TOKclass
)
2085 { AggregateDeclaration
*s
;
2087 s
= (AggregateDeclaration
*)parseAggregate();
2088 s
->storage_class
|= storage_class
;
2090 addComment(s
, comment
);
2094 ts
= parseBasicType();
2095 ts
= parseBasicType2(ts
);
2100 Loc loc
= this->loc
;
2101 TemplateParameters
*tpl
= NULL
;
2104 t
= parseDeclarator(ts
, &ident
, &tpl
);
2108 else if (t
!= tfirst
)
2109 error("multiple declarations must have the same type, not %s and %s",
2110 tfirst
->toChars(), t
->toChars());
2112 error("no identifier for declarator %s", t
->toChars());
2114 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2119 if (token
.value
== TOKassign
)
2122 init
= parseInitializer();
2124 if (tok
== TOKtypedef
)
2125 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2128 error("alias cannot have initializer");
2129 v
= new AliasDeclaration(loc
, ident
, t
);
2131 v
->storage_class
= storage_class
;
2132 if (link
== linkage
)
2136 Array
*ax
= new Array();
2138 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2141 switch (token
.value
)
2142 { case TOKsemicolon
:
2145 addComment(v
, comment
);
2150 addComment(v
, comment
);
2154 error("%s expected to close %s declaration", endToken(), Token::toChars(tok
));
2158 else if (t
->ty
== Tfunction
)
2159 { FuncDeclaration
*f
;
2162 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2163 addComment(f
, comment
);
2165 addComment(f
, NULL
);
2166 if (link
== linkage
)
2172 Array
*ax
= new Array();
2174 s
= new LinkDeclaration(link
, ax
);
2176 if (tpl
) // it's a function template
2178 TemplateDeclaration
*tempdecl
;
2180 // Wrap a template around the aggregate declaration
2181 decldefs
= new Array();
2183 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
);
2186 addComment(s
, comment
);
2190 { VarDeclaration
*v
;
2194 if (token
.value
== TOKassign
)
2197 init
= parseInitializer();
2199 v
= new VarDeclaration(loc
, t
, ident
, init
);
2200 v
->storage_class
= storage_class
;
2201 if (link
== linkage
)
2205 Array
*ax
= new Array();
2207 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2210 switch (token
.value
)
2211 { case TOKsemicolon
:
2214 addComment(v
, comment
);
2219 addComment(v
, comment
);
2223 error("%s expected, not '%s'", endToken(), token
.toChars());
2232 /*****************************************
2233 * Parse contracts following function declaration.
2236 void Parser::parseContracts(FuncDeclaration
*f
)
2239 enum LINK linksave
= linkage
;
2241 // The following is irrelevant, as it is overridden by sc->linkage in
2242 // TypeFunction::semantic
2243 linkage
= LINKd
; // nested functions have D linkage
2245 switch (token
.value
)
2249 if (token
.value
!= startBlockTok
)
2250 error("use %s to start a new block", Token::toChars(startBlockTok
));
2251 if (f
->frequire
|| f
->fensure
)
2252 error("missing body { ... } after in or out");
2253 f
->fbody
= parseStatement(PSsemi
| PScolon
);
2259 f
->fbody
= parseStatement(PScurly
);
2265 error("unexpected semi-colon after function declaration");
2268 if (f
->frequire
|| f
->fensure
)
2269 error("missing body { ... } after in or out");
2273 #if 0 // Do we want this for function declarations, so we can do:
2274 // int x, y, foo(), z;
2280 #if 0 // Dumped feature
2283 f
->fthrows
= new Array();
2288 tb
= parseBasicType();
2289 f
->fthrows
->push(tb
);
2290 if (token
.value
== TOKcomma
)
2303 error("redundant 'in' statement");
2304 f
->frequire
= parseStatement(PScurly
| PSscope
);
2308 // parse: out (identifier) { statement }
2310 if (token
.value
!= startBlockTok
)
2313 if (token
.value
!= TOKidentifier
)
2314 error("(identifier) following 'out' expected, not %s", token
.toChars());
2315 f
->outId
= token
.ident
;
2320 error("redundant 'out' statement");
2321 f
->fensure
= parseStatement(PScurly
| PSscope
);
2325 error("%s expected following function declaration", endToken());
2331 /*****************************************
2334 Initializer
*Parser::parseInitializer()
2336 StructInitializer
*is
;
2337 ArrayInitializer
*ia
;
2343 Loc loc
= this->loc
;
2347 switch (token
.value
)
2350 /* Scan ahead to see if it is a struct initializer or
2351 * a function literal.
2352 * If it contains a ';', it is a function literal.
2353 * Treat { } as a struct initializer.
2356 for (t
= peek(&token
); 1; t
= peek(t
))
2382 is
= new StructInitializer(loc
);
2387 switch (token
.value
)
2391 error("comma expected separating field initializers");
2393 if (t
->value
== TOKcolon
)
2397 nextToken(); // skip over ':'
2402 value
= parseInitializer();
2403 is
->addInit(id
, value
);
2412 case TOKrcurly
: // allow trailing comma's
2417 error("found EOF instead of initializer");
2421 value
= parseInitializer();
2422 is
->addInit(NULL
, value
);
2425 //error("found '%s' instead of field initializer", token.toChars());
2433 ia
= new ArrayInitializer(loc
);
2438 switch (token
.value
)
2442 { error("comma expected separating array initializers, not %s", token
.toChars());
2446 e
= parseAssignExp();
2449 if (token
.value
== TOKcolon
)
2452 value
= parseInitializer();
2455 { value
= new ExpInitializer(e
->loc
, e
);
2458 ia
->addInit(e
, value
);
2465 error("comma expected separating array initializers, not %s", token
.toChars());
2466 value
= parseInitializer();
2467 ia
->addInit(NULL
, value
);
2476 case TOKrbracket
: // allow trailing comma's
2481 error("found '%s' instead of array initializer", token
.toChars());
2490 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
|| t
->value
== TOKendline
)
2493 return new VoidInitializer(loc
);
2499 e
= parseAssignExp();
2500 ie
= new ExpInitializer(loc
, e
);
2505 Statement
*Parser::logStatement(int level
) {
2507 if (token
.value
!= TOKlparen
)
2508 error(loc
, "found '%s' when expecting '('", token
.toChars());
2509 return new LogStatement(loc
, level
, parseArguments());
2512 /*****************************************
2517 Statement
*DltParser::parseStatement(int flags
)
2520 if (flags
& (PScolon
| PSscope
))
2522 return Parser::parseStatement(flags
);
2525 Statement
*Parser::parseStatement(int flags
)
2528 Condition
*condition
;
2530 Statement
*elsebody
;
2531 Loc loc
= this->loc
;
2533 //printf("parseStatement()\n");
2535 if ((flags
& PScurly
) && token
.value
!= startBlockTok
)
2536 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2538 int tok
= token
.value
;
2540 switch (token
.value
)
2545 // Need to look ahead to see if it is a declaration, label, or expression
2547 if (t
->value
== TOKcolon
)
2551 ident
= token
.ident
;
2554 s
= parseStatement(PSsemi
);
2555 s
= new LabelStatement(loc
, ident
, s
);
2559 // fallthrough to TOKdot
2562 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2578 case TOKimaginary32v
:
2579 case TOKimaginary64v
:
2580 case TOKimaginary80v
:
2605 exp
= parseExpression();
2607 check(TOKsemicolon
, "statement");
2608 s
= new ExpStatement(loc
, exp
);
2613 { // Look ahead to see if it's static assert() or static if()
2617 if (t
->value
== TOKassert
)
2620 s
= new StaticAssertStatement(parseStaticAssert());
2623 if (t
->value
== TOKif
)
2626 condition
= parseStaticIfCondition();
2644 a
= parseDeclarations();
2647 Statements
*as
= new Statements();
2648 as
->reserve(a
->dim
);
2649 for (int i
= 0; i
< a
->dim
; i
++)
2651 Dsymbol
*d
= (Dsymbol
*)a
->data
[i
];
2652 s
= new DeclarationStatement(loc
, d
);
2655 s
= new CompoundStatement(loc
, as
);
2657 else if (a
->dim
== 1)
2659 Dsymbol
*d
= (Dsymbol
*)a
->data
[0];
2660 s
= new DeclarationStatement(loc
, d
);
2664 if (flags
& PSscope
)
2665 s
= new ScopeStatement(loc
, s
);
2675 d
= parseAggregate();
2676 s
= new DeclarationStatement(loc
, d
);
2684 s
= new DeclarationStatement(loc
, d
);
2690 if (t
->value
== TOKlparen
)
2693 check(TOKlparen
, "mixin");
2694 Expression
*e
= parseAssignExp();
2696 check(TOKsemicolon
);
2697 s
= new CompileStatement(loc
, e
);
2700 Dsymbol
*d
= parseMixin();
2701 s
= new DeclarationStatement(loc
, d
);
2707 { Statements
*statements
;
2709 if (token
.value
!= startBlockTok
)
2710 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2714 statements
= new Statements();
2715 while (token
.value
!= TOKrcurly
)
2717 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2721 s
= new CompoundStatement(loc
, statements
);
2722 if (flags
& (PSscope
| PScurlyscope
))
2723 s
= new ScopeStatement(loc
, s
);
2728 case TOKlog_error
: s
= logStatement(LogStatement::Error
); break;
2729 case TOKlog_warning
: s
= logStatement(LogStatement::Warn
); break;
2730 case TOKlog_info
: s
= logStatement(LogStatement::Info
); break;
2731 case TOKlog_trace
: s
= logStatement(LogStatement::Trace
); break;
2734 { Expression
*condition
;
2739 condition
= parseExpression();
2741 body
= parseStatement(PSscope
);
2742 s
= new WhileStatement(loc
, condition
, body
);
2747 if (!(flags
& PSsemi
))
2748 error("use '{ }' for an empty statement, not a ';'");
2750 s
= new ExpStatement(loc
, NULL
);
2755 Expression
*condition
;
2758 body
= parseStatement(PSscope
);
2761 condition
= parseExpression();
2763 s
= new DoStatement(loc
, body
, condition
);
2770 Expression
*condition
;
2771 Expression
*increment
;
2776 if (token
.value
== TOKlparen
) {
2777 /* for (init; cond; incr): ... */
2779 if (token
.value
== TOKsemicolon
)
2784 { init
= parseStatement(0);
2786 if (token
.value
== TOKsemicolon
)
2793 condition
= parseExpression();
2794 check(TOKsemicolon
, "for condition");
2796 if (token
.value
== TOKrparen
)
2801 { increment
= parseExpression();
2804 body
= parseStatement(PSscope
);
2805 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2807 s
= new ScopeStatement(loc
, s
);
2808 } else if (dltSyntax
)
2815 case TOKforeach_reverse
:
2817 /* for var in seq: ... */
2818 /* for index, var in seq: ... */
2819 Arguments
*arguments
;
2824 enum TOK op
= (TOK
) tok
;
2831 TOK inTok
= dltSyntax
? TOKin
: TOKsemicolon
;
2833 arguments
= new Arguments();
2838 Identifier
*ai
= NULL
;
2840 unsigned storageClass
;
2843 storageClass
= STCin
;
2844 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2845 { storageClass
= STCref
;
2848 if (token
.value
== TOKidentifier
)
2850 Token
*t
= peek(&token
);
2851 if (t
->value
== TOKcomma
|| t
->value
== inTok
)
2853 at
= NULL
; // infer argument type
2858 tb
= parseBasicType();
2859 at
= parseDeclarator(tb
, &ai
);
2861 error("no identifier for declarator %s", at
->toChars());
2863 a
= new Argument(storageClass
, at
, ai
, NULL
);
2865 if (token
.value
== TOKcomma
)
2874 aggr
= parseExpression();
2878 if (token
.value
== TOKreversed
) {
2879 op
= TOKforeach_reverse
;
2886 body
= parseStatement(PScolon
);
2887 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2892 { Argument
*arg
= NULL
;
2893 Expression
*condition
;
2895 Statement
*elsebody
;
2900 if (token
.value
== TOKauto
)
2903 if (token
.value
== TOKidentifier
)
2905 Token
*t
= peek(&token
);
2906 if (t
->value
== TOKassign
)
2908 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2913 { error("= expected following auto identifier");
2918 { error("identifier expected following auto");
2922 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
2928 tb
= parseBasicType();
2929 at
= parseDeclarator(tb
, &ai
);
2931 arg
= new Argument(STCin
, at
, ai
, NULL
);
2934 // Check for " ident;"
2935 else if (token
.value
== TOKidentifier
&& !dltSyntax
)
2937 Token
*t
= peek(&token
);
2938 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2940 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2943 if (1 || !global
.params
.useDeprecated
)
2944 error("if (v; e) is deprecated, use if (auto v = e)");
2948 condition
= parseExpression();
2950 ifbody
= parseStatement(PSscope
);
2951 if (token
.value
== TOKelse
)
2956 if (token
.value
== TOKcolon
) {
2957 elsebody
= parseStatement(PSscope
);
2958 } else if (token
.value
== TOKif
) {
2959 elsebody
= parseStatement(0);
2961 error("Expected 'else:' or 'else if', not 'else %s'", token
.toChars());
2966 elsebody
= parseStatement(PSscope
);
2970 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
2975 if (peek(&token
)->value
!= TOKlparen
)
2976 goto Ldeclaration
; // scope used as storage class
2979 if (token
.value
!= TOKidentifier
)
2980 { error("scope identifier expected");
2984 { TOK t
= TOKon_scope_exit
;
2985 Identifier
*id
= token
.ident
;
2988 t
= TOKon_scope_exit
;
2989 else if (id
== Id::failure
)
2990 t
= TOKon_scope_failure
;
2991 else if (id
== Id::success
)
2992 t
= TOKon_scope_success
;
2994 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
2997 Statement
*st
= parseStatement(PScolon
| PScurlyscope
);
2998 s
= new OnScopeStatement(loc
, t
, st
);
3004 condition
= parseDebugCondition();
3009 condition
= parseVersionCondition();
3013 if (dltSyntax
&& token
.value
!= TOKcolon
)
3014 error("expected colon after condition, not '%s'", token
.toChars());
3015 ifbody
= parseStatement(PScolon
/*PSsemi*/);
3017 if (token
.value
== TOKelse
)
3020 elsebody
= parseStatement(PScolon
/*PSsemi*/);
3022 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
3026 { Identifier
*ident
;
3027 Expressions
*args
= NULL
;
3032 if (token
.value
!= TOKidentifier
)
3033 { error("pragma(identifier expected");
3036 ident
= token
.ident
;
3038 if (token
.value
== TOKcomma
)
3039 args
= parseArguments(); // pragma(identifier, args...);
3041 check(TOKrparen
); // pragma(identifier);
3042 if (token
.value
== TOKsemicolon
)
3047 body
= parseStatement(PSsemi
| PScolon
);
3048 s
= new PragmaStatement(loc
, ident
, args
, body
);
3053 { Expression
*condition
;
3058 condition
= parseExpression();
3060 body
= parseStatement(PSscope
| PScolon
);
3061 s
= new SwitchStatement(loc
, condition
, body
);
3067 Statements
*statements
;
3068 Array cases
; // array of Expression's
3073 exp
= parseAssignExp();
3075 if (token
.value
!= TOKcomma
)
3081 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3087 statements
= new Statements();
3088 while (token
.value
!= TOKcase
&&
3089 token
.value
!= TOKdefault
&&
3090 token
.value
!= TOKrcurly
)
3092 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3094 s
= new CompoundStatement(loc
, statements
);
3097 s
= new ScopeStatement(loc
, s
);
3099 // Keep cases in order by building the case statements backwards
3100 for (int i
= cases
.dim
; i
; i
--)
3102 exp
= (Expression
*)cases
.data
[i
- 1];
3103 s
= new CaseStatement(loc
, exp
, s
);
3110 Statements
*statements
;
3116 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3122 statements
= new Statements();
3123 while (token
.value
!= TOKcase
&&
3124 token
.value
!= TOKdefault
&&
3125 token
.value
!= TOKrcurly
)
3127 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3129 s
= new CompoundStatement(loc
, statements
);
3132 s
= new ScopeStatement(loc
, s
);
3133 s
= new DefaultStatement(loc
, s
);
3141 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
3144 exp
= parseExpression();
3147 check(TOKsemicolon
, "return statement");
3148 else if (token
.value
!= TOKendline
) {
3149 error("Expected end-of-line after return statement, but found '%s'", token
.toChars());
3152 s
= new ReturnStatement(loc
, exp
);
3157 { Identifier
*ident
;
3160 if (token
.value
== TOKidentifier
)
3161 { ident
= token
.ident
;
3166 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3167 error("expected %s after break, not '%s'", endToken(), token
.toChars());
3171 s
= new BreakStatement(loc
, ident
);
3176 { Identifier
*ident
;
3179 if (token
.value
== TOKidentifier
)
3180 { ident
= token
.ident
;
3185 check(TOKsemicolon
, "continue statement");
3186 s
= new ContinueStatement(loc
, ident
);
3191 { Identifier
*ident
;
3194 if (token
.value
== TOKdefault
)
3197 s
= new GotoDefaultStatement(loc
);
3199 else if (token
.value
== TOKcase
)
3201 Expression
*exp
= NULL
;
3204 if (token
.value
!= TOKsemicolon
)
3205 exp
= parseExpression();
3206 s
= new GotoCaseStatement(loc
, exp
);
3210 if (token
.value
!= TOKidentifier
)
3211 { error("Identifier expected following goto");
3215 { ident
= token
.ident
;
3218 s
= new GotoStatement(loc
, ident
);
3220 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3221 error("expected %s after goto statement, not '%s'", endToken(), token
.toChars());
3226 case TOKsynchronized
:
3231 if (token
.value
== TOKlparen
)
3234 exp
= parseExpression();
3239 body
= parseStatement(PSscope
);
3240 s
= new SynchronizedStatement(loc
, exp
, body
);
3250 exp
= parseExpression();
3252 body
= parseStatement(PSscope
);
3253 s
= new WithStatement(loc
, exp
, body
);
3259 Array
*catches
= NULL
;
3260 Statement
*finalbody
= NULL
;
3263 body
= parseStatement(PSscope
);
3264 while (token
.value
== TOKcatch
)
3270 Loc loc
= this->loc
;
3273 if (token
.value
== startBlockTok
)
3281 t
= parseBasicType();
3283 t
= parseDeclarator(t
, &id
);
3286 handler
= parseStatement(PScolon
);
3287 c
= new Catch(loc
, t
, id
, handler
);
3289 catches
= new Array();
3293 if (token
.value
== TOKfinally
)
3295 finalbody
= parseStatement(PScolon
);
3299 if (!catches
&& !finalbody
)
3300 error("catch or finally expected following try");
3303 s
= new TryCatchStatement(loc
, body
, catches
);
3305 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3314 exp
= parseExpression();
3315 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3316 error("%s expected after throw statement, not '%s'", endToken(), token
.toChars());
3320 s
= new ThrowStatement(loc
, exp
);
3326 s
= parseStatement(PSsemi
| PScurlyscope
);
3327 s
= new VolatileStatement(loc
, s
);
3331 { Statements
*statements
;
3337 // Parse the asm block into a sequence of AsmStatements,
3338 // each AsmStatement is one instruction.
3339 // Separate out labels.
3340 // Defer parsing of AsmStatements until semantic processing.
3343 #if GDC_EXTENDED_ASM_SYNTAX
3344 if (token
.value
== TOKlparen
)
3351 check(startBlockTok
);
3353 ptoklist
= &toklist
;
3355 statements
= new Statements();
3358 switch (token
.value
)
3363 // Look ahead to see if it is a label
3365 if (t
->value
== TOKcolon
)
3367 label
= token
.ident
;
3368 labelloc
= this->loc
;
3377 if (toklist
|| label
)
3379 error("asm statements must end in ';'");
3386 if (toklist
|| label
)
3387 { // Create AsmStatement from list of tokens we've saved
3388 s
= new AsmStatement(this->loc
, toklist
);
3390 ptoklist
= &toklist
;
3392 { s
= new LabelStatement(labelloc
, label
, s
);
3395 statements
->push(s
);
3402 error("matching '}' expected, not end of file");
3407 // If the first token is a string or '(', parse as extended asm.
3411 statements
->push(s
);
3414 // ...else, drop through.
3418 *ptoklist
= new Token();
3419 memcpy(*ptoklist
, &token
, sizeof(Token
));
3420 ptoklist
= &(*ptoklist
)->next
;
3428 s
= new CompoundStatement(loc
, statements
);
3434 error("found '%s' instead of statement", token
.toChars());
3438 while (token
.value
!= TOKrcurly
&&
3439 token
.value
!= TOKsemicolon
&&
3440 token
.value
!= TOKeof
)
3442 if (token
.value
== TOKsemicolon
)
3451 Statement
*Parser::parseExtAsm(int expect_rparen
)
3453 Expression
* insnTemplate
;
3454 Expressions
* args
= NULL
;
3455 Array
* argNames
= NULL
;
3456 Expressions
* argConstraints
= NULL
;
3457 int nOutputArgs
= 0;
3458 Expressions
* clobbers
= NULL
;
3459 bool isInputPhase
= false; // Output operands first, then input.
3461 insnTemplate
= parseExpression();
3462 if (token
.value
== TOKrparen
|| token
.value
== TOKsemicolon
)
3466 Expression
* arg
= NULL
;
3467 Identifier
* name
= NULL
;
3468 Expression
* constraint
= NULL
;
3470 switch (token
.value
)
3481 error("unterminated statement");
3485 if (token
.value
== TOKidentifier
)
3491 error("expected identifier after '['");
3495 constraint
= parsePrimaryExp();
3496 if (constraint
->op
!= TOKstring
)
3497 error("expected constant string constraint for operand");
3498 arg
= parseAssignExp();
3501 args
= new Expressions
;
3502 argConstraints
= new Expressions
;
3503 argNames
= new Array
;
3506 argNames
->push(name
);
3507 argConstraints
->push(constraint
);
3511 if (token
.value
== TOKcomma
)
3518 isInputPhase
= true;
3525 Expression
* clobber
;
3527 switch (token
.value
)
3534 error("unterminated statement");
3537 clobber
= parseAssignExp();
3538 if (clobber
->op
!= TOKstring
)
3539 error("expected constant string constraint for clobber name");
3541 clobbers
= new Expressions
;
3542 clobbers
->push(clobber
);
3544 if (token
.value
== TOKcomma
)
3553 check(TOKsemicolon
);
3555 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3556 argConstraints
, nOutputArgs
, clobbers
);
3559 void Parser::optionalEndline() {
3560 while (token
.value
== TOKendline
) {
3565 void Parser::check(enum TOK value
)
3570 void Parser::check(Loc loc
, enum TOK value
)
3572 if (token
.value
!= value
)
3573 error(loc
, "found '%s' when expecting '%s'", token
.toChars(), Token::toChars(value
));
3577 void Parser::check(enum TOK value
, char *string
)
3579 if (token
.value
!= value
)
3580 error("found '%s' when expecting '%s' following '%s'",
3581 token
.toChars(), Token::toChars(value
), string
);
3585 char *Parser::endToken()
3590 char *DltParser::endToken()
3595 void Parser::checkLParen() { check(TOKlparen
); }
3596 void Parser::checkRParen() { check(TOKrparen
); }
3598 void DltParser::checkLParen() { }
3599 void DltParser::checkRParen() { }
3601 /************************************
3602 * Determine if the scanner is sitting on the start of a declaration.
3604 * needId 0 no identifier
3605 * 1 identifier optional
3606 * 2 must have identifier
3609 int Parser::isDeclaration(Token
*t
, int needId
, enum TOK endtok
, Token
**pt
)
3613 if (!isBasicType(&t
))
3615 if (!isDeclarator(&t
, &haveId
, endtok
))
3618 (needId
== 0 && !haveId
) ||
3619 (needId
== 2 && haveId
))
3628 int Parser::isBasicType(Token
**pt
)
3630 // This code parallels parseBasicType()
3643 if (t
->value
== TOKnot
)
3653 if (t
->value
== TOKdot
)
3657 if (t
->value
!= TOKidentifier
)
3660 if (t
->value
!= TOKnot
)
3664 if (t
->value
!= TOKlparen
)
3666 if (!skipParens(t
, &t
))
3678 /* typeof(exp).identifier...
3681 if (t
->value
!= TOKlparen
)
3683 if (!skipParens(t
, &t
))
3697 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3698 { // This code parallels parseDeclarator()
3702 //printf("Parser::isDeclarator()\n");
3704 if (t
->value
== TOKassign
)
3720 if (t
->value
== TOKrbracket
)
3724 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3725 { // It's an associative array declaration
3731 // [ expression .. expression ]
3732 if (!isExpression(&t
))
3734 if (t
->value
== TOKslice
)
3736 if (!isExpression(&t
))
3739 if (t
->value
!= TOKrbracket
)
3755 if (t
->value
== TOKrparen
)
3756 return FALSE
; // () is not a declarator
3758 /* Regard ( identifier ) as not a declarator
3759 * BUG: what about ( *identifier ) in
3761 * where f is a class instance with overloaded () ?
3762 * Should we just disallow C-style function pointer declarations?
3764 if (t
->value
== TOKidentifier
)
3765 { Token
*t2
= peek(t
);
3766 if (t2
->value
== TOKrparen
)
3771 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3780 if (!isParameters(&t
))
3795 if (t
->value
== TOKrbracket
)
3799 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3800 { // It's an associative array declaration
3806 if (!isExpression(&t
))
3808 if (t
->value
!= TOKrbracket
)
3817 if (!isParameters(&t
))
3821 // Valid tokens that follow a declaration
3830 // The !parens is to disallow unnecessary parentheses
3831 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3844 int Parser::isParameters(Token
**pt
)
3845 { // This code parallels parseParameters()
3849 //printf("isParameters()\n");
3850 if (t
->value
!= TOKlparen
)
3872 if (!isBasicType(&t
))
3875 if (t
->value
!= TOKdotdotdot
&&
3876 !isDeclarator(&t
, &tmp
, TOKreserved
))
3878 if (t
->value
== TOKassign
)
3880 if (!isExpression(&t
))
3883 if (t
->value
== TOKdotdotdot
)
3888 if (t
->value
== TOKcomma
)
3896 if (t
->value
!= TOKrparen
)
3903 int Parser::isExpression(Token
**pt
)
3905 // This is supposed to determine if something is an expression.
3906 // What it actually does is scan until a closing right bracket
3913 for (;; t
= peek(t
))
3931 if (brnest
|| panest
)
3958 /**********************************************
3960 * instance foo.bar(parameters...)
3962 * if (pt), *pt is set to the token following the closing )
3964 * 1 it's valid instance syntax
3965 * 0 invalid instance syntax
3968 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
3971 if (t
->value
!= TOKdot
)
3973 if (t
->value
!= TOKidentifier
)
3977 while (t
->value
== TOKdot
)
3980 if (t
->value
!= TOKidentifier
)
3984 if (t
->value
!= TOKlparen
)
3987 // Skip over the template arguments
3996 if (!skipParens(t
, &t
))
4012 if (t
->value
!= TOKcomma
)
4015 if (t
->value
!= TOKrparen
)
4026 /*******************************************
4027 * Skip parens, brackets.
4031 * *pt is set to closing token, which is ')' on success
4034 * 0 some parsing error
4037 int Parser::skipParens(Token
*t
, Token
**pt
)
4076 /********************************* Expression Parser ***************************/
4078 Expression
*Parser::parsePrimaryExp()
4083 Loc loc
= this->loc
;
4085 switch (token
.value
)
4090 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4091 { // identifier!(template-argument-list)
4092 TemplateInstance
*tempinst
;
4094 tempinst
= new TemplateInstance(loc
, id
);
4096 tempinst
->tiargs
= parseTemplateArgumentList();
4097 e
= new ScopeExp(loc
, tempinst
);
4100 e
= new IdentifierExp(loc
, id
);
4105 error("'$' is valid only inside [] of index or slice");
4106 e
= new DollarExp(loc
);
4111 // Signal global scope '.' operator with "" identifier
4112 e
= new IdentifierExp(loc
, Id::empty
);
4116 e
= new ThisExp(loc
);
4121 e
= new SuperExp(loc
);
4126 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
4131 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
4136 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
4141 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
4146 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
4151 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
4156 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
4160 case TOKimaginary32v
:
4161 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
4165 case TOKimaginary64v
:
4166 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
4170 case TOKimaginary80v
:
4171 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
4176 e
= new NullExp(loc
);
4181 e
= new IntegerExp(loc
, 1, Type::tbool
);
4186 e
= new IntegerExp(loc
, 0, Type::tbool
);
4191 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
4196 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
4201 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
4208 unsigned char postfix
;
4210 // cat adjacent strings
4213 postfix
= token
.postfix
;
4217 if (token
.value
== TOKstring
)
4223 { if (token
.postfix
!= postfix
)
4224 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4225 postfix
= token
.postfix
;
4231 s2
= (unsigned char *)mem
.malloc((len
+ 1) * sizeof(unsigned char));
4232 memcpy(s2
, s
, len1
* sizeof(unsigned char));
4233 memcpy(s2
+ len1
, token
.ustring
, (len2
+ 1) * sizeof(unsigned char));
4239 e
= new StringExp(loc
, s
, len
, postfix
);
4243 CASE_BASIC_TYPES_X(t
):
4246 check(TOKdot
, t
->toChars());
4247 if (token
.value
!= TOKidentifier
)
4248 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4251 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4260 exp
= parseExpression();
4262 t
= new TypeTypeof(loc
, exp
);
4263 if (token
.value
== TOKdot
)
4265 e
= new TypeExp(loc
, t
);
4273 check(TOKlparen
, "typeid");
4274 t
= parseBasicType();
4275 t
= parseDeclarator(t
,NULL
); // ( type )
4277 e
= new TypeidExp(loc
, t
);
4283 Identifier
*ident
= NULL
;
4285 enum TOK tok
= TOKreserved
;
4286 enum TOK tok2
= TOKreserved
;
4287 Loc loc
= this->loc
;
4290 if (token
.value
== TOKlparen
)
4293 targ
= parseBasicType();
4294 targ
= parseDeclarator(targ
, &ident
);
4295 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
4299 if (tok
== TOKequal
&&
4300 (token
.value
== TOKtypedef
||
4301 token
.value
== TOKstruct
||
4302 token
.value
== TOKunion
||
4303 token
.value
== TOKclass
||
4304 token
.value
== TOKsuper
||
4305 token
.value
== TOKenum
||
4306 token
.value
== TOKinterface
||
4307 token
.value
== TOKfunction
||
4308 token
.value
== TOKdelegate
||
4309 token
.value
== TOKreturn
))
4316 tspec
= parseBasicType();
4317 tspec
= parseDeclarator(tspec
, NULL
);
4323 { error("(type identifier : specialization) expected following is");
4326 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4331 { Expression
*msg
= NULL
;
4336 e
= parseAssignExp();
4337 if (token
.value
== (dltSyntax
? TOKelse
: TOKcomma
))
4339 msg
= parseAssignExp();
4343 e
= new AssertExp(loc
, e
, msg
);
4350 check(TOKlparen
, "mixin");
4351 e
= parseAssignExp();
4353 e
= new CompileExp(loc
, e
);
4360 check(TOKlparen
, "import");
4361 e
= parseAssignExp();
4363 e
= new FileExp(loc
, e
);
4368 if (peekPastParen(&token
)->value
== TOKlcurly
)
4369 { // (arguments) { statements... }
4375 e
= parseExpression();
4376 check(loc
, TOKrparen
);
4380 { /* Parse array literals and associative array literals:
4381 * [ value, value, value ... ]
4382 * [ key:value, key:value, key:value ... ]
4384 Expressions
*values
= new Expressions();
4385 Expressions
*keys
= NULL
;
4388 if (token
.value
!= TOKrbracket
)
4392 Expression
*e
= parseAssignExp();
4393 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4396 keys
= new Expressions();
4398 e
= parseAssignExp();
4401 { error("'key:value' expected for associative array literal");
4406 if (token
.value
== TOKrbracket
)
4414 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4416 e
= new ArrayLiteralExp(loc
, values
);
4421 // { statements... }
4431 /* function type(parameters) { body }
4432 * delegate type(parameters) { body }
4434 Arguments
*arguments
;
4436 FuncLiteralDeclaration
*fd
;
4439 if (token
.value
== TOKlcurly
)
4443 arguments
= new Arguments();
4447 if (token
.value
== TOKlparen
)
4451 t
= parseBasicType();
4452 t
= parseBasicType2(t
); // function return type
4454 arguments
= parseParameters(&varargs
);
4456 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
4457 fd
= new FuncLiteralDeclaration(loc
, 0, t
, save
, NULL
);
4459 e
= new FuncExp(loc
, fd
);
4464 error("expression expected, not '%s'", token
.toChars());
4466 // Anything for e, as long as it's not NULL
4467 e
= new IntegerExp(loc
, 0, Type::tint32
);
4471 return parsePostExp(e
);
4474 Expression
*Parser::parsePostExp(Expression
*e
)
4481 switch (token
.value
)
4485 if (token
.value
== TOKidentifier
)
4486 { Identifier
*id
= token
.ident
;
4489 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4490 { // identifier!(template-argument-list)
4491 TemplateInstance
*tempinst
;
4493 tempinst
= new TemplateInstance(loc
, id
);
4495 tempinst
->tiargs
= parseTemplateArgumentList();
4496 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4499 e
= new DotIdExp(loc
, e
, id
);
4502 else if (token
.value
== TOKnew
)
4508 error("identifier expected following '.', not '%s'", token
.toChars());
4512 e
= new PostExp(TOKplusplus
, loc
, e
);
4516 e
= new PostExp(TOKminusminus
, loc
, e
);
4520 e
= new CallExp(loc
, e
, parseArguments());
4524 { // array dereferences:
4527 // array[lwr .. upr]
4533 if (token
.value
== TOKrbracket
)
4535 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4540 index
= parseAssignExp();
4541 if (token
.value
== TOKslice
)
4542 { // array[lwr .. upr]
4544 upr
= parseAssignExp();
4545 e
= new SliceExp(loc
, e
, index
, upr
);
4548 { // array[index, i2, i3, i4, ...]
4549 Expressions
*arguments
= new Expressions();
4550 arguments
->push(index
);
4551 if (token
.value
== TOKcomma
)
4557 arg
= parseAssignExp();
4558 arguments
->push(arg
);
4559 if (token
.value
== TOKrbracket
)
4564 e
= new ArrayExp(loc
, e
, arguments
);
4579 Expression
*Parser::parseUnaryExp()
4581 Loc loc
= this->loc
;
4583 switch (token
.value
)
4587 e
= parseUnaryExp();
4588 e
= new AddrExp(loc
, e
);
4593 e
= parseUnaryExp();
4594 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4599 e
= parseUnaryExp();
4600 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4605 e
= parseUnaryExp();
4606 e
= new PtrExp(loc
, e
);
4611 e
= parseUnaryExp();
4612 e
= new NegExp(loc
, e
);
4617 e
= parseUnaryExp();
4618 e
= new UAddExp(loc
, e
);
4623 e
= parseUnaryExp();
4624 e
= new NotExp(loc
, e
);
4629 e
= parseUnaryExp();
4630 e
= new ComExp(loc
, e
);
4635 e
= parseUnaryExp();
4636 e
= new DeleteExp(loc
, e
);
4640 e
= parseNewExp(NULL
);
4643 case TOKcast
: // cast(type) expression
4648 t
= parseBasicType();
4649 t
= parseDeclarator(t
,NULL
); // ( type )
4652 e
= parseUnaryExp();
4653 e
= new CastExp(loc
, e
, t
);
4663 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4665 tk
= peek(tk
); // skip over right parenthesis
4685 case TOKimaginary32v
:
4686 case TOKimaginary64v
:
4687 case TOKimaginary80v
:
4705 CASE_BASIC_TYPES
: // (type)int.size
4710 t
= parseBasicType();
4711 t
= parseDeclarator(t
,NULL
);
4715 if (token
.value
== TOKdot
)
4718 if (token
.value
!= TOKidentifier
)
4719 { error("Identifier expected following (type).");
4722 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4724 e
= parsePostExp(e
);
4728 e
= parseUnaryExp();
4729 e
= new CastExp(loc
, e
, t
);
4730 error("C style cast illegal, use %s", e
->toChars());
4737 e
= parsePrimaryExp();
4741 e
= parsePrimaryExp();
4748 Expression
*Parser::parseMulExp()
4751 Loc loc
= this->loc
;
4753 e
= parseUnaryExp();
4756 switch (token
.value
)
4758 case TOKmul
: nextToken(); e2
= parseUnaryExp(); e
= new MulExp(loc
,e
,e2
); continue;
4759 case TOKdiv
: nextToken(); e2
= parseUnaryExp(); e
= new DivExp(loc
,e
,e2
); continue;
4760 case TOKmod
: nextToken(); e2
= parseUnaryExp(); e
= new ModExp(loc
,e
,e2
); continue;
4770 Expression
*Parser::parseAddExp()
4773 Loc loc
= this->loc
;
4778 switch (token
.value
)
4780 case TOKadd
: nextToken(); e2
= parseMulExp(); e
= new AddExp(loc
,e
,e2
); continue;
4781 case TOKmin
: nextToken(); e2
= parseMulExp(); e
= new MinExp(loc
,e
,e2
); continue;
4782 case TOKtilde
: nextToken(); e2
= parseMulExp(); e
= new CatExp(loc
,e
,e2
); continue;
4792 Expression
*Parser::parseShiftExp()
4795 Loc loc
= this->loc
;
4800 switch (token
.value
)
4802 case TOKshl
: nextToken(); e2
= parseAddExp(); e
= new ShlExp(loc
,e
,e2
); continue;
4803 case TOKshr
: nextToken(); e2
= parseAddExp(); e
= new ShrExp(loc
,e
,e2
); continue;
4804 case TOKushr
: nextToken(); e2
= parseAddExp(); e
= new UshrExp(loc
,e
,e2
); continue;
4814 Expression
*Parser::parseRelExp()
4818 Loc loc
= this->loc
;
4820 e
= parseShiftExp();
4823 switch (token
.value
)
4839 e2
= parseShiftExp();
4840 e
= new CmpExp(op
, loc
, e
, e2
);
4845 e2
= parseShiftExp();
4846 e
= new InExp(loc
, e
, e2
);
4857 Expression
*Parser::parseEqualExp()
4861 Loc loc
= this->loc
;
4865 { enum TOK value
= token
.value
;
4873 e
= new EqualExp(value
, loc
, e
, e2
);
4877 error("'===' is no longer legal, use 'is' instead");
4880 case TOKnotidentity
:
4881 error("'!==' is no longer legal, use '!is' instead");
4885 value
= TOKidentity
;
4889 // Attempt to identify '!is'
4891 if (t
->value
!= TOKis
)
4894 value
= TOKnotidentity
;
4900 e
= new IdentityExp(value
, loc
, e
, e2
);
4911 Expression
*Parser::parseCmpExp()
4915 Loc loc
= this->loc
;
4917 e
= parseShiftExp();
4918 enum TOK op
= token
.value
;
4925 e2
= parseShiftExp();
4926 e
= new EqualExp(op
, loc
, e
, e2
);
4934 // Attempt to identify '!is'
4936 if (t
->value
!= TOKis
)
4939 op
= TOKnotidentity
;
4944 e2
= parseShiftExp();
4945 e
= new IdentityExp(op
, loc
, e
, e2
);
4961 e2
= parseShiftExp();
4962 e
= new CmpExp(op
, loc
, e
, e2
);
4967 e2
= parseShiftExp();
4968 e
= new InExp(loc
, e
, e2
);
4977 Expression
*Parser::parseAndExp()
4980 Loc loc
= this->loc
;
4982 if (global
.params
.Dversion
== 1)
4984 e
= parseEqualExp();
4985 while (token
.value
== TOKand
)
4988 e2
= parseEqualExp();
4989 e
= new AndExp(loc
,e
,e2
);
4996 while (token
.value
== TOKand
)
5000 e
= new AndExp(loc
,e
,e2
);
5007 Expression
*Parser::parseXorExp()
5010 Loc loc
= this->loc
;
5013 while (token
.value
== TOKxor
)
5017 e
= new XorExp(loc
, e
, e2
);
5022 Expression
*Parser::parseOrExp()
5025 Loc loc
= this->loc
;
5028 while (token
.value
== TOKor
)
5032 e
= new OrExp(loc
, e
, e2
);
5037 Expression
*Parser::parseAndAndExp()
5040 Loc loc
= this->loc
;
5043 while (token
.value
== TOKandand
)
5047 e
= new AndAndExp(loc
, e
, e2
);
5052 Expression
*Parser::parseOrOrExp()
5055 Loc loc
= this->loc
;
5057 e
= parseAndAndExp();
5058 while (token
.value
== TOKoror
)
5061 e2
= parseAndAndExp();
5062 e
= new OrOrExp(loc
, e
, e2
);
5067 Expression
*Parser::parseCondExp()
5071 Loc loc
= this->loc
;
5074 if (token
.value
== TOKquestion
)
5077 e1
= parseExpression();
5079 e2
= parseCondExp();
5080 e
= new CondExp(loc
, e
, e1
, e2
);
5085 Expression
*DltParser::parseCondExp()
5089 Loc loc
= this->loc
;
5092 if (token
.value
== TOKif
)
5095 e1
= parseExpression();
5097 e2
= parseCondExp();
5098 e
= new CondExp(loc
, e1
, e
, e2
);
5103 Expression
*Parser::parseAssignExp()
5112 switch (token
.value
)
5114 #define X(tok,ector) \
5115 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5117 X(TOKassign
, AssignExp
);
5118 X(TOKaddass
, AddAssignExp
);
5119 X(TOKminass
, MinAssignExp
);
5120 X(TOKmulass
, MulAssignExp
);
5121 X(TOKdivass
, DivAssignExp
);
5122 X(TOKmodass
, ModAssignExp
);
5123 X(TOKandass
, AndAssignExp
);
5124 X(TOKorass
, OrAssignExp
);
5125 X(TOKxorass
, XorAssignExp
);
5126 X(TOKshlass
, ShlAssignExp
);
5127 X(TOKshrass
, ShrAssignExp
);
5128 X(TOKushrass
, UshrAssignExp
);
5129 X(TOKcatass
, CatAssignExp
);
5140 Expression
*Parser::parseExpression()
5143 Loc loc
= this->loc
;
5145 //printf("Parser::parseExpression()\n");
5146 e
= parseAssignExp();
5147 while (token
.value
== TOKcomma
)
5150 e2
= parseAssignExp();
5151 e
= new CommaExp(loc
, e
, e2
);
5158 /*************************
5159 * Collect argument list.
5160 * Assume current token is '(' or '['.
5163 Expressions
*Parser::parseArguments()
5165 Expressions
*arguments
;
5169 arguments
= new Expressions();
5170 if (token
.value
== TOKlbracket
)
5171 endtok
= TOKrbracket
;
5177 if (token
.value
!= endtok
)
5181 arg
= parseAssignExp();
5182 arguments
->push(arg
);
5183 if (token
.value
== endtok
)
5193 /*******************************************
5196 Expression
*Parser::parseNewExp(Expression
*thisexp
)
5198 Expressions
*newargs
;
5199 Expressions
*arguments
= NULL
;
5201 Loc loc
= this->loc
;
5205 if (token
.value
== TOKlparen
)
5207 newargs
= parseArguments();
5210 // An anonymous nested class starts with "class"
5211 if (token
.value
== TOKclass
)
5214 if (token
.value
== TOKlparen
)
5215 arguments
= parseArguments();
5217 BaseClasses
*baseclasses
= NULL
;
5218 if (token
.value
!= TOKlcurly
)
5219 baseclasses
= parseBaseClasses();
5221 Identifier
*id
= NULL
;
5222 ClassDeclaration
*cd
= new ClassDeclaration(loc
, id
, baseclasses
);
5224 if (token
.value
!= TOKlcurly
)
5225 { error("{ members } expected for anonymous class");
5231 Array
*decl
= parseDeclDefs(0);
5232 if (token
.value
!= TOKrcurly
)
5233 error("class member expected");
5238 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
5244 t
= parseBasicType();
5245 t
= parseBasicType2(t
);
5246 if (t
->ty
== Taarray
)
5248 Type
*index
= ((TypeAArray
*)t
)->index
;
5250 Expression
*e
= index
->toExpression();
5252 { arguments
= new Expressions();
5254 t
= new TypeDArray(t
->next
);
5258 error("need size of rightmost array, not type %s", index
->toChars());
5259 return new NullExp(loc
);
5262 else if (t
->ty
== Tsarray
)
5264 TypeSArray
*tsa
= (TypeSArray
*)t
;
5265 Expression
*e
= tsa
->dim
;
5267 arguments
= new Expressions();
5269 t
= new TypeDArray(t
->next
);
5271 else if (token
.value
== TOKlparen
)
5273 arguments
= parseArguments();
5276 t
= parseBasicType();
5277 while (token
.value
== TOKmul
)
5278 { t
= new TypePointer(t
);
5281 if (token
.value
== TOKlbracket
)
5286 e
= parseAssignExp();
5287 arguments
= new Array();
5290 t
= parseDeclarator(t
, NULL
);
5291 t
= new TypeDArray(t
);
5293 else if (token
.value
== TOKlparen
)
5294 arguments
= parseArguments();
5296 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5300 /**********************************************
5303 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5305 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5309 /********************************* ***************************/