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