Mercurial > projects > ddmd
annotate dmd/Parser.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | c494af1dba80 |
children | e3afd1303184 |
rev | line source |
---|---|
0 | 1 module dmd.Parser; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Lexer; |
5 import dmd.PostBlitDeclaration; | |
6 import dmd.FileInitExp; | |
7 import dmd.LineInitExp; | |
8 import dmd.EnumMember; | |
9 import dmd.CtorDeclaration; | |
10 import dmd.ShlAssignExp; | |
11 import dmd.ShrAssignExp; | |
12 import dmd.UshrAssignExp; | |
13 import dmd.CatAssignExp; | |
14 import dmd.StaticIfCondition; | |
15 import dmd.TraitsExp; | |
13 | 16 import dmd.TemplateMixin; |
0 | 17 import dmd.BaseClass; |
18 import dmd.AssignExp; | |
19 import dmd.TemplateInstance; | |
20 import dmd.NewExp; | |
21 import dmd.ArrayExp; | |
22 import dmd.DotTemplateInstanceExp; | |
23 import dmd.ClassDeclaration; | |
24 import dmd.NewAnonClassExp; | |
25 import dmd.InterfaceDeclaration; | |
26 import dmd.StructDeclaration; | |
27 import dmd.UnionDeclaration; | |
28 import dmd.AnonDeclaration; | |
29 import dmd.StructInitializer; | |
30 import dmd.ArrayInitializer; | |
31 import dmd.ExpInitializer; | |
32 import dmd.TemplateAliasParameter; | |
33 import dmd.TemplateTupleParameter; | |
34 import dmd.TemplateThisParameter; | |
35 import dmd.TemplateValueParameter; | |
36 import dmd.VoidInitializer; | |
37 import dmd.VersionCondition; | |
38 import dmd.DotIdExp; | |
39 import dmd.DebugCondition; | |
40 import dmd.PostExp; | |
41 import dmd.CallExp; | |
42 import dmd.SliceExp; | |
43 import dmd.FuncExp; | |
44 import dmd.AssocArrayLiteralExp; | |
45 import dmd.ArrayLiteralExp; | |
46 import dmd.IsExp; | |
47 import dmd.FuncLiteralDeclaration; | |
48 import dmd.AssertExp; | |
49 import dmd.CompileExp; | |
50 import dmd.FileExp; | |
19
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
51 import dmd.TemplateMixin; |
0 | 52 import dmd.TemplateParameter; |
53 import dmd.TemplateTypeParameter; | |
54 import dmd.TypeidExp; | |
55 import dmd.StringExp; | |
56 import dmd.ScopeExp; | |
57 import dmd.IdentifierExp; | |
58 import dmd.DollarExp; | |
59 import dmd.ThisExp; | |
60 import dmd.SuperExp; | |
61 import dmd.NullExp; | |
62 import dmd.RealExp; | |
63 import dmd.TypeExp; | |
64 import dmd.AddrExp; | |
65 import dmd.MOD; | |
66 import dmd.IntegerExp; | |
67 import dmd.CastExp; | |
68 import dmd.PtrExp; | |
69 import dmd.NegExp; | |
70 import dmd.XorAssignExp; | |
71 import dmd.OrAssignExp; | |
72 import dmd.UAddExp; | |
73 import dmd.NotExp; | |
74 import dmd.ComExp; | |
75 import dmd.DeleteExp; | |
76 import dmd.MulAssignExp; | |
77 import dmd.ModAssignExp; | |
78 import dmd.MinAssignExp; | |
79 import dmd.DivAssignExp; | |
80 import dmd.AndAssignExp; | |
81 import dmd.AddAssignExp; | |
135 | 82 import dmd.PowAssignExp; |
0 | 83 import dmd.ModuleDeclaration; |
84 import dmd.CaseRangeStatement; | |
85 import dmd.CommaExp; | |
86 import dmd.XorExp; | |
87 import dmd.CondExp; | |
88 import dmd.CmpExp; | |
89 import dmd.InExp; | |
90 import dmd.OrOrExp; | |
91 import dmd.OrExp; | |
92 import dmd.AddExp; | |
93 import dmd.MinExp; | |
94 import dmd.CatExp; | |
95 import dmd.AndAndExp; | |
96 import dmd.EqualExp; | |
97 import dmd.ShlExp; | |
98 import dmd.ShrExp; | |
99 import dmd.DivExp; | |
100 import dmd.MulExp; | |
101 import dmd.ModExp; | |
102 import dmd.UshrExp; | |
103 import dmd.IdentityExp; | |
104 import dmd.AndExp; | |
105 import dmd.Id; | |
106 import dmd.LabelStatement; | |
107 import dmd.ExpStatement; | |
108 import dmd.StaticAssertStatement; | |
109 import dmd.DeclarationStatement; | |
110 import dmd.ScopeStatement; | |
111 import dmd.PragmaStatement; | |
112 import dmd.WhileStatement; | |
113 import dmd.DoStatement; | |
114 import dmd.ForStatement; | |
115 import dmd.OnScopeStatement; | |
116 import dmd.IfStatement; | |
117 import dmd.SwitchStatement; | |
118 import dmd.CaseStatement; | |
119 import dmd.DefaultStatement; | |
120 import dmd.GotoDefaultStatement; | |
121 import dmd.GotoCaseStatement; | |
122 import dmd.GotoStatement; | |
123 import dmd.SynchronizedStatement; | |
124 import dmd.WithStatement; | |
125 import dmd.Catch; | |
126 import dmd.TryCatchStatement; | |
127 import dmd.TryFinallyStatement; | |
128 import dmd.ThrowStatement; | |
129 import dmd.VolatileStatement; | |
130 import dmd.ReturnStatement; | |
131 import dmd.BreakStatement; | |
132 import dmd.ContinueStatement; | |
133 import dmd.AsmStatement; | |
134 import dmd.TypeReturn; | |
135 import dmd.TypeTypeof; | |
136 import dmd.ForeachRangeStatement; | |
137 import dmd.ForeachStatement; | |
138 import dmd.CompileStatement; | |
139 import dmd.CompoundStatement; | |
140 import dmd.ConditionalStatement; | |
141 import dmd.CompoundDeclarationStatement; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
142 import dmd.Parameter; |
0 | 143 import dmd.ParseStatementFlags; |
79 | 144 import dmd.TypeNewArray; |
0 | 145 import dmd.TypeNext; |
146 import dmd.TypeInstance; | |
147 import dmd.TypePointer; | |
148 import dmd.TypeDArray; | |
149 import dmd.TypeAArray; | |
150 import dmd.TypeSlice; | |
151 import dmd.TypeSArray; | |
152 import dmd.TemplateInstance; | |
153 import dmd.TypeIdentifier; | |
154 import dmd.VarDeclaration; | |
155 import dmd.TypeFunction; | |
156 import dmd.TypeDelegate; | |
157 import dmd.TY; | |
158 import dmd.LinkDeclaration; | |
159 import dmd.Declaration; | |
160 import dmd.AggregateDeclaration; | |
161 import dmd.TypedefDeclaration; | |
162 import dmd.AliasDeclaration; | |
163 import dmd.LINK; | |
164 import dmd.Loc; | |
165 import dmd.Module; | |
166 import dmd.Array; | |
167 import dmd.Expression; | |
168 import dmd.TemplateDeclaration; | |
169 import dmd.ArrayTypes; | |
170 import dmd.Dsymbol; | |
171 import dmd.StaticAssert; | |
172 import dmd.TypeQualified; | |
173 import dmd.Condition; | |
174 import dmd.PostBlitDeclaration; | |
175 import dmd.DtorDeclaration; | |
176 import dmd.ConditionalDeclaration; | |
177 import dmd.StaticCtorDeclaration; | |
178 import dmd.StaticDtorDeclaration; | |
179 import dmd.InvariantDeclaration; | |
180 import dmd.UnitTestDeclaration; | |
181 import dmd.NewDeclaration; | |
182 import dmd.DeleteDeclaration; | |
183 import dmd.EnumDeclaration; | |
184 import dmd.Import; | |
185 import dmd.Type; | |
186 import dmd.Identifier; | |
187 import dmd.FuncDeclaration; | |
188 import dmd.Statement; | |
189 import dmd.Initializer; | |
190 import dmd.Token; | |
191 import dmd.TOK; | |
192 import dmd.ParseStatementFlags; | |
193 import dmd.PROT; | |
194 import dmd.STC; | |
195 import dmd.Util; | |
196 import dmd.CompileDeclaration; | |
197 import dmd.StaticIfDeclaration; | |
198 import dmd.StorageClassDeclaration; | |
199 import dmd.LinkDeclaration; | |
200 import dmd.ProtDeclaration; | |
201 import dmd.AlignDeclaration; | |
202 import dmd.PragmaDeclaration; | |
203 import dmd.DebugSymbol; | |
204 import dmd.VersionSymbol; | |
205 import dmd.AliasThis; | |
206 import dmd.Global; | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
207 import dmd.TRUST; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
208 import dmd.PowExp; |
0 | 209 |
210 import core.stdc.string : memcpy; | |
211 | |
34 | 212 import std.exception; |
4 | 213 import core.memory; |
0 | 214 |
215 class Parser : Lexer | |
216 { | |
217 ModuleDeclaration md; | |
218 LINK linkage; | |
219 Loc endloc; // set to location of last right curly | |
220 int inBrackets; // inside [] of array index or slice | |
221 | |
222 this(Module module_, ubyte* base, uint length, int doDocComment) | |
223 { | |
224 super(module_, base, 0, length, doDocComment, 0); | |
225 //printf("Parser.Parser()\n"); | |
226 linkage = LINK.LINKd; | |
227 //nextToken(); // start up the scanner | |
228 } | |
229 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
230 Dsymbols parseModule() |
0 | 231 { |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
232 typeof(return) decldefs; |
0 | 233 |
234 // ModuleDeclation leads off | |
235 if (token.value == TOK.TOKmodule) | |
236 { | |
79 | 237 string comment = token.blockComment; |
0 | 238 bool safe = false; |
239 | |
240 nextToken(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
241 static if(false) { |
0 | 242 version (DMDV2) { |
243 if (token.value == TOK.TOKlparen) | |
244 { | |
245 nextToken(); | |
246 if (token.value != TOK.TOKidentifier) | |
247 { | |
248 error("module (system) identifier expected"); | |
249 goto Lerr; | |
250 } | |
251 Identifier id = token.ident; | |
252 | |
253 if (id is Id.system) | |
254 safe = true; | |
255 else | |
256 error("(safe) expected, not %s", id.toChars()); | |
257 nextToken(); | |
258 check(TOK.TOKrparen); | |
259 } | |
260 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
261 } |
0 | 262 |
263 if (token.value != TOK.TOKidentifier) | |
264 { | |
265 error("Identifier expected following module"); | |
266 goto Lerr; | |
267 } | |
268 else | |
269 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
270 Identifiers a = null; |
0 | 271 Identifier id = token.ident; |
272 while (nextToken() == TOK.TOKdot) | |
273 { | |
274 if (!a) | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
275 a = new Identifiers(); |
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
276 a.push(id); |
0 | 277 nextToken(); |
278 if (token.value != TOK.TOKidentifier) | |
279 { error("Identifier expected following package"); | |
280 goto Lerr; | |
281 } | |
282 id = token.ident; | |
283 } | |
284 | |
285 md = new ModuleDeclaration(a, id, safe); | |
286 | |
287 if (token.value != TOK.TOKsemicolon) | |
288 error("';' expected following module declaration instead of %s", token.toChars()); | |
289 | |
290 nextToken(); | |
291 addComment(mod, comment); | |
292 } | |
293 } | |
294 | |
295 decldefs = parseDeclDefs(0); | |
296 if (token.value != TOK.TOKeof) | |
297 { | |
298 error("unrecognized declaration"); | |
299 goto Lerr; | |
300 } | |
301 | |
302 return decldefs; | |
303 | |
304 Lerr: | |
305 while (token.value != TOK.TOKsemicolon && token.value != TOK.TOKeof) | |
306 nextToken(); | |
307 | |
308 nextToken(); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
309 return new Dsymbols(); |
0 | 310 } |
311 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
312 Dsymbols parseDeclDefs(int once) |
0 | 313 { |
314 Dsymbol s; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
315 Dsymbols decldefs; |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
316 Dsymbols a; |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
317 Dsymbols aelse; |
0 | 318 PROT prot; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
319 StorageClass stc; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
320 StorageClass storageClass; |
0 | 321 Condition condition; |
79 | 322 string comment; |
0 | 323 |
324 //printf("Parser.parseDeclDefs()\n"); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
325 decldefs = new Dsymbols(); |
0 | 326 do |
327 { | |
328 comment = token.blockComment; | |
329 storageClass = STC.STCundefined; | |
330 switch (token.value) | |
331 { | |
332 case TOK.TOKenum: | |
333 { /* Determine if this is a manifest constant declaration, | |
334 * or a conventional enum. | |
335 */ | |
336 Token *t = peek(&token); | |
337 if (t.value == TOK.TOKlcurly || t.value == TOK.TOKcolon) | |
338 s = parseEnum(); | |
339 else if (t.value != TOK.TOKidentifier) | |
340 goto Ldeclaration; | |
341 else | |
342 { | |
343 t = peek(t); | |
344 if (t.value == TOK.TOKlcurly || t.value == TOK.TOKcolon || | |
345 t.value == TOK.TOKsemicolon) | |
346 s = parseEnum(); | |
347 else | |
348 goto Ldeclaration; | |
349 } | |
350 break; | |
351 } | |
352 | |
353 case TOK.TOKstruct: | |
354 case TOK.TOKunion: | |
355 case TOK.TOKclass: | |
356 case TOK.TOKinterface: | |
357 s = parseAggregate(); | |
358 break; | |
359 | |
360 case TOK.TOKimport: | |
361 s = parseImport(decldefs, 0); | |
362 break; | |
363 | |
364 case TOK.TOKtemplate: | |
365 s = cast(Dsymbol)parseTemplateDeclaration(); | |
366 break; | |
367 | |
368 case TOK.TOKmixin: | |
369 { Loc loc = this.loc; | |
370 if (peek(&token).value == TOK.TOKlparen) | |
371 { // mixin(string) | |
372 nextToken(); | |
373 check(TOK.TOKlparen, "mixin"); | |
374 Expression e = parseAssignExp(); | |
375 check(TOK.TOKrparen); | |
376 check(TOK.TOKsemicolon); | |
377 s = new CompileDeclaration(loc, e); | |
378 break; | |
379 } | |
380 s = parseMixin(); | |
381 break; | |
382 } | |
383 | |
384 case TOK.TOKwchar: case TOK.TOKdchar: | |
385 case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar: | |
386 case TOK.TOKint8: case TOK.TOKuns8: | |
387 case TOK.TOKint16: case TOK.TOKuns16: | |
388 case TOK.TOKint32: case TOK.TOKuns32: | |
389 case TOK.TOKint64: case TOK.TOKuns64: | |
390 case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80: | |
391 case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80: | |
392 case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80: | |
393 case TOK.TOKvoid: | |
394 case TOK.TOKalias: | |
395 case TOK.TOKtypedef: | |
396 case TOK.TOKidentifier: | |
397 case TOK.TOKtypeof: | |
398 case TOK.TOKdot: | |
399 Ldeclaration: | |
400 a = parseDeclarations(STC.STCundefined); | |
401 decldefs.append(a); | |
402 continue; | |
403 | |
404 case TOK.TOKthis: | |
405 s = parseCtor(); | |
406 break; | |
407 | |
408 static if (false) { // dead end, use this(this){} instead | |
409 case TOK.TOKassign: | |
410 s = parsePostBlit(); | |
411 break; | |
412 } | |
413 case TOK.TOKtilde: | |
414 s = parseDtor(); | |
415 break; | |
416 | |
417 case TOK.TOKinvariant: | |
418 { Token *t; | |
419 t = peek(&token); | |
420 if (t.value == TOK.TOKlparen) | |
421 { | |
422 if (peek(t).value == TOK.TOKrparen) | |
423 // invariant() forms start of class invariant | |
424 s = parseInvariant(); | |
425 else | |
426 // invariant(type) | |
427 goto Ldeclaration; | |
428 } | |
429 else | |
430 { | |
431 stc = STC.STCimmutable; | |
432 goto Lstc; | |
433 } | |
434 break; | |
435 } | |
436 | |
437 case TOK.TOKunittest: | |
438 s = parseUnitTest(); | |
439 break; | |
440 | |
441 case TOK.TOKnew: | |
442 s = parseNew(); | |
443 break; | |
444 | |
445 case TOK.TOKdelete: | |
446 s = parseDelete(); | |
447 break; | |
448 | |
449 case TOK.TOKeof: | |
450 case TOK.TOKrcurly: | |
451 return decldefs; | |
452 | |
453 case TOK.TOKstatic: | |
454 nextToken(); | |
455 if (token.value == TOK.TOKthis) | |
456 s = parseStaticCtor(); | |
457 else if (token.value == TOK.TOKtilde) | |
458 s = parseStaticDtor(); | |
459 else if (token.value == TOK.TOKassert) | |
460 s = parseStaticAssert(); | |
461 else if (token.value == TOK.TOKif) | |
462 { condition = parseStaticIfCondition(); | |
463 a = parseBlock(); | |
464 aelse = null; | |
465 if (token.value == TOK.TOKelse) | |
466 { nextToken(); | |
467 aelse = parseBlock(); | |
468 } | |
469 s = new StaticIfDeclaration(condition, a, aelse); | |
470 break; | |
471 } | |
472 else if (token.value == TOK.TOKimport) | |
473 { | |
474 s = parseImport(decldefs, 1); | |
475 } | |
476 else | |
477 { stc = STC.STCstatic; | |
478 goto Lstc2; | |
479 } | |
480 break; | |
481 | |
482 case TOK.TOKconst: | |
483 if (peek(&token).value == TOK.TOKlparen) | |
484 goto Ldeclaration; | |
485 stc = STC.STCconst; | |
486 goto Lstc; | |
487 | |
488 case TOK.TOKimmutable: | |
489 if (peek(&token).value == TOK.TOKlparen) | |
490 goto Ldeclaration; | |
491 stc = STC.STCimmutable; | |
492 goto Lstc; | |
493 | |
494 case TOK.TOKshared: | |
495 if (peek(&token).value == TOK.TOKlparen) | |
496 goto Ldeclaration; | |
497 stc = STC.STCshared; | |
498 goto Lstc; | |
499 | |
135 | 500 case TOKwild: |
501 if (peek(&token).value == TOK.TOKlparen) | |
502 goto Ldeclaration; | |
503 stc = STCwild; | |
504 goto Lstc; | |
505 | |
0 | 506 case TOK.TOKfinal: stc = STC.STCfinal; goto Lstc; |
507 case TOK.TOKauto: stc = STC.STCauto; goto Lstc; | |
508 case TOK.TOKscope: stc = STC.STCscope; goto Lstc; | |
509 case TOK.TOKoverride: stc = STC.STCoverride; goto Lstc; | |
510 case TOK.TOKabstract: stc = STC.STCabstract; goto Lstc; | |
511 case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto Lstc; | |
512 case TOK.TOKdeprecated: stc = STC.STCdeprecated; goto Lstc; | |
513 version (DMDV2) { | |
514 case TOK.TOKnothrow: stc = STC.STCnothrow; goto Lstc; | |
515 case TOK.TOKpure: stc = STC.STCpure; goto Lstc; | |
516 case TOK.TOKref: stc = STC.STCref; goto Lstc; | |
517 case TOK.TOKtls: stc = STC.STCtls; goto Lstc; | |
518 case TOK.TOKgshared: | |
519 stc = STC.STCgshared; goto Lstc; | |
520 //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
521 case TOK.TOKat: stc = parseAttribute(); goto Lstc; |
0 | 522 } |
523 | |
524 Lstc: | |
525 if (storageClass & stc) | |
526 error("redundant storage class %s", Token.toChars(token.value)); | |
527 composeStorageClass(storageClass | stc); | |
528 nextToken(); | |
529 Lstc2: | |
530 storageClass |= stc; | |
531 switch (token.value) | |
532 { | |
533 case TOK.TOKconst: | |
534 case TOK.TOKinvariant: | |
535 case TOK.TOKimmutable: | |
536 case TOK.TOKshared: | |
135 | 537 case TOKwild: |
0 | 538 // If followed by a (, it is not a storage class |
539 if (peek(&token).value == TOK.TOKlparen) | |
540 break; | |
541 if (token.value == TOK.TOKconst) | |
542 stc = STC.STCconst; | |
543 else if (token.value == TOK.TOKshared) | |
544 stc = STC.STCshared; | |
135 | 545 else if (token.value == TOKwild) |
546 stc = STC.STCwild; | |
0 | 547 else |
548 stc = STC.STCimmutable; | |
549 goto Lstc; | |
550 case TOK.TOKfinal: stc = STC.STCfinal; goto Lstc; | |
551 case TOK.TOKauto: stc = STC.STCauto; goto Lstc; | |
552 case TOK.TOKscope: stc = STC.STCscope; goto Lstc; | |
553 case TOK.TOKoverride: stc = STC.STCoverride; goto Lstc; | |
554 case TOK.TOKabstract: stc = STC.STCabstract; goto Lstc; | |
555 case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto Lstc; | |
556 case TOK.TOKdeprecated: stc = STC.STCdeprecated; goto Lstc; | |
557 case TOK.TOKnothrow: stc = STC.STCnothrow; goto Lstc; | |
558 case TOK.TOKpure: stc = STC.STCpure; goto Lstc; | |
559 case TOK.TOKref: stc = STC.STCref; goto Lstc; | |
560 case TOK.TOKtls: stc = STC.STCtls; goto Lstc; | |
561 case TOK.TOKgshared: stc = STC.STCgshared; goto Lstc; | |
562 //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
563 case TOK.TOKat: stc = parseAttribute(); goto Lstc; |
0 | 564 default: |
565 break; | |
566 } | |
567 | |
568 /* Look for auto initializers: | |
569 * storage_class identifier = initializer; | |
570 */ | |
571 if (token.value == TOK.TOKidentifier && | |
572 peek(&token).value == TOK.TOKassign) | |
573 { | |
574 a = parseAutoDeclarations(storageClass, comment); | |
575 decldefs.append(a); | |
576 continue; | |
577 } | |
578 | |
579 /* Look for return type inference for template functions. | |
580 */ | |
581 Token *tk; | |
582 if (token.value == TOK.TOKidentifier && | |
583 (tk = peek(&token)).value == TOK.TOKlparen && | |
584 skipParens(tk, &tk) && | |
585 (peek(tk).value == TOK.TOKlparen || | |
586 peek(tk).value == TOK.TOKlcurly) | |
587 ) | |
588 { | |
589 a = parseDeclarations(storageClass); | |
590 decldefs.append(a); | |
591 continue; | |
592 } | |
593 a = parseBlock(); | |
594 s = new StorageClassDeclaration(storageClass, a); | |
595 break; | |
596 | |
597 case TOK.TOKextern: | |
598 if (peek(&token).value != TOK.TOKlparen) | |
599 { | |
600 stc = STC.STCextern; | |
601 goto Lstc; | |
602 } | |
603 { | |
604 LINK linksave = linkage; | |
605 linkage = parseLinkage(); | |
606 a = parseBlock(); | |
607 s = new LinkDeclaration(linkage, a); | |
608 linkage = linksave; | |
609 break; | |
610 } | |
611 | |
612 case TOK.TOKprivate: prot = PROT.PROTprivate; goto Lprot; | |
613 case TOK.TOKpackage: prot = PROT.PROTpackage; goto Lprot; | |
614 case TOK.TOKprotected: prot = PROT.PROTprotected; goto Lprot; | |
615 case TOK.TOKpublic: prot = PROT.PROTpublic; goto Lprot; | |
616 case TOK.TOKexport: prot = PROT.PROTexport; goto Lprot; | |
617 Lprot: | |
618 nextToken(); | |
619 switch (token.value) | |
620 { | |
621 case TOK.TOKprivate: | |
622 case TOK.TOKpackage: | |
623 case TOK.TOKprotected: | |
624 case TOK.TOKpublic: | |
625 case TOK.TOKexport: | |
626 error("redundant protection attribute"); | |
627 break; | |
628 default: | |
629 break; | |
630 } | |
631 a = parseBlock(); | |
632 s = new ProtDeclaration(prot, a); | |
633 break; | |
634 | |
635 case TOK.TOKalign: | |
636 { uint n; | |
637 | |
638 s = null; | |
639 nextToken(); | |
640 if (token.value == TOK.TOKlparen) | |
641 { | |
642 nextToken(); | |
643 if (token.value == TOK.TOKint32v) | |
644 n = cast(uint)token.uns64value; | |
645 else | |
646 { error("integer expected, not %s", token.toChars()); | |
647 n = 1; | |
648 } | |
649 nextToken(); | |
650 check(TOK.TOKrparen); | |
651 } | |
652 else | |
653 n = global.structalign; // default | |
654 | |
655 a = parseBlock(); | |
656 s = new AlignDeclaration(n, a); | |
657 break; | |
658 } | |
659 | |
660 case TOK.TOKpragma: | |
661 { Identifier ident; | |
662 Expressions args = null; | |
663 | |
664 nextToken(); | |
665 check(TOK.TOKlparen); | |
666 if (token.value != TOK.TOKidentifier) | |
667 { error("pragma(identifier expected"); | |
668 goto Lerror; | |
669 } | |
670 ident = token.ident; | |
671 nextToken(); | |
672 if (token.value == TOK.TOKcomma && peekNext() != TOK.TOKrparen) | |
673 args = parseArguments(); // pragma(identifier, args...) | |
674 else | |
675 check(TOK.TOKrparen); // pragma(identifier) | |
676 | |
677 if (token.value == TOK.TOKsemicolon) | |
678 a = null; | |
679 else | |
680 a = parseBlock(); | |
681 s = new PragmaDeclaration(loc, ident, args, a); | |
682 break; | |
683 } | |
684 | |
685 case TOK.TOKdebug: | |
686 nextToken(); | |
687 if (token.value == TOK.TOKassign) | |
688 { | |
689 nextToken(); | |
690 if (token.value == TOK.TOKidentifier) | |
691 s = new DebugSymbol(loc, token.ident); | |
692 else if (token.value == TOK.TOKint32v) | |
693 s = new DebugSymbol(loc, cast(uint)token.uns64value); | |
694 else | |
695 { error("identifier or integer expected, not %s", token.toChars()); | |
696 s = null; | |
697 } | |
698 nextToken(); | |
699 if (token.value != TOK.TOKsemicolon) | |
700 error("semicolon expected"); | |
701 nextToken(); | |
702 break; | |
703 } | |
704 | |
705 condition = parseDebugCondition(); | |
706 goto Lcondition; | |
707 | |
708 case TOK.TOKversion: | |
709 nextToken(); | |
710 if (token.value == TOK.TOKassign) | |
711 { | |
712 nextToken(); | |
713 if (token.value == TOK.TOKidentifier) | |
714 s = new VersionSymbol(loc, token.ident); | |
715 else if (token.value == TOK.TOKint32v) | |
716 s = new VersionSymbol(loc, cast(uint)token.uns64value); | |
717 else | |
718 { error("identifier or integer expected, not %s", token.toChars()); | |
719 s = null; | |
720 } | |
721 nextToken(); | |
722 if (token.value != TOK.TOKsemicolon) | |
723 error("semicolon expected"); | |
724 nextToken(); | |
725 break; | |
726 } | |
727 condition = parseVersionCondition(); | |
728 goto Lcondition; | |
729 | |
730 Lcondition: | |
731 a = parseBlock(); | |
732 aelse = null; | |
733 if (token.value == TOK.TOKelse) | |
734 { nextToken(); | |
735 aelse = parseBlock(); | |
736 } | |
737 s = new ConditionalDeclaration(condition, a, aelse); | |
738 break; | |
739 | |
740 case TOK.TOKsemicolon: // empty declaration | |
741 nextToken(); | |
742 continue; | |
743 | |
744 default: | |
745 error("Declaration expected, not '%s'",token.toChars()); | |
746 Lerror: | |
747 while (token.value != TOK.TOKsemicolon && token.value != TOK.TOKeof) | |
748 nextToken(); | |
749 nextToken(); | |
750 s = null; | |
751 continue; | |
752 } | |
753 if (s) | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
754 { decldefs.push(s); |
0 | 755 addComment(s, comment); |
756 } | |
757 } while (!once); | |
758 return decldefs; | |
759 } | |
760 | |
761 /***************************************** | |
762 * Parse auto declarations of the form: | |
763 * storageClass ident = init, ident = init, ... ; | |
764 * and return the array of them. | |
765 * Starts with token on the first ident. | |
766 * Ends with scanner past closing ';' | |
767 */ | |
79 | 768 version (DMDV2) |
769 { | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
770 Dsymbols parseAutoDeclarations(StorageClass storageClass, const(char)[] comment) |
0 | 771 { |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
772 auto a = new Dsymbols; |
0 | 773 |
774 while (true) | |
775 { | |
776 Identifier ident = token.ident; | |
777 nextToken(); // skip over ident | |
778 assert(token.value == TOKassign); | |
779 nextToken(); // skip over '=' | |
780 Initializer init = parseInitializer(); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
781 auto v = new VarDeclaration(loc, null, ident, init); |
0 | 782 v.storage_class = storageClass; |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
783 a.push(v); |
0 | 784 if (token.value == TOKsemicolon) |
785 { | |
786 nextToken(); | |
787 addComment(v, comment); | |
788 } | |
789 else if (token.value == TOKcomma) | |
790 { | |
791 nextToken(); | |
792 if (token.value == TOKidentifier && | |
793 peek(&token).value == TOKassign) | |
794 { | |
795 addComment(v, comment); | |
796 continue; | |
797 } | |
798 else | |
799 error("Identifier expected following comma"); | |
800 } | |
801 else | |
802 error("semicolon expected following auto declaration, not '%s'", token.toChars()); | |
803 break; | |
804 } | |
805 return a; | |
806 } | |
807 } | |
808 /******************************************** | |
809 * Parse declarations after an align, protection, or extern decl. | |
810 */ | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
811 Dsymbols parseBlock() |
0 | 812 { |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
813 Dsymbols a = null; |
0 | 814 Dsymbol ss; |
815 | |
816 //printf("parseBlock()\n"); | |
817 switch (token.value) | |
818 { | |
819 case TOK.TOKsemicolon: | |
820 error("declaration expected following attribute, not ';'"); | |
821 nextToken(); | |
822 break; | |
823 | |
824 case TOK.TOKeof: | |
825 error("declaration expected following attribute, not EOF"); | |
826 break; | |
827 | |
828 case TOK.TOKlcurly: | |
829 nextToken(); | |
830 a = parseDeclDefs(0); | |
831 if (token.value != TOK.TOKrcurly) | |
832 { /* { */ | |
833 error("matching '}' expected, not %s", token.toChars()); | |
834 } | |
835 else | |
836 nextToken(); | |
837 break; | |
838 | |
839 case TOK.TOKcolon: | |
840 nextToken(); | |
841 static if (false) { | |
842 a = null; | |
843 } else { | |
844 a = parseDeclDefs(0); // grab declarations up to closing curly bracket | |
845 } | |
846 break; | |
847 | |
848 default: | |
849 a = parseDeclDefs(1); | |
850 break; | |
851 } | |
852 return a; | |
853 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
854 version(DMDV2) { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
855 void composeStorageClass(StorageClass stc) |
0 | 856 { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
857 StorageClass u = stc; |
0 | 858 u &= STC.STCconst | STC.STCimmutable | STC.STCmanifest; |
859 if (u & (u - 1)) | |
860 error("conflicting storage class %s", Token.toChars(token.value)); | |
861 | |
862 u = stc; | |
863 u &= STC.STCgshared | STC.STCshared | STC.STCtls; | |
864 if (u & (u - 1)) | |
865 error("conflicting storage class %s", Token.toChars(token.value)); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
866 u = stc; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
867 u &= STCsafe | STCsystem | STCtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
868 if (u & (u - 1)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
869 error("conflicting attribute @%s", token.toChars()); |
0 | 870 } |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
871 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
872 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
873 /*********************************************** |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
874 * Parse storage class, lexer is on '@' |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
875 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
876 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
877 version(DMDV2) { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
878 StorageClass parseAttribute() |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
879 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
880 nextToken(); |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
881 StorageClass stc = STCundefined; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
882 if (token.value != TOKidentifier) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
883 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
884 error("identifier expected after @, not %s", token.toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
885 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
886 else if (token.ident == Id.property) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
887 stc = STCproperty; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
888 else if (token.ident == Id.safe) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
889 stc = STCsafe; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
890 else if (token.ident == Id.trusted) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
891 stc = STCtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
892 else if (token.ident == Id.system) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
893 stc = STCsystem; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
894 else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
895 error("valid attribute identifiers are @property, @safe, @trusted, @system, not @%s", token.toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
896 return stc; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
897 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
898 } |
0 | 899 /************************************** |
900 * Parse constraint. | |
901 * Constraint is of the form: | |
902 * if ( ConstraintExpression ) | |
903 */ | |
904 version (DMDV2) { | |
905 Expression parseConstraint() | |
906 { | |
907 Expression e = null; | |
908 | |
909 if (token.value == TOKif) | |
910 { | |
911 nextToken(); // skip over 'if' | |
912 check(TOKlparen); | |
913 e = parseExpression(); | |
914 check(TOKrparen); | |
915 } | |
916 return e; | |
917 } | |
918 } | |
919 /************************************** | |
920 * Parse a TemplateDeclaration. | |
921 */ | |
922 TemplateDeclaration parseTemplateDeclaration() | |
923 { | |
924 TemplateDeclaration tempdecl; | |
925 Identifier id; | |
926 TemplateParameters tpl; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
927 Dsymbols decldefs; |
0 | 928 Expression constraint = null; |
929 Loc loc = this.loc; | |
930 | |
931 nextToken(); | |
932 if (token.value != TOKidentifier) | |
933 { | |
934 error("TemplateIdentifier expected following template"); | |
935 goto Lerr; | |
936 } | |
937 id = token.ident; | |
938 nextToken(); | |
939 tpl = parseTemplateParameterList(); | |
940 if (!tpl) | |
941 goto Lerr; | |
942 | |
943 constraint = parseConstraint(); | |
944 | |
945 if (token.value != TOKlcurly) | |
946 { | |
947 error("members of template declaration expected"); | |
948 goto Lerr; | |
949 } | |
950 else | |
951 { | |
952 nextToken(); | |
953 decldefs = parseDeclDefs(0); | |
954 if (token.value != TOKrcurly) | |
955 { | |
956 error("template member expected"); | |
957 goto Lerr; | |
958 } | |
959 nextToken(); | |
960 } | |
961 | |
962 tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs); | |
963 return tempdecl; | |
964 | |
965 Lerr: | |
966 return null; | |
967 } | |
968 | |
969 /****************************************** | |
970 * Parse template parameter list. | |
971 * Input: | |
972 * flag 0: parsing "( list )" | |
973 * 1: parsing non-empty "list )" | |
974 */ | |
975 TemplateParameters parseTemplateParameterList(int flag = 0) | |
976 { | |
977 TemplateParameters tpl = new TemplateParameters(); | |
978 | |
979 if (!flag && token.value != TOKlparen) | |
980 { | |
981 error("parenthesized TemplateParameterList expected following TemplateIdentifier"); | |
982 goto Lerr; | |
983 } | |
984 nextToken(); | |
985 | |
986 // Get array of TemplateParameters | |
987 if (flag || token.value != TOKrparen) | |
988 { | |
989 int isvariadic = 0; | |
990 | |
991 while (true) | |
992 { | |
993 TemplateParameter tp; | |
994 Identifier tp_ident = null; | |
995 Type tp_spectype = null; | |
996 Type tp_valtype = null; | |
997 Type tp_defaulttype = null; | |
998 Expression tp_specvalue = null; | |
999 Expression tp_defaultvalue = null; | |
1000 Token* t; | |
1001 | |
1002 // Get TemplateParameter | |
1003 | |
1004 // First, look ahead to see if it is a TypeParameter or a ValueParameter | |
1005 t = peek(&token); | |
1006 if (token.value == TOKalias) | |
1007 { | |
1008 // AliasParameter | |
1009 nextToken(); | |
1010 Type spectype = null; | |
1011 if (isDeclaration(&token, 2, TOKreserved, null)) | |
1012 { | |
1013 spectype = parseType(&tp_ident); | |
1014 } | |
1015 else | |
1016 { | |
1017 if (token.value != TOKidentifier) | |
1018 { | |
1019 error("identifier expected for template alias parameter"); | |
1020 goto Lerr; | |
1021 } | |
1022 tp_ident = token.ident; | |
1023 nextToken(); | |
1024 } | |
1025 Object spec = null; | |
1026 if (token.value == TOKcolon) // : Type | |
1027 { | |
1028 nextToken(); | |
1029 if (isDeclaration(&token, 0, TOKreserved, null)) | |
1030 spec = parseType(); | |
1031 else | |
1032 spec = parseCondExp(); | |
1033 } | |
1034 Object def = null; | |
1035 if (token.value == TOKassign) // = Type | |
1036 { | |
1037 nextToken(); | |
1038 if (isDeclaration(&token, 0, TOKreserved, null)) | |
1039 def = parseType(); | |
1040 else | |
1041 def = parseCondExp(); | |
1042 } | |
1043 tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def); | |
1044 } | |
1045 else if (t.value == TOKcolon || t.value == TOKassign || | |
1046 t.value == TOKcomma || t.value == TOKrparen) | |
1047 { // TypeParameter | |
1048 if (token.value != TOKidentifier) | |
1049 { error("identifier expected for template type parameter"); | |
1050 goto Lerr; | |
1051 } | |
1052 tp_ident = token.ident; | |
1053 nextToken(); | |
1054 if (token.value == TOKcolon) // : Type | |
1055 { | |
1056 nextToken(); | |
1057 tp_spectype = parseType(); | |
1058 } | |
1059 if (token.value == TOKassign) // = Type | |
1060 { | |
1061 nextToken(); | |
1062 tp_defaulttype = parseType(); | |
1063 } | |
1064 tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype); | |
1065 } | |
1066 else if (token.value == TOKidentifier && t.value == TOKdotdotdot) | |
1067 { // ident... | |
1068 if (isvariadic) | |
1069 error("variadic template parameter must be last"); | |
1070 isvariadic = 1; | |
1071 tp_ident = token.ident; | |
1072 nextToken(); | |
1073 nextToken(); | |
1074 tp = new TemplateTupleParameter(loc, tp_ident); | |
1075 } | |
1076 /// version (DMDV2) { | |
1077 else if (token.value == TOKthis) | |
1078 { // ThisParameter | |
1079 nextToken(); | |
1080 if (token.value != TOKidentifier) | |
1081 { error("identifier expected for template this parameter"); | |
1082 goto Lerr; | |
1083 } | |
1084 tp_ident = token.ident; | |
1085 nextToken(); | |
1086 if (token.value == TOKcolon) // : Type | |
1087 { | |
1088 nextToken(); | |
1089 tp_spectype = parseType(); | |
1090 } | |
1091 if (token.value == TOKassign) // = Type | |
1092 { | |
1093 nextToken(); | |
1094 tp_defaulttype = parseType(); | |
1095 } | |
1096 tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype); | |
1097 } | |
1098 /// } | |
1099 else | |
1100 { // ValueParameter | |
1101 tp_valtype = parseType(&tp_ident); | |
1102 if (!tp_ident) | |
1103 { | |
1104 error("identifier expected for template value parameter"); | |
1105 tp_ident = new Identifier("error", TOKidentifier); | |
1106 } | |
1107 if (token.value == TOKcolon) // : CondExpression | |
1108 { | |
1109 nextToken(); | |
1110 tp_specvalue = parseCondExp(); | |
1111 } | |
1112 if (token.value == TOKassign) // = CondExpression | |
1113 { | |
1114 nextToken(); | |
1115 tp_defaultvalue = parseDefaultInitExp(); | |
1116 } | |
1117 tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue); | |
1118 } | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1119 tpl.push(tp); |
0 | 1120 if (token.value != TOKcomma) |
1121 break; | |
1122 nextToken(); | |
1123 } | |
1124 } | |
1125 check(TOKrparen); | |
1126 | |
1127 Lerr: | |
1128 return tpl; | |
1129 } | |
19
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1130 |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1131 /****************************************** |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1132 * Parse template mixin. |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1133 * mixin Foo; |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1134 * mixin Foo!(args); |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1135 * mixin a.b.c!(args).Foo!(args); |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1136 * mixin Foo!(args) identifier; |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1137 * mixin typeof(expr).identifier!(args); |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1138 */ |
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1139 |
0 | 1140 Dsymbol parseMixin() |
1141 { | |
13 | 1142 TemplateMixin tm; |
1143 Identifier id; | |
1144 Type tqual; | |
1145 Objects tiargs; | |
1146 Array idents; | |
1147 | |
1148 //printf("parseMixin()\n"); | |
1149 nextToken(); | |
1150 tqual = null; | |
1151 if (token.value == TOKdot) | |
1152 { | |
1153 id = Id.empty; | |
1154 } | |
1155 else | |
1156 { | |
1157 if (token.value == TOKtypeof) | |
1158 { | |
1159 tqual = parseTypeof(); | |
1160 check(TOKdot); | |
1161 } | |
1162 if (token.value != TOKidentifier) | |
1163 { | |
1164 error("identifier expected, not %s", token.toChars()); | |
1165 id = Id.empty; | |
1166 } | |
1167 else | |
1168 id = token.ident; | |
1169 nextToken(); | |
1170 } | |
1171 | |
1172 idents = new Array(); | |
1173 while (1) | |
1174 { | |
1175 tiargs = null; | |
1176 if (token.value == TOKnot) | |
1177 { | |
1178 nextToken(); | |
1179 if (token.value == TOKlparen) | |
1180 tiargs = parseTemplateArgumentList(); | |
1181 else | |
1182 tiargs = parseTemplateArgument(); | |
1183 } | |
1184 if (token.value != TOKdot) | |
1185 break; | |
1186 if (tiargs) | |
1187 { | |
1188 TemplateInstance tempinst = new TemplateInstance(loc, id); | |
1189 tempinst.tiargs = tiargs; | |
1190 id = cast(Identifier)tempinst; | |
1191 tiargs = null; | |
1192 } | |
1193 idents.push(cast(void*)id); | |
1194 nextToken(); | |
1195 if (token.value != TOKidentifier) | |
1196 { | |
1197 error("identifier expected following '.' instead of '%s'", token.toChars()); | |
1198 break; | |
1199 } | |
1200 id = token.ident; | |
1201 nextToken(); | |
1202 } | |
1203 idents.push(cast(void*)id); | |
1204 if (token.value == TOKidentifier) | |
1205 { | |
1206 id = token.ident; | |
1207 nextToken(); | |
1208 } | |
1209 else | |
1210 id = null; | |
1211 | |
1212 tm = new TemplateMixin(loc, id, tqual, idents, tiargs); | |
1213 if (token.value != TOKsemicolon) | |
1214 error("';' expected after mixin"); | |
1215 nextToken(); | |
1216 return tm; | |
0 | 1217 } |
1218 | |
1219 /****************************************** | |
1220 * Parse template argument list. | |
1221 * Input: | |
1222 * current token is opening '(' | |
1223 * Output: | |
1224 * current token is one after closing ')' | |
1225 */ | |
1226 Objects parseTemplateArgumentList() | |
1227 { | |
1228 //printf("Parser.parseTemplateArgumentList()\n"); | |
1229 if (token.value != TOKlparen && token.value != TOKlcurly) | |
1230 { | |
1231 error("!(TemplateArgumentList) expected following TemplateIdentifier"); | |
1232 return new Objects(); | |
1233 } | |
1234 return parseTemplateArgumentList2(); | |
1235 } | |
1236 | |
1237 Objects parseTemplateArgumentList2() | |
1238 { | |
1239 //printf("Parser.parseTemplateArgumentList2()\n"); | |
1240 Objects tiargs = new Objects(); | |
1241 TOK endtok = TOKrparen; | |
1242 nextToken(); | |
1243 | |
1244 // Get TemplateArgumentList | |
1245 if (token.value != endtok) | |
1246 { | |
1247 while (1) | |
1248 { | |
1249 // See if it is an Expression or a Type | |
1250 if (isDeclaration(&token, 0, TOKreserved, null)) | |
1251 { // Template argument is a type | |
1252 Type ta = parseType(); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1253 tiargs.push(ta); |
0 | 1254 } |
1255 else | |
1256 { // Template argument is an expression | |
1257 Expression ea = parseAssignExp(); | |
1258 | |
1259 if (ea.op == TOKfunction) | |
1260 { | |
1261 FuncLiteralDeclaration fd = (cast(FuncExp)ea).fd; | |
1262 if (fd.type.ty == Tfunction) | |
1263 { | |
1264 TypeFunction tf = cast(TypeFunction)fd.type; | |
1265 /* If there are parameters that consist of only an identifier, | |
1266 * rather than assuming the identifier is a type, as we would | |
1267 * for regular function declarations, assume the identifier | |
1268 * is the parameter name, and we're building a template with | |
1269 * a deduced type. | |
1270 */ | |
1271 TemplateParameters tpl = null; | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
1272 foreach (param; tf.parameters) |
0 | 1273 { |
1274 if (param.ident is null && | |
1275 param.type && | |
1276 param.type.ty == Tident && | |
1277 (cast(TypeIdentifier)param.type).idents.dim == 0 | |
1278 ) | |
1279 { | |
1280 /* Switch parameter type to parameter identifier, | |
1281 * parameterize with template type parameter _T | |
1282 */ | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
1283 auto pt = cast(TypeIdentifier)param.type; |
0 | 1284 param.ident = pt.ident; |
1285 Identifier id = Lexer.uniqueId("__T"); | |
1286 param.type = new TypeIdentifier(pt.loc, id); | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1287 auto tp = new TemplateTypeParameter(fd.loc, id, null, null); |
0 | 1288 if (!tpl) |
1289 tpl = new TemplateParameters(); | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1290 tpl.push(tp); |
0 | 1291 } |
1292 } | |
1293 | |
1294 if (tpl) | |
1295 { | |
1296 // Wrap a template around function fd | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1297 auto decldefs = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1298 decldefs.push(fd); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1299 auto tempdecl = new TemplateDeclaration(fd.loc, fd.ident, tpl, null, decldefs); |
0 | 1300 tempdecl.literal = 1; // it's a template 'literal' |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1301 tiargs.push(tempdecl); |
0 | 1302 goto L1; |
1303 } | |
1304 } | |
1305 } | |
1306 | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1307 tiargs.push(ea); |
0 | 1308 } |
1309 L1: | |
1310 if (token.value != TOKcomma) | |
1311 break; | |
1312 nextToken(); | |
1313 } | |
1314 } | |
1315 check(endtok, "template argument list"); | |
1316 return tiargs; | |
1317 } | |
1318 | |
2 | 1319 /***************************** |
1320 * Parse single template argument, to support the syntax: | |
1321 * foo!arg | |
1322 * Input: | |
1323 * current token is the arg | |
1324 */ | |
0 | 1325 Objects parseTemplateArgument() |
1326 { | |
2 | 1327 //printf("parseTemplateArgument()\n"); |
1328 Objects tiargs = new Objects(); | |
1329 Type ta; | |
1330 switch (token.value) | |
1331 { | |
1332 case TOKidentifier: | |
1333 ta = new TypeIdentifier(loc, token.ident); | |
1334 goto LabelX; | |
1335 | |
1336 case TOKvoid: ta = Type.tvoid; goto LabelX; | |
1337 case TOKint8: ta = Type.tint8; goto LabelX; | |
1338 case TOKuns8: ta = Type.tuns8; goto LabelX; | |
1339 case TOKint16: ta = Type.tint16; goto LabelX; | |
1340 case TOKuns16: ta = Type.tuns16; goto LabelX; | |
1341 case TOKint32: ta = Type.tint32; goto LabelX; | |
1342 case TOKuns32: ta = Type.tuns32; goto LabelX; | |
1343 case TOKint64: ta = Type.tint64; goto LabelX; | |
1344 case TOKuns64: ta = Type.tuns64; goto LabelX; | |
1345 case TOKfloat32: ta = Type.tfloat32; goto LabelX; | |
1346 case TOKfloat64: ta = Type.tfloat64; goto LabelX; | |
1347 case TOKfloat80: ta = Type.tfloat80; goto LabelX; | |
1348 case TOKimaginary32: ta = Type.timaginary32; goto LabelX; | |
1349 case TOKimaginary64: ta = Type.timaginary64; goto LabelX; | |
1350 case TOKimaginary80: ta = Type.timaginary80; goto LabelX; | |
1351 case TOKcomplex32: ta = Type.tcomplex32; goto LabelX; | |
1352 case TOKcomplex64: ta = Type.tcomplex64; goto LabelX; | |
1353 case TOKcomplex80: ta = Type.tcomplex80; goto LabelX; | |
1354 case TOKbit: ta = Type.tbit; goto LabelX; | |
1355 case TOKbool: ta = Type.tbool; goto LabelX; | |
1356 case TOKchar: ta = Type.tchar; goto LabelX; | |
1357 case TOKwchar: ta = Type.twchar; goto LabelX; | |
1358 case TOKdchar: ta = Type.tdchar; goto LabelX; | |
1359 LabelX: | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1360 tiargs.push(ta); |
2 | 1361 nextToken(); |
1362 break; | |
1363 | |
1364 case TOKint32v: | |
1365 case TOKuns32v: | |
1366 case TOKint64v: | |
1367 case TOKuns64v: | |
1368 case TOKfloat32v: | |
1369 case TOKfloat64v: | |
1370 case TOKfloat80v: | |
1371 case TOKimaginary32v: | |
1372 case TOKimaginary64v: | |
1373 case TOKimaginary80v: | |
1374 case TOKnull: | |
1375 case TOKtrue: | |
1376 case TOKfalse: | |
1377 case TOKcharv: | |
1378 case TOKwcharv: | |
1379 case TOKdcharv: | |
1380 case TOKstring: | |
1381 case TOKfile: | |
1382 case TOKline: | |
1383 { | |
1384 // Template argument is an expression | |
1385 Expression ea = parsePrimaryExp(); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1386 tiargs.push(ea); |
2 | 1387 break; |
1388 } | |
1389 | |
1390 default: | |
1391 error("template argument expected following !"); | |
1392 break; | |
1393 } | |
1394 | |
1395 if (token.value == TOKnot) | |
1396 error("multiple ! arguments are not allowed"); | |
1397 return tiargs; | |
0 | 1398 } |
1399 | |
1400 /********************************** | |
1401 * Parse a static assertion. | |
1402 */ | |
1403 StaticAssert parseStaticAssert() | |
1404 { | |
1405 Loc loc = this.loc; | |
1406 Expression exp; | |
1407 Expression msg = null; | |
1408 | |
1409 //printf("parseStaticAssert()\n"); | |
1410 nextToken(); | |
1411 check(TOK.TOKlparen); | |
1412 exp = parseAssignExp(); | |
1413 if (token.value == TOK.TOKcomma) | |
1414 { | |
1415 nextToken(); | |
1416 msg = parseAssignExp(); | |
1417 } | |
1418 | |
1419 check(TOK.TOKrparen); | |
1420 check(TOK.TOKsemicolon); | |
1421 | |
1422 return new StaticAssert(loc, exp, msg); | |
1423 } | |
1424 | |
1425 TypeQualified parseTypeof() | |
1426 { | |
1427 TypeQualified t; | |
1428 Loc loc = this.loc; | |
1429 | |
1430 nextToken(); | |
1431 check(TOK.TOKlparen); | |
1432 if (token.value == TOK.TOKreturn) // typeof(return) | |
1433 { | |
1434 nextToken(); | |
1435 t = new TypeReturn(loc); | |
1436 } | |
1437 else | |
1438 { | |
1439 Expression exp = parseExpression(); // typeof(expression) | |
1440 t = new TypeTypeof(loc, exp); | |
1441 } | |
1442 check(TOK.TOKrparen); | |
1443 return t; | |
1444 } | |
1445 | |
1446 /*********************************** | |
1447 * Parse extern (linkage) | |
1448 * The parser is on the 'extern' token. | |
1449 */ | |
1450 LINK parseLinkage() | |
1451 { | |
1452 LINK link = LINK.LINKdefault; | |
1453 nextToken(); | |
1454 assert(token.value == TOK.TOKlparen); | |
1455 nextToken(); | |
1456 if (token.value == TOK.TOKidentifier) | |
1457 { | |
1458 Identifier id = token.ident; | |
1459 | |
1460 nextToken(); | |
1461 if (id == Id.Windows) | |
1462 link = LINK.LINKwindows; | |
1463 else if (id == Id.Pascal) | |
1464 link = LINK.LINKpascal; | |
1465 else if (id == Id.D) | |
1466 link = LINK.LINKd; | |
1467 else if (id == Id.C) | |
1468 { | |
1469 link = LINK.LINKc; | |
1470 if (token.value == TOK.TOKplusplus) | |
1471 { | |
1472 link = LINK.LINKcpp; | |
1473 nextToken(); | |
1474 } | |
1475 } | |
1476 else if (id == Id.System) | |
1477 { | |
114 | 1478 version (Windows) |
1479 { | |
0 | 1480 link = LINK.LINKwindows; |
114 | 1481 } |
1482 else | |
1483 { | |
0 | 1484 link = LINK.LINKc; |
1485 } | |
1486 } | |
1487 else | |
1488 { | |
1489 error("valid linkage identifiers are D, C, C++, Pascal, Windows, System"); | |
1490 link = LINK.LINKd; | |
1491 } | |
1492 } | |
1493 else | |
1494 { | |
1495 link = LINK.LINKd; // default | |
1496 } | |
1497 check(TOK.TOKrparen); | |
1498 | |
1499 return link; | |
1500 } | |
1501 | |
1502 | |
1503 /************************************** | |
1504 * Parse a debug conditional | |
1505 */ | |
1506 Condition parseDebugCondition() | |
1507 { | |
1508 Condition c; | |
1509 | |
1510 if (token.value == TOK.TOKlparen) | |
1511 { | |
1512 nextToken(); | |
1513 uint level = 1; | |
1514 Identifier id = null; | |
1515 | |
1516 if (token.value == TOK.TOKidentifier) | |
1517 id = token.ident; | |
1518 else if (token.value == TOK.TOKint32v) | |
1519 level = cast(uint)token.uns64value; | |
1520 else | |
1521 error("identifier or integer expected, not %s", token.toChars()); | |
1522 | |
1523 nextToken(); | |
1524 check(TOK.TOKrparen); | |
1525 | |
1526 c = new DebugCondition(mod, level, id); | |
1527 } | |
1528 else | |
1529 c = new DebugCondition(mod, 1, null); | |
1530 | |
1531 return c; | |
1532 } | |
1533 | |
1534 /************************************** | |
1535 * Parse a version conditional | |
1536 */ | |
1537 Condition parseVersionCondition() | |
1538 { | |
1539 Condition c; | |
1540 uint level = 1; | |
1541 Identifier id = null; | |
1542 | |
1543 if (token.value == TOK.TOKlparen) | |
1544 { | |
1545 nextToken(); | |
1546 if (token.value == TOK.TOKidentifier) | |
1547 id = token.ident; | |
1548 else if (token.value == TOK.TOKint32v) | |
1549 level = cast(uint)token.uns64value; | |
1550 else { | |
1551 version (DMDV2) { | |
1552 /* Allow: | |
1553 * version (unittest) | |
1554 * even though unittest is a keyword | |
1555 */ | |
1556 if (token.value == TOK.TOKunittest) | |
1557 id = Lexer.idPool(Token.toChars(TOK.TOKunittest)); | |
1558 else | |
1559 error("identifier or integer expected, not %s", token.toChars()); | |
1560 } else { | |
1561 error("identifier or integer expected, not %s", token.toChars()); | |
1562 } | |
1563 } | |
1564 nextToken(); | |
1565 check(TOK.TOKrparen); | |
1566 } | |
1567 else | |
1568 error("(condition) expected following version"); | |
1569 | |
1570 c = new VersionCondition(mod, level, id); | |
1571 | |
1572 return c; | |
1573 } | |
1574 | |
1575 /*********************************************** | |
1576 * static if (expression) | |
1577 * body | |
1578 * else | |
1579 * body | |
1580 */ | |
1581 Condition parseStaticIfCondition() | |
1582 { | |
1583 Expression exp; | |
1584 Condition condition; | |
1585 Array aif; | |
1586 Array aelse; | |
1587 Loc loc = this.loc; | |
1588 | |
1589 nextToken(); | |
1590 if (token.value == TOKlparen) | |
1591 { | |
1592 nextToken(); | |
1593 exp = parseAssignExp(); | |
1594 check(TOKrparen); | |
1595 } | |
1596 else | |
1597 { | |
1598 error("(expression) expected following static if"); | |
1599 exp = null; | |
1600 } | |
1601 condition = new StaticIfCondition(loc, exp); | |
1602 return condition; | |
1603 } | |
1604 | |
1605 /***************************************** | |
1606 * Parse a constructor definition: | |
1607 * this(parameters) { body } | |
1608 * or postblit: | |
1609 * this(this) { body } | |
1610 * or constructor template: | |
1611 * this(templateparameters)(parameters) { body } | |
1612 * Current token is 'this'. | |
1613 */ | |
1614 | |
1615 Dsymbol parseCtor() | |
1616 { | |
1617 Loc loc = this.loc; | |
1618 | |
1619 nextToken(); | |
1620 if (token.value == TOK.TOKlparen && peek(&token).value == TOK.TOKthis) | |
1621 { // this(this) { ... } | |
1622 nextToken(); | |
1623 nextToken(); | |
1624 check(TOK.TOKrparen); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1625 auto f = new PostBlitDeclaration(loc, Loc(0)); |
0 | 1626 parseContracts(f); |
1627 return f; | |
1628 } | |
1629 | |
1630 /* Look ahead to see if: | |
1631 * this(...)(...) | |
1632 * which is a constructor template | |
1633 */ | |
1634 TemplateParameters tpl = null; | |
1635 if (token.value == TOK.TOKlparen && peekPastParen(&token).value == TOK.TOKlparen) | |
1636 { tpl = parseTemplateParameterList(); | |
1637 | |
1638 int varargs; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1639 auto arguments = parseParameters(&varargs); |
0 | 1640 |
1641 Expression constraint = null; | |
1642 if (tpl) | |
1643 constraint = parseConstraint(); | |
1644 | |
1645 CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs); | |
1646 parseContracts(f); | |
1647 | |
1648 // Wrap a template around it | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1649 auto decldefs = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1650 decldefs.push(f); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1651 auto tempdecl = new TemplateDeclaration(loc, f.ident, tpl, constraint, decldefs); |
0 | 1652 return tempdecl; |
1653 } | |
1654 | |
1655 /* Just a regular constructor | |
1656 */ | |
1657 int varargs; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1658 auto arguments = parseParameters(&varargs); |
0 | 1659 CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs); |
1660 parseContracts(f); | |
1661 return f; | |
1662 } | |
1663 | |
1664 PostBlitDeclaration parsePostBlit() | |
1665 { | |
1666 assert(false); | |
1667 } | |
1668 | |
1669 /***************************************** | |
1670 * Parse a destructor definition: | |
1671 * ~this() { body } | |
1672 * Current token is '~'. | |
1673 */ | |
1674 DtorDeclaration parseDtor() | |
1675 { | |
1676 DtorDeclaration f; | |
1677 Loc loc = this.loc; | |
1678 | |
1679 nextToken(); | |
1680 check(TOKthis); | |
1681 check(TOKlparen); | |
1682 check(TOKrparen); | |
1683 | |
1684 f = new DtorDeclaration(loc, Loc(0)); | |
1685 parseContracts(f); | |
1686 return f; | |
1687 } | |
1688 | |
1689 /***************************************** | |
1690 * Parse a static constructor definition: | |
1691 * static this() { body } | |
1692 * Current token is 'this'. | |
1693 */ | |
1694 StaticCtorDeclaration parseStaticCtor() | |
1695 { | |
1696 StaticCtorDeclaration f; | |
1697 Loc loc = this.loc; | |
1698 | |
1699 nextToken(); | |
1700 check(TOKlparen); | |
1701 check(TOKrparen); | |
1702 | |
1703 f = new StaticCtorDeclaration(loc, Loc(0)); | |
1704 parseContracts(f); | |
1705 return f; | |
1706 } | |
1707 | |
1708 /***************************************** | |
1709 * Parse a static destructor definition: | |
1710 * static ~this() { body } | |
1711 * Current token is '~'. | |
1712 */ | |
1713 StaticDtorDeclaration parseStaticDtor() | |
1714 { | |
1715 StaticDtorDeclaration f; | |
1716 Loc loc = this.loc; | |
1717 | |
1718 nextToken(); | |
1719 check(TOKthis); | |
1720 check(TOKlparen); | |
1721 check(TOKrparen); | |
1722 | |
1723 f = new StaticDtorDeclaration(loc, Loc(0)); | |
1724 parseContracts(f); | |
1725 return f; | |
1726 } | |
1727 | |
1728 /***************************************** | |
1729 * Parse an invariant definition: | |
1730 * invariant() { body } | |
1731 * Current token is 'invariant'. | |
1732 */ | |
1733 InvariantDeclaration parseInvariant() | |
1734 { | |
1735 InvariantDeclaration f; | |
1736 Loc loc = this.loc; | |
1737 | |
1738 nextToken(); | |
1739 if (token.value == TOKlparen) // optional () | |
1740 { | |
1741 nextToken(); | |
1742 check(TOKrparen); | |
1743 } | |
1744 | |
1745 f = new InvariantDeclaration(loc, Loc(0)); | |
1746 f.fbody = parseStatement(ParseStatementFlags.PScurly); | |
1747 return f; | |
1748 } | |
1749 | |
1750 /***************************************** | |
1751 * Parse a unittest definition: | |
1752 * unittest { body } | |
1753 * Current token is 'unittest'. | |
1754 */ | |
1755 UnitTestDeclaration parseUnitTest() | |
1756 { | |
1757 Loc loc = this.loc; | |
1758 | |
1759 nextToken(); | |
1760 | |
1761 UnitTestDeclaration f = new UnitTestDeclaration(loc, this.loc); | |
1762 f.fbody = parseStatement(ParseStatementFlags.PScurly); | |
1763 | |
1764 return f; | |
1765 } | |
1766 | |
123 | 1767 /***************************************** |
1768 * Parse a new definition: | |
1769 * new(arguments) { body } | |
1770 * Current token is 'new'. | |
1771 */ | |
0 | 1772 NewDeclaration parseNew() |
1773 { | |
123 | 1774 NewDeclaration f; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1775 scope arguments = new Parameters(); |
123 | 1776 int varargs; |
1777 Loc loc = this.loc; | |
1778 | |
1779 nextToken(); | |
1780 arguments = parseParameters(&varargs); | |
1781 f = new NewDeclaration(loc, Loc(0), arguments, varargs); | |
1782 parseContracts(f); | |
1783 return f; | |
0 | 1784 } |
1785 | |
123 | 1786 /***************************************** |
1787 * Parse a delete definition: | |
1788 * delete(arguments) { body } | |
1789 * Current token is 'delete'. | |
1790 */ | |
0 | 1791 DeleteDeclaration parseDelete() |
1792 { | |
123 | 1793 DeleteDeclaration f; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1794 scope Parameters arguments; |
123 | 1795 int varargs; |
1796 Loc loc = this.loc; | |
1797 | |
1798 nextToken(); | |
1799 arguments = parseParameters(&varargs); | |
1800 if (varargs) | |
1801 error("... not allowed in delete function parameter list"); | |
1802 f = new DeleteDeclaration(loc, Loc(0), arguments); | |
1803 parseContracts(f); | |
1804 return f; | |
0 | 1805 } |
1806 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1807 Parameters parseParameters(int* pvarargs) |
0 | 1808 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1809 auto arguments = new Parameters(); |
0 | 1810 int varargs = 0; |
1811 int hasdefault = 0; | |
1812 | |
1813 check(TOK.TOKlparen); | |
1814 while (1) | |
1815 { Type *tb; | |
1816 Identifier ai = null; | |
1817 Type at; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1818 Parameter a; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
1819 StorageClass storageClass = STC.STCundefined; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
1820 StorageClass stc; |
0 | 1821 Expression ae; |
1822 | |
1823 for ( ;1; nextToken()) | |
1824 { | |
1825 switch (token.value) | |
1826 { | |
1827 case TOK.TOKrparen: | |
1828 break; | |
1829 | |
1830 case TOK.TOKdotdotdot: | |
1831 varargs = 1; | |
1832 nextToken(); | |
1833 break; | |
1834 | |
1835 case TOK.TOKconst: | |
1836 if (peek(&token).value == TOK.TOKlparen) | |
1837 goto Ldefault; | |
1838 stc = STC.STCconst; | |
1839 goto L2; | |
1840 | |
1841 case TOK.TOKinvariant: | |
1842 case TOK.TOKimmutable: | |
1843 if (peek(&token).value == TOK.TOKlparen) | |
1844 goto Ldefault; | |
1845 stc = STC.STCimmutable; | |
1846 goto L2; | |
1847 | |
1848 case TOK.TOKshared: | |
1849 if (peek(&token).value == TOK.TOKlparen) | |
1850 goto Ldefault; | |
1851 stc = STC.STCshared; | |
1852 goto L2; | |
135 | 1853 |
1854 case TOKwild: | |
1855 if (peek(&token).value == TOK.TOKlparen) | |
1856 goto Ldefault; | |
1857 stc = STCwild; | |
1858 goto L2; | |
0 | 1859 |
1860 case TOK.TOKin: stc = STC.STCin; goto L2; | |
1861 case TOK.TOKout: stc = STC.STCout; goto L2; | |
135 | 1862 version(D1INOUT) { |
0 | 1863 case TOK.TOKinout: |
135 | 1864 } |
0 | 1865 case TOK.TOKref: stc = STC.STCref; goto L2; |
1866 case TOK.TOKlazy: stc = STC.STClazy; goto L2; | |
1867 case TOK.TOKscope: stc = STC.STCscope; goto L2; | |
1868 case TOK.TOKfinal: stc = STC.STCfinal; goto L2; | |
135 | 1869 case TOK.TOKauto: stc = STCauto; goto L2; |
0 | 1870 L2: |
1871 if (storageClass & stc || | |
1872 (storageClass & STC.STCin && stc & (STC.STCconst | STC.STCscope)) || | |
1873 (stc & STC.STCin && storageClass & (STC.STCconst | STC.STCscope)) | |
1874 ) | |
1875 error("redundant storage class %s", Token.toChars(token.value)); | |
1876 storageClass |= stc; | |
1877 composeStorageClass(storageClass); | |
1878 continue; | |
1879 | |
1880 static if (false) { | |
1881 case TOK.TOKstatic: stc = STC.STCstatic; goto L2; | |
1882 case TOK.TOKauto: storageClass = STC.STCauto; goto L4; | |
1883 case TOK.TOKalias: storageClass = STC.STCalias; goto L4; | |
1884 L4: | |
1885 nextToken(); | |
1886 if (token.value == TOK.TOKidentifier) | |
1887 { ai = token.ident; | |
1888 nextToken(); | |
1889 } | |
1890 else | |
1891 ai = null; | |
1892 at = null; // no type | |
1893 ae = null; // no default argument | |
1894 if (token.value == TOK.TOKassign) // = defaultArg | |
1895 { nextToken(); | |
1896 ae = parseDefaultInitExp(); | |
1897 hasdefault = 1; | |
1898 } | |
1899 else | |
1900 { if (hasdefault) | |
1901 error("default argument expected for alias %s", | |
1902 ai ? ai.toChars() : ""); | |
1903 } | |
1904 goto L3; | |
1905 } | |
1906 | |
1907 default: | |
1908 Ldefault: | |
1909 stc = (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy)); | |
1910 if (stc & (stc - 1)) // if stc is not a power of 2 | |
1911 error("incompatible parameter storage classes"); | |
1912 if ((storageClass & (STC.STCconst | STC.STCout)) == (STC.STCconst | STC.STCout)) | |
1913 error("out cannot be const"); | |
1914 if ((storageClass & (STC.STCimmutable | STC.STCout)) == (STC.STCimmutable | STC.STCout)) | |
1915 error("out cannot be immutable"); | |
1916 if ((storageClass & STC.STCscope) && | |
1917 (storageClass & (STC.STCref | STC.STCout))) | |
1918 error("scope cannot be ref or out"); | |
1919 at = parseType(&ai); | |
1920 ae = null; | |
1921 if (token.value == TOK.TOKassign) // = defaultArg | |
1922 { nextToken(); | |
1923 ae = parseDefaultInitExp(); | |
1924 hasdefault = 1; | |
1925 } | |
1926 else | |
1927 { if (hasdefault) | |
1928 error("default argument expected for %s", | |
1929 ai ? ai.toChars() : at.toChars()); | |
1930 } | |
1931 if (token.value == TOK.TOKdotdotdot) | |
1932 { /* This is: | |
1933 * at ai ... | |
1934 */ | |
1935 | |
1936 if (storageClass & (STC.STCout | STC.STCref)) | |
1937 error("variadic argument cannot be out or ref"); | |
1938 varargs = 2; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1939 a = new Parameter(storageClass, at, ai, ae); |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
1940 arguments.push(a); |
0 | 1941 nextToken(); |
1942 break; | |
1943 } | |
1944 L3: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
1945 a = new Parameter(storageClass, at, ai, ae); |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
1946 arguments.push(a); |
0 | 1947 if (token.value == TOK.TOKcomma) |
1948 { nextToken(); | |
1949 goto L1; | |
1950 } | |
1951 break; | |
1952 } | |
1953 break; | |
1954 } | |
1955 break; | |
1956 | |
1957 L1: ; | |
1958 } | |
1959 check(TOK.TOKrparen); | |
1960 *pvarargs = varargs; | |
1961 return arguments; | |
1962 } | |
1963 | |
1964 EnumDeclaration parseEnum() | |
1965 { | |
1966 EnumDeclaration e; | |
1967 Identifier id; | |
1968 Type memtype; | |
1969 Loc loc = this.loc; | |
1970 | |
1971 //printf("Parser.parseEnum()\n"); | |
1972 nextToken(); | |
1973 if (token.value == TOK.TOKidentifier) | |
1974 { | |
1975 id = token.ident; | |
1976 nextToken(); | |
1977 } | |
1978 else | |
1979 id = null; | |
1980 | |
1981 if (token.value == TOK.TOKcolon) | |
1982 { | |
1983 nextToken(); | |
1984 memtype = parseBasicType(); | |
1985 memtype = parseDeclarator(memtype, null, null); | |
1986 } | |
1987 else | |
1988 memtype = null; | |
1989 | |
1990 e = new EnumDeclaration(loc, id, memtype); | |
1991 if (token.value == TOK.TOKsemicolon && id) | |
1992 nextToken(); | |
1993 else if (token.value == TOK.TOKlcurly) | |
1994 { | |
1995 //printf("enum definition\n"); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
1996 e.members = new Dsymbols(); |
0 | 1997 nextToken(); |
79 | 1998 string comment = token.blockComment; |
0 | 1999 while (token.value != TOK.TOKrcurly) |
2000 { | |
2001 /* Can take the following forms: | |
2002 * 1. ident | |
2003 * 2. ident = value | |
2004 * 3. type ident = value | |
2005 */ | |
2006 | |
2007 loc = this.loc; | |
2008 | |
2009 Type type = null; | |
2010 Identifier ident; | |
2011 Token* tp = peek(&token); | |
2012 if (token.value == TOK.TOKidentifier && | |
2013 (tp.value == TOK.TOKassign || tp.value == TOK.TOKcomma || tp.value == TOK.TOKrcurly)) | |
2014 { | |
2015 ident = token.ident; | |
2016 type = null; | |
2017 nextToken(); | |
2018 } | |
2019 else | |
2020 { | |
2021 type = parseType(&ident, null); | |
2022 if (id || memtype) | |
2023 error("type only allowed if anonymous enum and no enum type"); | |
2024 } | |
2025 | |
2026 Expression value; | |
2027 if (token.value == TOK.TOKassign) | |
2028 { | |
2029 nextToken(); | |
2030 value = parseAssignExp(); | |
2031 } | |
2032 else | |
2033 { | |
2034 value = null; | |
2035 if (type) | |
2036 error("if type, there must be an initializer"); | |
2037 } | |
2038 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2039 auto em = new EnumMember(loc, ident, value, type); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2040 e.members.push(em); |
0 | 2041 |
2042 if (token.value == TOK.TOKrcurly) { | |
2043 ; | |
2044 } else { | |
2045 addComment(em, comment); | |
2046 comment = null; | |
2047 check(TOK.TOKcomma); | |
2048 } | |
2049 addComment(em, comment); | |
2050 comment = token.blockComment; | |
2051 } | |
2052 nextToken(); | |
2053 } | |
2054 else | |
2055 error("enum declaration is invalid"); | |
2056 | |
2057 //printf("-parseEnum() %s\n", e.toChars()); | |
2058 return e; | |
2059 } | |
2060 | |
2061 Dsymbol parseAggregate() | |
2062 { | |
2063 AggregateDeclaration a = null; | |
2064 int anon = 0; | |
2065 TOK tok; | |
2066 Identifier id; | |
2067 TemplateParameters tpl = null; | |
2068 Expression constraint = null; | |
2069 | |
2070 //printf("Parser.parseAggregate()\n"); | |
2071 tok = token.value; | |
2072 nextToken(); | |
2073 if (token.value != TOK.TOKidentifier) | |
2074 { | |
2075 id = null; | |
2076 } | |
2077 else | |
2078 { | |
2079 id = token.ident; | |
2080 nextToken(); | |
2081 | |
2082 if (token.value == TOK.TOKlparen) | |
2083 { | |
2084 // Class template declaration. | |
2085 | |
2086 // Gather template parameter list | |
2087 tpl = parseTemplateParameterList(); | |
2088 constraint = parseConstraint(); | |
2089 } | |
2090 } | |
2091 | |
2092 Loc loc = this.loc; | |
2093 switch (tok) | |
2094 { case TOK.TOKclass: | |
2095 case TOK.TOKinterface: | |
2096 { | |
2097 if (!id) | |
2098 error("anonymous classes not allowed"); | |
2099 | |
2100 // Collect base class(es) | |
2101 BaseClasses baseclasses = null; | |
2102 if (token.value == TOK.TOKcolon) | |
2103 { | |
2104 nextToken(); | |
2105 baseclasses = parseBaseClasses(); | |
2106 | |
2107 if (token.value != TOK.TOKlcurly) | |
2108 error("members expected"); | |
2109 } | |
2110 | |
2111 if (tok == TOK.TOKclass) | |
2112 a = new ClassDeclaration(loc, id, baseclasses); | |
2113 else | |
2114 a = new InterfaceDeclaration(loc, id, baseclasses); | |
2115 break; | |
2116 } | |
2117 | |
2118 case TOK.TOKstruct: | |
2119 if (id) | |
2120 a = new StructDeclaration(loc, id); | |
2121 else | |
2122 anon = 1; | |
2123 break; | |
2124 | |
2125 case TOK.TOKunion: | |
2126 if (id) | |
2127 a = new UnionDeclaration(loc, id); | |
2128 else | |
2129 anon = 2; | |
2130 break; | |
2131 | |
2132 default: | |
2133 assert(0); | |
2134 break; | |
2135 } | |
2136 if (a && token.value == TOK.TOKsemicolon) | |
2137 { nextToken(); | |
2138 } | |
2139 else if (token.value == TOK.TOKlcurly) | |
2140 { | |
2141 //printf("aggregate definition\n"); | |
2142 nextToken(); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2143 auto decl = parseDeclDefs(0); |
0 | 2144 if (token.value != TOK.TOKrcurly) |
2145 error("} expected following member declarations in aggregate"); | |
2146 nextToken(); | |
2147 if (anon) | |
2148 { | |
2149 /* Anonymous structs/unions are more like attributes. | |
2150 */ | |
2151 return new AnonDeclaration(loc, anon - 1, decl); | |
2152 } | |
2153 else | |
2154 a.members = decl; | |
2155 } | |
2156 else | |
2157 { | |
2158 error("{ } expected following aggregate declaration"); | |
2159 a = new StructDeclaration(loc, null); | |
2160 } | |
2161 | |
2162 if (tpl) | |
2163 { // Wrap a template around the aggregate declaration | |
2164 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2165 auto decldefs = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2166 decldefs.push(a); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2167 auto tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs); |
0 | 2168 return tempdecl; |
2169 } | |
2170 | |
2171 return a; | |
2172 } | |
2173 | |
2174 BaseClasses parseBaseClasses() | |
2175 { | |
2176 BaseClasses baseclasses = new BaseClasses(); | |
2177 | |
2178 for (; 1; nextToken()) | |
2179 { | |
2180 PROT protection = PROT.PROTpublic; | |
2181 switch (token.value) | |
2182 { | |
2183 case TOK.TOKprivate: | |
2184 protection = PROT.PROTprivate; | |
2185 nextToken(); | |
2186 break; | |
2187 case TOK.TOKpackage: | |
2188 protection = PROT.PROTpackage; | |
2189 nextToken(); | |
2190 break; | |
2191 case TOK.TOKprotected: | |
2192 protection = PROT.PROTprotected; | |
2193 nextToken(); | |
2194 break; | |
2195 case TOK.TOKpublic: | |
2196 protection = PROT.PROTpublic; | |
2197 nextToken(); | |
2198 break; | |
2199 default: | |
2200 break; /// | |
2201 } | |
2202 if (token.value == TOK.TOKidentifier) | |
2203 { | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
2204 auto b = new BaseClass(parseBasicType(), protection); |
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
2205 baseclasses.push(b); |
0 | 2206 if (token.value != TOK.TOKcomma) |
2207 break; | |
2208 } | |
2209 else | |
2210 { | |
2211 error("base classes expected instead of %s", token.toChars()); | |
2212 return null; | |
2213 } | |
2214 } | |
2215 return baseclasses; | |
2216 } | |
2217 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2218 Import parseImport(Dsymbols decldefs, int isstatic) |
0 | 2219 { |
2220 Import s; | |
2221 Identifier id; | |
2222 Identifier aliasid = null; | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
2223 Identifiers a; |
0 | 2224 Loc loc; |
2225 | |
2226 //printf("Parser.parseImport()\n"); | |
2227 do | |
2228 { | |
2229 L1: | |
2230 nextToken(); | |
2231 if (token.value != TOK.TOKidentifier) | |
2232 { | |
2233 error("Identifier expected following import"); | |
2234 break; | |
2235 } | |
2236 | |
2237 loc = this.loc; | |
2238 a = null; | |
2239 id = token.ident; | |
2240 nextToken(); | |
2241 if (!aliasid && token.value == TOK.TOKassign) | |
2242 { | |
2243 aliasid = id; | |
2244 goto L1; | |
2245 } | |
2246 while (token.value == TOK.TOKdot) | |
2247 { | |
2248 if (!a) | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
2249 a = new Identifiers(); |
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
2250 a.push(id); |
0 | 2251 nextToken(); |
2252 if (token.value != TOK.TOKidentifier) | |
2253 { | |
2254 error("identifier expected following package"); | |
2255 break; | |
2256 } | |
2257 id = token.ident; | |
2258 nextToken(); | |
2259 } | |
2260 | |
2261 s = new Import(loc, a, id, aliasid, isstatic); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2262 decldefs.push(s); |
0 | 2263 |
2264 /* Look for | |
2265 * : alias=name, alias=name; | |
2266 * syntax. | |
2267 */ | |
2268 if (token.value == TOK.TOKcolon) | |
2269 { | |
2270 do | |
2271 { | |
2272 Identifier name; | |
2273 | |
2274 nextToken(); | |
2275 if (token.value != TOK.TOKidentifier) | |
2276 { | |
2277 error("Identifier expected following :"); | |
2278 break; | |
2279 } | |
2280 Identifier alias_ = token.ident; | |
2281 nextToken(); | |
2282 if (token.value == TOK.TOKassign) | |
2283 { | |
2284 nextToken(); | |
2285 if (token.value != TOK.TOKidentifier) | |
2286 { | |
2287 error("Identifier expected following %s=", alias_.toChars()); | |
2288 break; | |
2289 } | |
2290 name = token.ident; | |
2291 nextToken(); | |
2292 } | |
2293 else | |
2294 { | |
2295 name = alias_; | |
2296 alias_ = null; | |
2297 } | |
2298 s.addAlias(name, alias_); | |
2299 } while (token.value == TOK.TOKcomma); | |
2300 | |
2301 break; // no comma-separated imports of this form | |
2302 } | |
2303 | |
2304 aliasid = null; | |
2305 | |
2306 } while (token.value == TOK.TOKcomma); | |
2307 | |
2308 if (token.value == TOK.TOKsemicolon) | |
2309 nextToken(); | |
2310 else | |
2311 { | |
2312 error("';' expected"); | |
2313 nextToken(); | |
2314 } | |
2315 | |
2316 return null; | |
2317 } | |
2318 | |
2319 Type parseType(Identifier* pident = null, TemplateParameters* tpl = null) | |
2320 { | |
2321 Type t; | |
2322 | |
2323 /* Take care of the storage class prefixes that | |
2324 * serve as type attributes: | |
2325 * const shared, shared const, const, invariant, shared | |
2326 */ | |
2327 if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() != TOK.TOKlparen || | |
2328 token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() != TOK.TOKlparen) | |
2329 { | |
2330 nextToken(); | |
2331 nextToken(); | |
2332 /* shared const type | |
2333 */ | |
2334 t = parseType(pident, tpl); | |
2335 t = t.makeSharedConst(); | |
2336 return t; | |
2337 } | |
135 | 2338 else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() != TOKlparen || |
2339 token.value == TOKshared && peekNext() == TOKwild && peekNext2() != TOKlparen) | |
2340 { | |
2341 nextToken(); | |
2342 nextToken(); | |
2343 /* shared wild type | |
2344 */ | |
2345 t = parseType(pident, tpl); | |
2346 t = t.makeSharedWild(); | |
2347 return t; | |
2348 } | |
0 | 2349 else if (token.value == TOK.TOKconst && peekNext() != TOK.TOKlparen) |
2350 { | |
2351 nextToken(); | |
2352 /* const type | |
2353 */ | |
2354 t = parseType(pident, tpl); | |
2355 t = t.makeConst(); | |
2356 return t; | |
2357 } | |
2358 else if ((token.value == TOK.TOKinvariant || token.value == TOK.TOKimmutable) && | |
2359 peekNext() != TOK.TOKlparen) | |
2360 { | |
2361 nextToken(); | |
2362 /* invariant type | |
2363 */ | |
2364 t = parseType(pident, tpl); | |
2365 t = t.makeInvariant(); | |
2366 return t; | |
2367 } | |
2368 else if (token.value == TOK.TOKshared && peekNext() != TOK.TOKlparen) | |
2369 { | |
2370 nextToken(); | |
2371 /* shared type | |
2372 */ | |
2373 t = parseType(pident, tpl); | |
2374 t = t.makeShared(); | |
2375 return t; | |
2376 } | |
135 | 2377 else if (token.value == TOKwild && peekNext() != TOKlparen) |
2378 { | |
2379 nextToken(); | |
2380 /* wild type | |
2381 */ | |
2382 t = parseType(pident, tpl); | |
2383 t = t.makeWild(); | |
2384 return t; | |
2385 } | |
0 | 2386 else |
2387 t = parseBasicType(); | |
2388 t = parseDeclarator(t, pident, tpl); | |
2389 return t; | |
2390 } | |
2391 | |
2392 Type parseBasicType() | |
2393 { | |
2394 Type t; | |
2395 Identifier id; | |
2396 TypeQualified tid; | |
2397 | |
2398 //printf("parseBasicType()\n"); | |
2399 switch (token.value) | |
2400 { | |
2401 case TOK.TOKvoid: t = Type.tvoid; goto LabelX; | |
2402 case TOK.TOKint8: t = Type.tint8; goto LabelX; | |
2403 case TOK.TOKuns8: t = Type.tuns8; goto LabelX; | |
2404 case TOK.TOKint16: t = Type.tint16; goto LabelX; | |
2405 case TOK.TOKuns16: t = Type.tuns16; goto LabelX; | |
2406 case TOK.TOKint32: t = Type.tint32; goto LabelX; | |
2407 case TOK.TOKuns32: t = Type.tuns32; goto LabelX; | |
2408 case TOK.TOKint64: t = Type.tint64; goto LabelX; | |
2409 case TOK.TOKuns64: t = Type.tuns64; goto LabelX; | |
2410 case TOK.TOKfloat32: t = Type.tfloat32; goto LabelX; | |
2411 case TOK.TOKfloat64: t = Type.tfloat64; goto LabelX; | |
2412 case TOK.TOKfloat80: t = Type.tfloat80; goto LabelX; | |
2413 case TOK.TOKimaginary32: t = Type.timaginary32; goto LabelX; | |
2414 case TOK.TOKimaginary64: t = Type.timaginary64; goto LabelX; | |
2415 case TOK.TOKimaginary80: t = Type.timaginary80; goto LabelX; | |
2416 case TOK.TOKcomplex32: t = Type.tcomplex32; goto LabelX; | |
2417 case TOK.TOKcomplex64: t = Type.tcomplex64; goto LabelX; | |
2418 case TOK.TOKcomplex80: t = Type.tcomplex80; goto LabelX; | |
2419 case TOK.TOKbit: t = Type.tbit; goto LabelX; | |
2420 case TOK.TOKbool: t = Type.tbool; goto LabelX; | |
2421 case TOK.TOKchar: t = Type.tchar; goto LabelX; | |
2422 case TOK.TOKwchar: t = Type.twchar; goto LabelX; | |
2423 case TOK.TOKdchar: t = Type.tdchar; goto LabelX; | |
2424 LabelX: | |
2425 nextToken(); | |
2426 break; | |
2427 | |
2428 case TOK.TOKidentifier: | |
2429 id = token.ident; | |
2430 nextToken(); | |
2431 if (token.value == TOK.TOKnot) | |
2432 { // ident!(template_arguments) | |
2433 TemplateInstance tempinst = new TemplateInstance(loc, id); | |
2434 nextToken(); | |
2435 if (token.value == TOK.TOKlparen) | |
2436 // ident!(template_arguments) | |
2437 tempinst.tiargs = parseTemplateArgumentList(); | |
2438 else | |
2439 // ident!template_argument | |
2440 tempinst.tiargs = parseTemplateArgument(); | |
2441 tid = new TypeInstance(loc, tempinst); | |
2442 goto Lident2; | |
2443 } | |
2444 Lident: | |
2445 tid = new TypeIdentifier(loc, id); | |
2446 Lident2: | |
2447 while (token.value == TOK.TOKdot) | |
2448 { nextToken(); | |
2449 if (token.value != TOK.TOKidentifier) | |
2450 { error("identifier expected following '.' instead of '%s'", token.toChars()); | |
2451 break; | |
2452 } | |
2453 id = token.ident; | |
2454 nextToken(); | |
2455 if (token.value == TOK.TOKnot) | |
2456 { | |
2457 TemplateInstance tempinst = new TemplateInstance(loc, id); | |
2458 nextToken(); | |
2459 if (token.value == TOK.TOKlparen) | |
2460 // ident!(template_arguments) | |
2461 tempinst.tiargs = parseTemplateArgumentList(); | |
2462 else | |
2463 // ident!template_argument | |
2464 tempinst.tiargs = parseTemplateArgument(); | |
56 | 2465 tid.addIdent(tempinst); |
0 | 2466 } |
2467 else | |
2468 tid.addIdent(id); | |
2469 } | |
2470 t = tid; | |
2471 break; | |
2472 | |
2473 case TOK.TOKdot: | |
2474 // Leading . as in .foo | |
2475 id = Id.empty; | |
2476 goto Lident; | |
2477 | |
2478 case TOK.TOKtypeof: | |
2479 // typeof(expression) | |
2480 tid = parseTypeof(); | |
2481 goto Lident2; | |
2482 | |
2483 case TOK.TOKconst: | |
2484 // const(type) | |
2485 nextToken(); | |
2486 check(TOK.TOKlparen); | |
2487 t = parseType(); | |
2488 check(TOK.TOKrparen); | |
2489 if (t.isShared()) | |
2490 t = t.makeSharedConst(); | |
2491 else | |
2492 t = t.makeConst(); | |
2493 break; | |
2494 | |
2495 case TOK.TOKinvariant: | |
2496 case TOK.TOKimmutable: | |
2497 // invariant(type) | |
2498 nextToken(); | |
2499 check(TOK.TOKlparen); | |
2500 t = parseType(); | |
2501 check(TOK.TOKrparen); | |
2502 t = t.makeInvariant(); | |
2503 break; | |
2504 | |
2505 case TOK.TOKshared: | |
2506 // shared(type) | |
2507 nextToken(); | |
2508 check(TOK.TOKlparen); | |
2509 t = parseType(); | |
2510 check(TOK.TOKrparen); | |
2511 if (t.isConst()) | |
2512 t = t.makeSharedConst(); | |
135 | 2513 else if (t.isWild()) |
2514 t = t.makeSharedWild(); | |
0 | 2515 else |
2516 t = t.makeShared(); | |
2517 break; | |
2518 | |
135 | 2519 case TOKwild: |
2520 // wild(type) | |
2521 nextToken(); | |
2522 check(TOK.TOKlparen); | |
2523 t = parseType(); | |
2524 check(TOK.TOKrparen); | |
2525 if (t.isShared()) | |
2526 t = t.makeSharedWild(); | |
2527 else | |
2528 t = t.makeWild(); | |
2529 break; | |
2530 | |
0 | 2531 default: |
2532 error("basic type expected, not %s", token.toChars()); | |
2533 t = Type.tint32; | |
2534 break; | |
2535 } | |
2536 return t; | |
2537 } | |
2538 | |
2539 Type parseBasicType2(Type t) | |
2540 { | |
79 | 2541 //writef("parseBasicType2()\n"); |
0 | 2542 while (1) |
2543 { | |
79 | 2544 switch (token.value) |
0 | 2545 { |
79 | 2546 case TOK.TOKmul: |
2547 t = new TypePointer(t); | |
2548 nextToken(); | |
2549 continue; | |
2550 | |
2551 case TOK.TOKlbracket: | |
2552 // Handle []. Make sure things like | |
2553 // int[3][1] a; | |
2554 // is (array[1] of array[3] of int) | |
0 | 2555 nextToken(); |
79 | 2556 if (token.value == TOK.TOKrbracket) |
2557 { | |
2558 t = new TypeDArray(t); // [] | |
2559 nextToken(); | |
2560 } | |
2561 else if (token.value == TOKnew && peekNext() == TOKrbracket) | |
0 | 2562 { |
79 | 2563 t = new TypeNewArray(t); // [new] |
2564 nextToken(); | |
2565 nextToken(); | |
2566 } | |
2567 else if (isDeclaration(&token, 0, TOK.TOKrbracket, null)) | |
2568 { // It's an associative array declaration | |
2569 | |
2570 //printf("it's an associative array\n"); | |
2571 Type index = parseType(); // [ type ] | |
2572 t = new TypeAArray(t, index); | |
2573 check(TOK.TOKrbracket); | |
0 | 2574 } |
2575 else | |
79 | 2576 { |
2577 //printf("it's type[expression]\n"); | |
2578 inBrackets++; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2579 Expression e = parseAssignExp(); // [ expression ] |
79 | 2580 if (token.value == TOK.TOKslice) |
2581 { | |
2582 nextToken(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2583 Expression e2 = parseAssignExp(); // [ exp .. exp ] |
79 | 2584 t = new TypeSlice(t, e, e2); |
2585 } | |
2586 else | |
2587 t = new TypeSArray(t,e); | |
2588 inBrackets--; | |
2589 check(TOK.TOKrbracket); | |
2590 } | |
2591 continue; | |
2592 | |
2593 case TOK.TOKdelegate: | |
2594 case TOK.TOKfunction: | |
2595 { // Handle delegate declaration: | |
2596 // t delegate(parameter list) nothrow pure | |
2597 // t function(parameter list) nothrow pure | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2598 Parameters arguments; |
79 | 2599 int varargs; |
2600 bool ispure = false; | |
2601 bool isnothrow = false; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2602 bool isproperty = false; |
79 | 2603 TOK save = token.value; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2604 TRUST trust = TRUSTdefault; |
79 | 2605 |
2606 nextToken(); | |
2607 arguments = parseParameters(&varargs); | |
2608 while (1) | |
2609 { // Postfixes | |
2610 if (token.value == TOK.TOKpure) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2611 ispure = true; |
79 | 2612 else if (token.value == TOK.TOKnothrow) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2613 isnothrow = true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2614 else if (token.value == TOKat) |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
2615 { StorageClass stc = parseAttribute(); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2616 switch (cast(uint)(stc >> 32)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2617 { case STCproperty >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2618 isproperty = true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2619 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2620 case STCsafe >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2621 trust = TRUSTsafe; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2622 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2623 case STCsystem >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2624 trust = TRUSTsystem; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2625 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2626 case STCtrusted >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2627 trust = TRUSTtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2628 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2629 case 0: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2630 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2631 default: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2632 assert(0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2633 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2634 } |
79 | 2635 else |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2636 break; |
79 | 2637 nextToken(); |
2638 } | |
2639 TypeFunction tf = new TypeFunction(arguments, t, varargs, linkage); | |
2640 tf.ispure = ispure; | |
2641 tf.isnothrow = isnothrow; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2642 tf.isproperty = isproperty; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2643 tf.trust = trust; |
79 | 2644 if (save == TOK.TOKdelegate) |
2645 t = new TypeDelegate(tf); | |
0 | 2646 else |
79 | 2647 t = new TypePointer(tf); // pointer to function |
2648 continue; | |
2649 } | |
2650 | |
2651 default: | |
2652 return t; | |
2653 } | |
2654 assert(0); | |
0 | 2655 } |
2656 assert(0); | |
2657 return null; | |
2658 } | |
2659 | |
2660 Type parseDeclarator(Type t, Identifier* pident, TemplateParameters* tpl = null) | |
2661 { | |
2662 Type ts; | |
2663 | |
2664 //printf("parseDeclarator(tpl = %p)\n", tpl); | |
2665 t = parseBasicType2(t); | |
2666 | |
2667 switch (token.value) | |
2668 { | |
2669 | |
2670 case TOK.TOKidentifier: | |
2671 if (pident) | |
2672 *pident = token.ident; | |
2673 else | |
2674 error("unexpected identifer '%s' in declarator", token.ident.toChars()); | |
2675 ts = t; | |
2676 nextToken(); | |
2677 break; | |
2678 | |
2679 case TOK.TOKlparen: | |
2680 /* Parse things with parentheses around the identifier, like: | |
2681 * int (*ident[3])[] | |
2682 * although the D style would be: | |
2683 * int[]*[3] ident | |
2684 */ | |
2685 nextToken(); | |
2686 ts = parseDeclarator(t, pident); | |
2687 check(TOK.TOKrparen); | |
2688 break; | |
2689 | |
2690 default: | |
2691 ts = t; | |
2692 break; | |
2693 } | |
2694 | |
2695 // parse DeclaratorSuffixes | |
2696 while (1) | |
2697 { | |
2698 switch (token.value) | |
2699 { | |
2700 version (CARRAYDECL) { | |
2701 /* Support C style array syntax: | |
2702 * int ident[] | |
2703 * as opposed to D-style: | |
2704 * int[] ident | |
2705 */ | |
2706 case TOK.TOKlbracket: | |
2707 { // This is the old C-style post [] syntax. | |
2708 TypeNext ta; | |
2709 nextToken(); | |
2710 if (token.value == TOK.TOKrbracket) | |
2711 { // It's a dynamic array | |
2712 ta = new TypeDArray(t); // [] | |
2713 nextToken(); | |
2714 } | |
79 | 2715 else if (token.value == TOKnew && peekNext() == TOKrbracket) |
2716 { | |
2717 t = new TypeNewArray(t); // [new] | |
2718 nextToken(); | |
2719 nextToken(); | |
2720 } | |
0 | 2721 else if (isDeclaration(&token, 0, TOK.TOKrbracket, null)) |
2722 { // It's an associative array | |
2723 | |
2724 //printf("it's an associative array\n"); | |
2725 Type index = parseType(); // [ type ] | |
2726 check(TOK.TOKrbracket); | |
2727 ta = new TypeAArray(t, index); | |
2728 } | |
2729 else | |
2730 { | |
2731 //printf("It's a static array\n"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2732 Expression e = parseAssignExp(); // [ expression ] |
0 | 2733 ta = new TypeSArray(t, e); |
2734 check(TOK.TOKrbracket); | |
2735 } | |
2736 | |
2737 /* Insert ta into | |
2738 * ts . ... . t | |
2739 * so that | |
2740 * ts . ... . ta . t | |
2741 */ | |
2742 Type* pt; | |
2743 for (pt = &ts; *pt !is t; pt = &(cast(TypeNext)*pt).next) { | |
2744 ; | |
2745 } | |
2746 *pt = ta; | |
2747 continue; | |
2748 } | |
2749 } | |
2750 case TOK.TOKlparen: | |
2751 { | |
2752 if (tpl) | |
2753 { | |
2754 /* Look ahead to see if this is (...)(...), | |
2755 * i.e. a function template declaration | |
2756 */ | |
2757 if (peekPastParen(&token).value == TOK.TOKlparen) | |
2758 { | |
2759 //printf("function template declaration\n"); | |
2760 | |
2761 // Gather template parameter list | |
2762 *tpl = parseTemplateParameterList(); | |
2763 } | |
2764 } | |
2765 | |
2766 int varargs; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2767 auto arguments = parseParameters(&varargs); |
0 | 2768 Type tf = new TypeFunction(arguments, t, varargs, linkage); |
2769 | |
2770 /* Parse const/invariant/nothrow/pure postfix | |
2771 */ | |
2772 while (1) | |
2773 { | |
2774 switch (token.value) | |
2775 { | |
2776 case TOK.TOKconst: | |
2777 if (tf.isShared()) | |
2778 tf = tf.makeSharedConst(); | |
2779 else | |
2780 tf = tf.makeConst(); | |
2781 nextToken(); | |
2782 continue; | |
2783 | |
2784 case TOK.TOKinvariant: | |
2785 case TOK.TOKimmutable: | |
2786 tf = tf.makeInvariant(); | |
2787 nextToken(); | |
2788 continue; | |
2789 | |
2790 case TOK.TOKshared: | |
2791 if (tf.isConst()) | |
2792 tf = tf.makeSharedConst(); | |
2793 else | |
2794 tf = tf.makeShared(); | |
2795 nextToken(); | |
2796 continue; | |
2797 | |
135 | 2798 case TOKwild: |
2799 if (tf.isShared()) | |
2800 tf = tf.makeSharedWild(); | |
2801 else | |
2802 tf = tf.makeWild(); | |
2803 nextToken(); | |
2804 continue; | |
2805 | |
0 | 2806 case TOK.TOKnothrow: |
2807 (cast(TypeFunction)tf).isnothrow = 1; | |
2808 nextToken(); | |
2809 continue; | |
2810 | |
2811 case TOK.TOKpure: | |
2812 (cast(TypeFunction)tf).ispure = 1; | |
2813 nextToken(); | |
2814 continue; | |
2815 | |
2816 case TOK.TOKat: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2817 { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
2818 StorageClass stc = parseAttribute(); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2819 auto tfunc = cast(TypeFunction)tf; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2820 switch (cast(uint)(stc >> 32)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2821 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2822 case STCproperty >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2823 tfunc.isproperty = 1; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2824 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2825 case STCsafe >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2826 tfunc.trust = TRUSTsafe; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2827 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2828 case STCsystem >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2829 tfunc.trust = TRUSTsystem; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2830 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2831 case STCtrusted >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2832 tfunc.trust = TRUSTtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2833 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2834 case 0: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2835 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2836 default: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2837 assert(0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2838 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2839 nextToken(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2840 continue; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2841 } |
0 | 2842 default: |
2843 break; /// | |
2844 } | |
2845 break; | |
2846 } | |
2847 | |
2848 /* Insert tf into | |
2849 * ts . ... . t | |
2850 * so that | |
2851 * ts . ... . tf . t | |
2852 */ | |
2853 Type* pt; | |
2854 for (pt = &ts; *pt !is t; pt = &(cast(TypeNext)*pt).next) { | |
2855 ; | |
2856 } | |
2857 *pt = tf; | |
2858 break; | |
2859 } | |
2860 | |
2861 default: | |
2862 break; /// | |
2863 } | |
2864 break; | |
2865 } | |
2866 | |
2867 return ts; | |
2868 } | |
2869 | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
2870 Dsymbols parseDeclarations(StorageClass storage_class) |
0 | 2871 { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
2872 StorageClass stc; |
0 | 2873 Type ts; |
2874 Type t; | |
2875 Type tfirst; | |
2876 Identifier ident; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2877 Dsymbols a; |
0 | 2878 TOK tok = TOK.TOKreserved; |
79 | 2879 string comment = token.blockComment; |
0 | 2880 LINK link = linkage; |
2881 | |
2882 //printf("parseDeclarations() %s\n", token.toChars()); | |
2883 if (storage_class) | |
2884 { ts = null; // infer type | |
2885 goto L2; | |
2886 } | |
2887 | |
2888 switch (token.value) | |
2889 { | |
2890 case TOK.TOKalias: | |
2891 /* Look for: | |
2892 * alias identifier this; | |
2893 */ | |
2894 tok = token.value; | |
2895 nextToken(); | |
2896 if (token.value == TOK.TOKidentifier && peek(&token).value == TOK.TOKthis) | |
2897 { | |
2898 AliasThis s = new AliasThis(this.loc, token.ident); | |
2899 nextToken(); | |
2900 check(TOK.TOKthis); | |
2901 check(TOK.TOKsemicolon); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2902 a = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
2903 a.push(s); |
0 | 2904 addComment(s, comment); |
2905 return a; | |
2906 } | |
2907 break; | |
2908 case TOK.TOKtypedef: | |
2909 tok = token.value; | |
2910 nextToken(); | |
2911 break; | |
2912 default: | |
2913 break; | |
2914 } | |
2915 | |
2916 storage_class = STC.STCundefined; | |
2917 while (1) | |
2918 { | |
2919 switch (token.value) | |
2920 { | |
2921 case TOK.TOKconst: | |
2922 if (peek(&token).value == TOK.TOKlparen) | |
2923 break; // const as type constructor | |
2924 stc = STC.STCconst; // const as storage class | |
2925 goto L1; | |
2926 | |
2927 case TOK.TOKinvariant: | |
2928 case TOK.TOKimmutable: | |
2929 if (peek(&token).value == TOK.TOKlparen) | |
2930 break; | |
2931 stc = STC.STCimmutable; | |
2932 goto L1; | |
2933 | |
2934 case TOK.TOKshared: | |
2935 if (peek(&token).value == TOK.TOKlparen) | |
2936 break; | |
2937 stc = STC.STCshared; | |
135 | 2938 goto L1; |
2939 | |
2940 case TOKwild: | |
2941 if (peek(&token).value == TOK.TOKlparen) | |
2942 break; | |
2943 stc = STC.STCwild; | |
0 | 2944 goto L1; |
2945 | |
2946 case TOK.TOKstatic: stc = STC.STCstatic; goto L1; | |
2947 case TOK.TOKfinal: stc = STC.STCfinal; goto L1; | |
2948 case TOK.TOKauto: stc = STC.STCauto; goto L1; | |
2949 case TOK.TOKscope: stc = STC.STCscope; goto L1; | |
2950 case TOK.TOKoverride: stc = STC.STCoverride; goto L1; | |
2951 case TOK.TOKabstract: stc = STC.STCabstract; goto L1; | |
2952 case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto L1; | |
2953 case TOK.TOKdeprecated: stc = STC.STCdeprecated; goto L1; | |
2954 version (DMDV2) { | |
2955 case TOK.TOKnothrow: stc = STC.STCnothrow; goto L1; | |
2956 case TOK.TOKpure: stc = STC.STCpure; goto L1; | |
2957 case TOK.TOKref: stc = STC.STCref; goto L1; | |
2958 case TOK.TOKtls: stc = STC.STCtls; goto L1; | |
2959 case TOK.TOKgshared: stc = STC.STCgshared; goto L1; | |
2960 case TOK.TOKenum: stc = STC.STCmanifest; goto L1; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
2961 case TOK.TOKat: stc = parseAttribute(); goto L1; |
0 | 2962 } |
2963 L1: | |
2964 if (storage_class & stc) | |
2965 error("redundant storage class '%s'", token.toChars()); | |
2966 storage_class = (storage_class | stc); | |
2967 composeStorageClass(storage_class); | |
2968 nextToken(); | |
2969 continue; | |
2970 | |
2971 case TOK.TOKextern: | |
2972 if (peek(&token).value != TOK.TOKlparen) | |
2973 { stc = STC.STCextern; | |
2974 goto L1; | |
2975 } | |
2976 | |
2977 link = parseLinkage(); | |
2978 continue; | |
2979 | |
2980 default: | |
2981 break; | |
2982 } | |
2983 break; | |
2984 } | |
2985 | |
2986 /* Look for auto initializers: | |
2987 * storage_class identifier = initializer; | |
2988 */ | |
2989 if (storage_class && | |
2990 token.value == TOK.TOKidentifier && | |
2991 peek(&token).value == TOK.TOKassign) | |
2992 { | |
2993 return parseAutoDeclarations(storage_class, comment); | |
2994 } | |
2995 | |
2996 if (token.value == TOK.TOKclass) | |
2997 { | |
2998 AggregateDeclaration s = cast(AggregateDeclaration)parseAggregate(); | |
2999 s.storage_class |= storage_class; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3000 a = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3001 a.push(s); |
0 | 3002 addComment(s, comment); |
3003 return a; | |
3004 } | |
3005 | |
3006 /* Look for return type inference for template functions. | |
3007 */ | |
3008 { | |
3009 Token *tk; | |
3010 if (storage_class && | |
3011 token.value == TOK.TOKidentifier && | |
3012 (tk = peek(&token)).value == TOK.TOKlparen && | |
3013 skipParens(tk, &tk) && | |
3014 peek(tk).value == TOK.TOKlparen) | |
3015 { | |
3016 ts = null; | |
3017 } | |
3018 else | |
3019 { | |
3020 ts = parseBasicType(); | |
3021 ts = parseBasicType2(ts); | |
3022 } | |
3023 } | |
3024 | |
3025 L2: | |
3026 tfirst = null; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3027 a = new Dsymbols(); |
0 | 3028 |
3029 while (1) | |
3030 { | |
3031 Loc loc = this.loc; | |
3032 TemplateParameters tpl = null; | |
3033 | |
3034 ident = null; | |
3035 t = parseDeclarator(ts, &ident, &tpl); | |
3036 assert(t); | |
3037 if (!tfirst) | |
3038 tfirst = t; | |
3039 else if (t != tfirst) | |
3040 error("multiple declarations must have the same type, not %s and %s", | |
3041 tfirst.toChars(), t.toChars()); | |
3042 if (!ident) | |
3043 error("no identifier for declarator %s", t.toChars()); | |
3044 | |
3045 if (tok == TOK.TOKtypedef || tok == TOK.TOKalias) | |
3046 { Declaration v; | |
3047 Initializer init = null; | |
3048 | |
3049 if (token.value == TOK.TOKassign) | |
3050 { | |
3051 nextToken(); | |
3052 init = parseInitializer(); | |
3053 } | |
3054 if (tok == TOK.TOKtypedef) | |
3055 v = new TypedefDeclaration(loc, ident, t, init); | |
3056 else | |
3057 { if (init) | |
3058 error("alias cannot have initializer"); | |
3059 v = new AliasDeclaration(loc, ident, t); | |
3060 } | |
3061 v.storage_class = storage_class; | |
3062 if (link == linkage) | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3063 a.push(v); |
0 | 3064 else |
3065 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3066 auto ax = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3067 ax.push(v); |
0 | 3068 Dsymbol s = new LinkDeclaration(link, ax); |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3069 a.push(s); |
0 | 3070 } |
3071 switch (token.value) | |
3072 { case TOK.TOKsemicolon: | |
3073 nextToken(); | |
3074 addComment(v, comment); | |
3075 break; | |
3076 | |
3077 case TOK.TOKcomma: | |
3078 nextToken(); | |
3079 addComment(v, comment); | |
3080 continue; | |
3081 | |
3082 default: | |
3083 error("semicolon expected to close %s declaration", Token.toChars(tok)); | |
3084 break; | |
3085 } | |
3086 } | |
3087 else if (t.ty == TY.Tfunction) | |
3088 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3089 auto tf = cast(TypeFunction)t; |
0 | 3090 Expression constraint = null; |
3091 static if (false) { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3092 if (Parameter.isTPL(tf.parameters)) |
0 | 3093 { |
3094 if (!tpl) | |
3095 tpl = new TemplateParameters(); | |
3096 } | |
3097 } | |
3098 FuncDeclaration f = | |
3099 new FuncDeclaration(loc, Loc(0), ident, storage_class, t); | |
3100 addComment(f, comment); | |
3101 if (tpl) | |
3102 constraint = parseConstraint(); | |
3103 parseContracts(f); | |
3104 addComment(f, null); | |
3105 Dsymbol s; | |
3106 if (link == linkage) | |
3107 { | |
3108 s = f; | |
3109 } | |
3110 else | |
3111 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3112 auto ax = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3113 ax.push(f); |
0 | 3114 s = new LinkDeclaration(link, ax); |
3115 } | |
3116 /* A template parameter list means it's a function template | |
3117 */ | |
3118 if (tpl) | |
3119 { | |
3120 // Wrap a template around the function declaration | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3121 auto decldefs = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3122 decldefs.push(s); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3123 auto tempdecl = |
0 | 3124 new TemplateDeclaration(loc, s.ident, tpl, constraint, decldefs); |
3125 s = tempdecl; | |
3126 } | |
3127 addComment(s, comment); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3128 a.push(s); |
0 | 3129 } |
3130 else | |
3131 { | |
3132 Initializer init = null; | |
3133 if (token.value == TOK.TOKassign) | |
3134 { | |
3135 nextToken(); | |
3136 init = parseInitializer(); | |
3137 } | |
3138 | |
3139 VarDeclaration v = new VarDeclaration(loc, t, ident, init); | |
3140 v.storage_class = storage_class; | |
3141 if (link == linkage) | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3142 a.push(v); |
0 | 3143 else |
3144 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3145 auto ax = new Dsymbols(); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3146 ax.push(v); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3147 auto s = new LinkDeclaration(link, ax); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3148 a.push(s); |
0 | 3149 } |
3150 switch (token.value) | |
3151 { case TOK.TOKsemicolon: | |
3152 nextToken(); | |
3153 addComment(v, comment); | |
3154 break; | |
3155 | |
3156 case TOK.TOKcomma: | |
3157 nextToken(); | |
3158 addComment(v, comment); | |
3159 continue; | |
3160 | |
3161 default: | |
3162 error("semicolon expected, not '%s'", token.toChars()); | |
3163 break; | |
3164 } | |
3165 } | |
3166 break; | |
3167 } | |
3168 return a; | |
3169 } | |
3170 | |
3171 void parseContracts(FuncDeclaration f) | |
3172 { | |
3173 LINK linksave = linkage; | |
3174 | |
3175 // The following is irrelevant, as it is overridden by sc.linkage in | |
3176 // TypeFunction.semantic | |
3177 linkage = LINK.LINKd; // nested functions have D linkage | |
3178 L1: | |
3179 switch (token.value) | |
3180 { | |
3181 case TOK.TOKlcurly: | |
3182 if (f.frequire || f.fensure) | |
3183 error("missing body { ... } after in or out"); | |
3184 f.fbody = parseStatement(ParseStatementFlags.PSsemi); | |
3185 f.endloc = endloc; | |
3186 break; | |
3187 | |
3188 case TOK.TOKbody: | |
3189 nextToken(); | |
3190 f.fbody = parseStatement(ParseStatementFlags.PScurly); | |
3191 f.endloc = endloc; | |
3192 break; | |
3193 | |
3194 case TOK.TOKsemicolon: | |
3195 if (f.frequire || f.fensure) | |
3196 error("missing body { ... } after in or out"); | |
3197 nextToken(); | |
3198 break; | |
3199 | |
3200 static if (false) { // Do we want this for function declarations, so we can do: | |
3201 // int x, y, foo(), z; | |
3202 case TOK.TOKcomma: | |
3203 nextToken(); | |
3204 continue; | |
3205 } | |
3206 | |
3207 static if (false) { // Dumped feature | |
3208 case TOK.TOKthrow: | |
3209 if (!f.fthrows) | |
3210 f.fthrows = new Array(); | |
3211 nextToken(); | |
3212 check(TOK.TOKlparen); | |
3213 while (1) | |
3214 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3215 Type tb = parseBasicType(); |
0 | 3216 f.fthrows.push(tb); |
3217 if (token.value == TOK.TOKcomma) | |
3218 { nextToken(); | |
3219 continue; | |
3220 } | |
3221 break; | |
3222 } | |
3223 check(TOK.TOKrparen); | |
3224 goto L1; | |
3225 } | |
3226 | |
3227 case TOK.TOKin: | |
3228 nextToken(); | |
3229 if (f.frequire) | |
3230 error("redundant 'in' statement"); | |
3231 f.frequire = parseStatement(ParseStatementFlags.PScurly | ParseStatementFlags.PSscope); | |
3232 goto L1; | |
3233 | |
3234 case TOK.TOKout: | |
3235 // parse: out (identifier) { statement } | |
3236 nextToken(); | |
3237 if (token.value != TOK.TOKlcurly) | |
3238 { | |
3239 check(TOK.TOKlparen); | |
3240 if (token.value != TOK.TOKidentifier) | |
3241 error("(identifier) following 'out' expected, not %s", token.toChars()); | |
3242 f.outId = token.ident; | |
3243 nextToken(); | |
3244 check(TOK.TOKrparen); | |
3245 } | |
3246 if (f.fensure) | |
3247 error("redundant 'out' statement"); | |
3248 f.fensure = parseStatement(ParseStatementFlags.PScurly | ParseStatementFlags.PSscope); | |
3249 goto L1; | |
3250 | |
3251 default: | |
3252 error("semicolon expected following function declaration"); | |
3253 break; | |
3254 } | |
3255 linkage = linksave; | |
3256 } | |
3257 | |
3258 Statement parseStatement(ParseStatementFlags flags) | |
3259 { | |
3260 Statement s; | |
3261 Token* t; | |
3262 Condition condition; | |
3263 Statement ifbody; | |
3264 Statement elsebody; | |
3265 bool isfinal; | |
3266 Loc loc = this.loc; | |
3267 | |
3268 //printf("parseStatement()\n"); | |
3269 | |
3270 if (flags & ParseStatementFlags.PScurly && token.value != TOK.TOKlcurly) | |
3271 error("statement expected to be { }, not %s", token.toChars()); | |
3272 | |
3273 switch (token.value) | |
3274 { | |
3275 case TOK.TOKidentifier: | |
3276 /* A leading identifier can be a declaration, label, or expression. | |
3277 * The easiest case to check first is label: | |
3278 */ | |
3279 t = peek(&token); | |
3280 if (t.value == TOK.TOKcolon) | |
3281 { // It's a label | |
3282 | |
3283 Identifier ident = token.ident; | |
3284 nextToken(); | |
3285 nextToken(); | |
3286 s = parseStatement(ParseStatementFlags.PSsemi); | |
3287 s = new LabelStatement(loc, ident, s); | |
3288 break; | |
3289 } | |
3290 // fallthrough to TOK.TOKdot | |
3291 case TOK.TOKdot: | |
3292 case TOK.TOKtypeof: | |
3293 if (isDeclaration(&token, 2, TOK.TOKreserved, null)) | |
3294 goto Ldeclaration; | |
3295 else | |
3296 goto Lexp; | |
3297 break; | |
3298 | |
3299 case TOK.TOKassert: | |
3300 case TOK.TOKthis: | |
3301 case TOK.TOKsuper: | |
3302 case TOK.TOKint32v: | |
3303 case TOK.TOKuns32v: | |
3304 case TOK.TOKint64v: | |
3305 case TOK.TOKuns64v: | |
3306 case TOK.TOKfloat32v: | |
3307 case TOK.TOKfloat64v: | |
3308 case TOK.TOKfloat80v: | |
3309 case TOK.TOKimaginary32v: | |
3310 case TOK.TOKimaginary64v: | |
3311 case TOK.TOKimaginary80v: | |
3312 case TOK.TOKcharv: | |
3313 case TOK.TOKwcharv: | |
3314 case TOK.TOKdcharv: | |
3315 case TOK.TOKnull: | |
3316 case TOK.TOKtrue: | |
3317 case TOK.TOKfalse: | |
3318 case TOK.TOKstring: | |
3319 case TOK.TOKlparen: | |
3320 case TOK.TOKcast: | |
3321 case TOK.TOKmul: | |
3322 case TOK.TOKmin: | |
3323 case TOK.TOKadd: | |
3324 case TOK.TOKplusplus: | |
3325 case TOK.TOKminusminus: | |
3326 case TOK.TOKnew: | |
3327 case TOK.TOKdelete: | |
3328 case TOK.TOKdelegate: | |
3329 case TOK.TOKfunction: | |
3330 case TOK.TOKtypeid: | |
3331 case TOK.TOKis: | |
3332 case TOK.TOKlbracket: | |
3333 version (DMDV2) { | |
3334 case TOK.TOKtraits: | |
3335 case TOK.TOKfile: | |
3336 case TOK.TOKline: | |
3337 } | |
3338 Lexp: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3339 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3340 auto exp = parseExpression(); |
0 | 3341 check(TOK.TOKsemicolon, "statement"); |
3342 s = new ExpStatement(loc, exp); | |
3343 break; | |
3344 } | |
3345 | |
3346 case TOK.TOKstatic: | |
3347 { // Look ahead to see if it's static assert() or static if() | |
3348 Token *tt; | |
3349 | |
3350 tt = peek(&token); | |
3351 if (tt.value == TOK.TOKassert) | |
3352 { | |
3353 nextToken(); | |
3354 s = new StaticAssertStatement(parseStaticAssert()); | |
3355 break; | |
3356 } | |
3357 if (tt.value == TOK.TOKif) | |
3358 { | |
3359 nextToken(); | |
3360 condition = parseStaticIfCondition(); | |
3361 goto Lcondition; | |
3362 } | |
132
c494af1dba80
Fixes for dmd 2.037
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
131
diff
changeset
|
3363 if (tt.value == TOK.TOKstruct || tt.value == TOK.TOKunion || tt.value == TOK.TOKclass) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3364 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3365 nextToken(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3366 auto a = parseBlock(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3367 Dsymbol d = new StorageClassDeclaration(STCstatic, a); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3368 s = new DeclarationStatement(loc, d); |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
3369 if (flags & ParseStatementFlags.PSscope) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3370 s = new ScopeStatement(loc, s); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3371 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3372 } |
0 | 3373 goto Ldeclaration; |
3374 } | |
3375 | |
3376 case TOK.TOKfinal: | |
3377 if (peekNext() == TOK.TOKswitch) | |
3378 { | |
3379 nextToken(); | |
3380 isfinal = true; | |
3381 goto Lswitch; | |
3382 } | |
3383 goto Ldeclaration; | |
3384 | |
3385 case TOK.TOKwchar: case TOK.TOKdchar: | |
3386 case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar: | |
3387 case TOK.TOKint8: case TOK.TOKuns8: | |
3388 case TOK.TOKint16: case TOK.TOKuns16: | |
3389 case TOK.TOKint32: case TOK.TOKuns32: | |
3390 case TOK.TOKint64: case TOK.TOKuns64: | |
3391 case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80: | |
3392 case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80: | |
3393 case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80: | |
3394 case TOK.TOKvoid: | |
3395 case TOK.TOKtypedef: | |
3396 case TOK.TOKalias: | |
3397 case TOK.TOKconst: | |
3398 case TOK.TOKauto: | |
3399 case TOK.TOKextern: | |
3400 case TOK.TOKinvariant: | |
3401 version (DMDV2) { | |
3402 case TOK.TOKimmutable: | |
3403 case TOK.TOKshared: | |
135 | 3404 case TOKwild: |
0 | 3405 case TOK.TOKnothrow: |
3406 case TOK.TOKpure: | |
3407 case TOK.TOKtls: | |
3408 case TOK.TOKgshared: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3409 case TOK.TOKat: |
0 | 3410 } |
3411 // case TOK.TOKtypeof: | |
3412 Ldeclaration: | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
3413 { Dsymbols a; |
0 | 3414 |
3415 a = parseDeclarations(STC.STCundefined); | |
3416 if (a.dim > 1) | |
3417 { | |
3418 Statements as = new Statements(); | |
3419 as.reserve(a.dim); | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
3420 foreach(Dsymbol d; a) |
0 | 3421 { |
3422 s = new DeclarationStatement(loc, d); | |
122
c77e9f4f1793
Statements -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
3423 as.push(s); |
0 | 3424 } |
3425 s = new CompoundDeclarationStatement(loc, as); | |
3426 } | |
3427 else if (a.dim == 1) | |
3428 { | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
3429 auto d = a[0]; |
0 | 3430 s = new DeclarationStatement(loc, d); |
3431 } | |
3432 else | |
3433 assert(0); | |
3434 if (flags & ParseStatementFlags.PSscope) | |
3435 s = new ScopeStatement(loc, s); | |
3436 break; | |
3437 } | |
3438 | |
3439 case TOK.TOKstruct: | |
3440 case TOK.TOKunion: | |
3441 case TOK.TOKclass: | |
3442 case TOK.TOKinterface: | |
3443 { Dsymbol d; | |
3444 | |
3445 d = parseAggregate(); | |
3446 s = new DeclarationStatement(loc, d); | |
3447 break; | |
3448 } | |
3449 | |
3450 case TOK.TOKenum: | |
3451 { /* Determine if this is a manifest constant declaration, | |
3452 * or a conventional enum. | |
3453 */ | |
3454 Dsymbol d; | |
3455 Token* tt = peek(&token); | |
3456 if (tt.value == TOK.TOKlcurly || tt.value == TOK.TOKcolon) | |
3457 d = parseEnum(); | |
3458 else if (tt.value != TOK.TOKidentifier) | |
3459 goto Ldeclaration; | |
3460 else | |
3461 { | |
3462 tt = peek(tt); | |
3463 if (tt.value == TOK.TOKlcurly || tt.value == TOK.TOKcolon || | |
3464 tt.value == TOK.TOKsemicolon) | |
3465 d = parseEnum(); | |
3466 else | |
3467 goto Ldeclaration; | |
3468 } | |
3469 s = new DeclarationStatement(loc, d); | |
3470 break; | |
3471 } | |
3472 | |
3473 case TOK.TOKmixin: | |
3474 { t = peek(&token); | |
3475 if (t.value == TOK.TOKlparen) | |
3476 { // mixin(string) | |
3477 nextToken(); | |
3478 check(TOK.TOKlparen, "mixin"); | |
3479 Expression e = parseAssignExp(); | |
3480 check(TOK.TOKrparen); | |
3481 check(TOK.TOKsemicolon); | |
3482 s = new CompileStatement(loc, e); | |
3483 break; | |
3484 } | |
3485 Dsymbol d = parseMixin(); | |
3486 s = new DeclarationStatement(loc, d); | |
3487 break; | |
3488 } | |
3489 | |
3490 case TOK.TOKlcurly: | |
79 | 3491 { |
3492 nextToken(); | |
3493 Statements statements = new Statements(); | |
3494 while (token.value != TOK.TOKrcurly && token.value != TOKeof) | |
0 | 3495 { |
122
c77e9f4f1793
Statements -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
3496 statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); |
0 | 3497 } |
3498 endloc = this.loc; | |
3499 s = new CompoundStatement(loc, statements); | |
3500 if (flags & (ParseStatementFlags.PSscope | ParseStatementFlags.PScurlyscope)) | |
3501 s = new ScopeStatement(loc, s); | |
3502 nextToken(); | |
3503 break; | |
3504 } | |
3505 | |
3506 case TOK.TOKwhile: | |
3507 { Expression condition2; | |
3508 Statement body_; | |
3509 | |
3510 nextToken(); | |
3511 check(TOK.TOKlparen); | |
3512 condition2 = parseExpression(); | |
3513 check(TOK.TOKrparen); | |
3514 body_ = parseStatement(ParseStatementFlags.PSscope); | |
3515 s = new WhileStatement(loc, condition2, body_); | |
3516 break; | |
3517 } | |
3518 | |
3519 case TOK.TOKsemicolon: | |
3520 if (!(flags & ParseStatementFlags.PSsemi)) | |
3521 error("use '{ }' for an empty statement, not a ';'"); | |
3522 nextToken(); | |
3523 s = new ExpStatement(loc, null); | |
3524 break; | |
3525 | |
3526 case TOK.TOKdo: | |
3527 { Statement body_; | |
3528 Expression condition2; | |
3529 | |
3530 nextToken(); | |
3531 body_ = parseStatement(ParseStatementFlags.PSscope); | |
3532 check(TOK.TOKwhile); | |
3533 check(TOK.TOKlparen); | |
3534 condition2 = parseExpression(); | |
3535 check(TOK.TOKrparen); | |
3536 s = new DoStatement(loc, body_, condition2); | |
3537 break; | |
3538 } | |
3539 | |
3540 case TOK.TOKfor: | |
3541 { | |
3542 Statement init; | |
3543 Expression condition2; | |
3544 Expression increment; | |
3545 Statement body_; | |
3546 | |
3547 nextToken(); | |
3548 check(TOK.TOKlparen); | |
3549 if (token.value == TOK.TOKsemicolon) | |
3550 { init = null; | |
3551 nextToken(); | |
3552 } | |
3553 else | |
3554 { init = parseStatement(cast(ParseStatementFlags)0); | |
3555 } | |
3556 if (token.value == TOK.TOKsemicolon) | |
3557 { | |
3558 condition2 = null; | |
3559 nextToken(); | |
3560 } | |
3561 else | |
3562 { | |
3563 condition2 = parseExpression(); | |
3564 check(TOK.TOKsemicolon, "for condition"); | |
3565 } | |
3566 if (token.value == TOK.TOKrparen) | |
3567 { increment = null; | |
3568 nextToken(); | |
3569 } | |
3570 else | |
3571 { increment = parseExpression(); | |
3572 check(TOK.TOKrparen); | |
3573 } | |
3574 body_ = parseStatement(ParseStatementFlags.PSscope); | |
3575 s = new ForStatement(loc, init, condition2, increment, body_); | |
3576 if (init) | |
3577 s = new ScopeStatement(loc, s); | |
3578 break; | |
3579 } | |
3580 | |
3581 case TOK.TOKforeach: | |
3582 case TOK.TOKforeach_reverse: | |
3583 { | |
3584 TOK op = token.value; | |
3585 | |
3586 nextToken(); | |
3587 check(TOK.TOKlparen); | |
3588 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3589 auto arguments = new Parameters(); |
0 | 3590 |
3591 while (1) | |
3592 { | |
3593 Identifier ai = null; | |
3594 Type at; | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
3595 StorageClass storageClass = STC.STCundefined; |
0 | 3596 |
135 | 3597 if (token.value == TOKref |
3598 //#if D1INOUT | |
3599 // || token.value == TOKinout | |
3600 //#endif | |
3601 ) | |
0 | 3602 { storageClass = STC.STCref; |
3603 nextToken(); | |
3604 } | |
3605 if (token.value == TOK.TOKidentifier) | |
3606 { | |
3607 Token *tt = peek(&token); | |
3608 if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon) | |
3609 { ai = token.ident; | |
3610 at = null; // infer argument type | |
3611 nextToken(); | |
3612 goto Larg; | |
3613 } | |
3614 } | |
3615 at = parseType(&ai); | |
3616 if (!ai) | |
3617 error("no identifier for declarator %s", at.toChars()); | |
3618 Larg: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3619 auto a = new Parameter(storageClass, at, ai, null); |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
3620 arguments.push(a); |
0 | 3621 if (token.value == TOK.TOKcomma) |
3622 { nextToken(); | |
3623 continue; | |
3624 } | |
3625 break; | |
3626 } | |
3627 check(TOK.TOKsemicolon); | |
3628 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3629 Expression aggr = parseExpression(); |
0 | 3630 if (token.value == TOK.TOKslice && arguments.dim == 1) |
3631 { | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
3632 auto a = arguments[0]; |
0 | 3633 delete arguments; |
3634 nextToken(); | |
3635 Expression upr = parseExpression(); | |
3636 check(TOK.TOKrparen); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3637 auto body_ = parseStatement(cast(ParseStatementFlags)0); |
0 | 3638 s = new ForeachRangeStatement(loc, op, a, aggr, upr, body_); |
3639 } | |
3640 else | |
3641 { | |
3642 check(TOK.TOKrparen); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3643 auto body_ = parseStatement(cast(ParseStatementFlags)0); |
0 | 3644 s = new ForeachStatement(loc, op, arguments, aggr, body_); |
3645 } | |
3646 break; | |
3647 } | |
3648 | |
3649 case TOK.TOKif: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3650 { Parameter arg = null; |
0 | 3651 Expression condition2; |
3652 Statement ifbody2; | |
3653 Statement elsebody2; | |
3654 | |
3655 nextToken(); | |
3656 check(TOK.TOKlparen); | |
3657 | |
3658 if (token.value == TOK.TOKauto) | |
3659 { | |
3660 nextToken(); | |
3661 if (token.value == TOK.TOKidentifier) | |
3662 { | |
3663 Token *tt = peek(&token); | |
3664 if (tt.value == TOK.TOKassign) | |
3665 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3666 arg = new Parameter(STC.STCundefined, null, token.ident, null); |
0 | 3667 nextToken(); |
3668 nextToken(); | |
3669 } | |
3670 else | |
3671 { error("= expected following auto identifier"); | |
3672 goto Lerror; | |
3673 } | |
3674 } | |
3675 else | |
3676 { error("identifier expected following auto"); | |
3677 goto Lerror; | |
3678 } | |
3679 } | |
3680 else if (isDeclaration(&token, 2, TOK.TOKassign, null)) | |
3681 { | |
3682 Type at; | |
3683 Identifier ai; | |
3684 | |
3685 at = parseType(&ai); | |
3686 check(TOK.TOKassign); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3687 arg = new Parameter(STC.STCundefined, at, ai, null); |
0 | 3688 } |
3689 | |
3690 // Check for " ident;" | |
3691 else if (token.value == TOK.TOKidentifier) | |
3692 { | |
3693 Token *tt = peek(&token); | |
3694 if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon) | |
3695 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
3696 arg = new Parameter(STC.STCundefined, null, token.ident, null); |
0 | 3697 nextToken(); |
3698 nextToken(); | |
3699 if (1 || !global.params.useDeprecated) | |
3700 error("if (v; e) is deprecated, use if (auto v = e)"); | |
3701 } | |
3702 } | |
3703 | |
3704 condition2 = parseExpression(); | |
3705 check(TOK.TOKrparen); | |
3706 ifbody2 = parseStatement(ParseStatementFlags.PSscope); | |
3707 if (token.value == TOK.TOKelse) | |
3708 { | |
3709 nextToken(); | |
3710 elsebody2 = parseStatement(ParseStatementFlags.PSscope); | |
3711 } | |
3712 else | |
3713 elsebody2 = null; | |
3714 s = new IfStatement(loc, arg, condition2, ifbody2, elsebody2); | |
3715 break; | |
3716 } | |
3717 | |
3718 case TOK.TOKscope: | |
3719 if (peek(&token).value != TOK.TOKlparen) | |
3720 goto Ldeclaration; // scope used as storage class | |
3721 nextToken(); | |
3722 check(TOK.TOKlparen); | |
3723 if (token.value != TOK.TOKidentifier) | |
3724 { error("scope identifier expected"); | |
3725 goto Lerror; | |
3726 } | |
3727 else | |
3728 { TOK tt = TOK.TOKon_scope_exit; | |
3729 Identifier id = token.ident; | |
3730 | |
3731 if (id == Id.exit) | |
3732 tt = TOK.TOKon_scope_exit; | |
3733 else if (id == Id.failure) | |
3734 tt = TOK.TOKon_scope_failure; | |
3735 else if (id == Id.success) | |
3736 tt = TOK.TOKon_scope_success; | |
3737 else | |
3738 error("valid scope identifiers are exit, failure, or success, not %s", id.toChars()); | |
3739 nextToken(); | |
3740 check(TOK.TOKrparen); | |
3741 Statement st = parseStatement(ParseStatementFlags.PScurlyscope); | |
3742 s = new OnScopeStatement(loc, tt, st); | |
3743 break; | |
3744 } | |
3745 | |
3746 case TOK.TOKdebug: | |
3747 nextToken(); | |
3748 condition = parseDebugCondition(); | |
3749 goto Lcondition; | |
3750 | |
3751 case TOK.TOKversion: | |
3752 nextToken(); | |
3753 condition = parseVersionCondition(); | |
3754 goto Lcondition; | |
3755 | |
3756 Lcondition: | |
3757 ifbody = parseStatement(cast(ParseStatementFlags)0 /*ParseStatementFlags.PSsemi*/); | |
3758 elsebody = null; | |
3759 if (token.value == TOK.TOKelse) | |
3760 { | |
3761 nextToken(); | |
3762 elsebody = parseStatement(cast(ParseStatementFlags)0 /*ParseStatementFlags.PSsemi*/); | |
3763 } | |
3764 s = new ConditionalStatement(loc, condition, ifbody, elsebody); | |
3765 break; | |
3766 | |
3767 case TOK.TOKpragma: | |
3768 { Identifier ident; | |
3769 Expressions args = null; | |
3770 Statement body_; | |
3771 | |
3772 nextToken(); | |
3773 check(TOK.TOKlparen); | |
3774 if (token.value != TOK.TOKidentifier) | |
3775 { error("pragma(identifier expected"); | |
3776 goto Lerror; | |
3777 } | |
3778 ident = token.ident; | |
3779 nextToken(); | |
3780 if (token.value == TOK.TOKcomma && peekNext() != TOK.TOKrparen) | |
3781 args = parseArguments(); // pragma(identifier, args...); | |
3782 else | |
3783 check(TOK.TOKrparen); // pragma(identifier); | |
3784 if (token.value == TOK.TOKsemicolon) | |
3785 { nextToken(); | |
3786 body_ = null; | |
3787 } | |
3788 else | |
3789 body_ = parseStatement(ParseStatementFlags.PSsemi); | |
3790 s = new PragmaStatement(loc, ident, args, body_); | |
3791 break; | |
3792 } | |
3793 | |
3794 case TOK.TOKswitch: | |
3795 isfinal = false; | |
3796 goto Lswitch; | |
3797 | |
3798 Lswitch: | |
3799 { | |
3800 nextToken(); | |
3801 check(TOK.TOKlparen); | |
3802 Expression condition2 = parseExpression(); | |
3803 check(TOK.TOKrparen); | |
3804 Statement body_ = parseStatement(ParseStatementFlags.PSscope); | |
3805 s = new SwitchStatement(loc, condition2, body_, isfinal); | |
3806 break; | |
3807 } | |
3808 | |
3809 case TOK.TOKcase: | |
3810 { Expression exp; | |
3811 Statements statements; | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
3812 scope cases = new Expressions(); // array of Expression's |
0 | 3813 Expression last = null; |
3814 | |
3815 while (1) | |
3816 { | |
3817 nextToken(); | |
3818 exp = parseAssignExp(); | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
3819 cases.push(exp); |
0 | 3820 if (token.value != TOK.TOKcomma) |
3821 break; | |
3822 } | |
3823 check(TOK.TOKcolon); | |
3824 | |
3825 version (DMDV2) { | |
3826 /* case exp: .. case last: | |
3827 */ | |
3828 if (token.value == TOK.TOKslice) | |
3829 { | |
3830 if (cases.dim > 1) | |
3831 error("only one case allowed for start of case range"); | |
3832 nextToken(); | |
3833 check(TOK.TOKcase); | |
3834 last = parseAssignExp(); | |
3835 check(TOK.TOKcolon); | |
3836 } | |
3837 } | |
3838 | |
3839 statements = new Statements(); | |
3840 while (token.value != TOK.TOKcase && | |
3841 token.value != TOK.TOKdefault && | |
79 | 3842 token.value != TOKeof && |
0 | 3843 token.value != TOK.TOKrcurly) |
3844 { | |
122
c77e9f4f1793
Statements -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
3845 statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); |
0 | 3846 } |
3847 s = new CompoundStatement(loc, statements); | |
3848 s = new ScopeStatement(loc, s); | |
3849 | |
3850 ///version (DMDV2) { | |
3851 if (last) | |
3852 { | |
3853 s = new CaseRangeStatement(loc, exp, last, s); | |
3854 } | |
3855 else | |
3856 ///} | |
3857 { | |
3858 // Keep cases in order by building the case statements backwards | |
3859 for (int i = cases.dim; i; i--) | |
3860 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
3861 exp = cases[i - 1]; |
0 | 3862 s = new CaseStatement(loc, exp, s); |
3863 } | |
3864 } | |
3865 break; | |
3866 } | |
3867 | |
3868 case TOK.TOKdefault: | |
3869 { | |
3870 Statements statements; | |
3871 | |
3872 nextToken(); | |
3873 check(TOK.TOKcolon); | |
3874 | |
3875 statements = new Statements(); | |
3876 while (token.value != TOK.TOKcase && | |
3877 token.value != TOK.TOKdefault && | |
79 | 3878 token.value != TOKeof && |
0 | 3879 token.value != TOK.TOKrcurly) |
3880 { | |
122
c77e9f4f1793
Statements -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
3881 statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); |
0 | 3882 } |
3883 s = new CompoundStatement(loc, statements); | |
3884 s = new ScopeStatement(loc, s); | |
3885 s = new DefaultStatement(loc, s); | |
3886 break; | |
3887 } | |
3888 | |
3889 case TOK.TOKreturn: | |
3890 { Expression exp; | |
3891 | |
3892 nextToken(); | |
3893 if (token.value == TOK.TOKsemicolon) | |
3894 exp = null; | |
3895 else | |
3896 exp = parseExpression(); | |
3897 check(TOK.TOKsemicolon, "return statement"); | |
3898 s = new ReturnStatement(loc, exp); | |
3899 break; | |
3900 } | |
3901 | |
3902 case TOK.TOKbreak: | |
3903 { Identifier ident; | |
3904 | |
3905 nextToken(); | |
3906 if (token.value == TOK.TOKidentifier) | |
3907 { ident = token.ident; | |
3908 nextToken(); | |
3909 } | |
3910 else | |
3911 ident = null; | |
3912 check(TOK.TOKsemicolon, "break statement"); | |
3913 s = new BreakStatement(loc, ident); | |
3914 break; | |
3915 } | |
3916 | |
3917 case TOK.TOKcontinue: | |
3918 { Identifier ident; | |
3919 | |
3920 nextToken(); | |
3921 if (token.value == TOK.TOKidentifier) | |
3922 { ident = token.ident; | |
3923 nextToken(); | |
3924 } | |
3925 else | |
3926 ident = null; | |
3927 check(TOK.TOKsemicolon, "continue statement"); | |
3928 s = new ContinueStatement(loc, ident); | |
3929 break; | |
3930 } | |
3931 | |
3932 case TOK.TOKgoto: | |
3933 { Identifier ident; | |
3934 | |
3935 nextToken(); | |
3936 if (token.value == TOK.TOKdefault) | |
3937 { | |
3938 nextToken(); | |
3939 s = new GotoDefaultStatement(loc); | |
3940 } | |
3941 else if (token.value == TOK.TOKcase) | |
3942 { | |
3943 Expression exp = null; | |
3944 | |
3945 nextToken(); | |
3946 if (token.value != TOK.TOKsemicolon) | |
3947 exp = parseExpression(); | |
3948 s = new GotoCaseStatement(loc, exp); | |
3949 } | |
3950 else | |
3951 { | |
3952 if (token.value != TOK.TOKidentifier) | |
3953 { error("Identifier expected following goto"); | |
3954 ident = null; | |
3955 } | |
3956 else | |
3957 { ident = token.ident; | |
3958 nextToken(); | |
3959 } | |
3960 s = new GotoStatement(loc, ident); | |
3961 } | |
3962 check(TOK.TOKsemicolon, "goto statement"); | |
3963 break; | |
3964 } | |
3965 | |
3966 case TOK.TOKsynchronized: | |
3967 { Expression exp; | |
3968 Statement body_; | |
3969 | |
3970 nextToken(); | |
3971 if (token.value == TOK.TOKlparen) | |
3972 { | |
3973 nextToken(); | |
3974 exp = parseExpression(); | |
3975 check(TOK.TOKrparen); | |
3976 } | |
3977 else | |
3978 exp = null; | |
3979 body_ = parseStatement(ParseStatementFlags.PSscope); | |
3980 s = new SynchronizedStatement(loc, exp, body_); | |
3981 break; | |
3982 } | |
3983 | |
3984 case TOK.TOKwith: | |
3985 { Expression exp; | |
3986 Statement body_; | |
3987 | |
3988 nextToken(); | |
3989 check(TOK.TOKlparen); | |
3990 exp = parseExpression(); | |
3991 check(TOK.TOKrparen); | |
3992 body_ = parseStatement(ParseStatementFlags.PSscope); | |
3993 s = new WithStatement(loc, exp, body_); | |
3994 break; | |
3995 } | |
3996 | |
3997 case TOK.TOKtry: | |
3998 { Statement body_; | |
3999 Array catches = null; | |
4000 Statement finalbody = null; | |
4001 | |
4002 nextToken(); | |
4003 body_ = parseStatement(ParseStatementFlags.PSscope); | |
4004 while (token.value == TOK.TOKcatch) | |
4005 { | |
4006 Statement handler; | |
4007 Catch c; | |
4008 Type tt; | |
4009 Identifier id; | |
4010 Loc loc2 = this.loc; | |
4011 | |
4012 nextToken(); | |
4013 if (token.value == TOK.TOKlcurly) | |
4014 { | |
4015 tt = null; | |
4016 id = null; | |
4017 } | |
4018 else | |
4019 { | |
4020 check(TOK.TOKlparen); | |
4021 id = null; | |
4022 tt = parseType(&id); | |
4023 check(TOK.TOKrparen); | |
4024 } | |
4025 handler = parseStatement(cast(ParseStatementFlags)0); | |
4026 c = new Catch(loc2, tt, id, handler); | |
4027 if (!catches) | |
4028 catches = new Array(); | |
4029 catches.push(cast(void*)c); | |
4030 } | |
4031 | |
4032 if (token.value == TOK.TOKfinally) | |
4033 { nextToken(); | |
4034 finalbody = parseStatement(cast(ParseStatementFlags)0); | |
4035 } | |
4036 | |
4037 s = body_; | |
4038 if (!catches && !finalbody) | |
4039 error("catch or finally expected following try"); | |
4040 else | |
4041 { if (catches) | |
4042 s = new TryCatchStatement(loc, body_, catches); | |
4043 if (finalbody) | |
4044 s = new TryFinallyStatement(loc, s, finalbody); | |
4045 } | |
4046 break; | |
4047 } | |
4048 | |
4049 case TOK.TOKthrow: | |
4050 { Expression exp; | |
4051 | |
4052 nextToken(); | |
4053 exp = parseExpression(); | |
4054 check(TOK.TOKsemicolon, "throw statement"); | |
4055 s = new ThrowStatement(loc, exp); | |
4056 break; | |
4057 } | |
4058 | |
4059 case TOK.TOKvolatile: | |
4060 nextToken(); | |
4061 s = parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope); | |
4062 version (DMDV2) { | |
4063 if (!global.params.useDeprecated) | |
4064 error("volatile statements deprecated; used synchronized statements instead"); | |
4065 } | |
4066 s = new VolatileStatement(loc, s); | |
4067 break; | |
4068 | |
4069 case TOK.TOKasm: | |
4070 { Statements statements; | |
4071 Identifier label; | |
4072 Loc labelloc; | |
4073 Token* toklist; | |
4074 Token** ptoklist; | |
4075 | |
4076 // Parse the asm block into a sequence of AsmStatements, | |
4077 // each AsmStatement is one instruction. | |
4078 // Separate out labels. | |
4079 // Defer parsing of AsmStatements until semantic processing. | |
4080 | |
4081 nextToken(); | |
4082 check(TOK.TOKlcurly); | |
4083 toklist = null; | |
4084 ptoklist = &toklist; | |
4085 label = null; | |
4086 statements = new Statements(); | |
4087 while (1) | |
4088 { | |
4089 switch (token.value) | |
4090 { | |
4091 case TOK.TOKidentifier: | |
4092 if (!toklist) | |
4093 { | |
4094 // Look ahead to see if it is a label | |
4095 t = peek(&token); | |
4096 if (t.value == TOK.TOKcolon) | |
4097 { // It's a label | |
4098 label = token.ident; | |
4099 labelloc = this.loc; | |
4100 nextToken(); | |
4101 nextToken(); | |
4102 continue; | |
4103 } | |
4104 } | |
4105 goto Ldefault; | |
4106 | |
4107 case TOK.TOKrcurly: | |
4108 if (toklist || label) | |
4109 { | |
4110 error("asm statements must end in ';'"); | |
4111 } | |
4112 break; | |
4113 | |
4114 case TOK.TOKsemicolon: | |
4115 s = null; | |
4116 if (toklist || label) | |
4117 { // Create AsmStatement from list of tokens we've saved | |
4118 s = new AsmStatement(this.loc, toklist); | |
4119 toklist = null; | |
4120 ptoklist = &toklist; | |
4121 if (label) | |
4122 { | |
4123 s = new LabelStatement(labelloc, label, s); | |
4124 label = null; | |
4125 } | |
122
c77e9f4f1793
Statements -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
4126 statements.push(s); |
0 | 4127 } |
4128 nextToken(); | |
4129 continue; | |
4130 | |
4131 case TOK.TOKeof: | |
4132 /* { */ | |
4133 error("matching '}' expected, not end of file"); | |
4134 break; | |
4135 | |
4136 default: | |
4137 Ldefault: | |
4138 *ptoklist = new Token(); | |
4139 memcpy(*ptoklist, &token, Token.sizeof); | |
4140 ptoklist = &(*ptoklist).next; | |
4141 *ptoklist = null; | |
4142 | |
4143 nextToken(); | |
4144 continue; | |
4145 } | |
4146 break; | |
4147 } | |
4148 s = new CompoundStatement(loc, statements); | |
4149 nextToken(); | |
4150 break; | |
4151 } | |
4152 | |
4153 default: | |
4154 error("found '%s' instead of statement", token.toChars()); | |
4155 goto Lerror; | |
4156 | |
4157 Lerror: | |
4158 while (token.value != TOK.TOKrcurly && | |
4159 token.value != TOK.TOKsemicolon && | |
4160 token.value != TOK.TOKeof) | |
4161 nextToken(); | |
4162 if (token.value == TOK.TOKsemicolon) | |
4163 nextToken(); | |
4164 s = null; | |
4165 break; | |
4166 } | |
4167 | |
4168 return s; | |
4169 } | |
4170 | |
4171 /***************************************** | |
4172 * Parse initializer for variable declaration. | |
4173 */ | |
4174 Initializer parseInitializer() | |
4175 { | |
4176 StructInitializer is_; | |
4177 ArrayInitializer ia; | |
4178 ExpInitializer ie; | |
4179 Expression e; | |
4180 Identifier id; | |
4181 Initializer value; | |
4182 int comma; | |
4183 Loc loc = this.loc; | |
4184 Token* t; | |
4185 int braces; | |
4186 int brackets; | |
4187 | |
4188 switch (token.value) | |
4189 { | |
4190 case TOK.TOKlcurly: | |
4191 /* Scan ahead to see if it is a struct initializer or | |
4192 * a function literal. | |
4193 * If it contains a ';', it is a function literal. | |
4194 * Treat { } as a struct initializer. | |
4195 */ | |
4196 braces = 1; | |
4197 for (t = peek(&token); 1; t = peek(t)) | |
4198 { | |
4199 switch (t.value) | |
4200 { | |
4201 case TOK.TOKsemicolon: | |
4202 case TOK.TOKreturn: | |
4203 goto Lexpression; | |
4204 | |
4205 case TOK.TOKlcurly: | |
4206 braces++; | |
4207 continue; | |
4208 | |
4209 case TOK.TOKrcurly: | |
4210 if (--braces == 0) | |
4211 break; | |
4212 continue; | |
4213 | |
4214 case TOK.TOKeof: | |
4215 break; | |
4216 | |
4217 default: | |
4218 continue; | |
4219 } | |
4220 break; | |
4221 } | |
4222 | |
4223 is_ = new StructInitializer(loc); | |
4224 nextToken(); | |
4225 comma = 0; | |
4226 while (1) | |
4227 { | |
4228 switch (token.value) | |
4229 { | |
4230 case TOK.TOKidentifier: | |
4231 if (comma == 1) | |
4232 error("comma expected separating field initializers"); | |
4233 t = peek(&token); | |
4234 if (t.value == TOK.TOKcolon) | |
4235 { | |
4236 id = token.ident; | |
4237 nextToken(); | |
4238 nextToken(); // skip over ':' | |
4239 } | |
4240 else | |
4241 { | |
4242 id = null; | |
4243 } | |
4244 value = parseInitializer(); | |
4245 is_.addInit(id, value); | |
4246 comma = 1; | |
4247 continue; | |
4248 | |
4249 case TOK.TOKcomma: | |
4250 nextToken(); | |
4251 comma = 2; | |
4252 continue; | |
4253 | |
4254 case TOK.TOKrcurly: // allow trailing comma's | |
4255 nextToken(); | |
4256 break; | |
4257 | |
4258 case TOK.TOKeof: | |
4259 error("found EOF instead of initializer"); | |
4260 break; | |
4261 | |
4262 default: | |
4263 value = parseInitializer(); | |
4264 is_.addInit(null, value); | |
4265 comma = 1; | |
4266 continue; | |
4267 //error("found '%s' instead of field initializer", token.toChars()); | |
4268 //break; | |
4269 } | |
4270 break; | |
4271 } | |
4272 return is_; | |
4273 | |
4274 case TOK.TOKlbracket: | |
4275 /* Scan ahead to see if it is an array initializer or | |
4276 * an expression. | |
4277 * If it ends with a ';' ',' or '}', it is an array initializer. | |
4278 */ | |
4279 brackets = 1; | |
4280 for (t = peek(&token); 1; t = peek(t)) | |
4281 { | |
4282 switch (t.value) | |
4283 { | |
4284 case TOK.TOKlbracket: | |
4285 brackets++; | |
4286 continue; | |
4287 | |
4288 case TOK.TOKrbracket: | |
4289 if (--brackets == 0) | |
4290 { | |
4291 t = peek(t); | |
4292 if (t.value != TOK.TOKsemicolon && | |
4293 t.value != TOK.TOKcomma && | |
4294 t.value != TOK.TOKrcurly) | |
4295 goto Lexpression; | |
4296 break; | |
4297 } | |
4298 continue; | |
4299 | |
4300 case TOK.TOKeof: | |
4301 break; | |
4302 | |
4303 default: | |
4304 continue; | |
4305 } | |
4306 break; | |
4307 } | |
4308 | |
4309 ia = new ArrayInitializer(loc); | |
4310 nextToken(); | |
4311 comma = 0; | |
4312 while (true) | |
4313 { | |
4314 switch (token.value) | |
4315 { | |
4316 default: | |
4317 if (comma == 1) | |
4318 { | |
4319 error("comma expected separating array initializers, not %s", token.toChars()); | |
4320 nextToken(); | |
4321 break; | |
4322 } | |
4323 e = parseAssignExp(); | |
4324 if (!e) | |
4325 break; | |
4326 if (token.value == TOK.TOKcolon) | |
4327 { | |
4328 nextToken(); | |
4329 value = parseInitializer(); | |
4330 } | |
4331 else | |
4332 { value = new ExpInitializer(e.loc, e); | |
4333 e = null; | |
4334 } | |
4335 ia.addInit(e, value); | |
4336 comma = 1; | |
4337 continue; | |
4338 | |
4339 case TOK.TOKlcurly: | |
4340 case TOK.TOKlbracket: | |
4341 if (comma == 1) | |
4342 error("comma expected separating array initializers, not %s", token.toChars()); | |
4343 value = parseInitializer(); | |
4344 ia.addInit(null, value); | |
4345 comma = 1; | |
4346 continue; | |
4347 | |
4348 case TOK.TOKcomma: | |
4349 nextToken(); | |
4350 comma = 2; | |
4351 continue; | |
4352 | |
4353 case TOK.TOKrbracket: // allow trailing comma's | |
4354 nextToken(); | |
4355 break; | |
4356 | |
4357 case TOK.TOKeof: | |
4358 error("found '%s' instead of array initializer", token.toChars()); | |
4359 break; | |
4360 } | |
4361 break; | |
4362 } | |
4363 return ia; | |
4364 | |
4365 case TOK.TOKvoid: | |
4366 t = peek(&token); | |
4367 if (t.value == TOK.TOKsemicolon || t.value == TOK.TOKcomma) | |
4368 { | |
4369 nextToken(); | |
4370 return new VoidInitializer(loc); | |
4371 } | |
4372 goto Lexpression; | |
4373 | |
4374 default: | |
4375 Lexpression: | |
4376 e = parseAssignExp(); | |
4377 ie = new ExpInitializer(loc, e); | |
4378 return ie; | |
4379 } | |
4380 } | |
4381 | |
4382 /***************************************** | |
4383 * Parses default argument initializer expression that is an assign expression, | |
4384 * with special handling for __FILE__ and __LINE__. | |
4385 */ | |
4386 version (DMDV2) { | |
4387 Expression parseDefaultInitExp() | |
4388 { | |
4389 if (token.value == TOK.TOKfile || | |
4390 token.value == TOK.TOKline) | |
4391 { | |
4392 Token* t = peek(&token); | |
4393 if (t.value == TOK.TOKcomma || t.value == TOK.TOKrparen) | |
4394 { | |
4395 Expression e; | |
4396 | |
4397 if (token.value == TOK.TOKfile) | |
4398 e = new FileInitExp(loc); | |
4399 else | |
4400 e = new LineInitExp(loc); | |
4401 nextToken(); | |
4402 return e; | |
4403 } | |
4404 } | |
4405 | |
4406 Expression e = parseAssignExp(); | |
4407 return e; | |
4408 } | |
4409 } | |
4410 void check(Loc loc, TOK value) | |
4411 { | |
4412 if (token.value != value) | |
4413 error(loc, "found '%s' when expecting '%s'", token.toChars(), Token.toChars(value)); | |
4414 nextToken(); | |
4415 } | |
4416 | |
4417 void check(TOK value) | |
4418 { | |
4419 check(loc, value); | |
4420 } | |
4421 | |
4422 void check(TOK value, string string_) | |
4423 { | |
4424 if (token.value != value) { | |
4425 error("found '%s' when expecting '%s' following '%s'", token.toChars(), Token.toChars(value), string_); | |
4426 } | |
4427 nextToken(); | |
4428 } | |
4429 | |
4430 /************************************ | |
4431 * Determine if the scanner is sitting on the start of a declaration. | |
4432 * Input: | |
4433 * needId 0 no identifier | |
4434 * 1 identifier optional | |
4435 * 2 must have identifier | |
4436 * Output: | |
4437 * if *pt is not null, it is set to the ending token, which would be endtok | |
4438 */ | |
4439 | |
4440 bool isDeclaration(Token* t, int needId, TOK endtok, Token** pt) | |
4441 { | |
4442 //printf("isDeclaration(needId = %d)\n", needId); | |
4443 int haveId = 0; | |
4444 | |
4445 version (DMDV2) { | |
4446 if ((t.value == TOK.TOKconst || | |
4447 t.value == TOK.TOKinvariant || | |
4448 t.value == TOK.TOKimmutable || | |
135 | 4449 t.value == TOKwild || |
0 | 4450 t.value == TOK.TOKshared) && |
4451 peek(t).value != TOK.TOKlparen) | |
4452 { | |
4453 /* const type | |
4454 * immutable type | |
4455 * shared type | |
135 | 4456 * wild type |
0 | 4457 */ |
4458 t = peek(t); | |
4459 } | |
4460 } | |
4461 | |
4462 if (!isBasicType(&t)) | |
4463 { | |
4464 goto Lisnot; | |
4465 } | |
4466 if (!isDeclarator(&t, &haveId, endtok)) | |
4467 goto Lisnot; | |
4468 if ( needId == 1 || | |
4469 (needId == 0 && !haveId) || | |
4470 (needId == 2 && haveId)) | |
4471 { | |
4472 if (pt) | |
4473 *pt = t; | |
4474 goto Lis; | |
4475 } | |
4476 else | |
4477 goto Lisnot; | |
4478 | |
4479 Lis: | |
4480 //printf("\tis declaration, t = %s\n", t.toChars()); | |
4481 return true; | |
4482 | |
4483 Lisnot: | |
4484 //printf("\tis not declaration\n"); | |
4485 return false; | |
4486 } | |
4487 | |
4488 bool isBasicType(Token** pt) | |
4489 { | |
4490 // This code parallels parseBasicType() | |
4491 Token* t = *pt; | |
4492 Token* t2; | |
4493 int parens; | |
4494 int haveId = 0; | |
4495 | |
4496 switch (t.value) | |
4497 { | |
4498 case TOKwchar: | |
4499 case TOKdchar: | |
4500 case TOKbit: | |
4501 case TOKbool: | |
4502 case TOKchar: | |
4503 case TOKint8: | |
4504 case TOKuns8: | |
4505 case TOKint16: | |
4506 case TOKuns16: | |
4507 case TOKint32: | |
4508 case TOKuns32: | |
4509 case TOKint64: | |
4510 case TOKuns64: | |
4511 case TOKfloat32: | |
4512 case TOKfloat64: | |
4513 case TOKfloat80: | |
4514 case TOKimaginary32: | |
4515 case TOKimaginary64: | |
4516 case TOKimaginary80: | |
4517 case TOKcomplex32: | |
4518 case TOKcomplex64: | |
4519 case TOKcomplex80: | |
4520 case TOKvoid: | |
4521 t = peek(t); | |
4522 break; | |
4523 | |
4524 case TOK.TOKidentifier: | |
4525 L5: | |
4526 t = peek(t); | |
4527 if (t.value == TOK.TOKnot) | |
4528 { | |
4529 goto L4; | |
4530 } | |
4531 goto L3; | |
4532 while (1) | |
4533 { | |
4534 L2: | |
4535 t = peek(t); | |
4536 L3: | |
4537 if (t.value == TOK.TOKdot) | |
4538 { | |
4539 Ldot: | |
4540 t = peek(t); | |
4541 if (t.value != TOK.TOKidentifier) | |
4542 goto Lfalse; | |
4543 t = peek(t); | |
4544 if (t.value != TOK.TOKnot) | |
4545 goto L3; | |
4546 L4: | |
4547 /* Seen a ! | |
4548 * Look for: | |
4549 * !( args ), !identifier, etc. | |
4550 */ | |
4551 t = peek(t); | |
4552 switch (t.value) | |
4553 { case TOK.TOKidentifier: | |
4554 goto L5; | |
4555 case TOK.TOKlparen: | |
4556 if (!skipParens(t, &t)) | |
4557 goto Lfalse; | |
4558 break; | |
4559 case TOK.TOKwchar: case TOK.TOKdchar: | |
4560 case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar: | |
4561 case TOK.TOKint8: case TOK.TOKuns8: | |
4562 case TOK.TOKint16: case TOK.TOKuns16: | |
4563 case TOK.TOKint32: case TOK.TOKuns32: | |
4564 case TOK.TOKint64: case TOK.TOKuns64: | |
4565 case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80: | |
4566 case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80: | |
4567 case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80: | |
4568 case TOK.TOKvoid: | |
4569 case TOK.TOKint32v: | |
4570 case TOK.TOKuns32v: | |
4571 case TOK.TOKint64v: | |
4572 case TOK.TOKuns64v: | |
4573 case TOK.TOKfloat32v: | |
4574 case TOK.TOKfloat64v: | |
4575 case TOK.TOKfloat80v: | |
4576 case TOK.TOKimaginary32v: | |
4577 case TOK.TOKimaginary64v: | |
4578 case TOK.TOKimaginary80v: | |
4579 case TOK.TOKnull: | |
4580 case TOK.TOKtrue: | |
4581 case TOK.TOKfalse: | |
4582 case TOK.TOKcharv: | |
4583 case TOK.TOKwcharv: | |
4584 case TOK.TOKdcharv: | |
4585 case TOK.TOKstring: | |
4586 case TOK.TOKfile: | |
4587 case TOK.TOKline: | |
4588 goto L2; | |
4589 default: | |
4590 goto Lfalse; | |
4591 } | |
4592 } | |
4593 else | |
4594 break; | |
4595 } | |
4596 break; | |
4597 | |
4598 case TOK.TOKdot: | |
4599 goto Ldot; | |
4600 | |
4601 case TOK.TOKtypeof: | |
4602 /* typeof(exp).identifier... | |
4603 */ | |
4604 t = peek(t); | |
4605 if (t.value != TOK.TOKlparen) | |
4606 goto Lfalse; | |
4607 if (!skipParens(t, &t)) | |
4608 goto Lfalse; | |
4609 goto L2; | |
4610 | |
4611 case TOK.TOKconst: | |
4612 case TOK.TOKinvariant: | |
4613 case TOK.TOKimmutable: | |
4614 case TOK.TOKshared: | |
135 | 4615 case TOKwild: |
4616 // const(type) or immutable(type) or shared(type) or wild(type) | |
0 | 4617 t = peek(t); |
4618 if (t.value != TOK.TOKlparen) | |
4619 goto Lfalse; | |
4620 t = peek(t); | |
4621 if (!isDeclaration(t, 0, TOK.TOKrparen, &t)) | |
4622 { | |
4623 goto Lfalse; | |
4624 } | |
4625 t = peek(t); | |
4626 break; | |
4627 | |
4628 default: | |
4629 goto Lfalse; | |
4630 } | |
4631 *pt = t; | |
4632 //printf("is\n"); | |
4633 return true; | |
4634 | |
4635 Lfalse: | |
4636 //printf("is not\n"); | |
4637 return false; | |
4638 } | |
4639 | |
4640 bool isDeclarator(Token** pt, int* haveId, TOK endtok) | |
4641 { | |
4642 // This code parallels parseDeclarator() | |
4643 Token* t = *pt; | |
4644 bool parens; | |
4645 | |
4646 //printf("Parser.isDeclarator()\n"); | |
4647 //t.print(); | |
4648 if (t.value == TOK.TOKassign) | |
4649 return false; | |
4650 | |
4651 while (true) | |
4652 { | |
4653 parens = false; | |
4654 switch (t.value) | |
4655 { | |
4656 case TOK.TOKmul: | |
4657 //case TOKand: | |
4658 t = peek(t); | |
4659 continue; | |
4660 | |
4661 case TOK.TOKlbracket: | |
4662 t = peek(t); | |
4663 if (t.value == TOK.TOKrbracket) | |
4664 { | |
4665 t = peek(t); | |
4666 } | |
79 | 4667 else if (t.value == TOKnew && peek(t).value == TOKrbracket) |
4668 { | |
4669 t = peek(t); | |
4670 t = peek(t); | |
4671 } | |
0 | 4672 else if (isDeclaration(t, 0, TOK.TOKrbracket, &t)) |
4673 { | |
4674 // It's an associative array declaration | |
4675 t = peek(t); | |
4676 } | |
4677 else | |
4678 { | |
4679 // [ expression ] | |
4680 // [ expression .. expression ] | |
4681 if (!isExpression(&t)) | |
4682 return false; | |
4683 if (t.value == TOK.TOKslice) | |
4684 { | |
4685 t = peek(t); | |
4686 if (!isExpression(&t)) | |
4687 return false; | |
4688 } | |
4689 if (t.value != TOK.TOKrbracket) | |
4690 return false; | |
4691 t = peek(t); | |
4692 } | |
4693 continue; | |
4694 | |
4695 case TOK.TOKidentifier: | |
4696 if (*haveId) | |
4697 return false; | |
4698 *haveId = true; | |
4699 t = peek(t); | |
4700 break; | |
4701 | |
4702 case TOK.TOKlparen: | |
4703 t = peek(t); | |
4704 | |
4705 if (t.value == TOK.TOKrparen) | |
4706 return false; // () is not a declarator | |
4707 | |
4708 /* Regard ( identifier ) as not a declarator | |
4709 * BUG: what about ( *identifier ) in | |
4710 * f(*p)(x); | |
4711 * where f is a class instance with overloaded () ? | |
4712 * Should we just disallow C-style function pointer declarations? | |
4713 */ | |
4714 if (t.value == TOK.TOKidentifier) | |
4715 { | |
4716 Token *t2 = peek(t); | |
4717 if (t2.value == TOK.TOKrparen) | |
4718 return false; | |
4719 } | |
4720 | |
4721 if (!isDeclarator(&t, haveId, TOK.TOKrparen)) | |
4722 return false; | |
4723 t = peek(t); | |
4724 parens = true; | |
4725 break; | |
4726 | |
4727 case TOK.TOKdelegate: | |
4728 case TOK.TOKfunction: | |
4729 t = peek(t); | |
4730 if (!isParameters(&t)) | |
4731 return false; | |
4732 continue; | |
4733 default: | |
4734 break; /// | |
4735 } | |
4736 break; | |
4737 } | |
4738 | |
4739 while (1) | |
4740 { | |
4741 switch (t.value) | |
4742 { | |
4743 version (CARRAYDECL) { | |
4744 case TOK.TOKlbracket: | |
4745 parens = false; | |
4746 t = peek(t); | |
4747 if (t.value == TOK.TOKrbracket) | |
4748 { | |
4749 t = peek(t); | |
4750 } | |
4751 else if (isDeclaration(t, 0, TOKrbracket, &t)) | |
4752 { | |
4753 // It's an associative array declaration | |
4754 t = peek(t); | |
4755 } | |
4756 else | |
4757 { | |
4758 // [ expression ] | |
4759 if (!isExpression(&t)) | |
4760 return false; | |
4761 if (t.value != TOK.TOKrbracket) | |
4762 return false; | |
4763 t = peek(t); | |
4764 } | |
4765 continue; | |
4766 } | |
4767 | |
4768 case TOK.TOKlparen: | |
4769 parens = false; | |
4770 if (!isParameters(&t)) | |
4771 return false; | |
4772 version (DMDV2) { | |
4773 while (true) | |
4774 { | |
4775 switch (t.value) | |
4776 { | |
4777 case TOK.TOKconst: | |
4778 case TOK.TOKinvariant: | |
4779 case TOK.TOKimmutable: | |
4780 case TOK.TOKshared: | |
135 | 4781 case TOKwild: |
0 | 4782 case TOK.TOKpure: |
4783 case TOK.TOKnothrow: | |
4784 t = peek(t); | |
4785 continue; | |
4786 case TOK.TOKat: | |
4787 t = peek(t); // skip '@' | |
4788 t = peek(t); // skip identifier | |
4789 continue; | |
4790 default: | |
4791 break; | |
4792 } | |
4793 break; | |
4794 } | |
4795 } | |
4796 continue; | |
4797 | |
4798 // Valid tokens that follow a declaration | |
4799 case TOK.TOKrparen: | |
4800 case TOK.TOKrbracket: | |
4801 case TOK.TOKassign: | |
4802 case TOK.TOKcomma: | |
4803 case TOK.TOKsemicolon: | |
4804 case TOK.TOKlcurly: | |
4805 case TOK.TOKin: | |
4806 // The !parens is to disallow unnecessary parentheses | |
4807 if (!parens && (endtok == TOK.TOKreserved || endtok == t.value)) | |
4808 { | |
4809 *pt = t; | |
4810 return true; | |
4811 } | |
4812 return false; | |
4813 | |
4814 default: | |
4815 return false; | |
4816 } | |
4817 } | |
4818 } | |
4819 | |
4820 bool isParameters(Token** pt) | |
4821 { | |
4822 // This code parallels parseParameters() | |
4823 Token* t = *pt; | |
4824 | |
4825 //printf("isParameters()\n"); | |
4826 if (t.value != TOKlparen) | |
4827 return false; | |
4828 | |
4829 t = peek(t); | |
4830 for (;1; t = peek(t)) | |
4831 { | |
4832 L1: | |
4833 switch (t.value) | |
4834 { | |
4835 case TOKrparen: | |
4836 break; | |
4837 | |
4838 case TOKdotdotdot: | |
4839 t = peek(t); | |
4840 break; | |
4841 | |
135 | 4842 version(D1INOUT) { |
4843 case TOKinout: | |
4844 } | |
0 | 4845 case TOKin: |
4846 case TOKout: | |
4847 case TOKref: | |
4848 case TOKlazy: | |
4849 case TOKfinal: | |
135 | 4850 case TOKauto: |
0 | 4851 continue; |
4852 | |
4853 case TOKconst: | |
4854 case TOKinvariant: | |
4855 case TOKimmutable: | |
4856 case TOKshared: | |
135 | 4857 case TOKwild: |
0 | 4858 t = peek(t); |
4859 if (t.value == TOKlparen) | |
4860 { | |
4861 t = peek(t); | |
4862 if (!isDeclaration(t, 0, TOKrparen, &t)) | |
4863 return false; | |
4864 t = peek(t); // skip past closing ')' | |
4865 goto L2; | |
4866 } | |
4867 goto L1; | |
4868 | |
4869 static if (false) { | |
4870 case TOKstatic: | |
4871 continue; | |
4872 case TOKauto: | |
4873 case TOKalias: | |
4874 t = peek(t); | |
4875 if (t.value == TOKidentifier) | |
4876 t = peek(t); | |
4877 if (t.value == TOKassign) | |
4878 { t = peek(t); | |
4879 if (!isExpression(&t)) | |
4880 return false; | |
4881 } | |
4882 goto L3; | |
4883 } | |
4884 | |
4885 default: | |
4886 { | |
4887 if (!isBasicType(&t)) | |
4888 return false; | |
4889 L2: | |
4890 int tmp = false; | |
4891 if (t.value != TOKdotdotdot && | |
4892 !isDeclarator(&t, &tmp, TOKreserved)) | |
4893 return false; | |
4894 if (t.value == TOKassign) | |
4895 { | |
4896 t = peek(t); | |
4897 if (!isExpression(&t)) | |
4898 return false; | |
4899 } | |
4900 if (t.value == TOKdotdotdot) | |
4901 { | |
4902 t = peek(t); | |
4903 break; | |
4904 } | |
4905 } | |
4906 L3: | |
4907 if (t.value == TOKcomma) | |
4908 { | |
4909 continue; | |
4910 } | |
4911 break; | |
4912 } | |
4913 break; | |
4914 } | |
4915 | |
4916 if (t.value != TOKrparen) | |
4917 return false; | |
4918 | |
4919 t = peek(t); | |
4920 *pt = t; | |
4921 return true; | |
4922 } | |
4923 | |
4924 bool isExpression(Token** pt) | |
4925 { | |
4926 // This is supposed to determine if something is an expression. | |
4927 // What it actually does is scan until a closing right bracket | |
4928 // is found. | |
4929 | |
4930 Token* t = *pt; | |
4931 int brnest = 0; | |
4932 int panest = 0; | |
4933 int curlynest = 0; | |
4934 | |
4935 for (;; t = peek(t)) | |
4936 { | |
4937 switch (t.value) | |
4938 { | |
4939 case TOKlbracket: | |
4940 brnest++; | |
4941 continue; | |
4942 | |
4943 case TOKrbracket: | |
4944 if (--brnest >= 0) | |
4945 continue; | |
4946 break; | |
4947 | |
4948 case TOKlparen: | |
4949 panest++; | |
4950 continue; | |
4951 | |
4952 case TOKcomma: | |
4953 if (brnest || panest) | |
4954 continue; | |
4955 break; | |
4956 | |
4957 case TOKrparen: | |
4958 if (--panest >= 0) | |
4959 continue; | |
4960 break; | |
4961 | |
4962 case TOKlcurly: | |
4963 curlynest++; | |
4964 continue; | |
4965 | |
4966 case TOKrcurly: | |
4967 if (--curlynest >= 0) | |
4968 continue; | |
4969 return false; | |
4970 | |
4971 case TOKslice: | |
4972 if (brnest) | |
4973 continue; | |
4974 break; | |
4975 | |
4976 case TOKsemicolon: | |
4977 if (curlynest) | |
4978 continue; | |
4979 return false; | |
4980 | |
4981 case TOKeof: | |
4982 return false; | |
4983 | |
4984 default: | |
4985 continue; | |
4986 } | |
4987 break; | |
4988 } | |
4989 | |
4990 *pt = t; | |
4991 return true; | |
4992 } | |
4993 | |
4994 int isTemplateInstance(Token t, Token* pt) | |
4995 { | |
4996 assert(false); | |
4997 } | |
4998 | |
4999 /******************************************* | |
5000 * Skip parens, brackets. | |
5001 * Input: | |
5002 * t is on opening ( | |
5003 * Output: | |
5004 * *pt is set to closing token, which is ')' on success | |
5005 * Returns: | |
5006 * !=0 successful | |
5007 * 0 some parsing error | |
5008 */ | |
5009 bool skipParens(Token* t, Token** pt) | |
5010 { | |
5011 int parens = 0; | |
5012 | |
5013 while (1) | |
5014 { | |
5015 switch (t.value) | |
5016 { | |
5017 case TOKlparen: | |
5018 parens++; | |
5019 break; | |
5020 | |
5021 case TOKrparen: | |
5022 parens--; | |
5023 if (parens < 0) | |
5024 goto Lfalse; | |
5025 if (parens == 0) | |
5026 goto Ldone; | |
5027 break; | |
5028 | |
5029 case TOKeof: | |
5030 case TOKsemicolon: | |
5031 goto Lfalse; | |
5032 | |
5033 default: | |
5034 break; | |
5035 } | |
5036 t = peek(t); | |
5037 } | |
5038 | |
5039 Ldone: | |
5040 if (*pt) | |
5041 *pt = t; | |
5042 return true; | |
5043 | |
5044 Lfalse: | |
5045 return false; | |
5046 } | |
5047 | |
5048 Expression parseExpression() | |
5049 { | |
5050 Expression e; | |
5051 Expression e2; | |
5052 Loc loc = this.loc; | |
5053 | |
5054 //printf("Parser.parseExpression() loc = %d\n", loc.linnum); | |
5055 e = parseAssignExp(); | |
5056 while (token.value == TOK.TOKcomma) | |
5057 { | |
5058 nextToken(); | |
5059 e2 = parseAssignExp(); | |
5060 e = new CommaExp(loc, e, e2); | |
5061 loc = this.loc; | |
5062 } | |
5063 return e; | |
5064 } | |
5065 | |
5066 Expression parsePrimaryExp() | |
5067 { | |
5068 Expression e; | |
5069 Type t; | |
5070 Identifier id; | |
5071 TOK save; | |
5072 Loc loc = this.loc; | |
5073 | |
5074 //printf("parsePrimaryExp(): loc = %d\n", loc.linnum); | |
5075 switch (token.value) | |
5076 { | |
5077 case TOK.TOKidentifier: | |
5078 id = token.ident; | |
5079 nextToken(); | |
5080 if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis) | |
5081 { // identifier!(template-argument-list) | |
5082 TemplateInstance tempinst; | |
5083 | |
5084 tempinst = new TemplateInstance(loc, id); | |
5085 nextToken(); | |
5086 if (token.value == TOK.TOKlparen) | |
5087 // ident!(template_arguments) | |
5088 tempinst.tiargs = parseTemplateArgumentList(); | |
5089 else | |
5090 // ident!template_argument | |
5091 tempinst.tiargs = parseTemplateArgument(); | |
5092 e = new ScopeExp(loc, tempinst); | |
5093 } | |
5094 else | |
5095 e = new IdentifierExp(loc, id); | |
5096 break; | |
5097 | |
5098 case TOK.TOKdollar: | |
5099 if (!inBrackets) | |
5100 error("'$' is valid only inside [] of index or slice"); | |
5101 e = new DollarExp(loc); | |
5102 nextToken(); | |
5103 break; | |
5104 | |
5105 case TOK.TOKdot: | |
5106 // Signal global scope '.' operator with "" identifier | |
5107 e = new IdentifierExp(loc, Id.empty); | |
5108 break; | |
5109 | |
5110 case TOK.TOKthis: | |
5111 e = new ThisExp(loc); | |
5112 nextToken(); | |
5113 break; | |
5114 | |
5115 case TOK.TOKsuper: | |
5116 e = new SuperExp(loc); | |
5117 nextToken(); | |
5118 break; | |
5119 | |
5120 case TOK.TOKint32v: | |
5121 e = new IntegerExp(loc, token.int32value, Type.tint32); | |
5122 nextToken(); | |
5123 break; | |
5124 | |
5125 case TOK.TOKuns32v: | |
5126 e = new IntegerExp(loc, token.uns32value, Type.tuns32); | |
5127 nextToken(); | |
5128 break; | |
5129 | |
5130 case TOK.TOKint64v: | |
5131 e = new IntegerExp(loc, token.int64value, Type.tint64); | |
5132 nextToken(); | |
5133 break; | |
5134 | |
5135 case TOK.TOKuns64v: | |
5136 e = new IntegerExp(loc, token.uns64value, Type.tuns64); | |
5137 nextToken(); | |
5138 break; | |
5139 | |
5140 case TOK.TOKfloat32v: | |
5141 e = new RealExp(loc, token.float80value, Type.tfloat32); | |
5142 nextToken(); | |
5143 break; | |
5144 | |
5145 case TOK.TOKfloat64v: | |
5146 e = new RealExp(loc, token.float80value, Type.tfloat64); | |
5147 nextToken(); | |
5148 break; | |
5149 | |
5150 case TOK.TOKfloat80v: | |
5151 e = new RealExp(loc, token.float80value, Type.tfloat80); | |
5152 nextToken(); | |
5153 break; | |
5154 | |
5155 case TOK.TOKimaginary32v: | |
5156 e = new RealExp(loc, token.float80value, Type.timaginary32); | |
5157 nextToken(); | |
5158 break; | |
5159 | |
5160 case TOK.TOKimaginary64v: | |
5161 e = new RealExp(loc, token.float80value, Type.timaginary64); | |
5162 nextToken(); | |
5163 break; | |
5164 | |
5165 case TOK.TOKimaginary80v: | |
5166 e = new RealExp(loc, token.float80value, Type.timaginary80); | |
5167 nextToken(); | |
5168 break; | |
5169 | |
5170 case TOK.TOKnull: | |
5171 e = new NullExp(loc); | |
5172 nextToken(); | |
5173 break; | |
5174 | |
5175 version (DMDV2) { | |
5176 case TOK.TOKfile: | |
5177 { | |
5178 string s = loc.filename ? loc.filename : mod.ident.toChars(); | |
5179 e = new StringExp(loc, s, 0); | |
5180 nextToken(); | |
5181 break; | |
5182 } | |
5183 | |
5184 case TOK.TOKline: | |
5185 e = new IntegerExp(loc, loc.linnum, Type.tint32); | |
5186 nextToken(); | |
5187 break; | |
5188 } | |
5189 | |
5190 case TOK.TOKtrue: | |
5191 e = new IntegerExp(loc, 1, Type.tbool); | |
5192 nextToken(); | |
5193 break; | |
5194 | |
5195 case TOK.TOKfalse: | |
5196 e = new IntegerExp(loc, 0, Type.tbool); | |
5197 nextToken(); | |
5198 break; | |
5199 | |
5200 case TOK.TOKcharv: | |
5201 e = new IntegerExp(loc, token.uns32value, Type.tchar); | |
5202 nextToken(); | |
5203 break; | |
5204 | |
5205 case TOK.TOKwcharv: | |
5206 e = new IntegerExp(loc, token.uns32value, Type.twchar); | |
5207 nextToken(); | |
5208 break; | |
5209 | |
5210 case TOK.TOKdcharv: | |
5211 e = new IntegerExp(loc, token.uns32value, Type.tdchar); | |
5212 nextToken(); | |
5213 break; | |
5214 | |
5215 case TOK.TOKstring: | |
5216 { | |
5217 const(char)* s; | |
5218 uint len; | |
5219 ubyte postfix; | |
5220 | |
5221 // cat adjacent strings | |
5222 s = token.ustring; | |
5223 len = token.len; | |
5224 postfix = token.postfix; | |
5225 while (1) | |
5226 { | |
5227 nextToken(); | |
5228 if (token.value == TOK.TOKstring) | |
5229 { uint len1; | |
5230 uint len2; | |
5231 char* s2; | |
5232 | |
5233 if (token.postfix) | |
5234 { if (token.postfix != postfix) | |
5235 error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix); | |
5236 postfix = token.postfix; | |
5237 } | |
5238 | |
5239 len1 = len; | |
5240 len2 = token.len; | |
5241 len = len1 + len2; | |
2 | 5242 s2 = cast(char*)GC.malloc((len + 1) * ubyte.sizeof); |
0 | 5243 memcpy(s2, s, len1 * ubyte.sizeof); |
5244 memcpy(s2 + len1, token.ustring, (len2 + 1) * ubyte.sizeof); | |
5245 s = s2; | |
5246 } | |
5247 else | |
5248 break; | |
5249 } | |
5250 e = new StringExp(loc, assumeUnique(s[0..len]), postfix); | |
5251 break; | |
5252 } | |
5253 | |
5254 case TOK.TOKvoid: t = Type.tvoid; goto LabelX; | |
5255 case TOK.TOKint8: t = Type.tint8; goto LabelX; | |
5256 case TOK.TOKuns8: t = Type.tuns8; goto LabelX; | |
5257 case TOK.TOKint16: t = Type.tint16; goto LabelX; | |
5258 case TOK.TOKuns16: t = Type.tuns16; goto LabelX; | |
5259 case TOK.TOKint32: t = Type.tint32; goto LabelX; | |
5260 case TOK.TOKuns32: t = Type.tuns32; goto LabelX; | |
5261 case TOK.TOKint64: t = Type.tint64; goto LabelX; | |
5262 case TOK.TOKuns64: t = Type.tuns64; goto LabelX; | |
5263 case TOK.TOKfloat32: t = Type.tfloat32; goto LabelX; | |
5264 case TOK.TOKfloat64: t = Type.tfloat64; goto LabelX; | |
5265 case TOK.TOKfloat80: t = Type.tfloat80; goto LabelX; | |
5266 case TOK.TOKimaginary32: t = Type.timaginary32; goto LabelX; | |
5267 case TOK.TOKimaginary64: t = Type.timaginary64; goto LabelX; | |
5268 case TOK.TOKimaginary80: t = Type.timaginary80; goto LabelX; | |
5269 case TOK.TOKcomplex32: t = Type.tcomplex32; goto LabelX; | |
5270 case TOK.TOKcomplex64: t = Type.tcomplex64; goto LabelX; | |
5271 case TOK.TOKcomplex80: t = Type.tcomplex80; goto LabelX; | |
5272 case TOK.TOKbit: t = Type.tbit; goto LabelX; | |
5273 case TOK.TOKbool: t = Type.tbool; goto LabelX; | |
5274 case TOK.TOKchar: t = Type.tchar; goto LabelX; | |
5275 case TOK.TOKwchar: t = Type.twchar; goto LabelX; | |
5276 case TOK.TOKdchar: t = Type.tdchar; goto LabelX; | |
5277 LabelX: | |
5278 nextToken(); | |
5279 L1: | |
5280 check(TOK.TOKdot, t.toChars()); | |
5281 if (token.value != TOK.TOKidentifier) | |
5282 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t.toChars()); | |
5283 goto Lerr; | |
5284 } | |
5285 e = typeDotIdExp(loc, t, token.ident); | |
5286 nextToken(); | |
5287 break; | |
5288 | |
5289 case TOK.TOKtypeof: | |
5290 { | |
5291 t = parseTypeof(); | |
5292 e = new TypeExp(loc, t); | |
5293 break; | |
5294 } | |
5295 | |
5296 case TOK.TOKtypeid: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5297 { |
0 | 5298 nextToken(); |
5299 check(TOK.TOKlparen, "typeid"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5300 Object o; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
5301 if (isDeclaration(&token, 0, TOKreserved, null)) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5302 { // argument is a type |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5303 o = parseType(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5304 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5305 else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5306 { // argument is an expression |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5307 o = parseAssignExp(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5308 } |
0 | 5309 check(TOK.TOKrparen); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5310 e = new TypeidExp(loc, o); |
0 | 5311 break; |
5312 } | |
5313 | |
5314 version (DMDV2) { | |
5315 case TOK.TOKtraits: | |
5316 { /* __traits(identifier, args...) | |
5317 */ | |
5318 Identifier ident; | |
5319 Objects args = null; | |
5320 | |
5321 nextToken(); | |
5322 check(TOK.TOKlparen); | |
5323 if (token.value != TOK.TOKidentifier) | |
5324 { error("__traits(identifier, args...) expected"); | |
5325 goto Lerr; | |
5326 } | |
5327 ident = token.ident; | |
5328 nextToken(); | |
5329 if (token.value == TOK.TOKcomma) | |
5330 args = parseTemplateArgumentList2(); // __traits(identifier, args...) | |
5331 else | |
5332 check(TOK.TOKrparen); // __traits(identifier) | |
5333 | |
5334 e = new TraitsExp(loc, ident, args); | |
5335 break; | |
5336 } | |
5337 } | |
5338 | |
5339 case TOK.TOKis: | |
5340 { Type targ; | |
5341 Identifier ident = null; | |
5342 Type tspec = null; | |
5343 TOK tok = TOK.TOKreserved; | |
5344 TOK tok2 = TOK.TOKreserved; | |
5345 TemplateParameters tpl = null; | |
5346 Loc loc2 = this.loc; | |
5347 | |
5348 nextToken(); | |
5349 if (token.value == TOK.TOKlparen) | |
5350 { | |
5351 nextToken(); | |
5352 targ = parseType(&ident); | |
5353 if (token.value == TOK.TOKcolon || token.value == TOK.TOKequal) | |
5354 { | |
5355 tok = token.value; | |
5356 nextToken(); | |
5357 if (tok == TOK.TOKequal && | |
5358 (token.value == TOK.TOKtypedef || | |
5359 token.value == TOK.TOKstruct || | |
5360 token.value == TOK.TOKunion || | |
5361 token.value == TOK.TOKclass || | |
5362 token.value == TOK.TOKsuper || | |
5363 token.value == TOK.TOKenum || | |
5364 token.value == TOK.TOKinterface || | |
5365 ///version (DMDV2) { | |
5366 token.value == TOK.TOKconst && peek(&token).value == TOK.TOKrparen || | |
5367 token.value == TOK.TOKinvariant && peek(&token).value == TOK.TOKrparen || | |
5368 token.value == TOK.TOKimmutable && peek(&token).value == TOK.TOKrparen || | |
5369 token.value == TOK.TOKshared && peek(&token).value == TOK.TOKrparen || | |
135 | 5370 token.value == TOKwild && peek(&token).value == TOKrparen || |
0 | 5371 ///} |
5372 token.value == TOK.TOKfunction || | |
5373 token.value == TOK.TOKdelegate || | |
5374 token.value == TOK.TOKreturn)) | |
5375 { | |
5376 tok2 = token.value; | |
5377 nextToken(); | |
5378 } | |
5379 else | |
5380 { | |
5381 tspec = parseType(); | |
5382 } | |
5383 } | |
5384 if (ident && tspec) | |
5385 { | |
5386 if (token.value == TOK.TOKcomma) | |
5387 tpl = parseTemplateParameterList(1); | |
5388 else | |
5389 { tpl = new TemplateParameters(); | |
5390 check(TOK.TOKrparen); | |
5391 } | |
5392 TemplateParameter tp = new TemplateTypeParameter(loc2, ident, null, null); | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
5393 tpl.insert(0, tp); |
0 | 5394 } |
5395 else | |
5396 check(TOK.TOKrparen); | |
5397 } | |
5398 else | |
5399 { error("(type identifier : specialization) expected following is"); | |
5400 goto Lerr; | |
5401 } | |
5402 e = new IsExp(loc2, targ, ident, tok, tspec, tok2, tpl); | |
5403 break; | |
5404 } | |
5405 | |
5406 case TOK.TOKassert: | |
5407 { | |
5408 Expression msg = null; | |
5409 | |
5410 nextToken(); | |
5411 check(TOK.TOKlparen, "assert"); | |
5412 e = parseAssignExp(); | |
5413 if (token.value == TOK.TOKcomma) | |
5414 { nextToken(); | |
5415 msg = parseAssignExp(); | |
5416 } | |
5417 check(TOK.TOKrparen); | |
5418 e = new AssertExp(loc, e, msg); | |
5419 break; | |
5420 } | |
5421 | |
5422 case TOK.TOKmixin: | |
5423 { | |
5424 nextToken(); | |
5425 check(TOK.TOKlparen, "mixin"); | |
5426 e = parseAssignExp(); | |
5427 check(TOK.TOKrparen); | |
5428 e = new CompileExp(loc, e); | |
5429 break; | |
5430 } | |
5431 | |
5432 case TOK.TOKimport: | |
5433 { | |
5434 nextToken(); | |
5435 check(TOK.TOKlparen, "import"); | |
5436 e = parseAssignExp(); | |
5437 check(TOK.TOKrparen); | |
5438 e = new FileExp(loc, e); | |
5439 break; | |
5440 } | |
5441 | |
5442 case TOK.TOKlparen: | |
5443 if (peekPastParen(&token).value == TOK.TOKlcurly) | |
5444 { // (arguments) { statements... } | |
5445 save = TOK.TOKdelegate; | |
5446 goto case_delegate; | |
5447 } | |
5448 // ( expression ) | |
5449 nextToken(); | |
5450 e = parseExpression(); | |
5451 check(loc, TOK.TOKrparen); | |
5452 break; | |
5453 | |
5454 case TOK.TOKlbracket: | |
5455 { /* Parse array literals and associative array literals: | |
5456 * [ value, value, value ... ] | |
5457 * [ key:value, key:value, key:value ... ] | |
5458 */ | |
5459 Expressions values = new Expressions(); | |
5460 Expressions keys = null; | |
5461 | |
5462 nextToken(); | |
5463 if (token.value != TOK.TOKrbracket) | |
5464 { | |
5465 while (token.value != TOK.TOKeof) | |
5466 { | |
5467 Expression e2 = parseAssignExp(); | |
5468 if (token.value == TOK.TOKcolon && (keys || values.dim == 0)) | |
5469 { | |
5470 nextToken(); | |
5471 if (!keys) | |
5472 keys = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
5473 keys.push(e2); |
0 | 5474 e2 = parseAssignExp(); |
5475 } | |
5476 else if (keys) | |
5477 { | |
5478 error("'key:value' expected for associative array literal"); | |
5479 delete keys; | |
5480 keys = null; | |
5481 } | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
5482 values.push(e2); |
0 | 5483 if (token.value == TOK.TOKrbracket) |
5484 break; | |
5485 check(TOK.TOKcomma); | |
5486 } | |
5487 } | |
5488 check(TOK.TOKrbracket); | |
5489 | |
5490 if (keys) | |
5491 e = new AssocArrayLiteralExp(loc, keys, values); | |
5492 else | |
5493 e = new ArrayLiteralExp(loc, values); | |
5494 break; | |
5495 } | |
5496 | |
5497 case TOK.TOKlcurly: | |
5498 // { statements... } | |
5499 save = TOK.TOKdelegate; | |
5500 goto case_delegate; | |
5501 | |
5502 case TOK.TOKfunction: | |
5503 case TOK.TOKdelegate: | |
5504 save = token.value; | |
5505 nextToken(); | |
5506 case_delegate: | |
5507 { | |
5508 /* function type(parameters) { body } pure nothrow | |
5509 * delegate type(parameters) { body } pure nothrow | |
5510 * (parameters) { body } | |
5511 * { body } | |
5512 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5513 Parameters arguments; |
0 | 5514 int varargs; |
5515 FuncLiteralDeclaration fd; | |
5516 Type tt; | |
5517 bool isnothrow = false; | |
5518 bool ispure = false; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5519 bool isproperty = false; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5520 TRUST trust = TRUSTdefault; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5521 |
0 | 5522 if (token.value == TOK.TOKlcurly) |
5523 { | |
5524 tt = null; | |
5525 varargs = 0; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5526 arguments = new Parameters(); |
0 | 5527 } |
5528 else | |
5529 { | |
5530 if (token.value == TOK.TOKlparen) | |
5531 tt = null; | |
5532 else | |
5533 { | |
5534 tt = parseBasicType(); | |
5535 tt = parseBasicType2(tt); // function return type | |
5536 } | |
5537 arguments = parseParameters(&varargs); | |
5538 while (1) | |
5539 { | |
5540 if (token.value == TOK.TOKpure) | |
5541 ispure = true; | |
5542 else if (token.value == TOK.TOKnothrow) | |
5543 isnothrow = true; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5544 else if (token.value == TOKat) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5545 { |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
5546 StorageClass stc = parseAttribute(); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5547 switch (cast(uint)(stc >> 32)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5548 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5549 case STCproperty >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5550 isproperty = true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5551 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5552 case STCsafe >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5553 trust = TRUSTsafe; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5554 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5555 case STCsystem >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5556 trust = TRUSTsystem; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5557 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5558 case STCtrusted >> 32: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5559 trust = TRUSTtrusted; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5560 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5561 case 0: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5562 break; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5563 default: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5564 assert(0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5565 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5566 } |
0 | 5567 else |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5568 break; |
0 | 5569 nextToken(); |
5570 } | |
5571 } | |
5572 | |
5573 TypeFunction tf = new TypeFunction(arguments, tt, varargs, linkage); | |
5574 tf.ispure = ispure; | |
5575 tf.isnothrow = isnothrow; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5576 tf.isproperty = isproperty; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5577 tf.trust = trust; |
0 | 5578 fd = new FuncLiteralDeclaration(loc, Loc(0), tf, save, null); |
5579 parseContracts(fd); | |
5580 e = new FuncExp(loc, fd); | |
5581 break; | |
5582 } | |
5583 | |
5584 default: | |
5585 error("expression expected, not '%s'", token.toChars()); | |
5586 Lerr: | |
5587 // Anything for e, as long as it's not null | |
5588 e = new IntegerExp(loc, 0, Type.tint32); | |
5589 nextToken(); | |
5590 break; | |
5591 } | |
5592 return e; | |
5593 } | |
5594 | |
5595 Expression parseUnaryExp() | |
5596 { | |
5597 Expression e; | |
5598 Loc loc = this.loc; | |
5599 | |
5600 switch (token.value) | |
5601 { | |
5602 case TOK.TOKand: | |
5603 nextToken(); | |
5604 e = parseUnaryExp(); | |
5605 e = new AddrExp(loc, e); | |
5606 break; | |
5607 | |
5608 case TOK.TOKplusplus: | |
5609 nextToken(); | |
5610 e = parseUnaryExp(); | |
5611 e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32)); | |
5612 break; | |
5613 | |
5614 case TOK.TOKminusminus: | |
5615 nextToken(); | |
5616 e = parseUnaryExp(); | |
5617 e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32)); | |
5618 break; | |
5619 | |
5620 case TOK.TOKmul: | |
5621 nextToken(); | |
5622 e = parseUnaryExp(); | |
5623 e = new PtrExp(loc, e); | |
5624 break; | |
5625 | |
5626 case TOK.TOKmin: | |
5627 nextToken(); | |
5628 e = parseUnaryExp(); | |
5629 e = new NegExp(loc, e); | |
5630 break; | |
5631 | |
5632 case TOK.TOKadd: | |
5633 nextToken(); | |
5634 e = parseUnaryExp(); | |
5635 e = new UAddExp(loc, e); | |
5636 break; | |
5637 | |
5638 case TOK.TOKnot: | |
5639 nextToken(); | |
5640 e = parseUnaryExp(); | |
5641 e = new NotExp(loc, e); | |
5642 break; | |
5643 | |
5644 case TOK.TOKtilde: | |
5645 nextToken(); | |
5646 e = parseUnaryExp(); | |
5647 e = new ComExp(loc, e); | |
5648 break; | |
5649 | |
5650 case TOK.TOKdelete: | |
5651 nextToken(); | |
5652 e = parseUnaryExp(); | |
5653 e = new DeleteExp(loc, e); | |
5654 break; | |
5655 | |
5656 case TOK.TOKnew: | |
5657 e = parseNewExp(null); | |
5658 break; | |
5659 | |
5660 case TOK.TOKcast: // cast(type) expression | |
5661 { | |
5662 nextToken(); | |
5663 check(TOK.TOKlparen); | |
5664 /* Look for cast(), cast(const), cast(immutable), | |
135 | 5665 * cast(shared), cast(shared const), cast(wild), cast(shared wild) |
0 | 5666 */ |
5667 MOD m; | |
5668 if (token.value == TOK.TOKrparen) | |
5669 { | |
5670 m = MOD.MODundefined; | |
5671 goto Lmod1; | |
5672 } | |
5673 else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKrparen) | |
5674 { | |
5675 m = MOD.MODconst; | |
5676 goto Lmod2; | |
5677 } | |
5678 else if ((token.value == TOK.TOKimmutable || token.value == TOK.TOKinvariant) && peekNext() == TOK.TOKrparen) | |
5679 { | |
135 | 5680 m = MOD.MODimmutable; |
0 | 5681 goto Lmod2; |
5682 } | |
5683 else if (token.value == TOK.TOKshared && peekNext() == TOK.TOKrparen) | |
5684 { | |
5685 m = MOD.MODshared; | |
5686 goto Lmod2; | |
5687 } | |
135 | 5688 else if (token.value == TOKwild && peekNext() == TOK.TOKrparen) |
5689 { | |
5690 m = MODwild; | |
5691 goto Lmod2; | |
5692 } | |
5693 else if (token.value == TOKwild && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen || | |
5694 token.value == TOK.TOKshared && peekNext() == TOKwild && peekNext2() == TOK.TOKrparen) | |
5695 { | |
5696 m = MOD.MODshared | MOD.MODwild; | |
5697 goto Lmod3; | |
5698 } | |
0 | 5699 else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen || |
5700 token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() == TOK.TOKrparen) | |
5701 { | |
5702 m = MOD.MODshared | MOD.MODconst; | |
135 | 5703 Lmod3: |
0 | 5704 nextToken(); |
5705 Lmod2: | |
5706 nextToken(); | |
5707 Lmod1: | |
5708 nextToken(); | |
5709 e = parseUnaryExp(); | |
5710 e = new CastExp(loc, e, m); | |
5711 } | |
5712 else | |
5713 { | |
5714 Type t = parseType(); // ( type ) | |
5715 check(TOK.TOKrparen); | |
5716 e = parseUnaryExp(); | |
5717 e = new CastExp(loc, e, t); | |
5718 } | |
5719 break; | |
5720 } | |
5721 | |
5722 case TOK.TOKlparen: | |
5723 { Token *tk; | |
5724 | |
5725 tk = peek(&token); | |
5726 version (CCASTSYNTAX) { | |
5727 // If cast | |
5728 if (isDeclaration(tk, 0, TOK.TOKrparen, &tk)) | |
5729 { | |
5730 tk = peek(tk); // skip over right parenthesis | |
5731 switch (tk.value) | |
5732 { | |
5733 case TOK.TOKnot: | |
5734 tk = peek(tk); | |
5735 if (tk.value == TOK.TOKis) // !is | |
5736 break; | |
5737 case TOK.TOKdot: | |
5738 case TOK.TOKplusplus: | |
5739 case TOK.TOKminusminus: | |
5740 case TOK.TOKdelete: | |
5741 case TOK.TOKnew: | |
5742 case TOK.TOKlparen: | |
5743 case TOK.TOKidentifier: | |
5744 case TOK.TOKthis: | |
5745 case TOK.TOKsuper: | |
5746 case TOK.TOKint32v: | |
5747 case TOK.TOKuns32v: | |
5748 case TOK.TOKint64v: | |
5749 case TOK.TOKuns64v: | |
5750 case TOK.TOKfloat32v: | |
5751 case TOK.TOKfloat64v: | |
5752 case TOK.TOKfloat80v: | |
5753 case TOK.TOKimaginary32v: | |
5754 case TOK.TOKimaginary64v: | |
5755 case TOK.TOKimaginary80v: | |
5756 case TOK.TOKnull: | |
5757 case TOK.TOKtrue: | |
5758 case TOK.TOKfalse: | |
5759 case TOK.TOKcharv: | |
5760 case TOK.TOKwcharv: | |
5761 case TOK.TOKdcharv: | |
5762 case TOK.TOKstring: | |
5763 static if (false) { | |
5764 case TOK.TOKtilde: | |
5765 case TOK.TOKand: | |
5766 case TOK.TOKmul: | |
5767 case TOK.TOKmin: | |
5768 case TOK.TOKadd: | |
5769 } | |
5770 case TOK.TOKfunction: | |
5771 case TOK.TOKdelegate: | |
5772 case TOK.TOKtypeof: | |
5773 version (DMDV2) { | |
5774 case TOK.TOKfile: | |
5775 case TOK.TOKline: | |
5776 } | |
5777 case TOK.TOKwchar: case TOK.TOKdchar: | |
5778 case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar: | |
5779 case TOK.TOKint8: case TOK.TOKuns8: | |
5780 case TOK.TOKint16: case TOK.TOKuns16: | |
5781 case TOK.TOKint32: case TOK.TOKuns32: | |
5782 case TOK.TOKint64: case TOK.TOKuns64: | |
5783 case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80: | |
5784 case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80: | |
5785 case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80: | |
5786 case TOK.TOKvoid: // (type)int.size | |
5787 { | |
5788 // (type) una_exp | |
5789 nextToken(); | |
5790 Type t = parseType(); | |
5791 check(TOK.TOKrparen); | |
5792 | |
5793 // if .identifier | |
5794 if (token.value == TOK.TOKdot) | |
5795 { | |
5796 nextToken(); | |
5797 if (token.value != TOK.TOKidentifier) | |
5798 { | |
5799 error("Identifier expected following (type)."); | |
5800 return null; | |
5801 } | |
5802 e = typeDotIdExp(loc, t, token.ident); | |
5803 nextToken(); | |
5804 e = parsePostExp(e); | |
5805 } | |
5806 else | |
5807 { | |
5808 e = parseUnaryExp(); | |
5809 e = new CastExp(loc, e, t); | |
5810 error("C style cast illegal, use %s", e.toChars()); | |
5811 } | |
5812 return e; | |
5813 } | |
5814 | |
5815 default: | |
5816 break; /// | |
5817 } | |
5818 } | |
5819 } | |
5820 e = parsePrimaryExp(); | |
5821 e = parsePostExp(e); | |
5822 break; | |
5823 } | |
5824 default: | |
5825 e = parsePrimaryExp(); | |
5826 e = parsePostExp(e); | |
5827 break; | |
5828 } | |
5829 assert(e); | |
135 | 5830 |
5831 // ^^ is right associative and has higher precedence than the unary operators | |
5832 while (token.value == TOK.TOKpow) | |
5833 { | |
5834 nextToken(); | |
5835 Expression e2 = parseUnaryExp(); | |
5836 e = new PowExp(loc, e, e2); | |
5837 } | |
5838 | |
0 | 5839 return e; |
5840 } | |
5841 | |
5842 Expression parsePostExp(Expression e) | |
5843 { | |
5844 Loc loc; | |
5845 | |
5846 while (1) | |
5847 { | |
5848 loc = this.loc; | |
5849 switch (token.value) | |
5850 { | |
5851 case TOK.TOKdot: | |
5852 nextToken(); | |
5853 if (token.value == TOK.TOKidentifier) | |
5854 { Identifier id = token.ident; | |
5855 | |
5856 nextToken(); | |
5857 if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis) | |
5858 { // identifier!(template-argument-list) | |
5859 TemplateInstance tempinst = new TemplateInstance(loc, id); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5860 Objects tiargs; |
0 | 5861 nextToken(); |
5862 if (token.value == TOK.TOKlparen) | |
5863 // ident!(template_arguments) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5864 tiargs = parseTemplateArgumentList(); |
0 | 5865 else |
5866 // ident!template_argument | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5867 tiargs = parseTemplateArgument(); |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
5868 e = new DotTemplateInstanceExp(loc, e, id, tiargs); |
0 | 5869 } |
5870 else | |
5871 e = new DotIdExp(loc, e, id); | |
5872 continue; | |
5873 } | |
5874 else if (token.value == TOK.TOKnew) | |
5875 { | |
5876 e = parseNewExp(e); | |
5877 continue; | |
5878 } | |
5879 else | |
5880 error("identifier expected following '.', not '%s'", token.toChars()); | |
5881 break; | |
5882 | |
5883 case TOK.TOKplusplus: | |
5884 e = new PostExp(TOK.TOKplusplus, loc, e); | |
5885 break; | |
5886 | |
5887 case TOK.TOKminusminus: | |
5888 e = new PostExp(TOK.TOKminusminus, loc, e); | |
5889 break; | |
5890 | |
5891 case TOK.TOKlparen: | |
5892 e = new CallExp(loc, e, parseArguments()); | |
5893 continue; | |
5894 | |
5895 case TOK.TOKlbracket: | |
5896 { // array dereferences: | |
5897 // array[index] | |
5898 // array[] | |
5899 // array[lwr .. upr] | |
5900 Expression index; | |
5901 Expression upr; | |
5902 | |
5903 inBrackets++; | |
5904 nextToken(); | |
5905 if (token.value == TOK.TOKrbracket) | |
5906 { // array[] | |
5907 e = new SliceExp(loc, e, null, null); | |
5908 nextToken(); | |
5909 } | |
5910 else | |
5911 { | |
5912 index = parseAssignExp(); | |
5913 if (token.value == TOK.TOKslice) | |
5914 { // array[lwr .. upr] | |
5915 nextToken(); | |
5916 upr = parseAssignExp(); | |
5917 e = new SliceExp(loc, e, index, upr); | |
5918 } | |
5919 else | |
5920 { // array[index, i2, i3, i4, ...] | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
5921 auto arguments = new Expressions(); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
5922 arguments.push(index); |
0 | 5923 if (token.value == TOK.TOKcomma) |
5924 { | |
5925 nextToken(); | |
5926 while (1) | |
5927 { Expression arg; | |
5928 | |
5929 arg = parseAssignExp(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
5930 arguments.push(arg); |
0 | 5931 if (token.value == TOK.TOKrbracket) |
5932 break; | |
5933 check(TOK.TOKcomma); | |
5934 } | |
5935 } | |
5936 e = new ArrayExp(loc, e, arguments); | |
5937 } | |
5938 check(TOK.TOKrbracket); | |
5939 inBrackets--; | |
5940 } | |
5941 continue; | |
5942 } | |
5943 | |
5944 default: | |
5945 return e; | |
5946 } | |
5947 nextToken(); | |
5948 } | |
5949 | |
5950 assert(false); | |
5951 } | |
5952 | |
5953 Expression parseMulExp() | |
5954 { | |
5955 Expression e; | |
5956 Expression e2; | |
5957 Loc loc = this.loc; | |
5958 | |
5959 e = parseUnaryExp(); | |
5960 while (1) | |
5961 { | |
5962 switch (token.value) | |
5963 { | |
5964 case TOK.TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5965 case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
5966 case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; |
0 | 5967 |
5968 default: | |
5969 break; | |
5970 } | |
5971 break; | |
5972 } | |
5973 return e; | |
5974 } | |
5975 | |
5976 Expression parseShiftExp() | |
5977 { | |
5978 Expression e; | |
5979 Expression e2; | |
5980 Loc loc = this.loc; | |
5981 | |
5982 e = parseAddExp(); | |
5983 while (1) | |
5984 { | |
5985 switch (token.value) | |
5986 { | |
5987 case TOK.TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue; | |
5988 case TOK.TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue; | |
5989 case TOK.TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue; | |
5990 | |
5991 default: | |
5992 break; | |
5993 } | |
5994 break; | |
5995 } | |
5996 return e; | |
5997 } | |
5998 | |
5999 Expression parseAddExp() | |
6000 { | |
6001 Expression e; | |
6002 Expression e2; | |
6003 Loc loc = this.loc; | |
6004 | |
6005 e = parseMulExp(); | |
6006 while (1) | |
6007 { | |
6008 switch (token.value) | |
6009 { | |
6010 case TOK.TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue; | |
6011 case TOK.TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue; | |
6012 case TOK.TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue; | |
6013 | |
6014 default: | |
6015 break; | |
6016 } | |
6017 break; | |
6018 } | |
6019 return e; | |
6020 } | |
6021 | |
6022 Expression parseRelExp() | |
6023 { | |
6024 assert(false); | |
6025 } | |
6026 | |
6027 Expression parseEqualExp() | |
6028 { | |
6029 assert(false); | |
6030 } | |
6031 | |
6032 Expression parseCmpExp() | |
6033 { | |
6034 Expression e; | |
6035 Expression e2; | |
6036 Token* t; | |
6037 Loc loc = this.loc; | |
6038 | |
6039 e = parseShiftExp(); | |
6040 TOK op = token.value; | |
6041 | |
6042 switch (op) | |
6043 { | |
6044 case TOK.TOKequal: | |
6045 case TOK.TOKnotequal: | |
6046 nextToken(); | |
6047 e2 = parseShiftExp(); | |
6048 e = new EqualExp(op, loc, e, e2); | |
6049 break; | |
6050 | |
6051 case TOK.TOKis: | |
6052 op = TOK.TOKidentity; | |
6053 goto L1; | |
6054 | |
6055 case TOK.TOKnot: | |
6056 // Attempt to identify '!is' | |
6057 t = peek(&token); | |
6058 if (t.value != TOK.TOKis) | |
6059 break; | |
6060 nextToken(); | |
6061 op = TOK.TOKnotidentity; | |
6062 goto L1; | |
6063 | |
6064 L1: | |
6065 nextToken(); | |
6066 e2 = parseShiftExp(); | |
6067 e = new IdentityExp(op, loc, e, e2); | |
6068 break; | |
6069 | |
6070 case TOK.TOKlt: | |
6071 case TOK.TOKle: | |
6072 case TOK.TOKgt: | |
6073 case TOK.TOKge: | |
6074 case TOK.TOKunord: | |
6075 case TOK.TOKlg: | |
6076 case TOK.TOKleg: | |
6077 case TOK.TOKule: | |
6078 case TOK.TOKul: | |
6079 case TOK.TOKuge: | |
6080 case TOK.TOKug: | |
6081 case TOK.TOKue: | |
6082 nextToken(); | |
6083 e2 = parseShiftExp(); | |
6084 e = new CmpExp(op, loc, e, e2); | |
6085 break; | |
6086 | |
6087 case TOK.TOKin: | |
6088 nextToken(); | |
6089 e2 = parseShiftExp(); | |
6090 e = new InExp(loc, e, e2); | |
6091 break; | |
6092 | |
6093 default: | |
6094 break; | |
6095 } | |
6096 return e; | |
6097 } | |
6098 | |
6099 Expression parseAndExp() | |
6100 { | |
6101 Expression e; | |
6102 Expression e2; | |
6103 Loc loc = this.loc; | |
6104 | |
6105 if (global.params.Dversion == 1) | |
6106 { | |
6107 e = parseEqualExp(); | |
6108 while (token.value == TOK.TOKand) | |
6109 { | |
6110 nextToken(); | |
6111 e2 = parseEqualExp(); | |
6112 e = new AndExp(loc,e,e2); | |
6113 loc = this.loc; | |
6114 } | |
6115 } | |
6116 else | |
6117 { | |
6118 e = parseCmpExp(); | |
6119 while (token.value == TOK.TOKand) | |
6120 { | |
6121 nextToken(); | |
6122 e2 = parseCmpExp(); | |
6123 e = new AndExp(loc,e,e2); | |
6124 loc = this.loc; | |
6125 } | |
6126 } | |
6127 return e; | |
6128 } | |
6129 | |
6130 Expression parseXorExp() | |
6131 { | |
6132 Expression e; | |
6133 Expression e2; | |
6134 Loc loc = this.loc; | |
6135 | |
6136 e = parseAndExp(); | |
6137 while (token.value == TOK.TOKxor) | |
6138 { | |
6139 nextToken(); | |
6140 e2 = parseAndExp(); | |
6141 e = new XorExp(loc, e, e2); | |
6142 } | |
6143 | |
6144 return e; | |
6145 } | |
6146 | |
6147 Expression parseOrExp() | |
6148 { | |
6149 Expression e; | |
6150 Expression e2; | |
6151 Loc loc = this.loc; | |
6152 | |
6153 e = parseXorExp(); | |
6154 while (token.value == TOK.TOKor) | |
6155 { | |
6156 nextToken(); | |
6157 e2 = parseXorExp(); | |
6158 e = new OrExp(loc, e, e2); | |
6159 } | |
6160 return e; | |
6161 } | |
6162 | |
6163 Expression parseAndAndExp() | |
6164 { | |
6165 Expression e; | |
6166 Expression e2; | |
6167 Loc loc = this.loc; | |
6168 | |
6169 e = parseOrExp(); | |
6170 while (token.value == TOK.TOKandand) | |
6171 { | |
6172 nextToken(); | |
6173 e2 = parseOrExp(); | |
6174 e = new AndAndExp(loc, e, e2); | |
6175 } | |
6176 return e; | |
6177 } | |
6178 | |
6179 Expression parseOrOrExp() | |
6180 { | |
6181 Expression e; | |
6182 Expression e2; | |
6183 Loc loc = this.loc; | |
6184 | |
6185 e = parseAndAndExp(); | |
6186 while (token.value == TOK.TOKoror) | |
6187 { | |
6188 nextToken(); | |
6189 e2 = parseAndAndExp(); | |
6190 e = new OrOrExp(loc, e, e2); | |
6191 } | |
6192 | |
6193 return e; | |
6194 } | |
6195 | |
6196 Expression parseCondExp() | |
6197 { | |
6198 Expression e; | |
6199 Expression e1; | |
6200 Expression e2; | |
6201 Loc loc = this.loc; | |
6202 | |
6203 e = parseOrOrExp(); | |
6204 if (token.value == TOK.TOKquestion) | |
6205 { | |
6206 nextToken(); | |
6207 e1 = parseExpression(); | |
6208 check(TOK.TOKcolon); | |
6209 e2 = parseCondExp(); | |
6210 e = new CondExp(loc, e, e1, e2); | |
6211 } | |
6212 return e; | |
6213 } | |
6214 | |
6215 Expression parseAssignExp() | |
6216 { | |
6217 Expression e; | |
6218 Expression e2; | |
6219 Loc loc; | |
6220 | |
6221 e = parseCondExp(); | |
6222 while (1) | |
6223 { | |
6224 loc = this.loc; | |
6225 switch (token.value) | |
6226 { | |
6227 case TOK.TOKassign: nextToken(); e2 = parseAssignExp(); e = new AssignExp(loc,e,e2); continue; | |
6228 case TOK.TOKaddass: nextToken(); e2 = parseAssignExp(); e = new AddAssignExp(loc,e,e2); continue; | |
6229 case TOK.TOKminass: nextToken(); e2 = parseAssignExp(); e = new MinAssignExp(loc,e,e2); continue; | |
6230 case TOK.TOKmulass: nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue; | |
6231 case TOK.TOKdivass: nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue; | |
6232 case TOK.TOKmodass: nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue; | |
135 | 6233 case TOK.TOKpowass: nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue; |
0 | 6234 case TOK.TOKandass: nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue; |
6235 case TOK.TOKorass: nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue; | |
6236 case TOK.TOKxorass: nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue; | |
6237 case TOK.TOKshlass: nextToken(); e2 = parseAssignExp(); e = new ShlAssignExp(loc,e,e2); continue; | |
6238 case TOK.TOKshrass: nextToken(); e2 = parseAssignExp(); e = new ShrAssignExp(loc,e,e2); continue; | |
6239 case TOK.TOKushrass: nextToken(); e2 = parseAssignExp(); e = new UshrAssignExp(loc,e,e2); continue; | |
6240 case TOK.TOKcatass: nextToken(); e2 = parseAssignExp(); e = new CatAssignExp(loc,e,e2); continue; | |
6241 | |
6242 default: | |
6243 break; | |
6244 } | |
6245 break; | |
6246 } | |
6247 | |
6248 return e; | |
6249 } | |
6250 | |
6251 /************************* | |
6252 * Collect argument list. | |
6253 * Assume current token is ',', '(' or '['. | |
6254 */ | |
6255 Expressions parseArguments() | |
6256 { | |
6257 // function call | |
6258 Expressions arguments = new Expressions(); | |
6259 Expression arg; | |
6260 TOK endtok; | |
6261 | |
6262 if (token.value == TOK.TOKlbracket) | |
6263 endtok = TOK.TOKrbracket; | |
6264 else | |
6265 endtok = TOK.TOKrparen; | |
6266 | |
6267 { | |
6268 nextToken(); | |
6269 if (token.value != endtok) | |
6270 { | |
6271 while (1) | |
6272 { | |
6273 arg = parseAssignExp(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
6274 arguments.push(arg); |
0 | 6275 if (token.value == endtok) |
6276 break; | |
6277 check(TOK.TOKcomma); | |
6278 } | |
6279 } | |
6280 check(endtok); | |
6281 } | |
6282 return arguments; | |
6283 } | |
6284 | |
6285 Expression parseNewExp(Expression thisexp) | |
6286 { | |
6287 Type t; | |
6288 Expressions newargs; | |
6289 Expressions arguments = null; | |
6290 Expression e; | |
6291 Loc loc = this.loc; | |
6292 | |
6293 nextToken(); | |
6294 newargs = null; | |
6295 if (token.value == TOKlparen) | |
6296 { | |
6297 newargs = parseArguments(); | |
6298 } | |
6299 | |
6300 // An anonymous nested class starts with "class" | |
6301 if (token.value == TOKclass) | |
6302 { | |
6303 nextToken(); | |
6304 if (token.value == TOKlparen) | |
6305 arguments = parseArguments(); | |
6306 | |
6307 BaseClasses baseclasses = null; | |
6308 if (token.value != TOKlcurly) | |
6309 baseclasses = parseBaseClasses(); | |
6310 | |
6311 Identifier id = null; | |
6312 ClassDeclaration cd = new ClassDeclaration(loc, id, baseclasses); | |
6313 | |
6314 if (token.value != TOKlcurly) | |
6315 { | |
6316 error("{ members } expected for anonymous class"); | |
6317 cd.members = null; | |
6318 } | |
6319 else | |
6320 { | |
6321 nextToken(); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
56
diff
changeset
|
6322 auto decl = parseDeclDefs(0); |
0 | 6323 if (token.value != TOKrcurly) |
6324 error("class member expected"); | |
6325 nextToken(); | |
6326 cd.members = decl; | |
6327 } | |
6328 | |
6329 e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments); | |
6330 | |
6331 return e; | |
6332 } | |
6333 | |
6334 t = parseBasicType(); | |
6335 t = parseBasicType2(t); | |
6336 if (t.ty == Taarray) | |
6337 { | |
6338 TypeAArray taa = cast(TypeAArray)t; | |
6339 Type index = taa.index; | |
6340 | |
6341 Expression e2 = index.toExpression(); | |
6342 if (e2) | |
6343 { | |
6344 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
6345 arguments.push(e2); |
0 | 6346 t = new TypeDArray(taa.next); |
6347 } | |
6348 else | |
6349 { | |
6350 error("need size of rightmost array, not type %s", index.toChars()); | |
6351 return new NullExp(loc); | |
6352 } | |
6353 } | |
6354 else if (t.ty == Tsarray) | |
6355 { | |
6356 TypeSArray tsa = cast(TypeSArray)t; | |
6357 Expression ee = tsa.dim; | |
6358 | |
6359 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
6360 arguments.push(ee); |
0 | 6361 t = new TypeDArray(tsa.next); |
6362 } | |
6363 else if (token.value == TOKlparen) | |
6364 { | |
6365 arguments = parseArguments(); | |
6366 } | |
6367 | |
6368 e = new NewExp(loc, thisexp, newargs, t, arguments); | |
6369 return e; | |
6370 } | |
6371 | |
79 | 6372 void addComment(Dsymbol s, const(char)[] blockComment) |
0 | 6373 { |
6374 s.addComment(combineComments(blockComment, token.lineComment)); | |
6375 token.lineComment = null; | |
6376 } | |
19
01cadcfa4842
Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
6377 } |