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);
275 case TOKconst
: stc
= STCconst
; goto Lstc
;
276 case TOKfinal
: stc
= STCfinal
; goto Lstc
;
277 case TOKauto
: stc
= STCauto
; goto Lstc
;
278 case TOKscope
: stc
= STCscope
; goto Lstc
;
279 case TOKoverride
: stc
= STCoverride
; goto Lstc
;
280 case TOKabstract
: stc
= STCabstract
; goto Lstc
;
281 case TOKsynchronized
: stc
= STCsynchronized
; goto Lstc
;
282 case TOKdeprecated
: stc
= STCdeprecated
; goto Lstc
;
289 case TOKconst
: stc
|= STCconst
; goto Lstc
;
290 case TOKfinal
: stc
|= STCfinal
; goto Lstc
;
291 case TOKauto
: stc
|= STCauto
; goto Lstc
;
292 case TOKscope
: stc
|= STCscope
; goto Lstc
;
293 case TOKoverride
: stc
|= STCoverride
; goto Lstc
;
294 case TOKabstract
: stc
|= STCabstract
; goto Lstc
;
295 case TOKsynchronized
: stc
|= STCsynchronized
; goto Lstc
;
296 case TOKdeprecated
: stc
|= STCdeprecated
; goto Lstc
;
297 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
302 /* Look for auto initializers:
303 * storage_class identifier = initializer;
305 if (token
.value
== TOKidentifier
&&
306 peek(&token
)->value
== TOKassign
)
310 Identifier
*ident
= token
.ident
;
313 Initializer
*init
= parseInitializer();
314 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
315 v
->storage_class
= stc
;
317 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
321 else if (token
.value
== TOKcomma
)
324 if (token
.value
== TOKidentifier
&&
325 peek(&token
)->value
== TOKassign
)
328 addComment(s
, comment
);
332 error("Identifier expected following comma");
335 error("%s expected following declaration, not '%s'", endToken(), token
.toChars());
341 s
= new StorageClassDeclaration(stc
, a
);
346 if (peek(&token
)->value
!= TOKlparen
)
351 enum LINK linksave
= linkage
;
352 linkage
= parseLinkage();
354 s
= new LinkDeclaration(linkage
, a
);
358 case TOKprivate
: prot
= PROTprivate
; goto Lprot
;
359 case TOKpackage
: prot
= PROTpackage
; goto Lprot
;
360 case TOKprotected
: prot
= PROTprotected
; goto Lprot
;
361 case TOKpublic
: prot
= PROTpublic
; goto Lprot
;
362 case TOKexport
: prot
= PROTexport
; goto Lprot
;
367 s
= new ProtDeclaration(prot
, a
);
375 if (token
.value
== TOKlparen
)
378 if (token
.value
== TOKint32v
)
379 n
= (unsigned)token
.uns64value
;
381 { error("integer expected, not %s", token
.toChars());
388 n
= global
.structalign
; // default
391 s
= new AlignDeclaration(n
, a
);
397 Expressions
*args
= NULL
;
401 if (token
.value
!= TOKidentifier
)
402 { error("pragma(identifier expected");
407 if (token
.value
== TOKcomma
)
408 args
= parseArguments(); // pragma(identifier, args...)
410 check(TOKrparen
); // pragma(identifier)
412 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
417 a
= parseDeclDefs(0);
422 s
= new PragmaDeclaration(loc
, ident
, args
, a
);
428 if (token
.value
== TOKassign
)
431 if (token
.value
== TOKidentifier
)
432 s
= new DebugSymbol(loc
, token
.ident
);
433 else if (token
.value
== TOKint32v
)
434 s
= new DebugSymbol(loc
, (unsigned)token
.uns64value
);
436 { error("identifier or integer expected, not %s", token
.toChars());
440 if (token
.value
!= TOKsemicolon
)
441 error("semicolon expected");
446 condition
= parseDebugCondition();
451 if (token
.value
== TOKassign
)
454 if (token
.value
== TOKidentifier
)
455 s
= new VersionSymbol(loc
, token
.ident
);
456 else if (token
.value
== TOKint32v
)
457 s
= new VersionSymbol(loc
, (unsigned)token
.uns64value
);
459 { error("identifier or integer expected, not %s", token
.toChars());
463 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
)
464 error("%s expected after version assignment", endToken());
468 condition
= parseVersionCondition();
474 if (token
.value
== TOKelse
)
476 aelse
= parseBlock();
478 s
= new ConditionalDeclaration(condition
, a
, aelse
);
481 case TOKsemicolon
: // empty declaration
486 error("Declaration expected, not '%s'",token
.toChars());
488 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
&& token
.value
!= TOKeof
)
496 addComment(s
, comment
);
503 /********************************************
504 * Parse declarations after an align, protection, or extern decl.
507 Array
*Parser::parseBlock()
512 //printf("Parser::parseBlock()\n");
516 error("declaration expected following attribute, not ';'");
522 a
= parseDeclDefs(0);
523 if (token
.value
!= TOKrcurly
)
525 error("matching '}' expected, not %s", token
.toChars());
536 a
= parseDeclDefs(0); // grab declarations up to closing curly bracket
541 a
= parseDeclDefs(1);
547 Array
*DltParser::parseBlock()
557 error("declaration expected following attribute, not %s", token
.toChars());
563 a
= parseDeclDefs(0);
564 if (token
.value
!= TOKrcurly
)
566 error("matching end-of-block expected, not %s", token
.toChars());
573 a
= parseDeclDefs(1);
579 /**********************************
580 * Parse a static assertion.
583 StaticAssert
*Parser::parseStaticAssert()
587 Expression
*msg
= NULL
;
589 //printf("parseStaticAssert()\n");
592 exp
= parseAssignExp();
593 if (token
.value
== TOKcomma
)
595 msg
= parseAssignExp();
598 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
) {
600 return new StaticAssert(loc
, exp
, msg
);
602 error("expected %s after static assert", endToken());
606 /***********************************
607 * Parse extern (linkage)
608 * The parser is on the 'extern' token.
611 enum LINK
Parser::parseLinkage()
613 enum LINK link
= LINKdefault
;
615 assert(token
.value
== TOKlparen
);
617 if (token
.value
== TOKidentifier
)
618 { Identifier
*id
= token
.ident
;
621 if (id
== Id::Windows
)
623 else if (id
== Id::Pascal
)
625 else if (id
== Id::D
)
627 else if (id
== Id::C
)
630 if (token
.value
== TOKplusplus
)
635 else if (id
== Id::System
)
638 link
= d_gcc_is_target_win32() ? LINKwindows
: LINKc
;
649 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
655 link
= LINKd
; // default
661 /**************************************
662 * Parse a debug conditional
665 Condition
*Parser::parseDebugCondition()
669 if (token
.value
== TOKlparen
)
673 Identifier
*id
= NULL
;
675 if (token
.value
== TOKidentifier
)
677 else if (token
.value
== TOKint32v
)
678 level
= (unsigned)token
.uns64value
;
680 error("identifier or integer expected, not %s", token
.toChars());
683 c
= new DebugCondition(mod
, level
, id
);
684 if (dltSyntax
&& token
.value
!= TOKcolon
)
685 error("expected colon after debug(), not '%s'", token
.toChars());
687 if (dltSyntax
&& token
.value
!= TOKcolon
)
688 error("expected ':' or '(' after 'debug', not '%s'", token
.toChars());
689 c
= new DebugCondition(mod
, 1, NULL
);
695 /**************************************
696 * Parse a version conditional
699 Condition
*Parser::parseVersionCondition()
703 Identifier
*id
= NULL
;
705 if (token
.value
== TOKlparen
)
708 if (token
.value
== TOKidentifier
)
710 else if (token
.value
== TOKint32v
)
711 level
= (unsigned)token
.uns64value
;
715 * even though unittest is a keyword
717 else if (token
.value
== TOKunittest
)
718 id
= Lexer::idPool(Token::toChars(TOKunittest
));
721 error("identifier or integer expected, not %s", token
.toChars());
727 error("(condition) expected following version");
728 c
= new VersionCondition(mod
, level
, id
);
733 /***********************************************
734 * static if (expression)
740 Condition
*Parser::parseStaticIfCondition()
742 Condition
*condition
;
748 if (token
.value
== TOKlparen
)
751 exp
= parseAssignExp();
755 { error("(expression) expected following static if");
758 condition
= new StaticIfCondition(loc
, exp
);
763 /*****************************************
764 * Parse a constructor definition:
765 * this(arguments) { body }
766 * Current token is 'this'.
769 CtorDeclaration
*Parser::parseCtor()
772 Arguments
*arguments
;
777 arguments
= parseParameters(&varargs
);
778 f
= new CtorDeclaration(loc
, 0, arguments
, varargs
);
783 /*****************************************
784 * Parse a destructor definition:
786 * Current token is '~'.
789 DtorDeclaration
*Parser::parseDtor()
799 f
= new DtorDeclaration(loc
, 0);
804 /*****************************************
805 * Parse a static constructor definition:
806 * static this() { body }
807 * Current token is 'this'.
810 StaticCtorDeclaration
*Parser::parseStaticCtor()
812 StaticCtorDeclaration
*f
;
819 f
= new StaticCtorDeclaration(loc
, 0);
824 /*****************************************
825 * Parse a static destructor definition:
826 * static ~this() { body }
827 * Current token is '~'.
830 StaticDtorDeclaration
*Parser::parseStaticDtor()
832 StaticDtorDeclaration
*f
;
840 f
= new StaticDtorDeclaration(loc
, 0);
845 /*****************************************
846 * Parse an invariant definition:
848 * Current token is 'invariant'.
851 InvariantDeclaration
*Parser::parseInvariant()
853 InvariantDeclaration
*f
;
857 if (token
.value
== TOKlparen
) // optional ()
863 f
= new InvariantDeclaration(loc
, 0);
864 f
->fbody
= parseStatement(PScurly
);
868 /*****************************************
869 * Parse a unittest definition:
871 * Current token is 'unittest'.
874 UnitTestDeclaration
*Parser::parseUnitTest()
876 UnitTestDeclaration
*f
;
882 body
= parseStatement(PScurly
);
884 f
= new UnitTestDeclaration(loc
, this->loc
);
889 /*****************************************
890 * Parse a new definition:
891 * new(arguments) { body }
892 * Current token is 'new'.
895 NewDeclaration
*Parser::parseNew()
898 Arguments
*arguments
;
903 arguments
= parseParameters(&varargs
);
904 f
= new NewDeclaration(loc
, 0, arguments
, varargs
);
909 /*****************************************
910 * Parse a delete definition:
911 * delete(arguments) { body }
912 * Current token is 'delete'.
915 DeleteDeclaration
*Parser::parseDelete()
917 DeleteDeclaration
*f
;
918 Arguments
*arguments
;
923 arguments
= parseParameters(&varargs
);
925 error("... not allowed in delete function parameter list");
926 f
= new DeleteDeclaration(loc
, 0, arguments
);
931 /**********************************************
932 * Parse parameter list.
935 Arguments
*Parser::parseParameters(int *pvarargs
)
937 Arguments
*arguments
= new Arguments();
947 unsigned storageClass
;
951 storageClass
= STCin
; // parameter is "in" by default
963 storageClass
= STCin
;
968 storageClass
= STCout
;
974 storageClass
= STCref
;
979 storageClass
= STClazy
;
985 tb
= parseBasicType();
986 at
= parseDeclarator(tb
, &ai
);
988 if (token
.value
== TOKassign
) // = defaultArg
990 ae
= parseAssignExp();
995 error("default argument expected for %s",
996 ai
? ai
->toChars() : at
->toChars());
998 if (token
.value
== TOKdotdotdot
)
1003 if (storageClass
& (STCout
| STCref
))
1004 error("variadic argument cannot be out or ref");
1006 a
= new Argument(storageClass
, at
, ai
, ae
);
1011 a
= new Argument(storageClass
, at
, ai
, ae
);
1013 if (token
.value
== TOKcomma
)
1022 *pvarargs
= varargs
;
1027 /*************************************
1030 EnumDeclaration
*Parser::parseEnum()
1031 { EnumDeclaration
*e
;
1034 Loc loc
= this->loc
;
1036 //printf("Parser::parseEnum()\n");
1038 if (token
.value
== TOKidentifier
)
1045 if (token
.value
== TOKcolon
)
1048 t
= parseBasicType();
1053 e
= new EnumDeclaration(loc
, id
, t
);
1054 if (token
.value
== TOKsemicolon
&& id
)
1056 else if (token
.value
== startBlockTok
)
1058 //printf("enum definition\n");
1059 e
->members
= new Array();
1061 unsigned char *comment
= token
.blockComment
;
1063 while (token
.value
!= TOKrcurly
)
1065 if (token
.value
== TOKidentifier
)
1071 ident
= token
.ident
;
1074 if (token
.value
== TOKassign
)
1077 value
= parseAssignExp();
1079 em
= new EnumMember(loc
, ident
, value
);
1080 e
->members
->push(em
);
1082 if (token
.value
== TOKrcurly
)
1085 { addComment(em
, comment
);
1090 addComment(em
, comment
);
1091 comment
= token
.blockComment
;
1094 { error("enum member expected");
1101 error("enum declaration is invalid");
1106 Dsymbol
*Parser::parseAggregate()
1107 { AggregateDeclaration
*a
= NULL
;
1111 TemplateParameters
*tpl
= NULL
;
1113 //printf("Parser::parseAggregate()\n");
1116 if (token
.value
!= TOKidentifier
)
1123 if (token
.value
== TOKlparen
)
1124 { // Class template declaration.
1126 // Gather template parameter list
1127 tpl
= parseTemplateParameterList();
1131 Loc loc
= this->loc
;
1137 error("anonymous classes not allowed");
1139 // Collect base class(es)
1140 BaseClasses
*baseclasses
= NULL
;
1141 if (token
.value
== (dltSyntax
? TOKextends
: TOKcolon
))
1144 baseclasses
= parseBaseClasses();
1145 if (token
.value
!= startBlockTok
)
1146 error("members expected");
1149 if (tok
== TOKclass
)
1150 a
= new ClassDeclaration(loc
, id
, baseclasses
);
1152 a
= new InterfaceDeclaration(loc
, id
, baseclasses
);
1158 a
= new StructDeclaration(loc
, id
);
1165 a
= new UnionDeclaration(loc
, id
);
1174 if (a
&& token
.value
== (dltSyntax
? TOKendline
: TOKsemicolon
))
1177 else if (token
.value
== startBlockTok
)
1179 //printf("aggregate definition\n");
1182 Array
*decl
= parseDeclDefs(0);
1183 if (token
.value
!= TOKrcurly
)
1184 error("end-of-block expected following member declarations in aggregate");
1188 /* Anonymous structs/unions are more like attributes.
1190 return new AnonDeclaration(loc
, anon
- 1, decl
);
1197 error("%s expected following aggregate declaration", Token::toChars(startBlockTok
));
1198 a
= new StructDeclaration(loc
, NULL
);
1203 TemplateDeclaration
*tempdecl
;
1205 // Wrap a template around the aggregate declaration
1206 decldefs
= new Array();
1208 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
);
1215 /*******************************************
1218 BaseClasses
*Parser::parseBaseClasses()
1220 enum PROT protection
= PROTpublic
;
1221 BaseClasses
*baseclasses
= new BaseClasses();
1223 for (; 1; nextToken())
1225 switch (token
.value
)
1230 protection
= PROTprivate
;
1233 protection
= PROTpackage
;
1236 protection
= PROTprotected
;
1239 protection
= PROTpublic
;
1242 error("base classes expected instead of %s", token
.toChars());
1245 BaseClass
*b
= new BaseClass(parseBasicType(), protection
);
1246 baseclasses
->push(b
);
1247 if (token
.value
!= TOKcomma
)
1249 protection
= PROTpublic
;
1254 /**************************************
1255 * Parse a TemplateDeclaration.
1258 TemplateDeclaration
*Parser::parseTemplateDeclaration()
1260 TemplateDeclaration
*tempdecl
;
1262 TemplateParameters
*tpl
;
1264 Loc loc
= this->loc
;
1267 if (token
.value
!= TOKidentifier
)
1268 { error("TemplateIdentifier expected following template");
1273 tpl
= parseTemplateParameterList();
1277 if (token
.value
!= startBlockTok
)
1278 { error("members of template declaration expected");
1284 decldefs
= parseDeclDefs(0);
1285 if (token
.value
!= TOKrcurly
)
1286 { error("template member expected");
1292 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
);
1299 /******************************************
1300 * Parse template parameter list.
1303 TemplateParameters
*Parser::parseTemplateParameterList()
1305 TemplateParameters
*tpl
= new TemplateParameters();
1307 if (token
.value
!= TOKlparen
)
1308 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1313 // Get array of TemplateParameters
1314 if (token
.value
!= TOKrparen
)
1315 { int isvariadic
= 0;
1318 { TemplateParameter
*tp
;
1319 Identifier
*tp_ident
= NULL
;
1320 Type
*tp_spectype
= NULL
;
1321 Type
*tp_valtype
= NULL
;
1322 Type
*tp_defaulttype
= NULL
;
1323 Expression
*tp_specvalue
= NULL
;
1324 Expression
*tp_defaultvalue
= NULL
;
1327 // Get TemplateParameter
1329 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1331 if (token
.value
== TOKalias
)
1334 if (token
.value
!= TOKidentifier
)
1335 { error("Identifier expected for template parameter");
1338 tp_ident
= token
.ident
;
1340 if (token
.value
== TOKcolon
) // : Type
1343 tp_spectype
= parseBasicType();
1344 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1346 if (token
.value
== TOKassign
) // = Type
1349 tp_defaulttype
= parseBasicType();
1350 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1352 tp
= new TemplateAliasParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1354 else if (t
->value
== TOKcolon
|| t
->value
== TOKassign
||
1355 t
->value
== TOKcomma
|| t
->value
== TOKrparen
)
1357 if (token
.value
!= TOKidentifier
)
1358 { error("Identifier expected for template parameter");
1361 tp_ident
= token
.ident
;
1363 if (token
.value
== TOKcolon
) // : Type
1366 tp_spectype
= parseBasicType();
1367 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1369 if (token
.value
== TOKassign
) // = Type
1372 tp_defaulttype
= parseBasicType();
1373 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1375 tp
= new TemplateTypeParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1377 else if (token
.value
== TOKidentifier
&& t
->value
== TOKdotdotdot
)
1380 error("variadic template parameter must be last");
1382 tp_ident
= token
.ident
;
1385 tp
= new TemplateTupleParameter(loc
, tp_ident
);
1389 tp_valtype
= parseBasicType();
1390 tp_valtype
= parseDeclarator(tp_valtype
, &tp_ident
);
1393 error("no identifier for template value parameter");
1394 tp_ident
= new Identifier("error", TOKidentifier
);
1396 if (token
.value
== TOKcolon
) // : CondExpression
1399 tp_specvalue
= parseCondExp();
1401 if (token
.value
== TOKassign
) // = CondExpression
1404 tp_defaultvalue
= parseCondExp();
1406 tp
= new TemplateValueParameter(loc
, tp_ident
, tp_valtype
, tp_specvalue
, tp_defaultvalue
);
1409 if (token
.value
!= TOKcomma
)
1419 /******************************************
1420 * Parse template mixin.
1423 * mixin a.b.c!(args).Foo!(args);
1424 * mixin Foo!(args) identifier;
1425 * mixin typeof(expr).identifier!(args);
1428 Dsymbol
*Parser::parseMixin()
1436 //printf("parseMixin()\n");
1439 if (token
.value
== TOKdot
)
1445 if (token
.value
== TOKtypeof
)
1450 exp
= parseExpression();
1452 tqual
= new TypeTypeof(loc
, exp
);
1455 if (token
.value
!= TOKidentifier
)
1457 error("identifier expected, not %s", token
.toChars());
1464 idents
= new Array();
1468 if (token
.value
== TOKnot
)
1471 tiargs
= parseTemplateArgumentList();
1474 if (token
.value
!= TOKdot
)
1478 { TemplateInstance
*tempinst
= new TemplateInstance(loc
, id
);
1479 tempinst
->tiargs
= tiargs
;
1480 id
= (Identifier
*)tempinst
;
1486 if (token
.value
!= TOKidentifier
)
1487 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1495 if (token
.value
== TOKidentifier
)
1503 tm
= new TemplateMixin(loc
, id
, tqual
, idents
, tiargs
);
1504 if (token
.value
!= TOKsemicolon
)
1505 error("';' expected after mixin");
1514 /******************************************
1515 * Parse template argument list.
1517 * current token is opening '('
1519 * current token is one after closing ')'
1522 Objects
*Parser::parseTemplateArgumentList()
1524 //printf("Parser::parseTemplateArgumentList()\n");
1525 Objects
*tiargs
= new Objects();
1526 if (token
.value
!= TOKlparen
)
1527 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1532 // Get TemplateArgumentList
1533 if (token
.value
!= TOKrparen
)
1537 // See if it is an Expression or a Type
1538 if (isDeclaration(&token
, 0, TOKreserved
, NULL
))
1542 // Get TemplateArgument
1543 ta
= parseBasicType();
1544 ta
= parseDeclarator(ta
, NULL
);
1551 ea
= parseAssignExp();
1554 if (token
.value
!= TOKcomma
)
1559 check(TOKrparen
, "template argument list");
1563 Import
*Parser::parseImport(Array
*decldefs
, int isstatic
)
1566 Identifier
*aliasid
= NULL
;
1570 //printf("Parser::parseImport()\n");
1575 if (token
.value
!= TOKidentifier
)
1576 { error("Identifier expected following import");
1584 if (!aliasid
&& token
.value
== TOKassign
)
1589 while (token
.value
== TOKdot
)
1595 if (token
.value
!= TOKidentifier
)
1596 { error("Identifier expected following package");
1603 s
= new Import(loc
, a
, token
.ident
, aliasid
, isstatic
);
1607 * : alias=name, alias=name;
1610 if (token
.value
== TOKcolon
)
1619 if (dltSyntax
&& token
.value
== TOKrcurly
)
1621 if (token
.value
!= TOKidentifier
)
1622 { error("Identifier expected following :");
1625 alias
= token
.ident
;
1627 if (token
.value
== TOKassign
)
1630 if (token
.value
!= TOKidentifier
)
1631 { error("Identifier expected following %s=", alias
->toChars());
1641 s
->addAlias(name
, alias
);
1642 if (token
.value
!= TOKcomma
&& token
.value
!= TOKendline
)
1656 } while (token
.value
== TOKcomma
);
1658 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
1662 error("%s expected", endToken());
1669 Type
*Parser::parseBasicType()
1673 TemplateInstance
*tempinst
;
1675 //printf("parseBasicType()\n");
1676 switch (token
.value
)
1678 CASE_BASIC_TYPES_X(t
):
1685 if (token
.value
== TOKnot
)
1688 tempinst
= new TemplateInstance(loc
, id
);
1689 tempinst
->tiargs
= parseTemplateArgumentList();
1690 tid
= new TypeInstance(loc
, tempinst
);
1694 tid
= new TypeIdentifier(loc
, id
);
1696 while (token
.value
== TOKdot
)
1698 if (token
.value
!= TOKidentifier
)
1699 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1704 if (token
.value
== TOKnot
)
1707 tempinst
= new TemplateInstance(loc
, id
);
1708 tempinst
->tiargs
= parseTemplateArgumentList();
1709 tid
->addIdent((Identifier
*)tempinst
);
1726 exp
= parseExpression();
1728 tid
= new TypeTypeof(loc
, exp
);
1733 error("basic type expected, not %s", token
.toChars());
1740 Type
*Parser::parseBasicType2(Type
*t
)
1745 //printf("parseBasicType2()\n");
1748 switch (token
.value
)
1751 t
= new TypePointer(t
);
1757 // Handle []. Make sure things like
1759 // is (array[1] of array[3] of int)
1761 if (token
.value
== TOKrbracket
)
1763 t
= new TypeDArray(t
); // []
1766 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1767 { // It's an associative array declaration
1770 //printf("it's an associative array\n");
1771 index
= parseBasicType();
1772 index
= parseDeclarator(index
, NULL
); // [ type ]
1773 t
= new TypeAArray(t
, index
);
1778 //printf("it's [expression]\n");
1780 Expression
*e
= parseExpression(); // [ expression ]
1781 if (token
.value
== TOKslice
)
1785 e2
= parseExpression(); // [ exp .. exp ]
1786 t
= new TypeSlice(t
, e
, e2
);
1789 t
= new TypeSArray(t
,e
);
1795 // Handle []. Make sure things like
1797 // is (array[3] of array[1] of int)
1799 while (token
.value
== TOKlbracket
)
1802 if (token
.value
== TOKrbracket
)
1804 ta
= new TypeDArray(t
); // []
1807 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1808 { // It's an associative array declaration
1811 //printf("it's an associative array\n");
1812 index
= parseBasicType();
1813 index
= parseDeclarator(index
, NULL
); // [ type ]
1815 ta
= new TypeAArray(t
, index
);
1819 //printf("it's [expression]\n");
1820 Expression
*e
= parseExpression(); // [ expression ]
1821 ta
= new TypeSArray(t
,e
);
1825 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1835 { // Handle delegate declaration:
1836 // t delegate(parameter list)
1837 // t function(parameter list)
1838 Arguments
*arguments
;
1840 enum TOK save
= token
.value
;
1843 arguments
= parseParameters(&varargs
);
1844 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1845 if (save
== TOKdelegate
)
1846 t
= new TypeDelegate(t
);
1848 t
= new TypePointer(t
); // pointer to function
1861 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1865 //printf("parseDeclarator(tpl = %p)\n", tpl);
1866 t
= parseBasicType2(t
);
1868 switch (token
.value
)
1873 *pident
= token
.ident
;
1875 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1882 ts
= parseDeclarator(t
, pident
);
1893 switch (token
.value
)
1897 { // This is the old C-style post [] syntax.
1899 if (token
.value
== TOKrbracket
)
1901 ta
= new TypeDArray(t
); // []
1904 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1905 { // It's an associative array declaration
1908 //printf("it's an associative array\n");
1909 index
= parseBasicType();
1910 index
= parseDeclarator(index
, NULL
); // [ type ]
1912 ta
= new TypeAArray(t
, index
);
1916 //printf("it's [expression]\n");
1917 Expression
*e
= parseExpression(); // [ expression ]
1918 ta
= new TypeSArray(t
, e
);
1922 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1929 { Arguments
*arguments
;
1934 /* Look ahead to see if this is (...)(...),
1935 * i.e. a function template declaration
1937 if (peekPastParen(&token
)->value
== TOKlparen
)
1938 { // It's a function template declaration
1939 //printf("function template declaration\n");
1941 // Gather template parameter list
1942 *tpl
= parseTemplateParameterList();
1946 arguments
= parseParameters(&varargs
);
1947 Type
*ta
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1949 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1961 /**********************************
1962 * Return array of Declaration *'s.
1965 Array
*Parser::parseDeclarations()
1967 enum STC storage_class
;
1975 unsigned char *comment
= token
.blockComment
;
1976 enum LINK link
= linkage
;
1978 //printf("parseDeclarations()\n");
1979 switch (token
.value
)
1992 storage_class
= STCundefined
;
1995 switch (token
.value
)
1997 case TOKconst
: stc
= STCconst
; goto L1
;
1998 case TOKstatic
: stc
= STCstatic
; goto L1
;
1999 case TOKfinal
: stc
= STCfinal
; goto L1
;
2000 case TOKauto
: stc
= STCauto
; goto L1
;
2001 case TOKscope
: stc
= STCscope
; goto L1
;
2002 case TOKoverride
: stc
= STCoverride
; goto L1
;
2003 case TOKabstract
: stc
= STCabstract
; goto L1
;
2004 case TOKsynchronized
: stc
= STCsynchronized
; goto L1
;
2005 case TOKdeprecated
: stc
= STCdeprecated
; goto L1
;
2007 if (storage_class
& stc
)
2008 error("redundant storage class '%s'", token
.toChars());
2009 storage_class
= (STC
) (storage_class
| stc
);
2014 if (peek(&token
)->value
!= TOKlparen
)
2019 link
= parseLinkage();
2030 /* Look for auto initializers:
2031 * storage_class identifier = initializer;
2033 while (storage_class
&&
2034 token
.value
== TOKidentifier
&&
2035 peek(&token
)->value
== TOKassign
)
2037 ident
= token
.ident
;
2040 Initializer
*init
= parseInitializer();
2041 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
2042 v
->storage_class
= storage_class
;
2044 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
2047 addComment(v
, comment
);
2049 else if (token
.value
== TOKcomma
)
2052 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
2054 error("Identifier expected following comma");
2060 error("%s expected following auto declaration, not '%s'", endToken(), token
.toChars());
2064 if (token
.value
== TOKclass
)
2065 { AggregateDeclaration
*s
;
2067 s
= (AggregateDeclaration
*)parseAggregate();
2068 s
->storage_class
|= storage_class
;
2070 addComment(s
, comment
);
2074 ts
= parseBasicType();
2075 ts
= parseBasicType2(ts
);
2080 Loc loc
= this->loc
;
2081 TemplateParameters
*tpl
= NULL
;
2084 t
= parseDeclarator(ts
, &ident
, &tpl
);
2088 else if (t
!= tfirst
)
2089 error("multiple declarations must have the same type, not %s and %s",
2090 tfirst
->toChars(), t
->toChars());
2092 error("no identifier for declarator %s", t
->toChars());
2094 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2099 if (token
.value
== TOKassign
)
2102 init
= parseInitializer();
2104 if (tok
== TOKtypedef
)
2105 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2108 error("alias cannot have initializer");
2109 v
= new AliasDeclaration(loc
, ident
, t
);
2111 v
->storage_class
= storage_class
;
2112 if (link
== linkage
)
2116 Array
*ax
= new Array();
2118 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2121 switch (token
.value
)
2122 { case TOKsemicolon
:
2125 addComment(v
, comment
);
2130 addComment(v
, comment
);
2134 error("%s expected to close %s declaration", endToken(), Token::toChars(tok
));
2138 else if (t
->ty
== Tfunction
)
2139 { FuncDeclaration
*f
;
2142 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2143 addComment(f
, comment
);
2145 addComment(f
, NULL
);
2146 if (link
== linkage
)
2152 Array
*ax
= new Array();
2154 s
= new LinkDeclaration(link
, ax
);
2156 if (tpl
) // it's a function template
2158 TemplateDeclaration
*tempdecl
;
2160 // Wrap a template around the aggregate declaration
2161 decldefs
= new Array();
2163 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
);
2166 addComment(s
, comment
);
2170 { VarDeclaration
*v
;
2174 if (token
.value
== TOKassign
)
2177 init
= parseInitializer();
2179 v
= new VarDeclaration(loc
, t
, ident
, init
);
2180 v
->storage_class
= storage_class
;
2181 if (link
== linkage
)
2185 Array
*ax
= new Array();
2187 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2190 switch (token
.value
)
2191 { case TOKsemicolon
:
2194 addComment(v
, comment
);
2199 addComment(v
, comment
);
2203 error("%s expected, not '%s'", endToken(), token
.toChars());
2212 /*****************************************
2213 * Parse contracts following function declaration.
2216 void Parser::parseContracts(FuncDeclaration
*f
)
2219 enum LINK linksave
= linkage
;
2221 // The following is irrelevant, as it is overridden by sc->linkage in
2222 // TypeFunction::semantic
2223 linkage
= LINKd
; // nested functions have D linkage
2225 switch (token
.value
)
2229 if (token
.value
!= startBlockTok
)
2230 error("use %s to start a new block", Token::toChars(startBlockTok
));
2231 if (f
->frequire
|| f
->fensure
)
2232 error("missing body { ... } after in or out");
2233 f
->fbody
= parseStatement(PSsemi
| PScolon
);
2239 f
->fbody
= parseStatement(PScurly
);
2245 error("unexpected semi-colon after function declaration");
2248 if (f
->frequire
|| f
->fensure
)
2249 error("missing body { ... } after in or out");
2253 #if 0 // Do we want this for function declarations, so we can do:
2254 // int x, y, foo(), z;
2260 #if 0 // Dumped feature
2263 f
->fthrows
= new Array();
2268 tb
= parseBasicType();
2269 f
->fthrows
->push(tb
);
2270 if (token
.value
== TOKcomma
)
2283 error("redundant 'in' statement");
2284 f
->frequire
= parseStatement(PScurly
| PSscope
);
2288 // parse: out (identifier) { statement }
2290 if (token
.value
!= startBlockTok
)
2293 if (token
.value
!= TOKidentifier
)
2294 error("(identifier) following 'out' expected, not %s", token
.toChars());
2295 f
->outId
= token
.ident
;
2300 error("redundant 'out' statement");
2301 f
->fensure
= parseStatement(PScurly
| PSscope
);
2305 error("%s expected following function declaration", endToken());
2311 /*****************************************
2314 Initializer
*Parser::parseInitializer()
2316 StructInitializer
*is
;
2317 ArrayInitializer
*ia
;
2323 Loc loc
= this->loc
;
2327 switch (token
.value
)
2330 /* Scan ahead to see if it is a struct initializer or
2331 * a function literal.
2332 * If it contains a ';', it is a function literal.
2333 * Treat { } as a struct initializer.
2336 for (t
= peek(&token
); 1; t
= peek(t
))
2362 is
= new StructInitializer(loc
);
2367 switch (token
.value
)
2371 error("comma expected separating field initializers");
2373 if (t
->value
== TOKcolon
)
2377 nextToken(); // skip over ':'
2382 value
= parseInitializer();
2383 is
->addInit(id
, value
);
2392 case TOKrcurly
: // allow trailing comma's
2397 error("found EOF instead of initializer");
2401 value
= parseInitializer();
2402 is
->addInit(NULL
, value
);
2405 //error("found '%s' instead of field initializer", token.toChars());
2413 ia
= new ArrayInitializer(loc
);
2418 switch (token
.value
)
2422 { error("comma expected separating array initializers, not %s", token
.toChars());
2426 e
= parseAssignExp();
2429 if (token
.value
== TOKcolon
)
2432 value
= parseInitializer();
2435 { value
= new ExpInitializer(e
->loc
, e
);
2438 ia
->addInit(e
, value
);
2445 error("comma expected separating array initializers, not %s", token
.toChars());
2446 value
= parseInitializer();
2447 ia
->addInit(NULL
, value
);
2456 case TOKrbracket
: // allow trailing comma's
2461 error("found '%s' instead of array initializer", token
.toChars());
2470 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
|| t
->value
== TOKendline
)
2473 return new VoidInitializer(loc
);
2479 e
= parseAssignExp();
2480 ie
= new ExpInitializer(loc
, e
);
2486 /*****************************************
2491 Statement
*DltParser::parseStatement(int flags
)
2494 if (flags
& (PScolon
| PSscope
))
2496 return Parser::parseStatement(flags
);
2499 Statement
*Parser::parseStatement(int flags
)
2502 Condition
*condition
;
2504 Statement
*elsebody
;
2505 Loc loc
= this->loc
;
2507 //printf("parseStatement()\n");
2509 if ((flags
& PScurly
) && token
.value
!= startBlockTok
)
2510 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2512 int tok
= token
.value
;
2514 switch (token
.value
)
2519 // Need to look ahead to see if it is a declaration, label, or expression
2521 if (t
->value
== TOKcolon
)
2525 ident
= token
.ident
;
2528 s
= parseStatement(PSsemi
);
2529 s
= new LabelStatement(loc
, ident
, s
);
2533 // fallthrough to TOKdot
2536 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2552 case TOKimaginary32v
:
2553 case TOKimaginary64v
:
2554 case TOKimaginary80v
:
2579 exp
= parseExpression();
2581 check(TOKsemicolon
, "statement");
2582 s
= new ExpStatement(loc
, exp
);
2587 { // Look ahead to see if it's static assert() or static if()
2591 if (t
->value
== TOKassert
)
2594 s
= new StaticAssertStatement(parseStaticAssert());
2597 if (t
->value
== TOKif
)
2600 condition
= parseStaticIfCondition();
2618 a
= parseDeclarations();
2621 Statements
*as
= new Statements();
2622 as
->reserve(a
->dim
);
2623 for (int i
= 0; i
< a
->dim
; i
++)
2625 Dsymbol
*d
= (Dsymbol
*)a
->data
[i
];
2626 s
= new DeclarationStatement(loc
, d
);
2629 s
= new CompoundStatement(loc
, as
);
2631 else if (a
->dim
== 1)
2633 Dsymbol
*d
= (Dsymbol
*)a
->data
[0];
2634 s
= new DeclarationStatement(loc
, d
);
2638 if (flags
& PSscope
)
2639 s
= new ScopeStatement(loc
, s
);
2649 d
= parseAggregate();
2650 s
= new DeclarationStatement(loc
, d
);
2658 s
= new DeclarationStatement(loc
, d
);
2664 if (t
->value
== TOKlparen
)
2667 check(TOKlparen
, "mixin");
2668 Expression
*e
= parseAssignExp();
2670 check(TOKsemicolon
);
2671 s
= new CompileStatement(loc
, e
);
2674 Dsymbol
*d
= parseMixin();
2675 s
= new DeclarationStatement(loc
, d
);
2681 { Statements
*statements
;
2683 if (token
.value
!= startBlockTok
)
2684 error("statement expected to start with %s, not %s", Token::toChars(startBlockTok
), token
.toChars());
2688 statements
= new Statements();
2689 while (token
.value
!= TOKrcurly
)
2691 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2695 s
= new CompoundStatement(loc
, statements
);
2696 if (flags
& (PSscope
| PScurlyscope
))
2697 s
= new ScopeStatement(loc
, s
);
2703 { Expression
*condition
;
2708 condition
= parseExpression();
2710 body
= parseStatement(PSscope
);
2711 s
= new WhileStatement(loc
, condition
, body
);
2716 if (!(flags
& PSsemi
))
2717 error("use '{ }' for an empty statement, not a ';'");
2719 s
= new ExpStatement(loc
, NULL
);
2724 Expression
*condition
;
2727 body
= parseStatement(PSscope
);
2730 condition
= parseExpression();
2732 s
= new DoStatement(loc
, body
, condition
);
2739 Expression
*condition
;
2740 Expression
*increment
;
2745 if (token
.value
== TOKlparen
) {
2746 /* for (init; cond; incr): ... */
2748 if (token
.value
== TOKsemicolon
)
2753 { init
= parseStatement(0);
2755 check(TOKsemicolon
);
2757 if (token
.value
== TOKsemicolon
)
2764 condition
= parseExpression();
2765 check(TOKsemicolon
, "for condition");
2767 if (token
.value
== TOKrparen
)
2772 { increment
= parseExpression();
2775 body
= parseStatement(PSscope
);
2776 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2778 s
= new ScopeStatement(loc
, s
);
2779 } else if (dltSyntax
)
2786 case TOKforeach_reverse
:
2788 /* for var in seq: ... */
2789 /* for index, var in seq: ... */
2790 Arguments
*arguments
;
2795 enum TOK op
= (TOK
) tok
;
2802 TOK inTok
= dltSyntax
? TOKin
: TOKsemicolon
;
2804 arguments
= new Arguments();
2809 Identifier
*ai
= NULL
;
2811 unsigned storageClass
;
2814 storageClass
= STCin
;
2815 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2816 { storageClass
= STCref
;
2819 if (token
.value
== TOKidentifier
)
2821 Token
*t
= peek(&token
);
2822 if (t
->value
== TOKcomma
|| t
->value
== inTok
)
2824 at
= NULL
; // infer argument type
2829 tb
= parseBasicType();
2830 at
= parseDeclarator(tb
, &ai
);
2832 error("no identifier for declarator %s", at
->toChars());
2834 a
= new Argument(storageClass
, at
, ai
, NULL
);
2836 if (token
.value
== TOKcomma
)
2845 aggr
= parseExpression();
2849 if (token
.value
== TOKreversed
) {
2850 op
= TOKforeach_reverse
;
2857 body
= parseStatement(PScolon
);
2858 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2863 { Argument
*arg
= NULL
;
2864 Expression
*condition
;
2866 Statement
*elsebody
;
2871 if (token
.value
== TOKauto
)
2874 if (token
.value
== TOKidentifier
)
2876 Token
*t
= peek(&token
);
2877 if (t
->value
== TOKassign
)
2879 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2884 { error("= expected following auto identifier");
2889 { error("identifier expected following auto");
2893 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
2899 tb
= parseBasicType();
2900 at
= parseDeclarator(tb
, &ai
);
2902 arg
= new Argument(STCin
, at
, ai
, NULL
);
2905 // Check for " ident;"
2906 else if (token
.value
== TOKidentifier
&& !dltSyntax
)
2908 Token
*t
= peek(&token
);
2909 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2911 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2914 if (1 || !global
.params
.useDeprecated
)
2915 error("if (v; e) is deprecated, use if (auto v = e)");
2919 condition
= parseExpression();
2921 ifbody
= parseStatement(PSscope
);
2922 if (token
.value
== TOKelse
)
2927 if (token
.value
== TOKcolon
) {
2928 elsebody
= parseStatement(PSscope
);
2929 } else if (token
.value
== TOKif
) {
2930 elsebody
= parseStatement(0);
2932 error("Expected 'else:' or 'else if', not 'else %s'", token
.toChars());
2937 elsebody
= parseStatement(PSscope
);
2941 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
2946 if (peek(&token
)->value
!= TOKlparen
)
2947 goto Ldeclaration
; // scope used as storage class
2950 if (token
.value
!= TOKidentifier
)
2951 { error("scope identifier expected");
2955 { TOK t
= TOKon_scope_exit
;
2956 Identifier
*id
= token
.ident
;
2959 t
= TOKon_scope_exit
;
2960 else if (id
== Id::failure
)
2961 t
= TOKon_scope_failure
;
2962 else if (id
== Id::success
)
2963 t
= TOKon_scope_success
;
2965 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
2968 Statement
*st
= parseStatement(PScolon
| PScurlyscope
);
2969 s
= new OnScopeStatement(loc
, t
, st
);
2975 condition
= parseDebugCondition();
2980 condition
= parseVersionCondition();
2984 if (dltSyntax
&& token
.value
!= TOKcolon
)
2985 error("expected colon after condition, not '%s'", token
.toChars());
2986 ifbody
= parseStatement(PScolon
/*PSsemi*/);
2988 if (token
.value
== TOKelse
)
2991 elsebody
= parseStatement(PScolon
/*PSsemi*/);
2993 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
2997 { Identifier
*ident
;
2998 Expressions
*args
= NULL
;
3003 if (token
.value
!= TOKidentifier
)
3004 { error("pragma(identifier expected");
3007 ident
= token
.ident
;
3009 if (token
.value
== TOKcomma
)
3010 args
= parseArguments(); // pragma(identifier, args...);
3012 check(TOKrparen
); // pragma(identifier);
3013 if (token
.value
== TOKsemicolon
)
3018 body
= parseStatement(PSsemi
| PScolon
);
3019 s
= new PragmaStatement(loc
, ident
, args
, body
);
3024 { Expression
*condition
;
3029 condition
= parseExpression();
3031 body
= parseStatement(PSscope
| PScolon
);
3032 s
= new SwitchStatement(loc
, condition
, body
);
3038 Statements
*statements
;
3039 Array cases
; // array of Expression's
3044 exp
= parseAssignExp();
3046 if (token
.value
!= TOKcomma
)
3052 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3058 statements
= new Statements();
3059 while (token
.value
!= TOKcase
&&
3060 token
.value
!= TOKdefault
&&
3061 token
.value
!= TOKrcurly
)
3063 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3065 s
= new CompoundStatement(loc
, statements
);
3068 s
= new ScopeStatement(loc
, s
);
3070 // Keep cases in order by building the case statements backwards
3071 for (int i
= cases
.dim
; i
; i
--)
3073 exp
= (Expression
*)cases
.data
[i
- 1];
3074 s
= new CaseStatement(loc
, exp
, s
);
3081 Statements
*statements
;
3087 s
= parseStatement(PSsemi
| PScurlyscope
| PScolon
);
3093 statements
= new Statements();
3094 while (token
.value
!= TOKcase
&&
3095 token
.value
!= TOKdefault
&&
3096 token
.value
!= TOKrcurly
)
3098 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
3100 s
= new CompoundStatement(loc
, statements
);
3103 s
= new ScopeStatement(loc
, s
);
3104 s
= new DefaultStatement(loc
, s
);
3112 if (token
.value
== TOKsemicolon
|| token
.value
== TOKendline
)
3115 exp
= parseExpression();
3117 check(TOKsemicolon
, "return statement");
3118 else if (token
.value
== TOKsemicolon
)
3119 nextToken(); // Or we get unreachable statement errors
3120 else if (token
.value
!= TOKendline
) {
3121 error("Expected end-of-line after return statement, but found '%s'", token
.toChars());
3124 s
= new ReturnStatement(loc
, exp
);
3129 { Identifier
*ident
;
3132 if (token
.value
== TOKidentifier
)
3133 { ident
= token
.ident
;
3138 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3139 error("expected %s after break, not '%s'", endToken(), token
.toChars());
3141 s
= new BreakStatement(loc
, ident
);
3146 { Identifier
*ident
;
3149 if (token
.value
== TOKidentifier
)
3150 { ident
= token
.ident
;
3155 check(TOKsemicolon
, "continue statement");
3156 s
= new ContinueStatement(loc
, ident
);
3161 { Identifier
*ident
;
3164 if (token
.value
== TOKdefault
)
3167 s
= new GotoDefaultStatement(loc
);
3169 else if (token
.value
== TOKcase
)
3171 Expression
*exp
= NULL
;
3174 if (token
.value
!= TOKsemicolon
)
3175 exp
= parseExpression();
3176 s
= new GotoCaseStatement(loc
, exp
);
3180 if (token
.value
!= TOKidentifier
)
3181 { error("Identifier expected following goto");
3185 { ident
= token
.ident
;
3188 s
= new GotoStatement(loc
, ident
);
3190 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3191 error("expected %s after goto statement, not '%s'", endToken(), token
.toChars());
3196 case TOKsynchronized
:
3201 if (token
.value
== TOKlparen
)
3204 exp
= parseExpression();
3209 body
= parseStatement(PSscope
);
3210 s
= new SynchronizedStatement(loc
, exp
, body
);
3220 exp
= parseExpression();
3222 body
= parseStatement(PSscope
);
3223 s
= new WithStatement(loc
, exp
, body
);
3229 Array
*catches
= NULL
;
3230 Statement
*finalbody
= NULL
;
3233 body
= parseStatement(PSscope
);
3234 while (token
.value
== TOKcatch
)
3240 Loc loc
= this->loc
;
3243 if (token
.value
== startBlockTok
)
3251 t
= parseBasicType();
3253 t
= parseDeclarator(t
, &id
);
3256 handler
= parseStatement(PScolon
);
3257 c
= new Catch(loc
, t
, id
, handler
);
3259 catches
= new Array();
3263 if (token
.value
== TOKfinally
)
3265 finalbody
= parseStatement(PScolon
);
3269 if (!catches
&& !finalbody
)
3270 error("catch or finally expected following try");
3273 s
= new TryCatchStatement(loc
, body
, catches
);
3275 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3284 exp
= parseExpression();
3285 if (token
.value
!= TOKsemicolon
&& token
.value
!= TOKendline
) {
3286 error("%s expected after throw statement, not '%s'", endToken(), token
.toChars());
3288 s
= new ThrowStatement(loc
, exp
);
3294 s
= parseStatement(PSsemi
| PScurlyscope
);
3295 s
= new VolatileStatement(loc
, s
);
3299 { Statements
*statements
;
3305 // Parse the asm block into a sequence of AsmStatements,
3306 // each AsmStatement is one instruction.
3307 // Separate out labels.
3308 // Defer parsing of AsmStatements until semantic processing.
3311 #if GDC_EXTENDED_ASM_SYNTAX
3312 if (token
.value
== TOKlparen
)
3319 check(startBlockTok
);
3321 ptoklist
= &toklist
;
3323 statements
= new Statements();
3326 switch (token
.value
)
3331 // Look ahead to see if it is a label
3333 if (t
->value
== TOKcolon
)
3335 label
= token
.ident
;
3336 labelloc
= this->loc
;
3345 if (toklist
|| label
)
3347 error("asm statements must end in ';'");
3354 if (toklist
|| label
)
3355 { // Create AsmStatement from list of tokens we've saved
3356 s
= new AsmStatement(this->loc
, toklist
);
3358 ptoklist
= &toklist
;
3360 { s
= new LabelStatement(labelloc
, label
, s
);
3363 statements
->push(s
);
3370 error("matching '}' expected, not end of file");
3375 // If the first token is a string or '(', parse as extended asm.
3379 statements
->push(s
);
3382 // ...else, drop through.
3386 *ptoklist
= new Token();
3387 memcpy(*ptoklist
, &token
, sizeof(Token
));
3388 ptoklist
= &(*ptoklist
)->next
;
3396 s
= new CompoundStatement(loc
, statements
);
3402 error("found '%s' instead of statement", token
.toChars());
3406 while (token
.value
!= TOKrcurly
&&
3407 token
.value
!= TOKsemicolon
&&
3408 token
.value
!= TOKeof
)
3410 if (token
.value
== TOKsemicolon
)
3419 Statement
*Parser::parseExtAsm(int expect_rparen
)
3421 Expression
* insnTemplate
;
3422 Expressions
* args
= NULL
;
3423 Array
* argNames
= NULL
;
3424 Expressions
* argConstraints
= NULL
;
3425 int nOutputArgs
= 0;
3426 Expressions
* clobbers
= NULL
;
3427 bool isInputPhase
= false; // Output operands first, then input.
3429 insnTemplate
= parseExpression();
3430 if (token
.value
== TOKrparen
|| token
.value
== TOKsemicolon
)
3434 Expression
* arg
= NULL
;
3435 Identifier
* name
= NULL
;
3436 Expression
* constraint
= NULL
;
3438 switch (token
.value
)
3449 error("unterminated statement");
3453 if (token
.value
== TOKidentifier
)
3459 error("expected identifier after '['");
3463 constraint
= parsePrimaryExp();
3464 if (constraint
->op
!= TOKstring
)
3465 error("expected constant string constraint for operand");
3466 arg
= parseAssignExp();
3469 args
= new Expressions
;
3470 argConstraints
= new Expressions
;
3471 argNames
= new Array
;
3474 argNames
->push(name
);
3475 argConstraints
->push(constraint
);
3479 if (token
.value
== TOKcomma
)
3486 isInputPhase
= true;
3493 Expression
* clobber
;
3495 switch (token
.value
)
3502 error("unterminated statement");
3505 clobber
= parseAssignExp();
3506 if (clobber
->op
!= TOKstring
)
3507 error("expected constant string constraint for clobber name");
3509 clobbers
= new Expressions
;
3510 clobbers
->push(clobber
);
3512 if (token
.value
== TOKcomma
)
3521 check(TOKsemicolon
);
3523 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3524 argConstraints
, nOutputArgs
, clobbers
);
3527 void Parser::optionalEndline() {
3528 while (token
.value
== TOKendline
) {
3533 void Parser::check(enum TOK value
)
3538 void Parser::check(Loc loc
, enum TOK value
)
3540 if (token
.value
!= value
)
3541 error(loc
, "found '%s' when expecting '%s'", token
.toChars(), Token::toChars(value
));
3545 void Parser::check(enum TOK value
, char *string
)
3547 if (token
.value
!= value
)
3548 error("found '%s' when expecting '%s' following '%s'",
3549 token
.toChars(), Token::toChars(value
), string
);
3553 char *Parser::endToken()
3558 char *DltParser::endToken()
3563 void Parser::checkLParen() { check(TOKlparen
); }
3564 void Parser::checkRParen() { check(TOKrparen
); }
3566 void DltParser::checkLParen() { }
3567 void DltParser::checkRParen() { }
3569 /************************************
3570 * Determine if the scanner is sitting on the start of a declaration.
3572 * needId 0 no identifier
3573 * 1 identifier optional
3574 * 2 must have identifier
3577 int Parser::isDeclaration(Token
*t
, int needId
, enum TOK endtok
, Token
**pt
)
3581 if (!isBasicType(&t
))
3583 if (!isDeclarator(&t
, &haveId
, endtok
))
3586 (needId
== 0 && !haveId
) ||
3587 (needId
== 2 && haveId
))
3596 int Parser::isBasicType(Token
**pt
)
3598 // This code parallels parseBasicType()
3611 if (t
->value
== TOKnot
)
3621 if (t
->value
== TOKdot
)
3625 if (t
->value
!= TOKidentifier
)
3628 if (t
->value
!= TOKnot
)
3632 if (t
->value
!= TOKlparen
)
3634 if (!skipParens(t
, &t
))
3646 /* typeof(exp).identifier...
3649 if (t
->value
!= TOKlparen
)
3651 if (!skipParens(t
, &t
))
3665 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3666 { // This code parallels parseDeclarator()
3670 //printf("Parser::isDeclarator()\n");
3672 if (t
->value
== TOKassign
)
3687 if (t
->value
== TOKrbracket
)
3691 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3692 { // It's an associative array declaration
3698 // [ expression .. expression ]
3699 if (!isExpression(&t
))
3701 if (t
->value
== TOKslice
)
3703 if (!isExpression(&t
))
3706 if (t
->value
!= TOKrbracket
)
3722 if (t
->value
== TOKrparen
)
3723 return FALSE
; // () is not a declarator
3725 /* Regard ( identifier ) as not a declarator
3726 * BUG: what about ( *identifier ) in
3728 * where f is a class instance with overloaded () ?
3729 * Should we just disallow C-style function pointer declarations?
3731 if (t
->value
== TOKidentifier
)
3732 { Token
*t2
= peek(t
);
3733 if (t2
->value
== TOKrparen
)
3738 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3747 if (!isParameters(&t
))
3762 if (t
->value
== TOKrbracket
)
3766 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3767 { // It's an associative array declaration
3773 if (!isExpression(&t
))
3775 if (t
->value
!= TOKrbracket
)
3784 if (!isParameters(&t
))
3788 // Valid tokens that follow a declaration
3797 // The !parens is to disallow unnecessary parentheses
3798 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3811 int Parser::isParameters(Token
**pt
)
3812 { // This code parallels parseParameters()
3816 //printf("isParameters()\n");
3817 if (t
->value
!= TOKlparen
)
3839 if (!isBasicType(&t
))
3842 if (t
->value
!= TOKdotdotdot
&&
3843 !isDeclarator(&t
, &tmp
, TOKreserved
))
3845 if (t
->value
== TOKassign
)
3847 if (!isExpression(&t
))
3850 if (t
->value
== TOKdotdotdot
)
3855 if (t
->value
== TOKcomma
)
3863 if (t
->value
!= TOKrparen
)
3870 int Parser::isExpression(Token
**pt
)
3872 // This is supposed to determine if something is an expression.
3873 // What it actually does is scan until a closing right bracket
3880 for (;; t
= peek(t
))
3898 if (brnest
|| panest
)
3925 /**********************************************
3927 * instance foo.bar(parameters...)
3929 * if (pt), *pt is set to the token following the closing )
3931 * 1 it's valid instance syntax
3932 * 0 invalid instance syntax
3935 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
3938 if (t
->value
!= TOKdot
)
3940 if (t
->value
!= TOKidentifier
)
3944 while (t
->value
== TOKdot
)
3947 if (t
->value
!= TOKidentifier
)
3951 if (t
->value
!= TOKlparen
)
3954 // Skip over the template arguments
3963 if (!skipParens(t
, &t
))
3979 if (t
->value
!= TOKcomma
)
3982 if (t
->value
!= TOKrparen
)
3993 /*******************************************
3994 * Skip parens, brackets.
3998 * *pt is set to closing token, which is ')' on success
4001 * 0 some parsing error
4004 int Parser::skipParens(Token
*t
, Token
**pt
)
4043 /********************************* Expression Parser ***************************/
4045 Expression
*Parser::parsePrimaryExp()
4050 Loc loc
= this->loc
;
4052 switch (token
.value
)
4057 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4058 { // identifier!(template-argument-list)
4059 TemplateInstance
*tempinst
;
4061 tempinst
= new TemplateInstance(loc
, id
);
4063 tempinst
->tiargs
= parseTemplateArgumentList();
4064 e
= new ScopeExp(loc
, tempinst
);
4067 e
= new IdentifierExp(loc
, id
);
4072 error("'$' is valid only inside [] of index or slice");
4073 e
= new DollarExp(loc
);
4078 // Signal global scope '.' operator with "" identifier
4079 e
= new IdentifierExp(loc
, Id::empty
);
4083 e
= new ThisExp(loc
);
4088 e
= new SuperExp(loc
);
4093 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
4098 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
4103 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
4108 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
4113 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
4118 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
4123 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
4127 case TOKimaginary32v
:
4128 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
4132 case TOKimaginary64v
:
4133 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
4137 case TOKimaginary80v
:
4138 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
4143 e
= new NullExp(loc
);
4148 e
= new IntegerExp(loc
, 1, Type::tbool
);
4153 e
= new IntegerExp(loc
, 0, Type::tbool
);
4158 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
4163 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
4168 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
4175 unsigned char postfix
;
4177 // cat adjacent strings
4180 postfix
= token
.postfix
;
4184 if (token
.value
== TOKstring
)
4190 { if (token
.postfix
!= postfix
)
4191 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4192 postfix
= token
.postfix
;
4198 s2
= (unsigned char *)mem
.malloc((len
+ 1) * sizeof(unsigned char));
4199 memcpy(s2
, s
, len1
* sizeof(unsigned char));
4200 memcpy(s2
+ len1
, token
.ustring
, (len2
+ 1) * sizeof(unsigned char));
4206 e
= new StringExp(loc
, s
, len
, postfix
);
4210 CASE_BASIC_TYPES_X(t
):
4213 check(TOKdot
, t
->toChars());
4214 if (token
.value
!= TOKidentifier
)
4215 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4218 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4227 exp
= parseExpression();
4229 t
= new TypeTypeof(loc
, exp
);
4230 if (token
.value
== TOKdot
)
4232 e
= new TypeExp(loc
, t
);
4240 check(TOKlparen
, "typeid");
4241 t
= parseBasicType();
4242 t
= parseDeclarator(t
,NULL
); // ( type )
4244 e
= new TypeidExp(loc
, t
);
4250 Identifier
*ident
= NULL
;
4252 enum TOK tok
= TOKreserved
;
4253 enum TOK tok2
= TOKreserved
;
4254 Loc loc
= this->loc
;
4257 if (token
.value
== TOKlparen
)
4260 targ
= parseBasicType();
4261 targ
= parseDeclarator(targ
, &ident
);
4262 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
4266 if (tok
== TOKequal
&&
4267 (token
.value
== TOKtypedef
||
4268 token
.value
== TOKstruct
||
4269 token
.value
== TOKunion
||
4270 token
.value
== TOKclass
||
4271 token
.value
== TOKsuper
||
4272 token
.value
== TOKenum
||
4273 token
.value
== TOKinterface
||
4274 token
.value
== TOKfunction
||
4275 token
.value
== TOKdelegate
||
4276 token
.value
== TOKreturn
))
4283 tspec
= parseBasicType();
4284 tspec
= parseDeclarator(tspec
, NULL
);
4290 { error("(type identifier : specialization) expected following is");
4293 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4298 { Expression
*msg
= NULL
;
4303 e
= parseAssignExp();
4304 if (token
.value
== (dltSyntax
? TOKelse
: TOKcomma
))
4306 msg
= parseAssignExp();
4310 e
= new AssertExp(loc
, e
, msg
);
4317 check(TOKlparen
, "mixin");
4318 e
= parseAssignExp();
4320 e
= new CompileExp(loc
, e
);
4327 check(TOKlparen
, "import");
4328 e
= parseAssignExp();
4330 e
= new FileExp(loc
, e
);
4335 if (peekPastParen(&token
)->value
== TOKlcurly
)
4336 { // (arguments) { statements... }
4342 e
= parseExpression();
4343 check(loc
, TOKrparen
);
4347 { /* Parse array literals and associative array literals:
4348 * [ value, value, value ... ]
4349 * [ key:value, key:value, key:value ... ]
4351 Expressions
*values
= new Expressions();
4352 Expressions
*keys
= NULL
;
4355 if (token
.value
!= TOKrbracket
)
4359 Expression
*e
= parseAssignExp();
4360 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4363 keys
= new Expressions();
4365 e
= parseAssignExp();
4368 { error("'key:value' expected for associative array literal");
4373 if (token
.value
== TOKrbracket
)
4381 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4383 e
= new ArrayLiteralExp(loc
, values
);
4388 // { statements... }
4398 /* function type(parameters) { body }
4399 * delegate type(parameters) { body }
4401 Arguments
*arguments
;
4403 FuncLiteralDeclaration
*fd
;
4406 if (token
.value
== TOKlcurly
)
4410 arguments
= new Arguments();
4414 if (token
.value
== TOKlparen
)
4418 t
= parseBasicType();
4419 t
= parseBasicType2(t
); // function return type
4421 arguments
= parseParameters(&varargs
);
4423 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
4424 fd
= new FuncLiteralDeclaration(loc
, 0, t
, save
, NULL
);
4426 e
= new FuncExp(loc
, fd
);
4431 error("expression expected, not '%s'", token
.toChars());
4433 // Anything for e, as long as it's not NULL
4434 e
= new IntegerExp(loc
, 0, Type::tint32
);
4438 return parsePostExp(e
);
4441 Expression
*Parser::parsePostExp(Expression
*e
)
4448 switch (token
.value
)
4452 if (token
.value
== TOKidentifier
)
4453 { Identifier
*id
= token
.ident
;
4456 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4457 { // identifier!(template-argument-list)
4458 TemplateInstance
*tempinst
;
4460 tempinst
= new TemplateInstance(loc
, id
);
4462 tempinst
->tiargs
= parseTemplateArgumentList();
4463 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4466 e
= new DotIdExp(loc
, e
, id
);
4469 else if (token
.value
== TOKnew
)
4475 error("identifier expected following '.', not '%s'", token
.toChars());
4479 e
= new PostExp(TOKplusplus
, loc
, e
);
4483 e
= new PostExp(TOKminusminus
, loc
, e
);
4487 e
= new CallExp(loc
, e
, parseArguments());
4491 { // array dereferences:
4494 // array[lwr .. upr]
4500 if (token
.value
== TOKrbracket
)
4502 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4507 index
= parseAssignExp();
4508 if (token
.value
== TOKslice
)
4509 { // array[lwr .. upr]
4511 upr
= parseAssignExp();
4512 e
= new SliceExp(loc
, e
, index
, upr
);
4515 { // array[index, i2, i3, i4, ...]
4516 Expressions
*arguments
= new Expressions();
4517 arguments
->push(index
);
4518 if (token
.value
== TOKcomma
)
4524 arg
= parseAssignExp();
4525 arguments
->push(arg
);
4526 if (token
.value
== TOKrbracket
)
4531 e
= new ArrayExp(loc
, e
, arguments
);
4546 Expression
*Parser::parseUnaryExp()
4548 Loc loc
= this->loc
;
4550 switch (token
.value
)
4554 e
= parseUnaryExp();
4555 e
= new AddrExp(loc
, e
);
4560 e
= parseUnaryExp();
4561 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4566 e
= parseUnaryExp();
4567 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4572 e
= parseUnaryExp();
4573 e
= new PtrExp(loc
, e
);
4578 e
= parseUnaryExp();
4579 e
= new NegExp(loc
, e
);
4584 e
= parseUnaryExp();
4585 e
= new UAddExp(loc
, e
);
4590 e
= parseUnaryExp();
4591 e
= new NotExp(loc
, e
);
4596 e
= parseUnaryExp();
4597 e
= new ComExp(loc
, e
);
4602 e
= parseUnaryExp();
4603 e
= new DeleteExp(loc
, e
);
4607 e
= parseNewExp(NULL
);
4610 case TOKcast
: // cast(type) expression
4615 t
= parseBasicType();
4616 t
= parseDeclarator(t
,NULL
); // ( type )
4619 e
= parseUnaryExp();
4620 e
= new CastExp(loc
, e
, t
);
4630 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4632 tk
= peek(tk
); // skip over right parenthesis
4652 case TOKimaginary32v
:
4653 case TOKimaginary64v
:
4654 case TOKimaginary80v
:
4672 CASE_BASIC_TYPES
: // (type)int.size
4677 t
= parseBasicType();
4678 t
= parseDeclarator(t
,NULL
);
4682 if (token
.value
== TOKdot
)
4685 if (token
.value
!= TOKidentifier
)
4686 { error("Identifier expected following (type).");
4689 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4691 e
= parsePostExp(e
);
4695 e
= parseUnaryExp();
4696 e
= new CastExp(loc
, e
, t
);
4697 error("C style cast illegal, use %s", e
->toChars());
4704 e
= parsePrimaryExp();
4708 e
= parsePrimaryExp();
4715 Expression
*Parser::parseMulExp()
4718 Loc loc
= this->loc
;
4720 e
= parseUnaryExp();
4723 switch (token
.value
)
4725 case TOKmul
: nextToken(); e2
= parseUnaryExp(); e
= new MulExp(loc
,e
,e2
); continue;
4726 case TOKdiv
: nextToken(); e2
= parseUnaryExp(); e
= new DivExp(loc
,e
,e2
); continue;
4727 case TOKmod
: nextToken(); e2
= parseUnaryExp(); e
= new ModExp(loc
,e
,e2
); continue;
4737 Expression
*Parser::parseAddExp()
4740 Loc loc
= this->loc
;
4745 switch (token
.value
)
4747 case TOKadd
: nextToken(); e2
= parseMulExp(); e
= new AddExp(loc
,e
,e2
); continue;
4748 case TOKmin
: nextToken(); e2
= parseMulExp(); e
= new MinExp(loc
,e
,e2
); continue;
4749 case TOKtilde
: nextToken(); e2
= parseMulExp(); e
= new CatExp(loc
,e
,e2
); continue;
4759 Expression
*Parser::parseShiftExp()
4762 Loc loc
= this->loc
;
4767 switch (token
.value
)
4769 case TOKshl
: nextToken(); e2
= parseAddExp(); e
= new ShlExp(loc
,e
,e2
); continue;
4770 case TOKshr
: nextToken(); e2
= parseAddExp(); e
= new ShrExp(loc
,e
,e2
); continue;
4771 case TOKushr
: nextToken(); e2
= parseAddExp(); e
= new UshrExp(loc
,e
,e2
); continue;
4781 Expression
*Parser::parseRelExp()
4785 Loc loc
= this->loc
;
4787 e
= parseShiftExp();
4790 switch (token
.value
)
4806 e2
= parseShiftExp();
4807 e
= new CmpExp(op
, loc
, e
, e2
);
4812 e2
= parseShiftExp();
4813 e
= new InExp(loc
, e
, e2
);
4824 Expression
*Parser::parseEqualExp()
4828 Loc loc
= this->loc
;
4832 { enum TOK value
= token
.value
;
4840 e
= new EqualExp(value
, loc
, e
, e2
);
4844 error("'===' is no longer legal, use 'is' instead");
4847 case TOKnotidentity
:
4848 error("'!==' is no longer legal, use '!is' instead");
4852 value
= TOKidentity
;
4856 // Attempt to identify '!is'
4858 if (t
->value
!= TOKis
)
4861 value
= TOKnotidentity
;
4867 e
= new IdentityExp(value
, loc
, e
, e2
);
4878 Expression
*Parser::parseCmpExp()
4882 Loc loc
= this->loc
;
4884 e
= parseShiftExp();
4885 enum TOK op
= token
.value
;
4892 e2
= parseShiftExp();
4893 e
= new EqualExp(op
, loc
, e
, e2
);
4901 // Attempt to identify '!is'
4903 if (t
->value
!= TOKis
)
4906 op
= TOKnotidentity
;
4911 e2
= parseShiftExp();
4912 e
= new IdentityExp(op
, loc
, e
, e2
);
4928 e2
= parseShiftExp();
4929 e
= new CmpExp(op
, loc
, e
, e2
);
4934 e2
= parseShiftExp();
4935 e
= new InExp(loc
, e
, e2
);
4944 Expression
*Parser::parseAndExp()
4947 Loc loc
= this->loc
;
4949 if (global
.params
.Dversion
== 1)
4951 e
= parseEqualExp();
4952 while (token
.value
== TOKand
)
4955 e2
= parseEqualExp();
4956 e
= new AndExp(loc
,e
,e2
);
4963 while (token
.value
== TOKand
)
4967 e
= new AndExp(loc
,e
,e2
);
4974 Expression
*Parser::parseXorExp()
4977 Loc loc
= this->loc
;
4980 while (token
.value
== TOKxor
)
4984 e
= new XorExp(loc
, e
, e2
);
4989 Expression
*Parser::parseOrExp()
4992 Loc loc
= this->loc
;
4995 while (token
.value
== TOKor
)
4999 e
= new OrExp(loc
, e
, e2
);
5004 Expression
*Parser::parseAndAndExp()
5007 Loc loc
= this->loc
;
5010 while (token
.value
== TOKandand
)
5014 e
= new AndAndExp(loc
, e
, e2
);
5019 Expression
*Parser::parseOrOrExp()
5022 Loc loc
= this->loc
;
5024 e
= parseAndAndExp();
5025 while (token
.value
== TOKoror
)
5028 e2
= parseAndAndExp();
5029 e
= new OrOrExp(loc
, e
, e2
);
5034 Expression
*Parser::parseCondExp()
5038 Loc loc
= this->loc
;
5041 if (token
.value
== TOKquestion
)
5044 e1
= parseExpression();
5046 e2
= parseCondExp();
5047 e
= new CondExp(loc
, e
, e1
, e2
);
5052 Expression
*Parser::parseAssignExp()
5061 switch (token
.value
)
5063 #define X(tok,ector) \
5064 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
5066 X(TOKassign
, AssignExp
);
5067 X(TOKaddass
, AddAssignExp
);
5068 X(TOKminass
, MinAssignExp
);
5069 X(TOKmulass
, MulAssignExp
);
5070 X(TOKdivass
, DivAssignExp
);
5071 X(TOKmodass
, ModAssignExp
);
5072 X(TOKandass
, AndAssignExp
);
5073 X(TOKorass
, OrAssignExp
);
5074 X(TOKxorass
, XorAssignExp
);
5075 X(TOKshlass
, ShlAssignExp
);
5076 X(TOKshrass
, ShrAssignExp
);
5077 X(TOKushrass
, UshrAssignExp
);
5078 X(TOKcatass
, CatAssignExp
);
5089 Expression
*Parser::parseExpression()
5092 Loc loc
= this->loc
;
5094 //printf("Parser::parseExpression()\n");
5095 e
= parseAssignExp();
5096 while (token
.value
== TOKcomma
)
5099 e2
= parseAssignExp();
5100 e
= new CommaExp(loc
, e
, e2
);
5107 /*************************
5108 * Collect argument list.
5109 * Assume current token is '(' or '['.
5112 Expressions
*Parser::parseArguments()
5114 Expressions
*arguments
;
5118 arguments
= new Expressions();
5119 if (token
.value
== TOKlbracket
)
5120 endtok
= TOKrbracket
;
5126 if (token
.value
!= endtok
)
5130 arg
= parseAssignExp();
5131 arguments
->push(arg
);
5132 if (token
.value
== endtok
)
5142 /*******************************************
5145 Expression
*Parser::parseNewExp(Expression
*thisexp
)
5147 Expressions
*newargs
;
5148 Expressions
*arguments
= NULL
;
5150 Loc loc
= this->loc
;
5154 if (token
.value
== TOKlparen
)
5156 newargs
= parseArguments();
5159 // An anonymous nested class starts with "class"
5160 if (token
.value
== TOKclass
)
5163 if (token
.value
== TOKlparen
)
5164 arguments
= parseArguments();
5166 BaseClasses
*baseclasses
= NULL
;
5167 if (token
.value
!= TOKlcurly
)
5168 baseclasses
= parseBaseClasses();
5170 Identifier
*id
= NULL
;
5171 ClassDeclaration
*cd
= new ClassDeclaration(loc
, id
, baseclasses
);
5173 if (token
.value
!= TOKlcurly
)
5174 { error("{ members } expected for anonymous class");
5180 Array
*decl
= parseDeclDefs(0);
5181 if (token
.value
!= TOKrcurly
)
5182 error("class member expected");
5187 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
5193 t
= parseBasicType();
5194 t
= parseBasicType2(t
);
5195 if (t
->ty
== Taarray
)
5197 Type
*index
= ((TypeAArray
*)t
)->index
;
5199 Expression
*e
= index
->toExpression();
5201 { arguments
= new Expressions();
5203 t
= new TypeDArray(t
->next
);
5207 error("need size of rightmost array, not type %s", index
->toChars());
5208 return new NullExp(loc
);
5211 else if (t
->ty
== Tsarray
)
5213 TypeSArray
*tsa
= (TypeSArray
*)t
;
5214 Expression
*e
= tsa
->dim
;
5216 arguments
= new Expressions();
5218 t
= new TypeDArray(t
->next
);
5220 else if (token
.value
== TOKlparen
)
5222 arguments
= parseArguments();
5225 t
= parseBasicType();
5226 while (token
.value
== TOKmul
)
5227 { t
= new TypePointer(t
);
5230 if (token
.value
== TOKlbracket
)
5235 e
= parseAssignExp();
5236 arguments
= new Array();
5239 t
= parseDeclarator(t
, NULL
);
5240 t
= new TypeDArray(t
);
5242 else if (token
.value
== TOKlparen
)
5243 arguments
= parseArguments();
5245 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5249 /**********************************************
5252 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5254 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5258 /********************************* ***************************/