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