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)
67 //printf("Parser::Parser()\n");
72 //nextToken(); // start up the scanner
75 DltParser::DltParser(Module
*module
, unsigned char *base
, unsigned length
, int doDocComment
)
76 : Parser(module
, base
, length
, doDocComment
)
78 //printf("DltParser::DltParser(%s)\n", module->ident->string);
81 Array
*Parser::parseModule()
85 // ModuleDeclation leads off
86 if (token
.value
== TOKmodule
)
88 unsigned char *comment
= token
.blockComment
;
91 if (token
.value
!= TOKidentifier
)
92 { error("Identifier expected following module");
101 while (nextToken() == TOKdot
)
107 if (token
.value
!= TOKidentifier
)
108 { error("Identifier expected following package");
114 md
= new ModuleDeclaration(a
, id
);
116 if (token
.value
!= TOKsemicolon
)
117 error("';' expected following module declaration instead of %s", token
.toChars());
119 addComment(mod
, comment
);
123 decldefs
= parseDeclDefs(0);
124 if (token
.value
!= TOKeof
)
125 { error("unrecognized declaration");
131 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKeof
)
137 Array
*Parser::parseDeclDefs(int once
)
144 Condition
*condition
;
145 unsigned char *comment
;
147 //printf("Parser::parseDeclDefs()\n");
148 decldefs
= new Array();
151 comment
= token
.blockComment
;
162 s
= parseAggregate();
166 s
= parseImport(decldefs
, 0);
170 s
= (Dsymbol
*)parseTemplateDeclaration();
174 { Loc loc
= this->loc
;
175 if (peek(&token
)->value
== TOKlparen
)
178 check(TOKlparen
, "mixin");
179 Expression
*e
= parseAssignExp();
182 s
= new CompileDeclaration(loc
, e
);
196 a
= parseDeclarations();
210 s
= parseInvariant();
212 if (peek(&token
)->value
== TOKlcurly
)
213 s
= parseInvariant();
240 if (token
.value
== TOKthis
)
241 s
= parseStaticCtor();
242 else if (token
.value
== TOKtilde
)
243 s
= parseStaticDtor();
244 else if (token
.value
== TOKassert
)
245 s
= parseStaticAssert();
246 else if (token
.value
== TOKif
)
247 { condition
= parseStaticIfCondition();
250 if (token
.value
== TOKelse
)
252 aelse
= parseBlock();
254 s
= new StaticIfDeclaration(condition
, a
, aelse
);
257 else if (token
.value
== TOKimport
)
259 s
= parseImport(decldefs
, 1);
267 case TOKconst
: stc
= STCconst
; goto Lstc
;
268 case TOKfinal
: stc
= STCfinal
; goto Lstc
;
269 case TOKauto
: stc
= STCauto
; goto Lstc
;
270 case TOKscope
: stc
= STCscope
; goto Lstc
;
271 case TOKoverride
: stc
= STCoverride
; goto Lstc
;
272 case TOKabstract
: stc
= STCabstract
; goto Lstc
;
273 case TOKsynchronized
: stc
= STCsynchronized
; goto Lstc
;
274 case TOKdeprecated
: stc
= STCdeprecated
; goto Lstc
;
281 case TOKconst
: stc
|= STCconst
; goto Lstc
;
282 case TOKfinal
: stc
|= STCfinal
; goto Lstc
;
283 case TOKauto
: stc
|= STCauto
; goto Lstc
;
284 case TOKscope
: stc
|= STCscope
; goto Lstc
;
285 case TOKoverride
: stc
|= STCoverride
; goto Lstc
;
286 case TOKabstract
: stc
|= STCabstract
; goto Lstc
;
287 case TOKsynchronized
: stc
|= STCsynchronized
; goto Lstc
;
288 case TOKdeprecated
: stc
|= STCdeprecated
; goto Lstc
;
289 //case TOKinvariant: stc |= STCinvariant; goto Lstc;
294 /* Look for auto initializers:
295 * storage_class identifier = initializer;
297 if (token
.value
== TOKidentifier
&&
298 peek(&token
)->value
== TOKassign
)
302 Identifier
*ident
= token
.ident
;
305 Initializer
*init
= parseInitializer();
306 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
307 v
->storage_class
= stc
;
309 if (token
.value
== TOKsemicolon
)
313 else if (token
.value
== TOKcomma
)
316 if (token
.value
== TOKidentifier
&&
317 peek(&token
)->value
== TOKassign
)
320 addComment(s
, comment
);
324 error("Identifier expected following comma");
327 error("semicolon expected following auto declaration, not '%s'", token
.toChars());
333 s
= new StorageClassDeclaration(stc
, a
);
338 if (peek(&token
)->value
!= TOKlparen
)
343 enum LINK linksave
= linkage
;
344 linkage
= parseLinkage();
346 s
= new LinkDeclaration(linkage
, a
);
350 case TOKprivate
: prot
= PROTprivate
; goto Lprot
;
351 case TOKpackage
: prot
= PROTpackage
; goto Lprot
;
352 case TOKprotected
: prot
= PROTprotected
; goto Lprot
;
353 case TOKpublic
: prot
= PROTpublic
; goto Lprot
;
354 case TOKexport
: prot
= PROTexport
; goto Lprot
;
359 s
= new ProtDeclaration(prot
, a
);
367 if (token
.value
== TOKlparen
)
370 if (token
.value
== TOKint32v
)
371 n
= (unsigned)token
.uns64value
;
373 { error("integer expected, not %s", token
.toChars());
380 n
= global
.structalign
; // default
383 s
= new AlignDeclaration(n
, a
);
389 Expressions
*args
= NULL
;
393 if (token
.value
!= TOKidentifier
)
394 { error("pragma(identifier expected");
399 if (token
.value
== TOKcomma
)
400 args
= parseArguments(); // pragma(identifier, args...)
402 check(TOKrparen
); // pragma(identifier)
404 if (token
.value
== TOKsemicolon
)
408 s
= new PragmaDeclaration(loc
, ident
, args
, a
);
414 if (token
.value
== TOKassign
)
417 if (token
.value
== TOKidentifier
)
418 s
= new DebugSymbol(loc
, token
.ident
);
419 else if (token
.value
== TOKint32v
)
420 s
= new DebugSymbol(loc
, (unsigned)token
.uns64value
);
422 { error("identifier or integer expected, not %s", token
.toChars());
426 if (token
.value
!= TOKsemicolon
)
427 error("semicolon expected");
432 condition
= parseDebugCondition();
437 if (token
.value
== TOKassign
)
440 if (token
.value
== TOKidentifier
)
441 s
= new VersionSymbol(loc
, token
.ident
);
442 else if (token
.value
== TOKint32v
)
443 s
= new VersionSymbol(loc
, (unsigned)token
.uns64value
);
445 { error("identifier or integer expected, not %s", token
.toChars());
449 if (token
.value
!= TOKsemicolon
)
450 error("semicolon expected");
454 condition
= parseVersionCondition();
460 if (token
.value
== TOKelse
)
462 aelse
= parseBlock();
464 s
= new ConditionalDeclaration(condition
, a
, aelse
);
467 case TOKsemicolon
: // empty declaration
472 error("Declaration expected, not '%s'",token
.toChars());
474 while (token
.value
!= TOKsemicolon
&& token
.value
!= TOKeof
)
482 addComment(s
, comment
);
489 /********************************************
490 * Parse declarations after an align, protection, or extern decl.
493 Array
*Parser::parseBlock()
498 //printf("parseBlock()\n");
502 error("declaration expected following attribute, not ';'");
508 a
= parseDeclDefs(0);
509 if (token
.value
!= TOKrcurly
)
511 error("matching '}' expected, not %s", token
.toChars());
522 a
= parseDeclDefs(0); // grab declarations up to closing curly bracket
527 a
= parseDeclDefs(1);
533 /**********************************
534 * Parse a static assertion.
537 StaticAssert
*Parser::parseStaticAssert()
541 Expression
*msg
= NULL
;
543 //printf("parseStaticAssert()\n");
546 exp
= parseAssignExp();
547 if (token
.value
== TOKcomma
)
549 msg
= parseAssignExp();
553 return new StaticAssert(loc
, exp
, msg
);
557 /***********************************
558 * Parse extern (linkage)
559 * The parser is on the 'extern' token.
562 enum LINK
Parser::parseLinkage()
564 enum LINK link
= LINKdefault
;
566 assert(token
.value
== TOKlparen
);
568 if (token
.value
== TOKidentifier
)
569 { Identifier
*id
= token
.ident
;
572 if (id
== Id::Windows
)
574 else if (id
== Id::Pascal
)
576 else if (id
== Id::D
)
578 else if (id
== Id::C
)
581 if (token
.value
== TOKplusplus
)
586 else if (id
== Id::System
)
589 link
= d_gcc_is_target_win32() ? LINKwindows
: LINKc
;
600 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
606 link
= LINKd
; // default
612 /**************************************
613 * Parse a debug conditional
616 Condition
*Parser::parseDebugCondition()
620 if (token
.value
== TOKlparen
)
624 Identifier
*id
= NULL
;
626 if (token
.value
== TOKidentifier
)
628 else if (token
.value
== TOKint32v
)
629 level
= (unsigned)token
.uns64value
;
631 error("identifier or integer expected, not %s", token
.toChars());
634 c
= new DebugCondition(mod
, level
, id
);
637 c
= new DebugCondition(mod
, 1, NULL
);
642 /**************************************
643 * Parse a version conditional
646 Condition
*Parser::parseVersionCondition()
650 Identifier
*id
= NULL
;
652 if (token
.value
== TOKlparen
)
655 if (token
.value
== TOKidentifier
)
657 else if (token
.value
== TOKint32v
)
658 level
= (unsigned)token
.uns64value
;
662 * even though unittest is a keyword
664 else if (token
.value
== TOKunittest
)
665 id
= Lexer::idPool(Token::toChars(TOKunittest
));
668 error("identifier or integer expected, not %s", token
.toChars());
674 error("(condition) expected following version");
675 c
= new VersionCondition(mod
, level
, id
);
680 /***********************************************
681 * static if (expression)
687 Condition
*Parser::parseStaticIfCondition()
689 Condition
*condition
;
695 if (token
.value
== TOKlparen
)
698 exp
= parseAssignExp();
702 { error("(expression) expected following static if");
705 condition
= new StaticIfCondition(loc
, exp
);
710 /*****************************************
711 * Parse a constructor definition:
712 * this(arguments) { body }
713 * Current token is 'this'.
716 CtorDeclaration
*Parser::parseCtor()
719 Arguments
*arguments
;
724 arguments
= parseParameters(&varargs
);
725 f
= new CtorDeclaration(loc
, 0, arguments
, varargs
);
730 /*****************************************
731 * Parse a destructor definition:
733 * Current token is '~'.
736 DtorDeclaration
*Parser::parseDtor()
746 f
= new DtorDeclaration(loc
, 0);
751 /*****************************************
752 * Parse a static constructor definition:
753 * static this() { body }
754 * Current token is 'this'.
757 StaticCtorDeclaration
*Parser::parseStaticCtor()
759 StaticCtorDeclaration
*f
;
766 f
= new StaticCtorDeclaration(loc
, 0);
771 /*****************************************
772 * Parse a static destructor definition:
773 * static ~this() { body }
774 * Current token is '~'.
777 StaticDtorDeclaration
*Parser::parseStaticDtor()
779 StaticDtorDeclaration
*f
;
787 f
= new StaticDtorDeclaration(loc
, 0);
792 /*****************************************
793 * Parse an invariant definition:
795 * Current token is 'invariant'.
798 InvariantDeclaration
*Parser::parseInvariant()
800 InvariantDeclaration
*f
;
804 if (token
.value
== TOKlparen
) // optional ()
810 f
= new InvariantDeclaration(loc
, 0);
811 f
->fbody
= parseStatement(PScurly
);
815 /*****************************************
816 * Parse a unittest definition:
818 * Current token is 'unittest'.
821 UnitTestDeclaration
*Parser::parseUnitTest()
823 UnitTestDeclaration
*f
;
829 body
= parseStatement(PScurly
);
831 f
= new UnitTestDeclaration(loc
, this->loc
);
836 /*****************************************
837 * Parse a new definition:
838 * new(arguments) { body }
839 * Current token is 'new'.
842 NewDeclaration
*Parser::parseNew()
845 Arguments
*arguments
;
850 arguments
= parseParameters(&varargs
);
851 f
= new NewDeclaration(loc
, 0, arguments
, varargs
);
856 /*****************************************
857 * Parse a delete definition:
858 * delete(arguments) { body }
859 * Current token is 'delete'.
862 DeleteDeclaration
*Parser::parseDelete()
864 DeleteDeclaration
*f
;
865 Arguments
*arguments
;
870 arguments
= parseParameters(&varargs
);
872 error("... not allowed in delete function parameter list");
873 f
= new DeleteDeclaration(loc
, 0, arguments
);
878 /**********************************************
879 * Parse parameter list.
882 Arguments
*Parser::parseParameters(int *pvarargs
)
884 Arguments
*arguments
= new Arguments();
894 unsigned storageClass
;
898 storageClass
= STCin
; // parameter is "in" by default
910 storageClass
= STCin
;
915 storageClass
= STCout
;
921 storageClass
= STCref
;
926 storageClass
= STClazy
;
932 tb
= parseBasicType();
933 at
= parseDeclarator(tb
, &ai
);
935 if (token
.value
== TOKassign
) // = defaultArg
937 ae
= parseAssignExp();
942 error("default argument expected for %s",
943 ai
? ai
->toChars() : at
->toChars());
945 if (token
.value
== TOKdotdotdot
)
950 if (storageClass
& (STCout
| STCref
))
951 error("variadic argument cannot be out or ref");
953 a
= new Argument(storageClass
, at
, ai
, ae
);
958 a
= new Argument(storageClass
, at
, ai
, ae
);
960 if (token
.value
== TOKcomma
)
974 /*************************************
977 EnumDeclaration
*Parser::parseEnum()
978 { EnumDeclaration
*e
;
983 //printf("Parser::parseEnum()\n");
985 if (token
.value
== TOKidentifier
)
992 if (token
.value
== TOKcolon
)
995 t
= parseBasicType();
1000 e
= new EnumDeclaration(loc
, id
, t
);
1001 if (token
.value
== TOKsemicolon
&& id
)
1003 else if (token
.value
== TOKlcurly
)
1005 //printf("enum definition\n");
1006 e
->members
= new Array();
1008 unsigned char *comment
= token
.blockComment
;
1009 while (token
.value
!= TOKrcurly
)
1011 if (token
.value
== TOKidentifier
)
1017 ident
= token
.ident
;
1020 if (token
.value
== TOKassign
)
1023 value
= parseAssignExp();
1025 em
= new EnumMember(loc
, ident
, value
);
1026 e
->members
->push(em
);
1027 if (token
.value
== TOKrcurly
)
1030 { addComment(em
, comment
);
1034 addComment(em
, comment
);
1035 comment
= token
.blockComment
;
1038 { error("enum member expected");
1045 error("enum declaration is invalid");
1050 Dsymbol
*Parser::parseAggregate()
1051 { AggregateDeclaration
*a
= NULL
;
1055 TemplateParameters
*tpl
= NULL
;
1057 //printf("Parser::parseAggregate()\n");
1060 if (token
.value
!= TOKidentifier
)
1067 if (token
.value
== TOKlparen
)
1068 { // Class template declaration.
1070 // Gather template parameter list
1071 tpl
= parseTemplateParameterList();
1075 Loc loc
= this->loc
;
1081 error("anonymous classes not allowed");
1083 // Collect base class(es)
1084 BaseClasses
*baseclasses
= NULL
;
1085 if (token
.value
== TOKcolon
)
1088 baseclasses
= parseBaseClasses();
1090 if (token
.value
!= TOKlcurly
)
1091 error("members expected");
1094 if (tok
== TOKclass
)
1095 a
= new ClassDeclaration(loc
, id
, baseclasses
);
1097 a
= new InterfaceDeclaration(loc
, id
, baseclasses
);
1103 a
= new StructDeclaration(loc
, id
);
1110 a
= new UnionDeclaration(loc
, id
);
1119 if (a
&& token
.value
== TOKsemicolon
)
1122 else if (token
.value
== TOKlcurly
)
1124 //printf("aggregate definition\n");
1126 Array
*decl
= parseDeclDefs(0);
1127 if (token
.value
!= TOKrcurly
)
1128 error("} expected following member declarations in aggregate");
1132 /* Anonymous structs/unions are more like attributes.
1134 return new AnonDeclaration(loc
, anon
- 1, decl
);
1141 error("{ } expected following aggregate declaration");
1142 a
= new StructDeclaration(loc
, NULL
);
1147 TemplateDeclaration
*tempdecl
;
1149 // Wrap a template around the aggregate declaration
1150 decldefs
= new Array();
1152 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
);
1159 /*******************************************
1162 BaseClasses
*Parser::parseBaseClasses()
1164 enum PROT protection
= PROTpublic
;
1165 BaseClasses
*baseclasses
= new BaseClasses();
1167 for (; 1; nextToken())
1169 switch (token
.value
)
1174 protection
= PROTprivate
;
1177 protection
= PROTpackage
;
1180 protection
= PROTprotected
;
1183 protection
= PROTpublic
;
1186 error("base classes expected instead of %s", token
.toChars());
1189 BaseClass
*b
= new BaseClass(parseBasicType(), protection
);
1190 baseclasses
->push(b
);
1191 if (token
.value
!= TOKcomma
)
1193 protection
= PROTpublic
;
1198 /**************************************
1199 * Parse a TemplateDeclaration.
1202 TemplateDeclaration
*Parser::parseTemplateDeclaration()
1204 TemplateDeclaration
*tempdecl
;
1206 TemplateParameters
*tpl
;
1208 Loc loc
= this->loc
;
1211 if (token
.value
!= TOKidentifier
)
1212 { error("TemplateIdentifier expected following template");
1217 tpl
= parseTemplateParameterList();
1221 if (token
.value
!= TOKlcurly
)
1222 { error("members of template declaration expected");
1228 decldefs
= parseDeclDefs(0);
1229 if (token
.value
!= TOKrcurly
)
1230 { error("template member expected");
1236 tempdecl
= new TemplateDeclaration(loc
, id
, tpl
, decldefs
);
1243 /******************************************
1244 * Parse template parameter list.
1247 TemplateParameters
*Parser::parseTemplateParameterList()
1249 TemplateParameters
*tpl
= new TemplateParameters();
1251 if (token
.value
!= TOKlparen
)
1252 { error("parenthesized TemplateParameterList expected following TemplateIdentifier");
1257 // Get array of TemplateParameters
1258 if (token
.value
!= TOKrparen
)
1259 { int isvariadic
= 0;
1262 { TemplateParameter
*tp
;
1263 Identifier
*tp_ident
= NULL
;
1264 Type
*tp_spectype
= NULL
;
1265 Type
*tp_valtype
= NULL
;
1266 Type
*tp_defaulttype
= NULL
;
1267 Expression
*tp_specvalue
= NULL
;
1268 Expression
*tp_defaultvalue
= NULL
;
1271 // Get TemplateParameter
1273 // First, look ahead to see if it is a TypeParameter or a ValueParameter
1275 if (token
.value
== TOKalias
)
1278 if (token
.value
!= TOKidentifier
)
1279 { error("Identifier expected for template parameter");
1282 tp_ident
= token
.ident
;
1284 if (token
.value
== TOKcolon
) // : Type
1287 tp_spectype
= parseBasicType();
1288 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1290 if (token
.value
== TOKassign
) // = Type
1293 tp_defaulttype
= parseBasicType();
1294 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1296 tp
= new TemplateAliasParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1298 else if (t
->value
== TOKcolon
|| t
->value
== TOKassign
||
1299 t
->value
== TOKcomma
|| t
->value
== TOKrparen
)
1301 if (token
.value
!= TOKidentifier
)
1302 { error("Identifier expected for template parameter");
1305 tp_ident
= token
.ident
;
1307 if (token
.value
== TOKcolon
) // : Type
1310 tp_spectype
= parseBasicType();
1311 tp_spectype
= parseDeclarator(tp_spectype
, NULL
);
1313 if (token
.value
== TOKassign
) // = Type
1316 tp_defaulttype
= parseBasicType();
1317 tp_defaulttype
= parseDeclarator(tp_defaulttype
, NULL
);
1319 tp
= new TemplateTypeParameter(loc
, tp_ident
, tp_spectype
, tp_defaulttype
);
1321 else if (token
.value
== TOKidentifier
&& t
->value
== TOKdotdotdot
)
1324 error("variadic template parameter must be last");
1326 tp_ident
= token
.ident
;
1329 tp
= new TemplateTupleParameter(loc
, tp_ident
);
1333 tp_valtype
= parseBasicType();
1334 tp_valtype
= parseDeclarator(tp_valtype
, &tp_ident
);
1337 error("no identifier for template value parameter");
1338 tp_ident
= new Identifier("error", TOKidentifier
);
1340 if (token
.value
== TOKcolon
) // : CondExpression
1343 tp_specvalue
= parseCondExp();
1345 if (token
.value
== TOKassign
) // = CondExpression
1348 tp_defaultvalue
= parseCondExp();
1350 tp
= new TemplateValueParameter(loc
, tp_ident
, tp_valtype
, tp_specvalue
, tp_defaultvalue
);
1353 if (token
.value
!= TOKcomma
)
1363 /******************************************
1364 * Parse template mixin.
1367 * mixin a.b.c!(args).Foo!(args);
1368 * mixin Foo!(args) identifier;
1369 * mixin typeof(expr).identifier!(args);
1372 Dsymbol
*Parser::parseMixin()
1380 //printf("parseMixin()\n");
1383 if (token
.value
== TOKdot
)
1389 if (token
.value
== TOKtypeof
)
1394 exp
= parseExpression();
1396 tqual
= new TypeTypeof(loc
, exp
);
1399 if (token
.value
!= TOKidentifier
)
1401 error("identifier expected, not %s", token
.toChars());
1408 idents
= new Array();
1412 if (token
.value
== TOKnot
)
1415 tiargs
= parseTemplateArgumentList();
1418 if (token
.value
!= TOKdot
)
1422 { TemplateInstance
*tempinst
= new TemplateInstance(loc
, id
);
1423 tempinst
->tiargs
= tiargs
;
1424 id
= (Identifier
*)tempinst
;
1430 if (token
.value
!= TOKidentifier
)
1431 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1439 if (token
.value
== TOKidentifier
)
1447 tm
= new TemplateMixin(loc
, id
, tqual
, idents
, tiargs
);
1448 if (token
.value
!= TOKsemicolon
)
1449 error("';' expected after mixin");
1458 /******************************************
1459 * Parse template argument list.
1461 * current token is opening '('
1463 * current token is one after closing ')'
1466 Objects
*Parser::parseTemplateArgumentList()
1468 //printf("Parser::parseTemplateArgumentList()\n");
1469 Objects
*tiargs
= new Objects();
1470 if (token
.value
!= TOKlparen
)
1471 { error("!(TemplateArgumentList) expected following TemplateIdentifier");
1476 // Get TemplateArgumentList
1477 if (token
.value
!= TOKrparen
)
1481 // See if it is an Expression or a Type
1482 if (isDeclaration(&token
, 0, TOKreserved
, NULL
))
1486 // Get TemplateArgument
1487 ta
= parseBasicType();
1488 ta
= parseDeclarator(ta
, NULL
);
1495 ea
= parseAssignExp();
1498 if (token
.value
!= TOKcomma
)
1503 check(TOKrparen
, "template argument list");
1507 Import
*Parser::parseImport(Array
*decldefs
, int isstatic
)
1510 Identifier
*aliasid
= NULL
;
1514 //printf("Parser::parseImport()\n");
1519 if (token
.value
!= TOKidentifier
)
1520 { error("Identifier expected following import");
1528 if (!aliasid
&& token
.value
== TOKassign
)
1533 while (token
.value
== TOKdot
)
1539 if (token
.value
!= TOKidentifier
)
1540 { error("Identifier expected following package");
1547 s
= new Import(loc
, a
, token
.ident
, aliasid
, isstatic
);
1551 * : alias=name, alias=name;
1554 if (token
.value
== TOKcolon
)
1561 if (token
.value
!= TOKidentifier
)
1562 { error("Identifier expected following :");
1565 alias
= token
.ident
;
1567 if (token
.value
== TOKassign
)
1570 if (token
.value
!= TOKidentifier
)
1571 { error("Identifier expected following %s=", alias
->toChars());
1581 s
->addAlias(name
, alias
);
1582 } while (token
.value
== TOKcomma
);
1583 break; // no comma-separated imports of this form
1587 } while (token
.value
== TOKcomma
);
1589 if (token
.value
== TOKsemicolon
)
1593 error("';' expected");
1600 Type
*Parser::parseBasicType()
1604 TemplateInstance
*tempinst
;
1606 //printf("parseBasicType()\n");
1607 switch (token
.value
)
1609 CASE_BASIC_TYPES_X(t
):
1616 if (token
.value
== TOKnot
)
1619 tempinst
= new TemplateInstance(loc
, id
);
1620 tempinst
->tiargs
= parseTemplateArgumentList();
1621 tid
= new TypeInstance(loc
, tempinst
);
1625 tid
= new TypeIdentifier(loc
, id
);
1627 while (token
.value
== TOKdot
)
1629 if (token
.value
!= TOKidentifier
)
1630 { error("identifier expected following '.' instead of '%s'", token
.toChars());
1635 if (token
.value
== TOKnot
)
1638 tempinst
= new TemplateInstance(loc
, id
);
1639 tempinst
->tiargs
= parseTemplateArgumentList();
1640 tid
->addIdent((Identifier
*)tempinst
);
1657 exp
= parseExpression();
1659 tid
= new TypeTypeof(loc
, exp
);
1664 error("basic type expected, not %s", token
.toChars());
1671 Type
*Parser::parseBasicType2(Type
*t
)
1676 //printf("parseBasicType2()\n");
1679 switch (token
.value
)
1682 t
= new TypePointer(t
);
1688 // Handle []. Make sure things like
1690 // is (array[1] of array[3] of int)
1692 if (token
.value
== TOKrbracket
)
1694 t
= new TypeDArray(t
); // []
1697 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1698 { // It's an associative array declaration
1701 //printf("it's an associative array\n");
1702 index
= parseBasicType();
1703 index
= parseDeclarator(index
, NULL
); // [ type ]
1704 t
= new TypeAArray(t
, index
);
1709 //printf("it's [expression]\n");
1711 Expression
*e
= parseExpression(); // [ expression ]
1712 if (token
.value
== TOKslice
)
1716 e2
= parseExpression(); // [ exp .. exp ]
1717 t
= new TypeSlice(t
, e
, e2
);
1720 t
= new TypeSArray(t
,e
);
1726 // Handle []. Make sure things like
1728 // is (array[3] of array[1] of int)
1730 while (token
.value
== TOKlbracket
)
1733 if (token
.value
== TOKrbracket
)
1735 ta
= new TypeDArray(t
); // []
1738 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1739 { // It's an associative array declaration
1742 //printf("it's an associative array\n");
1743 index
= parseBasicType();
1744 index
= parseDeclarator(index
, NULL
); // [ type ]
1746 ta
= new TypeAArray(t
, index
);
1750 //printf("it's [expression]\n");
1751 Expression
*e
= parseExpression(); // [ expression ]
1752 ta
= new TypeSArray(t
,e
);
1756 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1766 { // Handle delegate declaration:
1767 // t delegate(parameter list)
1768 // t function(parameter list)
1769 Arguments
*arguments
;
1771 enum TOK save
= token
.value
;
1774 arguments
= parseParameters(&varargs
);
1775 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1776 if (save
== TOKdelegate
)
1777 t
= new TypeDelegate(t
);
1779 t
= new TypePointer(t
); // pointer to function
1792 Type
*Parser::parseDeclarator(Type
*t
, Identifier
**pident
, TemplateParameters
**tpl
)
1796 //printf("parseDeclarator(tpl = %p)\n", tpl);
1797 t
= parseBasicType2(t
);
1799 switch (token
.value
)
1804 *pident
= token
.ident
;
1806 error("unexpected identifer '%s' in declarator", token
.ident
->toChars());
1813 ts
= parseDeclarator(t
, pident
);
1824 switch (token
.value
)
1828 { // This is the old C-style post [] syntax.
1830 if (token
.value
== TOKrbracket
)
1832 ta
= new TypeDArray(t
); // []
1835 else if (isDeclaration(&token
, 0, TOKrbracket
, NULL
))
1836 { // It's an associative array declaration
1839 //printf("it's an associative array\n");
1840 index
= parseBasicType();
1841 index
= parseDeclarator(index
, NULL
); // [ type ]
1843 ta
= new TypeAArray(t
, index
);
1847 //printf("it's [expression]\n");
1848 Expression
*e
= parseExpression(); // [ expression ]
1849 ta
= new TypeSArray(t
, e
);
1853 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1860 { Arguments
*arguments
;
1865 /* Look ahead to see if this is (...)(...),
1866 * i.e. a function template declaration
1868 if (peekPastParen(&token
)->value
== TOKlparen
)
1869 { // It's a function template declaration
1870 //printf("function template declaration\n");
1872 // Gather template parameter list
1873 *tpl
= parseTemplateParameterList();
1877 arguments
= parseParameters(&varargs
);
1878 Type
*ta
= new TypeFunction(arguments
, t
, varargs
, linkage
);
1880 for (pt
= &ts
; *pt
!= t
; pt
= &(*pt
)->next
)
1892 /**********************************
1893 * Return array of Declaration *'s.
1896 Array
*Parser::parseDeclarations()
1898 enum STC storage_class
;
1906 unsigned char *comment
= token
.blockComment
;
1907 enum LINK link
= linkage
;
1909 //printf("parseDeclarations()\n");
1910 switch (token
.value
)
1923 storage_class
= STCundefined
;
1926 switch (token
.value
)
1928 case TOKconst
: stc
= STCconst
; goto L1
;
1929 case TOKstatic
: stc
= STCstatic
; goto L1
;
1930 case TOKfinal
: stc
= STCfinal
; goto L1
;
1931 case TOKauto
: stc
= STCauto
; goto L1
;
1932 case TOKscope
: stc
= STCscope
; goto L1
;
1933 case TOKoverride
: stc
= STCoverride
; goto L1
;
1934 case TOKabstract
: stc
= STCabstract
; goto L1
;
1935 case TOKsynchronized
: stc
= STCsynchronized
; goto L1
;
1936 case TOKdeprecated
: stc
= STCdeprecated
; goto L1
;
1938 if (storage_class
& stc
)
1939 error("redundant storage class '%s'", token
.toChars());
1940 storage_class
= (STC
) (storage_class
| stc
);
1945 if (peek(&token
)->value
!= TOKlparen
)
1950 link
= parseLinkage();
1961 /* Look for auto initializers:
1962 * storage_class identifier = initializer;
1964 while (storage_class
&&
1965 token
.value
== TOKidentifier
&&
1966 peek(&token
)->value
== TOKassign
)
1968 ident
= token
.ident
;
1971 Initializer
*init
= parseInitializer();
1972 VarDeclaration
*v
= new VarDeclaration(loc
, NULL
, ident
, init
);
1973 v
->storage_class
= storage_class
;
1975 if (token
.value
== TOKsemicolon
)
1978 addComment(v
, comment
);
1980 else if (token
.value
== TOKcomma
)
1983 if (!(token
.value
== TOKidentifier
&& peek(&token
)->value
== TOKassign
))
1985 error("Identifier expected following comma");
1991 error("semicolon expected following auto declaration, not '%s'", token
.toChars());
1995 if (token
.value
== TOKclass
)
1996 { AggregateDeclaration
*s
;
1998 s
= (AggregateDeclaration
*)parseAggregate();
1999 s
->storage_class
|= storage_class
;
2001 addComment(s
, comment
);
2005 ts
= parseBasicType();
2006 ts
= parseBasicType2(ts
);
2011 Loc loc
= this->loc
;
2012 TemplateParameters
*tpl
= NULL
;
2015 t
= parseDeclarator(ts
, &ident
, &tpl
);
2019 else if (t
!= tfirst
)
2020 error("multiple declarations must have the same type, not %s and %s",
2021 tfirst
->toChars(), t
->toChars());
2023 error("no identifier for declarator %s", t
->toChars());
2025 if (tok
== TOKtypedef
|| tok
== TOKalias
)
2030 if (token
.value
== TOKassign
)
2033 init
= parseInitializer();
2035 if (tok
== TOKtypedef
)
2036 v
= new TypedefDeclaration(loc
, ident
, t
, init
);
2039 error("alias cannot have initializer");
2040 v
= new AliasDeclaration(loc
, ident
, t
);
2042 v
->storage_class
= storage_class
;
2043 if (link
== linkage
)
2047 Array
*ax
= new Array();
2049 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2052 switch (token
.value
)
2053 { case TOKsemicolon
:
2055 addComment(v
, comment
);
2060 addComment(v
, comment
);
2064 error("semicolon expected to close %s declaration", Token::toChars(tok
));
2068 else if (t
->ty
== Tfunction
)
2069 { FuncDeclaration
*f
;
2072 f
= new FuncDeclaration(loc
, 0, ident
, storage_class
, t
);
2073 addComment(f
, comment
);
2075 addComment(f
, NULL
);
2076 if (link
== linkage
)
2082 Array
*ax
= new Array();
2084 s
= new LinkDeclaration(link
, ax
);
2086 if (tpl
) // it's a function template
2088 TemplateDeclaration
*tempdecl
;
2090 // Wrap a template around the aggregate declaration
2091 decldefs
= new Array();
2093 tempdecl
= new TemplateDeclaration(loc
, s
->ident
, tpl
, decldefs
);
2096 addComment(s
, comment
);
2100 { VarDeclaration
*v
;
2104 if (token
.value
== TOKassign
)
2107 init
= parseInitializer();
2109 v
= new VarDeclaration(loc
, t
, ident
, init
);
2110 v
->storage_class
= storage_class
;
2111 if (link
== linkage
)
2115 Array
*ax
= new Array();
2117 Dsymbol
*s
= new LinkDeclaration(link
, ax
);
2120 switch (token
.value
)
2121 { case TOKsemicolon
:
2123 addComment(v
, comment
);
2128 addComment(v
, comment
);
2132 error("semicolon expected, not '%s'", token
.toChars());
2141 /*****************************************
2142 * Parse contracts following function declaration.
2145 void Parser::parseContracts(FuncDeclaration
*f
)
2148 enum LINK linksave
= linkage
;
2150 // The following is irrelevant, as it is overridden by sc->linkage in
2151 // TypeFunction::semantic
2152 linkage
= LINKd
; // nested functions have D linkage
2154 switch (token
.value
)
2157 if (f
->frequire
|| f
->fensure
)
2158 error("missing body { ... } after in or out");
2159 f
->fbody
= parseStatement(PSsemi
);
2165 f
->fbody
= parseStatement(PScurly
);
2170 if (f
->frequire
|| f
->fensure
)
2171 error("missing body { ... } after in or out");
2175 #if 0 // Do we want this for function declarations, so we can do:
2176 // int x, y, foo(), z;
2182 #if 0 // Dumped feature
2185 f
->fthrows
= new Array();
2190 tb
= parseBasicType();
2191 f
->fthrows
->push(tb
);
2192 if (token
.value
== TOKcomma
)
2205 error("redundant 'in' statement");
2206 f
->frequire
= parseStatement(PScurly
| PSscope
);
2210 // parse: out (identifier) { statement }
2212 if (token
.value
!= TOKlcurly
)
2215 if (token
.value
!= TOKidentifier
)
2216 error("(identifier) following 'out' expected, not %s", token
.toChars());
2217 f
->outId
= token
.ident
;
2222 error("redundant 'out' statement");
2223 f
->fensure
= parseStatement(PScurly
| PSscope
);
2227 error("semicolon expected following function declaration");
2233 /*****************************************
2236 Initializer
*Parser::parseInitializer()
2238 StructInitializer
*is
;
2239 ArrayInitializer
*ia
;
2245 Loc loc
= this->loc
;
2249 switch (token
.value
)
2252 /* Scan ahead to see if it is a struct initializer or
2253 * a function literal.
2254 * If it contains a ';', it is a function literal.
2255 * Treat { } as a struct initializer.
2258 for (t
= peek(&token
); 1; t
= peek(t
))
2284 is
= new StructInitializer(loc
);
2289 switch (token
.value
)
2293 error("comma expected separating field initializers");
2295 if (t
->value
== TOKcolon
)
2299 nextToken(); // skip over ':'
2304 value
= parseInitializer();
2305 is
->addInit(id
, value
);
2314 case TOKrcurly
: // allow trailing comma's
2319 error("found EOF instead of initializer");
2323 value
= parseInitializer();
2324 is
->addInit(NULL
, value
);
2327 //error("found '%s' instead of field initializer", token.toChars());
2335 ia
= new ArrayInitializer(loc
);
2340 switch (token
.value
)
2344 { error("comma expected separating array initializers, not %s", token
.toChars());
2348 e
= parseAssignExp();
2351 if (token
.value
== TOKcolon
)
2354 value
= parseInitializer();
2357 { value
= new ExpInitializer(e
->loc
, e
);
2360 ia
->addInit(e
, value
);
2367 error("comma expected separating array initializers, not %s", token
.toChars());
2368 value
= parseInitializer();
2369 ia
->addInit(NULL
, value
);
2378 case TOKrbracket
: // allow trailing comma's
2383 error("found '%s' instead of array initializer", token
.toChars());
2392 if (t
->value
== TOKsemicolon
|| t
->value
== TOKcomma
)
2395 return new VoidInitializer(loc
);
2401 e
= parseAssignExp();
2402 ie
= new ExpInitializer(loc
, e
);
2408 /*****************************************
2413 Statement
*Parser::parseStatement(int flags
)
2416 Condition
*condition
;
2418 Statement
*elsebody
;
2419 Loc loc
= this->loc
;
2421 //printf("parseStatement()\n");
2423 if (flags
& PScurly
&& token
.value
!= TOKlcurly
)
2424 error("statement expected to be { }, not %s", token
.toChars());
2426 switch (token
.value
)
2429 // Need to look ahead to see if it is a declaration, label, or expression
2431 if (t
->value
== TOKcolon
)
2435 ident
= token
.ident
;
2438 s
= parseStatement(PSsemi
);
2439 s
= new LabelStatement(loc
, ident
, s
);
2442 // fallthrough to TOKdot
2445 if (isDeclaration(&token
, 2, TOKreserved
, NULL
))
2461 case TOKimaginary32v
:
2462 case TOKimaginary64v
:
2463 case TOKimaginary80v
:
2488 exp
= parseExpression();
2489 check(TOKsemicolon
, "statement");
2490 s
= new ExpStatement(loc
, exp
);
2495 { // Look ahead to see if it's static assert() or static if()
2499 if (t
->value
== TOKassert
)
2502 s
= new StaticAssertStatement(parseStaticAssert());
2505 if (t
->value
== TOKif
)
2508 condition
= parseStaticIfCondition();
2526 a
= parseDeclarations();
2529 Statements
*as
= new Statements();
2530 as
->reserve(a
->dim
);
2531 for (int i
= 0; i
< a
->dim
; i
++)
2533 Dsymbol
*d
= (Dsymbol
*)a
->data
[i
];
2534 s
= new DeclarationStatement(loc
, d
);
2537 s
= new CompoundStatement(loc
, as
);
2539 else if (a
->dim
== 1)
2541 Dsymbol
*d
= (Dsymbol
*)a
->data
[0];
2542 s
= new DeclarationStatement(loc
, d
);
2546 if (flags
& PSscope
)
2547 s
= new ScopeStatement(loc
, s
);
2557 d
= parseAggregate();
2558 s
= new DeclarationStatement(loc
, d
);
2566 s
= new DeclarationStatement(loc
, d
);
2572 if (t
->value
== TOKlparen
)
2575 check(TOKlparen
, "mixin");
2576 Expression
*e
= parseAssignExp();
2578 check(TOKsemicolon
);
2579 s
= new CompileStatement(loc
, e
);
2582 Dsymbol
*d
= parseMixin();
2583 s
= new DeclarationStatement(loc
, d
);
2588 { Statements
*statements
;
2591 statements
= new Statements();
2592 while (token
.value
!= TOKrcurly
)
2594 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2597 s
= new CompoundStatement(loc
, statements
);
2598 if (flags
& (PSscope
| PScurlyscope
))
2599 s
= new ScopeStatement(loc
, s
);
2605 { Expression
*condition
;
2610 condition
= parseExpression();
2612 body
= parseStatement(PSscope
);
2613 s
= new WhileStatement(loc
, condition
, body
);
2618 if (!(flags
& PSsemi
))
2619 error("use '{ }' for an empty statement, not a ';'");
2621 s
= new ExpStatement(loc
, NULL
);
2626 Expression
*condition
;
2629 body
= parseStatement(PSscope
);
2632 condition
= parseExpression();
2634 s
= new DoStatement(loc
, body
, condition
);
2641 Expression
*condition
;
2642 Expression
*increment
;
2647 if (token
.value
== TOKsemicolon
)
2652 { init
= parseStatement(0);
2654 if (token
.value
== TOKsemicolon
)
2661 condition
= parseExpression();
2662 check(TOKsemicolon
, "for condition");
2664 if (token
.value
== TOKrparen
)
2669 { increment
= parseExpression();
2672 body
= parseStatement(PSscope
);
2673 s
= new ForStatement(loc
, init
, condition
, increment
, body
);
2675 s
= new ScopeStatement(loc
, s
);
2680 case TOKforeach_reverse
:
2682 enum TOK op
= token
.value
;
2683 Arguments
*arguments
;
2692 arguments
= new Arguments();
2697 Identifier
*ai
= NULL
;
2699 unsigned storageClass
;
2702 storageClass
= STCin
;
2703 if (token
.value
== TOKinout
|| token
.value
== TOKref
)
2704 { storageClass
= STCref
;
2707 if (token
.value
== TOKidentifier
)
2709 Token
*t
= peek(&token
);
2710 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2712 at
= NULL
; // infer argument type
2717 tb
= parseBasicType();
2718 at
= parseDeclarator(tb
, &ai
);
2720 error("no identifier for declarator %s", at
->toChars());
2722 a
= new Argument(storageClass
, at
, ai
, NULL
);
2724 if (token
.value
== TOKcomma
)
2730 check(TOKsemicolon
);
2732 aggr
= parseExpression();
2734 body
= parseStatement(0);
2735 s
= new ForeachStatement(loc
, op
, arguments
, aggr
, body
);
2740 { Argument
*arg
= NULL
;
2741 Expression
*condition
;
2743 Statement
*elsebody
;
2748 if (token
.value
== TOKauto
)
2751 if (token
.value
== TOKidentifier
)
2753 Token
*t
= peek(&token
);
2754 if (t
->value
== TOKassign
)
2756 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2761 { error("= expected following auto identifier");
2766 { error("identifier expected following auto");
2770 else if (isDeclaration(&token
, 2, TOKassign
, NULL
))
2776 tb
= parseBasicType();
2777 at
= parseDeclarator(tb
, &ai
);
2779 arg
= new Argument(STCin
, at
, ai
, NULL
);
2782 // Check for " ident;"
2783 else if (token
.value
== TOKidentifier
)
2785 Token
*t
= peek(&token
);
2786 if (t
->value
== TOKcomma
|| t
->value
== TOKsemicolon
)
2788 arg
= new Argument(STCin
, NULL
, token
.ident
, NULL
);
2791 if (1 || !global
.params
.useDeprecated
)
2792 error("if (v; e) is deprecated, use if (auto v = e)");
2796 condition
= parseExpression();
2798 ifbody
= parseStatement(PSscope
);
2799 if (token
.value
== TOKelse
)
2802 elsebody
= parseStatement(PSscope
);
2806 s
= new IfStatement(loc
, arg
, condition
, ifbody
, elsebody
);
2811 if (peek(&token
)->value
!= TOKlparen
)
2812 goto Ldeclaration
; // scope used as storage class
2815 if (token
.value
!= TOKidentifier
)
2816 { error("scope identifier expected");
2820 { TOK t
= TOKon_scope_exit
;
2821 Identifier
*id
= token
.ident
;
2824 t
= TOKon_scope_exit
;
2825 else if (id
== Id::failure
)
2826 t
= TOKon_scope_failure
;
2827 else if (id
== Id::success
)
2828 t
= TOKon_scope_success
;
2830 error("valid scope identifiers are exit, failure, or success, not %s", id
->toChars());
2833 Statement
*st
= parseStatement(PScurlyscope
);
2834 s
= new OnScopeStatement(loc
, t
, st
);
2840 condition
= parseDebugCondition();
2845 condition
= parseVersionCondition();
2849 ifbody
= parseStatement(0 /*PSsemi*/);
2851 if (token
.value
== TOKelse
)
2854 elsebody
= parseStatement(0 /*PSsemi*/);
2856 s
= new ConditionalStatement(loc
, condition
, ifbody
, elsebody
);
2860 { Identifier
*ident
;
2861 Expressions
*args
= NULL
;
2866 if (token
.value
!= TOKidentifier
)
2867 { error("pragma(identifier expected");
2870 ident
= token
.ident
;
2872 if (token
.value
== TOKcomma
)
2873 args
= parseArguments(); // pragma(identifier, args...);
2875 check(TOKrparen
); // pragma(identifier);
2876 if (token
.value
== TOKsemicolon
)
2881 body
= parseStatement(PSsemi
);
2882 s
= new PragmaStatement(loc
, ident
, args
, body
);
2887 { Expression
*condition
;
2892 condition
= parseExpression();
2894 body
= parseStatement(PSscope
);
2895 s
= new SwitchStatement(loc
, condition
, body
);
2901 Statements
*statements
;
2902 Array cases
; // array of Expression's
2907 exp
= parseAssignExp();
2909 if (token
.value
!= TOKcomma
)
2914 statements
= new Statements();
2915 while (token
.value
!= TOKcase
&&
2916 token
.value
!= TOKdefault
&&
2917 token
.value
!= TOKrcurly
)
2919 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2921 s
= new CompoundStatement(loc
, statements
);
2922 s
= new ScopeStatement(loc
, s
);
2924 // Keep cases in order by building the case statements backwards
2925 for (int i
= cases
.dim
; i
; i
--)
2927 exp
= (Expression
*)cases
.data
[i
- 1];
2928 s
= new CaseStatement(loc
, exp
, s
);
2935 Statements
*statements
;
2940 statements
= new Statements();
2941 while (token
.value
!= TOKcase
&&
2942 token
.value
!= TOKdefault
&&
2943 token
.value
!= TOKrcurly
)
2945 statements
->push(parseStatement(PSsemi
| PScurlyscope
));
2947 s
= new CompoundStatement(loc
, statements
);
2948 s
= new ScopeStatement(loc
, s
);
2949 s
= new DefaultStatement(loc
, s
);
2957 if (token
.value
== TOKsemicolon
)
2960 exp
= parseExpression();
2961 check(TOKsemicolon
, "return statement");
2962 s
= new ReturnStatement(loc
, exp
);
2967 { Identifier
*ident
;
2970 if (token
.value
== TOKidentifier
)
2971 { ident
= token
.ident
;
2976 check(TOKsemicolon
, "break statement");
2977 s
= new BreakStatement(loc
, ident
);
2982 { Identifier
*ident
;
2985 if (token
.value
== TOKidentifier
)
2986 { ident
= token
.ident
;
2991 check(TOKsemicolon
, "continue statement");
2992 s
= new ContinueStatement(loc
, ident
);
2997 { Identifier
*ident
;
3000 if (token
.value
== TOKdefault
)
3003 s
= new GotoDefaultStatement(loc
);
3005 else if (token
.value
== TOKcase
)
3007 Expression
*exp
= NULL
;
3010 if (token
.value
!= TOKsemicolon
)
3011 exp
= parseExpression();
3012 s
= new GotoCaseStatement(loc
, exp
);
3016 if (token
.value
!= TOKidentifier
)
3017 { error("Identifier expected following goto");
3021 { ident
= token
.ident
;
3024 s
= new GotoStatement(loc
, ident
);
3026 check(TOKsemicolon
, "goto statement");
3030 case TOKsynchronized
:
3035 if (token
.value
== TOKlparen
)
3038 exp
= parseExpression();
3043 body
= parseStatement(PSscope
);
3044 s
= new SynchronizedStatement(loc
, exp
, body
);
3054 exp
= parseExpression();
3056 body
= parseStatement(PSscope
);
3057 s
= new WithStatement(loc
, exp
, body
);
3063 Array
*catches
= NULL
;
3064 Statement
*finalbody
= NULL
;
3067 body
= parseStatement(PSscope
);
3068 while (token
.value
== TOKcatch
)
3074 Loc loc
= this->loc
;
3077 if (token
.value
== TOKlcurly
)
3085 t
= parseBasicType();
3087 t
= parseDeclarator(t
, &id
);
3090 handler
= parseStatement(0);
3091 c
= new Catch(loc
, t
, id
, handler
);
3093 catches
= new Array();
3097 if (token
.value
== TOKfinally
)
3099 finalbody
= parseStatement(0);
3103 if (!catches
&& !finalbody
)
3104 error("catch or finally expected following try");
3107 s
= new TryCatchStatement(loc
, body
, catches
);
3109 s
= new TryFinallyStatement(loc
, s
, finalbody
);
3118 exp
= parseExpression();
3119 check(TOKsemicolon
, "throw statement");
3120 s
= new ThrowStatement(loc
, exp
);
3126 s
= parseStatement(PSsemi
| PScurlyscope
);
3127 s
= new VolatileStatement(loc
, s
);
3131 { Statements
*statements
;
3137 // Parse the asm block into a sequence of AsmStatements,
3138 // each AsmStatement is one instruction.
3139 // Separate out labels.
3140 // Defer parsing of AsmStatements until semantic processing.
3143 #if GDC_EXTENDED_ASM_SYNTAX
3144 if (token
.value
== TOKlparen
)
3153 ptoklist
= &toklist
;
3155 statements
= new Statements();
3158 switch (token
.value
)
3163 // Look ahead to see if it is a label
3165 if (t
->value
== TOKcolon
)
3167 label
= token
.ident
;
3168 labelloc
= this->loc
;
3177 if (toklist
|| label
)
3179 error("asm statements must end in ';'");
3185 if (toklist
|| label
)
3186 { // Create AsmStatement from list of tokens we've saved
3187 s
= new AsmStatement(this->loc
, toklist
);
3189 ptoklist
= &toklist
;
3191 { s
= new LabelStatement(labelloc
, label
, s
);
3194 statements
->push(s
);
3201 error("matching '}' expected, not end of file");
3206 // If the first token is a string or '(', parse as extended asm.
3210 statements
->push(s
);
3213 // ...else, drop through.
3217 *ptoklist
= new Token();
3218 memcpy(*ptoklist
, &token
, sizeof(Token
));
3219 ptoklist
= &(*ptoklist
)->next
;
3227 s
= new CompoundStatement(loc
, statements
);
3233 error("found '%s' instead of statement", token
.toChars());
3237 while (token
.value
!= TOKrcurly
&&
3238 token
.value
!= TOKsemicolon
&&
3239 token
.value
!= TOKeof
)
3241 if (token
.value
== TOKsemicolon
)
3250 Statement
*Parser::parseExtAsm(int expect_rparen
)
3252 Expression
* insnTemplate
;
3253 Expressions
* args
= NULL
;
3254 Array
* argNames
= NULL
;
3255 Expressions
* argConstraints
= NULL
;
3256 int nOutputArgs
= 0;
3257 Expressions
* clobbers
= NULL
;
3258 bool isInputPhase
= false; // Output operands first, then input.
3260 insnTemplate
= parseExpression();
3261 if (token
.value
== TOKrparen
|| token
.value
== TOKsemicolon
)
3265 Expression
* arg
= NULL
;
3266 Identifier
* name
= NULL
;
3267 Expression
* constraint
= NULL
;
3269 switch (token
.value
)
3280 error("unterminated statement");
3284 if (token
.value
== TOKidentifier
)
3290 error("expected identifier after '['");
3294 constraint
= parsePrimaryExp();
3295 if (constraint
->op
!= TOKstring
)
3296 error("expected constant string constraint for operand");
3297 arg
= parseAssignExp();
3300 args
= new Expressions
;
3301 argConstraints
= new Expressions
;
3302 argNames
= new Array
;
3305 argNames
->push(name
);
3306 argConstraints
->push(constraint
);
3310 if (token
.value
== TOKcomma
)
3317 isInputPhase
= true;
3324 Expression
* clobber
;
3326 switch (token
.value
)
3333 error("unterminated statement");
3336 clobber
= parseAssignExp();
3337 if (clobber
->op
!= TOKstring
)
3338 error("expected constant string constraint for clobber name");
3340 clobbers
= new Expressions
;
3341 clobbers
->push(clobber
);
3343 if (token
.value
== TOKcomma
)
3352 check(TOKsemicolon
);
3354 return new ExtAsmStatement(loc
, insnTemplate
, args
, argNames
,
3355 argConstraints
, nOutputArgs
, clobbers
);
3358 void Parser::check(enum TOK value
)
3363 void Parser::check(Loc loc
, enum TOK value
)
3365 if (token
.value
!= value
)
3366 error(loc
, "found '%s' when expecting '%s'", token
.toChars(), Token::toChars(value
));
3370 void Parser::check(enum TOK value
, char *string
)
3372 if (token
.value
!= value
)
3373 error("found '%s' when expecting '%s' following '%s'",
3374 token
.toChars(), Token::toChars(value
), string
);
3378 /************************************
3379 * Determine if the scanner is sitting on the start of a declaration.
3381 * needId 0 no identifier
3382 * 1 identifier optional
3383 * 2 must have identifier
3386 int Parser::isDeclaration(Token
*t
, int needId
, enum TOK endtok
, Token
**pt
)
3390 if (!isBasicType(&t
))
3392 if (!isDeclarator(&t
, &haveId
, endtok
))
3395 (needId
== 0 && !haveId
) ||
3396 (needId
== 2 && haveId
))
3405 int Parser::isBasicType(Token
**pt
)
3407 // This code parallels parseBasicType()
3420 if (t
->value
== TOKnot
)
3430 if (t
->value
== TOKdot
)
3434 if (t
->value
!= TOKidentifier
)
3437 if (t
->value
!= TOKnot
)
3441 if (t
->value
!= TOKlparen
)
3443 if (!skipParens(t
, &t
))
3455 /* typeof(exp).identifier...
3458 if (t
->value
!= TOKlparen
)
3460 if (!skipParens(t
, &t
))
3474 int Parser::isDeclarator(Token
**pt
, int *haveId
, enum TOK endtok
)
3475 { // This code parallels parseDeclarator()
3479 //printf("Parser::isDeclarator()\n");
3481 if (t
->value
== TOKassign
)
3496 if (t
->value
== TOKrbracket
)
3500 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3501 { // It's an associative array declaration
3507 // [ expression .. expression ]
3508 if (!isExpression(&t
))
3510 if (t
->value
== TOKslice
)
3512 if (!isExpression(&t
))
3515 if (t
->value
!= TOKrbracket
)
3531 if (t
->value
== TOKrparen
)
3532 return FALSE
; // () is not a declarator
3534 /* Regard ( identifier ) as not a declarator
3535 * BUG: what about ( *identifier ) in
3537 * where f is a class instance with overloaded () ?
3538 * Should we just disallow C-style function pointer declarations?
3540 if (t
->value
== TOKidentifier
)
3541 { Token
*t2
= peek(t
);
3542 if (t2
->value
== TOKrparen
)
3547 if (!isDeclarator(&t
, haveId
, TOKrparen
))
3556 if (!isParameters(&t
))
3571 if (t
->value
== TOKrbracket
)
3575 else if (isDeclaration(t
, 0, TOKrbracket
, &t
))
3576 { // It's an associative array declaration
3582 if (!isExpression(&t
))
3584 if (t
->value
!= TOKrbracket
)
3593 if (!isParameters(&t
))
3597 // Valid tokens that follow a declaration
3605 // The !parens is to disallow unnecessary parentheses
3606 if (!parens
&& (endtok
== TOKreserved
|| endtok
== t
->value
))
3619 int Parser::isParameters(Token
**pt
)
3620 { // This code parallels parseParameters()
3624 //printf("isParameters()\n");
3625 if (t
->value
!= TOKlparen
)
3647 if (!isBasicType(&t
))
3650 if (t
->value
!= TOKdotdotdot
&&
3651 !isDeclarator(&t
, &tmp
, TOKreserved
))
3653 if (t
->value
== TOKassign
)
3655 if (!isExpression(&t
))
3658 if (t
->value
== TOKdotdotdot
)
3663 if (t
->value
== TOKcomma
)
3671 if (t
->value
!= TOKrparen
)
3678 int Parser::isExpression(Token
**pt
)
3680 // This is supposed to determine if something is an expression.
3681 // What it actually does is scan until a closing right bracket
3688 for (;; t
= peek(t
))
3706 if (brnest
|| panest
)
3733 /**********************************************
3735 * instance foo.bar(parameters...)
3737 * if (pt), *pt is set to the token following the closing )
3739 * 1 it's valid instance syntax
3740 * 0 invalid instance syntax
3743 int Parser::isTemplateInstance(Token
*t
, Token
**pt
)
3746 if (t
->value
!= TOKdot
)
3748 if (t
->value
!= TOKidentifier
)
3752 while (t
->value
== TOKdot
)
3755 if (t
->value
!= TOKidentifier
)
3759 if (t
->value
!= TOKlparen
)
3762 // Skip over the template arguments
3771 if (!skipParens(t
, &t
))
3787 if (t
->value
!= TOKcomma
)
3790 if (t
->value
!= TOKrparen
)
3801 /*******************************************
3802 * Skip parens, brackets.
3806 * *pt is set to closing token, which is ')' on success
3809 * 0 some parsing error
3812 int Parser::skipParens(Token
*t
, Token
**pt
)
3851 /********************************* Expression Parser ***************************/
3853 Expression
*Parser::parsePrimaryExp()
3858 Loc loc
= this->loc
;
3860 switch (token
.value
)
3865 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
3866 { // identifier!(template-argument-list)
3867 TemplateInstance
*tempinst
;
3869 tempinst
= new TemplateInstance(loc
, id
);
3871 tempinst
->tiargs
= parseTemplateArgumentList();
3872 e
= new ScopeExp(loc
, tempinst
);
3875 e
= new IdentifierExp(loc
, id
);
3880 error("'$' is valid only inside [] of index or slice");
3881 e
= new DollarExp(loc
);
3886 // Signal global scope '.' operator with "" identifier
3887 e
= new IdentifierExp(loc
, Id::empty
);
3891 e
= new ThisExp(loc
);
3896 e
= new SuperExp(loc
);
3901 e
= new IntegerExp(loc
, (d_int32
)token
.int64value
, Type::tint32
);
3906 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tuns32
);
3911 e
= new IntegerExp(loc
, token
.int64value
, Type::tint64
);
3916 e
= new IntegerExp(loc
, token
.uns64value
, Type::tuns64
);
3921 e
= new RealExp(loc
, token
.float80value
, Type::tfloat32
);
3926 e
= new RealExp(loc
, token
.float80value
, Type::tfloat64
);
3931 e
= new RealExp(loc
, token
.float80value
, Type::tfloat80
);
3935 case TOKimaginary32v
:
3936 e
= new RealExp(loc
, token
.float80value
, Type::timaginary32
);
3940 case TOKimaginary64v
:
3941 e
= new RealExp(loc
, token
.float80value
, Type::timaginary64
);
3945 case TOKimaginary80v
:
3946 e
= new RealExp(loc
, token
.float80value
, Type::timaginary80
);
3951 e
= new NullExp(loc
);
3956 e
= new IntegerExp(loc
, 1, Type::tbool
);
3961 e
= new IntegerExp(loc
, 0, Type::tbool
);
3966 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tchar
);
3971 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::twchar
);
3976 e
= new IntegerExp(loc
, (d_uns32
)token
.uns64value
, Type::tdchar
);
3983 unsigned char postfix
;
3985 // cat adjacent strings
3988 postfix
= token
.postfix
;
3992 if (token
.value
== TOKstring
)
3998 { if (token
.postfix
!= postfix
)
3999 error("mismatched string literal postfixes '%c' and '%c'", postfix
, token
.postfix
);
4000 postfix
= token
.postfix
;
4006 s2
= (unsigned char *)mem
.malloc((len
+ 1) * sizeof(unsigned char));
4007 memcpy(s2
, s
, len1
* sizeof(unsigned char));
4008 memcpy(s2
+ len1
, token
.ustring
, (len2
+ 1) * sizeof(unsigned char));
4014 e
= new StringExp(loc
, s
, len
, postfix
);
4018 CASE_BASIC_TYPES_X(t
):
4021 check(TOKdot
, t
->toChars());
4022 if (token
.value
!= TOKidentifier
)
4023 { error("found '%s' when expecting identifier following '%s.'", token
.toChars(), t
->toChars());
4026 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4035 exp
= parseExpression();
4037 t
= new TypeTypeof(loc
, exp
);
4038 if (token
.value
== TOKdot
)
4040 e
= new TypeExp(loc
, t
);
4048 check(TOKlparen
, "typeid");
4049 t
= parseBasicType();
4050 t
= parseDeclarator(t
,NULL
); // ( type )
4052 e
= new TypeidExp(loc
, t
);
4058 Identifier
*ident
= NULL
;
4060 enum TOK tok
= TOKreserved
;
4061 enum TOK tok2
= TOKreserved
;
4062 Loc loc
= this->loc
;
4065 if (token
.value
== TOKlparen
)
4068 targ
= parseBasicType();
4069 targ
= parseDeclarator(targ
, &ident
);
4070 if (token
.value
== TOKcolon
|| token
.value
== TOKequal
)
4074 if (tok
== TOKequal
&&
4075 (token
.value
== TOKtypedef
||
4076 token
.value
== TOKstruct
||
4077 token
.value
== TOKunion
||
4078 token
.value
== TOKclass
||
4079 token
.value
== TOKsuper
||
4080 token
.value
== TOKenum
||
4081 token
.value
== TOKinterface
||
4082 token
.value
== TOKfunction
||
4083 token
.value
== TOKdelegate
||
4084 token
.value
== TOKreturn
))
4091 tspec
= parseBasicType();
4092 tspec
= parseDeclarator(tspec
, NULL
);
4098 { error("(type identifier : specialization) expected following is");
4101 e
= new IsExp(loc
, targ
, ident
, tok
, tspec
, tok2
);
4106 { Expression
*msg
= NULL
;
4109 check(TOKlparen
, "assert");
4110 e
= parseAssignExp();
4111 if (token
.value
== TOKcomma
)
4113 msg
= parseAssignExp();
4116 e
= new AssertExp(loc
, e
, msg
);
4123 check(TOKlparen
, "mixin");
4124 e
= parseAssignExp();
4126 e
= new CompileExp(loc
, e
);
4133 check(TOKlparen
, "import");
4134 e
= parseAssignExp();
4136 e
= new FileExp(loc
, e
);
4141 if (peekPastParen(&token
)->value
== TOKlcurly
)
4142 { // (arguments) { statements... }
4148 e
= parseExpression();
4149 check(loc
, TOKrparen
);
4153 { /* Parse array literals and associative array literals:
4154 * [ value, value, value ... ]
4155 * [ key:value, key:value, key:value ... ]
4157 Expressions
*values
= new Expressions();
4158 Expressions
*keys
= NULL
;
4161 if (token
.value
!= TOKrbracket
)
4165 Expression
*e
= parseAssignExp();
4166 if (token
.value
== TOKcolon
&& (keys
|| values
->dim
== 0))
4169 keys
= new Expressions();
4171 e
= parseAssignExp();
4174 { error("'key:value' expected for associative array literal");
4179 if (token
.value
== TOKrbracket
)
4187 e
= new AssocArrayLiteralExp(loc
, keys
, values
);
4189 e
= new ArrayLiteralExp(loc
, values
);
4194 // { statements... }
4204 /* function type(parameters) { body }
4205 * delegate type(parameters) { body }
4207 Arguments
*arguments
;
4209 FuncLiteralDeclaration
*fd
;
4212 if (token
.value
== TOKlcurly
)
4216 arguments
= new Arguments();
4220 if (token
.value
== TOKlparen
)
4224 t
= parseBasicType();
4225 t
= parseBasicType2(t
); // function return type
4227 arguments
= parseParameters(&varargs
);
4229 t
= new TypeFunction(arguments
, t
, varargs
, linkage
);
4230 fd
= new FuncLiteralDeclaration(loc
, 0, t
, save
, NULL
);
4232 e
= new FuncExp(loc
, fd
);
4237 error("expression expected, not '%s'", token
.toChars());
4239 // Anything for e, as long as it's not NULL
4240 e
= new IntegerExp(loc
, 0, Type::tint32
);
4244 return parsePostExp(e
);
4247 Expression
*Parser::parsePostExp(Expression
*e
)
4254 switch (token
.value
)
4258 if (token
.value
== TOKidentifier
)
4259 { Identifier
*id
= token
.ident
;
4262 if (token
.value
== TOKnot
&& peek(&token
)->value
== TOKlparen
)
4263 { // identifier!(template-argument-list)
4264 TemplateInstance
*tempinst
;
4266 tempinst
= new TemplateInstance(loc
, id
);
4268 tempinst
->tiargs
= parseTemplateArgumentList();
4269 e
= new DotTemplateInstanceExp(loc
, e
, tempinst
);
4272 e
= new DotIdExp(loc
, e
, id
);
4275 else if (token
.value
== TOKnew
)
4281 error("identifier expected following '.', not '%s'", token
.toChars());
4285 e
= new PostExp(TOKplusplus
, loc
, e
);
4289 e
= new PostExp(TOKminusminus
, loc
, e
);
4293 e
= new CallExp(loc
, e
, parseArguments());
4297 { // array dereferences:
4300 // array[lwr .. upr]
4306 if (token
.value
== TOKrbracket
)
4308 e
= new SliceExp(loc
, e
, NULL
, NULL
);
4313 index
= parseAssignExp();
4314 if (token
.value
== TOKslice
)
4315 { // array[lwr .. upr]
4317 upr
= parseAssignExp();
4318 e
= new SliceExp(loc
, e
, index
, upr
);
4321 { // array[index, i2, i3, i4, ...]
4322 Expressions
*arguments
= new Expressions();
4323 arguments
->push(index
);
4324 if (token
.value
== TOKcomma
)
4330 arg
= parseAssignExp();
4331 arguments
->push(arg
);
4332 if (token
.value
== TOKrbracket
)
4337 e
= new ArrayExp(loc
, e
, arguments
);
4352 Expression
*Parser::parseUnaryExp()
4354 Loc loc
= this->loc
;
4356 switch (token
.value
)
4360 e
= parseUnaryExp();
4361 e
= new AddrExp(loc
, e
);
4366 e
= parseUnaryExp();
4367 e
= new AddAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4372 e
= parseUnaryExp();
4373 e
= new MinAssignExp(loc
, e
, new IntegerExp(loc
, 1, Type::tint32
));
4378 e
= parseUnaryExp();
4379 e
= new PtrExp(loc
, e
);
4384 e
= parseUnaryExp();
4385 e
= new NegExp(loc
, e
);
4390 e
= parseUnaryExp();
4391 e
= new UAddExp(loc
, e
);
4396 e
= parseUnaryExp();
4397 e
= new NotExp(loc
, e
);
4402 e
= parseUnaryExp();
4403 e
= new ComExp(loc
, e
);
4408 e
= parseUnaryExp();
4409 e
= new DeleteExp(loc
, e
);
4413 e
= parseNewExp(NULL
);
4416 case TOKcast
: // cast(type) expression
4421 t
= parseBasicType();
4422 t
= parseDeclarator(t
,NULL
); // ( type )
4425 e
= parseUnaryExp();
4426 e
= new CastExp(loc
, e
, t
);
4436 if (isDeclaration(tk
, 0, TOKrparen
, &tk
))
4438 tk
= peek(tk
); // skip over right parenthesis
4458 case TOKimaginary32v
:
4459 case TOKimaginary64v
:
4460 case TOKimaginary80v
:
4478 CASE_BASIC_TYPES
: // (type)int.size
4483 t
= parseBasicType();
4484 t
= parseDeclarator(t
,NULL
);
4488 if (token
.value
== TOKdot
)
4491 if (token
.value
!= TOKidentifier
)
4492 { error("Identifier expected following (type).");
4495 e
= new TypeDotIdExp(loc
, t
, token
.ident
);
4497 e
= parsePostExp(e
);
4501 e
= parseUnaryExp();
4502 e
= new CastExp(loc
, e
, t
);
4503 error("C style cast illegal, use %s", e
->toChars());
4510 e
= parsePrimaryExp();
4514 e
= parsePrimaryExp();
4521 Expression
*Parser::parseMulExp()
4524 Loc loc
= this->loc
;
4526 e
= parseUnaryExp();
4529 switch (token
.value
)
4531 case TOKmul
: nextToken(); e2
= parseUnaryExp(); e
= new MulExp(loc
,e
,e2
); continue;
4532 case TOKdiv
: nextToken(); e2
= parseUnaryExp(); e
= new DivExp(loc
,e
,e2
); continue;
4533 case TOKmod
: nextToken(); e2
= parseUnaryExp(); e
= new ModExp(loc
,e
,e2
); continue;
4543 Expression
*Parser::parseAddExp()
4546 Loc loc
= this->loc
;
4551 switch (token
.value
)
4553 case TOKadd
: nextToken(); e2
= parseMulExp(); e
= new AddExp(loc
,e
,e2
); continue;
4554 case TOKmin
: nextToken(); e2
= parseMulExp(); e
= new MinExp(loc
,e
,e2
); continue;
4555 case TOKtilde
: nextToken(); e2
= parseMulExp(); e
= new CatExp(loc
,e
,e2
); continue;
4565 Expression
*Parser::parseShiftExp()
4568 Loc loc
= this->loc
;
4573 switch (token
.value
)
4575 case TOKshl
: nextToken(); e2
= parseAddExp(); e
= new ShlExp(loc
,e
,e2
); continue;
4576 case TOKshr
: nextToken(); e2
= parseAddExp(); e
= new ShrExp(loc
,e
,e2
); continue;
4577 case TOKushr
: nextToken(); e2
= parseAddExp(); e
= new UshrExp(loc
,e
,e2
); continue;
4587 Expression
*Parser::parseRelExp()
4591 Loc loc
= this->loc
;
4593 e
= parseShiftExp();
4596 switch (token
.value
)
4612 e2
= parseShiftExp();
4613 e
= new CmpExp(op
, loc
, e
, e2
);
4618 e2
= parseShiftExp();
4619 e
= new InExp(loc
, e
, e2
);
4630 Expression
*Parser::parseEqualExp()
4634 Loc loc
= this->loc
;
4638 { enum TOK value
= token
.value
;
4646 e
= new EqualExp(value
, loc
, e
, e2
);
4650 error("'===' is no longer legal, use 'is' instead");
4653 case TOKnotidentity
:
4654 error("'!==' is no longer legal, use '!is' instead");
4658 value
= TOKidentity
;
4662 // Attempt to identify '!is'
4664 if (t
->value
!= TOKis
)
4667 value
= TOKnotidentity
;
4673 e
= new IdentityExp(value
, loc
, e
, e2
);
4684 Expression
*Parser::parseCmpExp()
4688 Loc loc
= this->loc
;
4690 e
= parseShiftExp();
4691 enum TOK op
= token
.value
;
4698 e2
= parseShiftExp();
4699 e
= new EqualExp(op
, loc
, e
, e2
);
4707 // Attempt to identify '!is'
4709 if (t
->value
!= TOKis
)
4712 op
= TOKnotidentity
;
4717 e2
= parseShiftExp();
4718 e
= new IdentityExp(op
, loc
, e
, e2
);
4734 e2
= parseShiftExp();
4735 e
= new CmpExp(op
, loc
, e
, e2
);
4740 e2
= parseShiftExp();
4741 e
= new InExp(loc
, e
, e2
);
4750 Expression
*Parser::parseAndExp()
4753 Loc loc
= this->loc
;
4755 if (global
.params
.Dversion
== 1)
4757 e
= parseEqualExp();
4758 while (token
.value
== TOKand
)
4761 e2
= parseEqualExp();
4762 e
= new AndExp(loc
,e
,e2
);
4769 while (token
.value
== TOKand
)
4773 e
= new AndExp(loc
,e
,e2
);
4780 Expression
*Parser::parseXorExp()
4783 Loc loc
= this->loc
;
4786 while (token
.value
== TOKxor
)
4790 e
= new XorExp(loc
, e
, e2
);
4795 Expression
*Parser::parseOrExp()
4798 Loc loc
= this->loc
;
4801 while (token
.value
== TOKor
)
4805 e
= new OrExp(loc
, e
, e2
);
4810 Expression
*Parser::parseAndAndExp()
4813 Loc loc
= this->loc
;
4816 while (token
.value
== TOKandand
)
4820 e
= new AndAndExp(loc
, e
, e2
);
4825 Expression
*Parser::parseOrOrExp()
4828 Loc loc
= this->loc
;
4830 e
= parseAndAndExp();
4831 while (token
.value
== TOKoror
)
4834 e2
= parseAndAndExp();
4835 e
= new OrOrExp(loc
, e
, e2
);
4840 Expression
*Parser::parseCondExp()
4844 Loc loc
= this->loc
;
4847 if (token
.value
== TOKquestion
)
4850 e1
= parseExpression();
4852 e2
= parseCondExp();
4853 e
= new CondExp(loc
, e
, e1
, e2
);
4858 Expression
*Parser::parseAssignExp()
4867 switch (token
.value
)
4869 #define X(tok,ector) \
4870 case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
4872 X(TOKassign
, AssignExp
);
4873 X(TOKaddass
, AddAssignExp
);
4874 X(TOKminass
, MinAssignExp
);
4875 X(TOKmulass
, MulAssignExp
);
4876 X(TOKdivass
, DivAssignExp
);
4877 X(TOKmodass
, ModAssignExp
);
4878 X(TOKandass
, AndAssignExp
);
4879 X(TOKorass
, OrAssignExp
);
4880 X(TOKxorass
, XorAssignExp
);
4881 X(TOKshlass
, ShlAssignExp
);
4882 X(TOKshrass
, ShrAssignExp
);
4883 X(TOKushrass
, UshrAssignExp
);
4884 X(TOKcatass
, CatAssignExp
);
4895 Expression
*Parser::parseExpression()
4898 Loc loc
= this->loc
;
4900 //printf("Parser::parseExpression()\n");
4901 e
= parseAssignExp();
4902 while (token
.value
== TOKcomma
)
4905 e2
= parseAssignExp();
4906 e
= new CommaExp(loc
, e
, e2
);
4913 /*************************
4914 * Collect argument list.
4915 * Assume current token is '(' or '['.
4918 Expressions
*Parser::parseArguments()
4920 Expressions
*arguments
;
4924 arguments
= new Expressions();
4925 if (token
.value
== TOKlbracket
)
4926 endtok
= TOKrbracket
;
4932 if (token
.value
!= endtok
)
4936 arg
= parseAssignExp();
4937 arguments
->push(arg
);
4938 if (token
.value
== endtok
)
4948 /*******************************************
4951 Expression
*Parser::parseNewExp(Expression
*thisexp
)
4953 Expressions
*newargs
;
4954 Expressions
*arguments
= NULL
;
4956 Loc loc
= this->loc
;
4960 if (token
.value
== TOKlparen
)
4962 newargs
= parseArguments();
4965 // An anonymous nested class starts with "class"
4966 if (token
.value
== TOKclass
)
4969 if (token
.value
== TOKlparen
)
4970 arguments
= parseArguments();
4972 BaseClasses
*baseclasses
= NULL
;
4973 if (token
.value
!= TOKlcurly
)
4974 baseclasses
= parseBaseClasses();
4976 Identifier
*id
= NULL
;
4977 ClassDeclaration
*cd
= new ClassDeclaration(loc
, id
, baseclasses
);
4979 if (token
.value
!= TOKlcurly
)
4980 { error("{ members } expected for anonymous class");
4986 Array
*decl
= parseDeclDefs(0);
4987 if (token
.value
!= TOKrcurly
)
4988 error("class member expected");
4993 e
= new NewAnonClassExp(loc
, thisexp
, newargs
, cd
, arguments
);
4999 t
= parseBasicType();
5000 t
= parseBasicType2(t
);
5001 if (t
->ty
== Taarray
)
5003 Type
*index
= ((TypeAArray
*)t
)->index
;
5005 Expression
*e
= index
->toExpression();
5007 { arguments
= new Expressions();
5009 t
= new TypeDArray(t
->next
);
5013 error("need size of rightmost array, not type %s", index
->toChars());
5014 return new NullExp(loc
);
5017 else if (t
->ty
== Tsarray
)
5019 TypeSArray
*tsa
= (TypeSArray
*)t
;
5020 Expression
*e
= tsa
->dim
;
5022 arguments
= new Expressions();
5024 t
= new TypeDArray(t
->next
);
5026 else if (token
.value
== TOKlparen
)
5028 arguments
= parseArguments();
5031 t
= parseBasicType();
5032 while (token
.value
== TOKmul
)
5033 { t
= new TypePointer(t
);
5036 if (token
.value
== TOKlbracket
)
5041 e
= parseAssignExp();
5042 arguments
= new Array();
5045 t
= parseDeclarator(t
, NULL
);
5046 t
= new TypeDArray(t
);
5048 else if (token
.value
== TOKlparen
)
5049 arguments
= parseArguments();
5051 e
= new NewExp(loc
, thisexp
, newargs
, t
, arguments
);
5055 /**********************************************
5058 void Parser::addComment(Dsymbol
*s
, unsigned char *blockComment
)
5060 s
->addComment(combineComments(blockComment
, token
.lineComment
));
5064 /********************************* ***************************/