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