Mercurial > projects > ldc
comparison dmd2/parse.c @ 1452:638d16625da2
LDC 2 compiles again.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 30 May 2009 17:23:32 +0100 |
parents | 356e65836fb5 |
children | 54b3c1394d62 |
comparison
equal
deleted
inserted
replaced
1423:42bd767ec5a4 | 1452:638d16625da2 |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2008 by Digital Mars | 3 // Copyright (c) 1999-2009 by Digital Mars |
4 // All Rights Reserved | 4 // All Rights Reserved |
5 // written by Walter Bright | 5 // written by Walter Bright |
6 // http://www.digitalmars.com | 6 // http://www.digitalmars.com |
7 // License for redistribution is by either the Artistic License | 7 // License for redistribution is by either the Artistic License |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | 8 // in artistic.txt, or the GNU General Public License in gnu.txt. |
11 // This is the D parser | 11 // This is the D parser |
12 | 12 |
13 #include <stdio.h> | 13 #include <stdio.h> |
14 #include <assert.h> | 14 #include <assert.h> |
15 | 15 |
16 #include "mem.h" | 16 #include "rmem.h" |
17 #include "lexer.h" | 17 #include "lexer.h" |
18 #include "parse.h" | 18 #include "parse.h" |
19 #include "init.h" | 19 #include "init.h" |
20 #include "attrib.h" | 20 #include "attrib.h" |
21 #include "cond.h" | 21 #include "cond.h" |
30 #include "declaration.h" | 30 #include "declaration.h" |
31 #include "aggregate.h" | 31 #include "aggregate.h" |
32 #include "enum.h" | 32 #include "enum.h" |
33 #include "id.h" | 33 #include "id.h" |
34 #include "version.h" | 34 #include "version.h" |
35 #include "aliasthis.h" | |
35 | 36 |
36 // How multiple declarations are parsed. | 37 // How multiple declarations are parsed. |
37 // If 1, treat as C. | 38 // If 1, treat as C. |
38 // If 0, treat: | 39 // If 0, treat: |
39 // int *p, i; | 40 // int *p, i; |
71 { | 72 { |
72 unsigned char *comment = token.blockComment; | 73 unsigned char *comment = token.blockComment; |
73 bool safe = FALSE; | 74 bool safe = FALSE; |
74 | 75 |
75 nextToken(); | 76 nextToken(); |
77 #if DMDV2 | |
76 if (token.value == TOKlparen) | 78 if (token.value == TOKlparen) |
77 { | 79 { |
78 nextToken(); | 80 nextToken(); |
79 if (token.value != TOKidentifier) | 81 if (token.value != TOKidentifier) |
80 { error("module (safe) identifier expected"); | 82 { error("module (system) identifier expected"); |
81 goto Lerr; | 83 goto Lerr; |
82 } | 84 } |
83 Identifier *id = token.ident; | 85 Identifier *id = token.ident; |
84 | 86 |
85 if (id == Id::system) | 87 if (id == Id::system) |
87 else | 89 else |
88 error("(safe) expected, not %s", id->toChars()); | 90 error("(safe) expected, not %s", id->toChars()); |
89 nextToken(); | 91 nextToken(); |
90 check(TOKrparen); | 92 check(TOKrparen); |
91 } | 93 } |
94 #endif | |
92 | 95 |
93 if (token.value != TOKidentifier) | 96 if (token.value != TOKidentifier) |
94 { error("Identifier expected following module"); | 97 { error("Identifier expected following module"); |
95 goto Lerr; | 98 goto Lerr; |
96 } | 99 } |
220 | 223 |
221 case TOKthis: | 224 case TOKthis: |
222 s = parseCtor(); | 225 s = parseCtor(); |
223 break; | 226 break; |
224 | 227 |
228 #if 0 // dead end, use this(this){} instead | |
225 case TOKassign: | 229 case TOKassign: |
226 s = parsePostBlit(); | 230 s = parsePostBlit(); |
227 break; | 231 break; |
228 | 232 #endif |
229 case TOKtilde: | 233 case TOKtilde: |
230 s = parseDtor(); | 234 s = parseDtor(); |
231 break; | 235 break; |
232 | 236 |
233 case TOKinvariant: | 237 case TOKinvariant: |
242 // invariant(type) | 246 // invariant(type) |
243 goto Ldeclaration; | 247 goto Ldeclaration; |
244 } | 248 } |
245 else | 249 else |
246 { | 250 { |
247 stc = STCinvariant; | 251 stc = STCimmutable; |
248 goto Lstc; | 252 goto Lstc; |
249 } | 253 } |
250 break; | 254 break; |
251 } | 255 } |
252 | 256 |
302 goto Lstc; | 306 goto Lstc; |
303 | 307 |
304 case TOKimmutable: | 308 case TOKimmutable: |
305 if (peek(&token)->value == TOKlparen) | 309 if (peek(&token)->value == TOKlparen) |
306 goto Ldeclaration; | 310 goto Ldeclaration; |
307 stc = STCinvariant; | 311 stc = STCimmutable; |
312 goto Lstc; | |
313 | |
314 case TOKshared: | |
315 if (peek(&token)->value == TOKlparen) | |
316 goto Ldeclaration; | |
317 stc = STCshared; | |
308 goto Lstc; | 318 goto Lstc; |
309 | 319 |
310 case TOKfinal: stc = STCfinal; goto Lstc; | 320 case TOKfinal: stc = STCfinal; goto Lstc; |
311 case TOKauto: stc = STCauto; goto Lstc; | 321 case TOKauto: stc = STCauto; goto Lstc; |
312 case TOKscope: stc = STCscope; goto Lstc; | 322 case TOKscope: stc = STCscope; goto Lstc; |
313 case TOKoverride: stc = STCoverride; goto Lstc; | 323 case TOKoverride: stc = STCoverride; goto Lstc; |
314 case TOKabstract: stc = STCabstract; goto Lstc; | 324 case TOKabstract: stc = STCabstract; goto Lstc; |
315 case TOKsynchronized: stc = STCsynchronized; goto Lstc; | 325 case TOKsynchronized: stc = STCsynchronized; goto Lstc; |
316 case TOKdeprecated: stc = STCdeprecated; goto Lstc; | 326 case TOKdeprecated: stc = STCdeprecated; goto Lstc; |
327 #if DMDV2 | |
317 case TOKnothrow: stc = STCnothrow; goto Lstc; | 328 case TOKnothrow: stc = STCnothrow; goto Lstc; |
318 case TOKpure: stc = STCpure; goto Lstc; | 329 case TOKpure: stc = STCpure; goto Lstc; |
319 case TOKref: stc = STCref; goto Lstc; | 330 case TOKref: stc = STCref; goto Lstc; |
320 case TOKtls: stc = STCtls; goto Lstc; | 331 case TOKtls: stc = STCtls; goto Lstc; |
332 case TOKgshared: stc = STCgshared; goto Lstc; | |
321 //case TOKmanifest: stc = STCmanifest; goto Lstc; | 333 //case TOKmanifest: stc = STCmanifest; goto Lstc; |
334 #endif | |
322 | 335 |
323 Lstc: | 336 Lstc: |
324 if (storageClass & stc) | 337 if (storageClass & stc) |
325 error("redundant storage class %s", Token::toChars(token.value)); | 338 error("redundant storage class %s", Token::toChars(token.value)); |
326 { | 339 composeStorageClass(storageClass | stc); |
327 unsigned u = storageClass | stc; | |
328 u &= STCconst | STCinvariant | STCmanifest; | |
329 if (u & (u - 1)) | |
330 error("conflicting storage class %s", Token::toChars(token.value)); | |
331 } | |
332 nextToken(); | 340 nextToken(); |
333 Lstc2: | 341 Lstc2: |
334 storageClass |= stc; | 342 storageClass |= stc; |
335 switch (token.value) | 343 switch (token.value) |
336 { | 344 { |
337 case TOKconst: | 345 case TOKconst: |
338 case TOKinvariant: | 346 case TOKinvariant: |
339 case TOKimmutable: | 347 case TOKimmutable: |
348 case TOKshared: | |
340 // If followed by a (, it is not a storage class | 349 // If followed by a (, it is not a storage class |
341 if (peek(&token)->value == TOKlparen) | 350 if (peek(&token)->value == TOKlparen) |
342 break; | 351 break; |
343 if (token.value == TOKconst) | 352 if (token.value == TOKconst) |
344 stc = STCconst; | 353 stc = STCconst; |
354 else if (token.value == TOKshared) | |
355 stc = STCshared; | |
345 else | 356 else |
346 stc = STCinvariant; | 357 stc = STCimmutable; |
347 goto Lstc; | 358 goto Lstc; |
348 case TOKfinal: stc = STCfinal; goto Lstc; | 359 case TOKfinal: stc = STCfinal; goto Lstc; |
349 case TOKauto: stc = STCauto; goto Lstc; | 360 case TOKauto: stc = STCauto; goto Lstc; |
350 case TOKscope: stc = STCscope; goto Lstc; | 361 case TOKscope: stc = STCscope; goto Lstc; |
351 case TOKoverride: stc = STCoverride; goto Lstc; | 362 case TOKoverride: stc = STCoverride; goto Lstc; |
354 case TOKdeprecated: stc = STCdeprecated; goto Lstc; | 365 case TOKdeprecated: stc = STCdeprecated; goto Lstc; |
355 case TOKnothrow: stc = STCnothrow; goto Lstc; | 366 case TOKnothrow: stc = STCnothrow; goto Lstc; |
356 case TOKpure: stc = STCpure; goto Lstc; | 367 case TOKpure: stc = STCpure; goto Lstc; |
357 case TOKref: stc = STCref; goto Lstc; | 368 case TOKref: stc = STCref; goto Lstc; |
358 case TOKtls: stc = STCtls; goto Lstc; | 369 case TOKtls: stc = STCtls; goto Lstc; |
370 case TOKgshared: stc = STCgshared; goto Lstc; | |
359 //case TOKmanifest: stc = STCmanifest; goto Lstc; | 371 //case TOKmanifest: stc = STCmanifest; goto Lstc; |
360 default: | 372 default: |
361 break; | 373 break; |
362 } | 374 } |
363 | 375 |
376 */ | 388 */ |
377 Token *tk; | 389 Token *tk; |
378 if (token.value == TOKidentifier && | 390 if (token.value == TOKidentifier && |
379 (tk = peek(&token))->value == TOKlparen && | 391 (tk = peek(&token))->value == TOKlparen && |
380 skipParens(tk, &tk) && | 392 skipParens(tk, &tk) && |
381 peek(tk)->value == TOKlparen) | 393 (peek(tk)->value == TOKlparen || |
394 peek(tk)->value == TOKlcurly) | |
395 ) | |
382 { | 396 { |
383 a = parseDeclarations(storageClass); | 397 a = parseDeclarations(storageClass); |
384 decldefs->append(a); | 398 decldefs->append(a); |
385 continue; | 399 continue; |
386 } | 400 } |
550 } | 564 } |
551 } while (!once); | 565 } while (!once); |
552 return decldefs; | 566 return decldefs; |
553 } | 567 } |
554 | 568 |
569 /********************************************* | |
570 * Give error on conflicting storage classes. | |
571 */ | |
572 | |
573 void Parser::composeStorageClass(unsigned stc) | |
574 { | |
575 unsigned u = stc; | |
576 u &= STCconst | STCimmutable | STCmanifest; | |
577 if (u & (u - 1)) | |
578 error("conflicting storage class %s", Token::toChars(token.value)); | |
579 u = stc; | |
580 u &= STCgshared | STCshared | STCtls; | |
581 if (u & (u - 1)) | |
582 error("conflicting storage class %s", Token::toChars(token.value)); | |
583 } | |
555 | 584 |
556 /******************************************** | 585 /******************************************** |
557 * Parse declarations after an align, protection, or extern decl. | 586 * Parse declarations after an align, protection, or extern decl. |
558 */ | 587 */ |
559 | 588 |
566 switch (token.value) | 595 switch (token.value) |
567 { | 596 { |
568 case TOKsemicolon: | 597 case TOKsemicolon: |
569 error("declaration expected following attribute, not ';'"); | 598 error("declaration expected following attribute, not ';'"); |
570 nextToken(); | 599 nextToken(); |
600 break; | |
601 | |
602 case TOKeof: | |
603 error("declaration expected following attribute, not EOF"); | |
571 break; | 604 break; |
572 | 605 |
573 case TOKlcurly: | 606 case TOKlcurly: |
574 nextToken(); | 607 nextToken(); |
575 a = parseDeclDefs(0); | 608 a = parseDeclDefs(0); |
795 } | 828 } |
796 | 829 |
797 | 830 |
798 /***************************************** | 831 /***************************************** |
799 * Parse a constructor definition: | 832 * Parse a constructor definition: |
800 * this(arguments) { body } | 833 * this(parameters) { body } |
801 * or postblit: | 834 * or postblit: |
802 * this(this) { body } | 835 * this(this) { body } |
836 * or constructor template: | |
837 * this(templateparameters)(parameters) { body } | |
803 * Current token is 'this'. | 838 * Current token is 'this'. |
804 */ | 839 */ |
805 | 840 |
806 FuncDeclaration *Parser::parseCtor() | 841 Dsymbol *Parser::parseCtor() |
807 { | 842 { |
808 Loc loc = this->loc; | 843 Loc loc = this->loc; |
809 | 844 |
810 nextToken(); | 845 nextToken(); |
811 if (token.value == TOKlparen && peek(&token)->value == TOKthis) | 846 if (token.value == TOKlparen && peek(&token)->value == TOKthis) |
815 check(TOKrparen); | 850 check(TOKrparen); |
816 PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0); | 851 PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0); |
817 parseContracts(f); | 852 parseContracts(f); |
818 return f; | 853 return f; |
819 } | 854 } |
855 | |
856 /* Look ahead to see if: | |
857 * this(...)(...) | |
858 * which is a constructor template | |
859 */ | |
860 TemplateParameters *tpl = NULL; | |
861 if (token.value == TOKlparen && peekPastParen(&token)->value == TOKlparen) | |
862 { tpl = parseTemplateParameterList(); | |
863 | |
864 int varargs; | |
865 Arguments *arguments = parseParameters(&varargs); | |
866 | |
867 Expression *constraint = NULL; | |
868 if (tpl) | |
869 constraint = parseConstraint(); | |
870 | |
871 CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs); | |
872 parseContracts(f); | |
873 | |
874 // Wrap a template around it | |
875 Array *decldefs = new Array(); | |
876 decldefs->push(f); | |
877 TemplateDeclaration *tempdecl = | |
878 new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs); | |
879 return tempdecl; | |
880 } | |
881 | |
882 /* Just a regular constructor | |
883 */ | |
820 int varargs; | 884 int varargs; |
821 Arguments *arguments = parseParameters(&varargs); | 885 Arguments *arguments = parseParameters(&varargs); |
822 CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs); | 886 CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs); |
823 parseContracts(f); | 887 parseContracts(f); |
824 return f; | 888 return f; |
1032 | 1096 |
1033 case TOKinvariant: | 1097 case TOKinvariant: |
1034 case TOKimmutable: | 1098 case TOKimmutable: |
1035 if (peek(&token)->value == TOKlparen) | 1099 if (peek(&token)->value == TOKlparen) |
1036 goto Ldefault; | 1100 goto Ldefault; |
1037 stc = STCinvariant; | 1101 stc = STCimmutable; |
1102 goto L2; | |
1103 | |
1104 case TOKshared: | |
1105 if (peek(&token)->value == TOKlparen) | |
1106 goto Ldefault; | |
1107 stc = STCshared; | |
1038 goto L2; | 1108 goto L2; |
1039 | 1109 |
1040 case TOKin: stc = STCin; goto L2; | 1110 case TOKin: stc = STCin; goto L2; |
1041 case TOKout: stc = STCout; goto L2; | 1111 case TOKout: stc = STCout; goto L2; |
1042 case TOKinout: | 1112 case TOKinout: |
1049 (storageClass & STCin && stc & (STCconst | STCscope)) || | 1119 (storageClass & STCin && stc & (STCconst | STCscope)) || |
1050 (stc & STCin && storageClass & (STCconst | STCscope)) | 1120 (stc & STCin && storageClass & (STCconst | STCscope)) |
1051 ) | 1121 ) |
1052 error("redundant storage class %s", Token::toChars(token.value)); | 1122 error("redundant storage class %s", Token::toChars(token.value)); |
1053 storageClass |= stc; | 1123 storageClass |= stc; |
1054 { | 1124 composeStorageClass(storageClass); |
1055 unsigned u = storageClass & (STCconst | STCinvariant); | |
1056 if (u & (u - 1)) | |
1057 error("conflicting storage class %s", Token::toChars(token.value)); | |
1058 } | |
1059 continue; | 1125 continue; |
1060 | 1126 |
1061 #if 0 | 1127 #if 0 |
1062 case TOKstatic: stc = STCstatic; goto L2; | 1128 case TOKstatic: stc = STCstatic; goto L2; |
1063 case TOKauto: storageClass = STCauto; goto L4; | 1129 case TOKauto: storageClass = STCauto; goto L4; |
1090 stc = storageClass & (STCin | STCout | STCref | STClazy); | 1156 stc = storageClass & (STCin | STCout | STCref | STClazy); |
1091 if (stc & (stc - 1)) // if stc is not a power of 2 | 1157 if (stc & (stc - 1)) // if stc is not a power of 2 |
1092 error("incompatible parameter storage classes"); | 1158 error("incompatible parameter storage classes"); |
1093 if ((storageClass & (STCconst | STCout)) == (STCconst | STCout)) | 1159 if ((storageClass & (STCconst | STCout)) == (STCconst | STCout)) |
1094 error("out cannot be const"); | 1160 error("out cannot be const"); |
1095 if ((storageClass & (STCinvariant | STCout)) == (STCinvariant | STCout)) | 1161 if ((storageClass & (STCimmutable | STCout)) == (STCimmutable | STCout)) |
1096 error("out cannot be invariant"); | 1162 error("out cannot be immutable"); |
1097 if ((storageClass & STCscope) && | 1163 if ((storageClass & STCscope) && |
1098 (storageClass & (STCref | STCout))) | 1164 (storageClass & (STCref | STCout))) |
1099 error("scope cannot be ref or out"); | 1165 error("scope cannot be ref or out"); |
1100 at = parseType(&ai); | 1166 at = parseType(&ai); |
1101 ae = NULL; | 1167 ae = NULL; |
1734 return parseTemplateArgumentList2(); | 1800 return parseTemplateArgumentList2(); |
1735 } | 1801 } |
1736 | 1802 |
1737 Objects *Parser::parseTemplateArgumentList2() | 1803 Objects *Parser::parseTemplateArgumentList2() |
1738 { | 1804 { |
1805 //printf("Parser::parseTemplateArgumentList2()\n"); | |
1739 Objects *tiargs = new Objects(); | 1806 Objects *tiargs = new Objects(); |
1740 enum TOK endtok = TOKrparen; | 1807 enum TOK endtok = TOKrparen; |
1741 nextToken(); | 1808 nextToken(); |
1742 | 1809 |
1743 // Get TemplateArgumentList | 1810 // Get TemplateArgumentList |
1752 tiargs->push(ta); | 1819 tiargs->push(ta); |
1753 } | 1820 } |
1754 else | 1821 else |
1755 { // Template argument is an expression | 1822 { // Template argument is an expression |
1756 Expression *ea = parseAssignExp(); | 1823 Expression *ea = parseAssignExp(); |
1824 | |
1825 if (ea->op == TOKfunction) | |
1826 { FuncLiteralDeclaration *fd = ((FuncExp *)ea)->fd; | |
1827 if (fd->type->ty == Tfunction) | |
1828 { | |
1829 TypeFunction *tf = (TypeFunction *)fd->type; | |
1830 /* If there are parameters that consist of only an identifier, | |
1831 * rather than assuming the identifier is a type, as we would | |
1832 * for regular function declarations, assume the identifier | |
1833 * is the parameter name, and we're building a template with | |
1834 * a deduced type. | |
1835 */ | |
1836 TemplateParameters *tpl = NULL; | |
1837 for (int i = 0; i < tf->parameters->dim; i++) | |
1838 { Argument *param = (Argument *)tf->parameters->data[i]; | |
1839 if (param->ident == NULL && | |
1840 param->type && | |
1841 param->type->ty == Tident && | |
1842 ((TypeIdentifier *)param->type)->idents.dim == 0 | |
1843 ) | |
1844 { | |
1845 /* Switch parameter type to parameter identifier, | |
1846 * parameterize with template type parameter _T | |
1847 */ | |
1848 TypeIdentifier *pt = (TypeIdentifier *)param->type; | |
1849 param->ident = pt->ident; | |
1850 Identifier *id = Lexer::uniqueId("__T"); | |
1851 param->type = new TypeIdentifier(pt->loc, id); | |
1852 TemplateParameter *tp = new TemplateTypeParameter(fd->loc, id, NULL, NULL); | |
1853 if (!tpl) | |
1854 tpl = new TemplateParameters(); | |
1855 tpl->push(tp); | |
1856 } | |
1857 } | |
1858 | |
1859 if (tpl) | |
1860 { // Wrap a template around function fd | |
1861 Array *decldefs = new Array(); | |
1862 decldefs->push(fd); | |
1863 TemplateDeclaration *tempdecl = | |
1864 new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs); | |
1865 tempdecl->literal = 1; // it's a template 'literal' | |
1866 tiargs->push(tempdecl); | |
1867 goto L1; | |
1868 } | |
1869 } | |
1870 } | |
1871 | |
1757 tiargs->push(ea); | 1872 tiargs->push(ea); |
1758 } | 1873 } |
1874 L1: | |
1759 if (token.value != TOKcomma) | 1875 if (token.value != TOKcomma) |
1760 break; | 1876 break; |
1761 nextToken(); | 1877 nextToken(); |
1762 } | 1878 } |
1763 } | 1879 } |
1853 if (!a) | 1969 if (!a) |
1854 a = new Array(); | 1970 a = new Array(); |
1855 a->push(id); | 1971 a->push(id); |
1856 nextToken(); | 1972 nextToken(); |
1857 if (token.value != TOKidentifier) | 1973 if (token.value != TOKidentifier) |
1858 { error("Identifier expected following package"); | 1974 { error("identifier expected following package"); |
1859 break; | 1975 break; |
1860 } | 1976 } |
1861 id = token.ident; | 1977 id = token.ident; |
1862 nextToken(); | 1978 nextToken(); |
1863 } | 1979 } |
1864 | 1980 |
1865 s = new Import(loc, a, token.ident, aliasid, isstatic); | 1981 s = new Import(loc, a, id, aliasid, isstatic); |
1866 decldefs->push(s); | 1982 decldefs->push(s); |
1867 | 1983 |
1868 /* Look for | 1984 /* Look for |
1869 * : alias=name, alias=name; | 1985 * : alias=name, alias=name; |
1870 * syntax. | 1986 * syntax. |
1871 */ | 1987 */ |
1872 if (token.value == TOKcolon) | 1988 if (token.value == TOKcolon) |
1873 { | 1989 { |
1874 do | 1990 do |
1875 { Identifier *name; | 1991 { Identifier *name; |
1876 Identifier *alias; | |
1877 | 1992 |
1878 nextToken(); | 1993 nextToken(); |
1879 if (token.value != TOKidentifier) | 1994 if (token.value != TOKidentifier) |
1880 { error("Identifier expected following :"); | 1995 { error("Identifier expected following :"); |
1881 break; | 1996 break; |
1882 } | 1997 } |
1883 alias = token.ident; | 1998 Identifier *alias = token.ident; |
1884 nextToken(); | 1999 nextToken(); |
1885 if (token.value == TOKassign) | 2000 if (token.value == TOKassign) |
1886 { | 2001 { |
1887 nextToken(); | 2002 nextToken(); |
1888 if (token.value != TOKidentifier) | 2003 if (token.value != TOKidentifier) |
1913 } | 2028 } |
1914 | 2029 |
1915 return NULL; | 2030 return NULL; |
1916 } | 2031 } |
1917 | 2032 |
2033 #if DMDV2 | |
1918 Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) | 2034 Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) |
1919 { Type *t; | 2035 { Type *t; |
1920 | 2036 |
1921 if (token.value == TOKconst && peek(&token)->value != TOKlparen) | 2037 /* Take care of the storage class prefixes that |
2038 * serve as type attributes: | |
2039 * const shared, shared const, const, invariant, shared | |
2040 */ | |
2041 if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen || | |
2042 token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen) | |
2043 { | |
2044 nextToken(); | |
2045 nextToken(); | |
2046 /* shared const type | |
2047 */ | |
2048 t = parseType(pident, tpl); | |
2049 t = t->makeSharedConst(); | |
2050 return t; | |
2051 } | |
2052 else if (token.value == TOKconst && peekNext() != TOKlparen) | |
1922 { | 2053 { |
1923 nextToken(); | 2054 nextToken(); |
1924 /* const type | 2055 /* const type |
1925 */ | 2056 */ |
1926 t = parseType(pident, tpl); | 2057 t = parseType(pident, tpl); |
1927 t = t->makeConst(); | 2058 t = t->makeConst(); |
1928 return t; | 2059 return t; |
1929 } | 2060 } |
1930 else if ((token.value == TOKinvariant || token.value == TOKimmutable) && | 2061 else if ((token.value == TOKinvariant || token.value == TOKimmutable) && |
1931 peek(&token)->value != TOKlparen) | 2062 peekNext() != TOKlparen) |
1932 { | 2063 { |
1933 nextToken(); | 2064 nextToken(); |
1934 /* invariant type | 2065 /* invariant type |
1935 */ | 2066 */ |
1936 t = parseType(pident, tpl); | 2067 t = parseType(pident, tpl); |
1937 t = t->makeInvariant(); | 2068 t = t->makeInvariant(); |
1938 return t; | 2069 return t; |
1939 } | 2070 } |
2071 else if (token.value == TOKshared && peekNext() != TOKlparen) | |
2072 { | |
2073 nextToken(); | |
2074 /* shared type | |
2075 */ | |
2076 t = parseType(pident, tpl); | |
2077 t = t->makeShared(); | |
2078 return t; | |
2079 } | |
1940 else | 2080 else |
1941 t = parseBasicType(); | 2081 t = parseBasicType(); |
1942 t = parseDeclarator(t, pident, tpl); | 2082 t = parseDeclarator(t, pident, tpl); |
1943 return t; | 2083 return t; |
1944 } | 2084 } |
2085 #endif | |
1945 | 2086 |
1946 Type *Parser::parseBasicType() | 2087 Type *Parser::parseBasicType() |
1947 { Type *t; | 2088 { Type *t; |
1948 Identifier *id; | 2089 Identifier *id; |
1949 TypeQualified *tid; | 2090 TypeQualified *tid; |
2014 // const(type) | 2155 // const(type) |
2015 nextToken(); | 2156 nextToken(); |
2016 check(TOKlparen); | 2157 check(TOKlparen); |
2017 t = parseType(); | 2158 t = parseType(); |
2018 check(TOKrparen); | 2159 check(TOKrparen); |
2019 t = t->makeConst(); | 2160 if (t->isShared()) |
2161 t = t->makeSharedConst(); | |
2162 else | |
2163 t = t->makeConst(); | |
2020 break; | 2164 break; |
2021 | 2165 |
2022 case TOKinvariant: | 2166 case TOKinvariant: |
2023 case TOKimmutable: | 2167 case TOKimmutable: |
2024 // invariant(type) | 2168 // invariant(type) |
2025 nextToken(); | 2169 nextToken(); |
2026 check(TOKlparen); | 2170 check(TOKlparen); |
2027 t = parseType(); | 2171 t = parseType(); |
2028 check(TOKrparen); | 2172 check(TOKrparen); |
2029 t = t->makeInvariant(); | 2173 t = t->makeInvariant(); |
2174 break; | |
2175 | |
2176 case TOKshared: | |
2177 // shared(type) | |
2178 nextToken(); | |
2179 check(TOKlparen); | |
2180 t = parseType(); | |
2181 check(TOKrparen); | |
2182 if (t->isConst()) | |
2183 t = t->makeSharedConst(); | |
2184 else | |
2185 t = t->makeShared(); | |
2030 break; | 2186 break; |
2031 | 2187 |
2032 default: | 2188 default: |
2033 error("basic type expected, not %s", token.toChars()); | 2189 error("basic type expected, not %s", token.toChars()); |
2034 t = Type::tint32; | 2190 t = Type::tint32; |
2245 while (1) | 2401 while (1) |
2246 { | 2402 { |
2247 switch (token.value) | 2403 switch (token.value) |
2248 { | 2404 { |
2249 case TOKconst: | 2405 case TOKconst: |
2250 tf = tf->makeConst(); | 2406 if (tf->isShared()) |
2407 tf = tf->makeSharedConst(); | |
2408 else | |
2409 tf = tf->makeConst(); | |
2251 nextToken(); | 2410 nextToken(); |
2252 continue; | 2411 continue; |
2253 | 2412 |
2254 case TOKinvariant: | 2413 case TOKinvariant: |
2255 case TOKimmutable: | 2414 case TOKimmutable: |
2256 tf = tf->makeInvariant(); | 2415 tf = tf->makeInvariant(); |
2416 nextToken(); | |
2417 continue; | |
2418 | |
2419 case TOKshared: | |
2420 if (tf->isConst()) | |
2421 tf = tf->makeSharedConst(); | |
2422 else | |
2423 tf = tf->makeShared(); | |
2257 nextToken(); | 2424 nextToken(); |
2258 continue; | 2425 continue; |
2259 | 2426 |
2260 case TOKnothrow: | 2427 case TOKnothrow: |
2261 ((TypeFunction *)tf)->isnothrow = 1; | 2428 ((TypeFunction *)tf)->isnothrow = 1; |
2314 goto L2; | 2481 goto L2; |
2315 } | 2482 } |
2316 | 2483 |
2317 switch (token.value) | 2484 switch (token.value) |
2318 { | 2485 { |
2486 case TOKalias: | |
2487 /* Look for: | |
2488 * alias identifier this; | |
2489 */ | |
2490 tok = token.value; | |
2491 nextToken(); | |
2492 if (token.value == TOKidentifier && peek(&token)->value == TOKthis) | |
2493 { | |
2494 AliasThis *s = new AliasThis(this->loc, token.ident); | |
2495 nextToken(); | |
2496 check(TOKthis); | |
2497 check(TOKsemicolon); | |
2498 a = new Array(); | |
2499 a->push(s); | |
2500 addComment(s, comment); | |
2501 return a; | |
2502 } | |
2503 break; | |
2319 case TOKtypedef: | 2504 case TOKtypedef: |
2320 case TOKalias: | |
2321 tok = token.value; | 2505 tok = token.value; |
2322 nextToken(); | 2506 nextToken(); |
2323 break; | 2507 break; |
2324 } | 2508 } |
2325 | 2509 |
2336 | 2520 |
2337 case TOKinvariant: | 2521 case TOKinvariant: |
2338 case TOKimmutable: | 2522 case TOKimmutable: |
2339 if (peek(&token)->value == TOKlparen) | 2523 if (peek(&token)->value == TOKlparen) |
2340 break; | 2524 break; |
2341 stc = STCinvariant; | 2525 stc = STCimmutable; |
2342 goto L1; | 2526 goto L1; |
2343 | 2527 |
2344 case TOKshared: | 2528 case TOKshared: |
2345 if (peek(&token)->value == TOKlparen) | 2529 if (peek(&token)->value == TOKlparen) |
2346 break; | 2530 break; |
2353 case TOKscope: stc = STCscope; goto L1; | 2537 case TOKscope: stc = STCscope; goto L1; |
2354 case TOKoverride: stc = STCoverride; goto L1; | 2538 case TOKoverride: stc = STCoverride; goto L1; |
2355 case TOKabstract: stc = STCabstract; goto L1; | 2539 case TOKabstract: stc = STCabstract; goto L1; |
2356 case TOKsynchronized: stc = STCsynchronized; goto L1; | 2540 case TOKsynchronized: stc = STCsynchronized; goto L1; |
2357 case TOKdeprecated: stc = STCdeprecated; goto L1; | 2541 case TOKdeprecated: stc = STCdeprecated; goto L1; |
2542 #if DMDV2 | |
2358 case TOKnothrow: stc = STCnothrow; goto L1; | 2543 case TOKnothrow: stc = STCnothrow; goto L1; |
2359 case TOKpure: stc = STCpure; goto L1; | 2544 case TOKpure: stc = STCpure; goto L1; |
2360 case TOKref: stc = STCref; goto L1; | 2545 case TOKref: stc = STCref; goto L1; |
2361 case TOKtls: stc = STCtls; goto L1; | 2546 case TOKtls: stc = STCtls; goto L1; |
2547 case TOKgshared: stc = STCgshared; goto L1; | |
2362 case TOKenum: stc = STCmanifest; goto L1; | 2548 case TOKenum: stc = STCmanifest; goto L1; |
2549 #endif | |
2363 L1: | 2550 L1: |
2364 if (storage_class & stc) | 2551 if (storage_class & stc) |
2365 error("redundant storage class '%s'", token.toChars()); | 2552 error("redundant storage class '%s'", token.toChars()); |
2366 storage_class = (STC) (storage_class | stc); | 2553 storage_class = (STC) (storage_class | stc); |
2367 { | 2554 composeStorageClass(storage_class); |
2368 unsigned u = storage_class; | |
2369 u &= STCconst | STCinvariant | STCmanifest; | |
2370 if (u & (u - 1)) | |
2371 error("conflicting storage class %s", Token::toChars(token.value)); | |
2372 } | |
2373 nextToken(); | 2555 nextToken(); |
2374 continue; | 2556 continue; |
2375 | 2557 |
2376 case TOKextern: | 2558 case TOKextern: |
2377 if (peek(&token)->value != TOKlparen) | 2559 if (peek(&token)->value != TOKlparen) |
3069 case TOKconst: | 3251 case TOKconst: |
3070 case TOKauto: | 3252 case TOKauto: |
3071 case TOKextern: | 3253 case TOKextern: |
3072 case TOKfinal: | 3254 case TOKfinal: |
3073 case TOKinvariant: | 3255 case TOKinvariant: |
3256 #if DMDV2 | |
3074 case TOKimmutable: | 3257 case TOKimmutable: |
3258 case TOKshared: | |
3259 case TOKnothrow: | |
3260 case TOKpure: | |
3261 case TOKtls: | |
3262 case TOKgshared: | |
3263 #endif | |
3075 // case TOKtypeof: | 3264 // case TOKtypeof: |
3076 Ldeclaration: | 3265 Ldeclaration: |
3077 { Array *a; | 3266 { Array *a; |
3078 | 3267 |
3079 a = parseDeclarations(STCundefined); | 3268 a = parseDeclarations(STCundefined); |
3085 { | 3274 { |
3086 Dsymbol *d = (Dsymbol *)a->data[i]; | 3275 Dsymbol *d = (Dsymbol *)a->data[i]; |
3087 s = new DeclarationStatement(loc, d); | 3276 s = new DeclarationStatement(loc, d); |
3088 as->push(s); | 3277 as->push(s); |
3089 } | 3278 } |
3090 s = new CompoundStatement(loc, as); | 3279 s = new CompoundDeclarationStatement(loc, as); |
3091 } | 3280 } |
3092 else if (a->dim == 1) | 3281 else if (a->dim == 1) |
3093 { | 3282 { |
3094 Dsymbol *d = (Dsymbol *)a->data[0]; | 3283 Dsymbol *d = (Dsymbol *)a->data[0]; |
3095 s = new DeclarationStatement(loc, d); | 3284 s = new DeclarationStatement(loc, d); |
3841 { | 4030 { |
3842 //printf("isDeclaration(needId = %d)\n", needId); | 4031 //printf("isDeclaration(needId = %d)\n", needId); |
3843 int haveId = 0; | 4032 int haveId = 0; |
3844 | 4033 |
3845 #if DMDV2 | 4034 #if DMDV2 |
3846 if ((t->value == TOKconst || t->value == TOKinvariant || token.value == TOKimmutable) && | 4035 if ((t->value == TOKconst || |
4036 t->value == TOKinvariant || | |
4037 t->value == TOKimmutable || | |
4038 t->value == TOKshared) && | |
3847 peek(t)->value != TOKlparen) | 4039 peek(t)->value != TOKlparen) |
3848 { /* const type | 4040 { /* const type |
3849 * invariant type | 4041 * immutable type |
4042 * shared type | |
3850 */ | 4043 */ |
3851 t = peek(t); | 4044 t = peek(t); |
3852 } | 4045 } |
3853 #endif | 4046 #endif |
3854 | 4047 |
3855 if (!isBasicType(&t)) | 4048 if (!isBasicType(&t)) |
4049 { | |
3856 goto Lisnot; | 4050 goto Lisnot; |
4051 } | |
3857 if (!isDeclarator(&t, &haveId, endtok)) | 4052 if (!isDeclarator(&t, &haveId, endtok)) |
3858 goto Lisnot; | 4053 goto Lisnot; |
3859 if ( needId == 1 || | 4054 if ( needId == 1 || |
3860 (needId == 0 && !haveId) || | 4055 (needId == 0 && !haveId) || |
3861 (needId == 2 && haveId)) | 4056 (needId == 2 && haveId)) |
3968 goto L2; | 4163 goto L2; |
3969 | 4164 |
3970 case TOKconst: | 4165 case TOKconst: |
3971 case TOKinvariant: | 4166 case TOKinvariant: |
3972 case TOKimmutable: | 4167 case TOKimmutable: |
3973 // const(type) or invariant(type) | 4168 case TOKshared: |
4169 // const(type) or immutable(type) or shared(type) | |
3974 t = peek(t); | 4170 t = peek(t); |
3975 if (t->value != TOKlparen) | 4171 if (t->value != TOKlparen) |
3976 goto Lfalse; | 4172 goto Lfalse; |
3977 t = peek(t); | 4173 t = peek(t); |
3978 if (!isDeclaration(t, 0, TOKrparen, &t)) | 4174 if (!isDeclaration(t, 0, TOKrparen, &t)) |
4175 { | |
3979 goto Lfalse; | 4176 goto Lfalse; |
4177 } | |
3980 t = peek(t); | 4178 t = peek(t); |
3981 break; | 4179 break; |
3982 | 4180 |
3983 default: | 4181 default: |
3984 goto Lfalse; | 4182 goto Lfalse; |
4006 { | 4204 { |
4007 parens = FALSE; | 4205 parens = FALSE; |
4008 switch (t->value) | 4206 switch (t->value) |
4009 { | 4207 { |
4010 case TOKmul: | 4208 case TOKmul: |
4011 // case TOKand: | 4209 //case TOKand: |
4012 t = peek(t); | 4210 t = peek(t); |
4013 continue; | 4211 continue; |
4014 | 4212 |
4015 case TOKlbracket: | 4213 case TOKlbracket: |
4016 t = peek(t); | 4214 t = peek(t); |
4111 | 4309 |
4112 case TOKlparen: | 4310 case TOKlparen: |
4113 parens = FALSE; | 4311 parens = FALSE; |
4114 if (!isParameters(&t)) | 4312 if (!isParameters(&t)) |
4115 return FALSE; | 4313 return FALSE; |
4314 #if DMDV2 | |
4116 while (1) | 4315 while (1) |
4117 { | 4316 { |
4118 switch (t->value) | 4317 switch (t->value) |
4119 { | 4318 { |
4120 case TOKconst: | 4319 case TOKconst: |
4121 case TOKinvariant: | 4320 case TOKinvariant: |
4122 case TOKimmutable: | 4321 case TOKimmutable: |
4322 case TOKshared: | |
4123 case TOKpure: | 4323 case TOKpure: |
4124 case TOKnothrow: | 4324 case TOKnothrow: |
4125 t = peek(t); | 4325 t = peek(t); |
4126 continue; | 4326 continue; |
4127 default: | 4327 default: |
4128 break; | 4328 break; |
4129 } | 4329 } |
4130 break; | 4330 break; |
4131 } | 4331 } |
4332 #endif | |
4132 continue; | 4333 continue; |
4133 | 4334 |
4134 // Valid tokens that follow a declaration | 4335 // Valid tokens that follow a declaration |
4135 case TOKrparen: | 4336 case TOKrparen: |
4136 case TOKrbracket: | 4337 case TOKrbracket: |
4180 case TOKref: | 4381 case TOKref: |
4181 case TOKlazy: | 4382 case TOKlazy: |
4182 case TOKconst: | 4383 case TOKconst: |
4183 case TOKinvariant: | 4384 case TOKinvariant: |
4184 case TOKimmutable: | 4385 case TOKimmutable: |
4386 case TOKshared: | |
4185 case TOKfinal: | 4387 case TOKfinal: |
4186 continue; | 4388 continue; |
4187 | 4389 |
4188 #if 0 | 4390 #if 0 |
4189 case TOKstatic: | 4391 case TOKstatic: |
4476 e = new SuperExp(loc); | 4678 e = new SuperExp(loc); |
4477 nextToken(); | 4679 nextToken(); |
4478 break; | 4680 break; |
4479 | 4681 |
4480 case TOKint32v: | 4682 case TOKint32v: |
4481 e = new IntegerExp(loc, token.int32value, Type::tint32); | 4683 e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32); |
4482 nextToken(); | 4684 nextToken(); |
4483 break; | 4685 break; |
4484 | 4686 |
4485 case TOKuns32v: | 4687 case TOKuns32v: |
4486 e = new IntegerExp(loc, token.uns32value, Type::tuns32); | 4688 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32); |
4487 nextToken(); | 4689 nextToken(); |
4488 break; | 4690 break; |
4489 | 4691 |
4490 case TOKint64v: | 4692 case TOKint64v: |
4491 e = new IntegerExp(loc, token.int64value, Type::tint64); | 4693 e = new IntegerExp(loc, token.int64value, Type::tint64); |
4532 nextToken(); | 4734 nextToken(); |
4533 break; | 4735 break; |
4534 | 4736 |
4535 #if DMDV2 | 4737 #if DMDV2 |
4536 case TOKfile: | 4738 case TOKfile: |
4537 { char *s = loc.filename ? loc.filename : mod->ident->toChars(); | 4739 { const char *s = loc.filename ? loc.filename : mod->ident->toChars(); |
4538 e = new StringExp(loc, s, strlen(s), 0); | 4740 e = new StringExp(loc, (char *)s, strlen(s), 0); |
4539 nextToken(); | 4741 nextToken(); |
4540 break; | 4742 break; |
4541 } | 4743 } |
4542 | 4744 |
4543 case TOKline: | 4745 case TOKline: |
4555 e = new IntegerExp(loc, 0, Type::tbool); | 4757 e = new IntegerExp(loc, 0, Type::tbool); |
4556 nextToken(); | 4758 nextToken(); |
4557 break; | 4759 break; |
4558 | 4760 |
4559 case TOKcharv: | 4761 case TOKcharv: |
4560 e = new IntegerExp(loc, token.uns32value, Type::tchar); | 4762 e = new IntegerExp(loc, (d_uns8)token.uns64value, Type::tchar); |
4561 nextToken(); | 4763 nextToken(); |
4562 break; | 4764 break; |
4563 | 4765 |
4564 case TOKwcharv: | 4766 case TOKwcharv: |
4565 e = new IntegerExp(loc, token.uns32value, Type::twchar); | 4767 e = new IntegerExp(loc, (d_uns16)token.uns64value, Type::twchar); |
4566 nextToken(); | 4768 nextToken(); |
4567 break; | 4769 break; |
4568 | 4770 |
4569 case TOKdcharv: | 4771 case TOKdcharv: |
4570 e = new IntegerExp(loc, token.uns32value, Type::tdchar); | 4772 e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar); |
4571 nextToken(); | 4773 nextToken(); |
4572 break; | 4774 break; |
4573 | 4775 |
4574 case TOKstring: | 4776 case TOKstring: |
4575 { unsigned char *s; | 4777 { unsigned char *s; |
4615 check(TOKdot, t->toChars()); | 4817 check(TOKdot, t->toChars()); |
4616 if (token.value != TOKidentifier) | 4818 if (token.value != TOKidentifier) |
4617 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars()); | 4819 { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars()); |
4618 goto Lerr; | 4820 goto Lerr; |
4619 } | 4821 } |
4620 e = new TypeDotIdExp(loc, t, token.ident); | 4822 e = typeDotIdExp(loc, t, token.ident); |
4621 nextToken(); | 4823 nextToken(); |
4622 break; | 4824 break; |
4623 | 4825 |
4624 case TOKtypeof: | 4826 case TOKtypeof: |
4625 { | 4827 { |
4688 token.value == TOKunion || | 4890 token.value == TOKunion || |
4689 token.value == TOKclass || | 4891 token.value == TOKclass || |
4690 token.value == TOKsuper || | 4892 token.value == TOKsuper || |
4691 token.value == TOKenum || | 4893 token.value == TOKenum || |
4692 token.value == TOKinterface || | 4894 token.value == TOKinterface || |
4895 #if DMDV2 | |
4693 token.value == TOKconst && peek(&token)->value == TOKrparen || | 4896 token.value == TOKconst && peek(&token)->value == TOKrparen || |
4694 token.value == TOKinvariant && peek(&token)->value == TOKrparen || | 4897 token.value == TOKinvariant && peek(&token)->value == TOKrparen || |
4695 token.value == TOKimmutable && peek(&token)->value == TOKrparen || | 4898 token.value == TOKimmutable && peek(&token)->value == TOKrparen || |
4899 token.value == TOKshared && peek(&token)->value == TOKrparen || | |
4900 #endif | |
4696 token.value == TOKfunction || | 4901 token.value == TOKfunction || |
4697 token.value == TOKdelegate || | 4902 token.value == TOKdelegate || |
4698 token.value == TOKreturn)) | 4903 token.value == TOKreturn)) |
4699 { | 4904 { |
4700 tok2 = token.value; | 4905 tok2 = token.value; |
4863 else | 5068 else |
4864 break; | 5069 break; |
4865 nextToken(); | 5070 nextToken(); |
4866 } | 5071 } |
4867 } | 5072 } |
5073 | |
4868 TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage); | 5074 TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage); |
4869 tf->ispure = ispure; | 5075 tf->ispure = ispure; |
4870 tf->isnothrow = isnothrow; | 5076 tf->isnothrow = isnothrow; |
4871 fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL); | 5077 fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL); |
4872 parseContracts(fd); | 5078 parseContracts(fd); |
5056 case TOKnew: | 5262 case TOKnew: |
5057 e = parseNewExp(NULL); | 5263 e = parseNewExp(NULL); |
5058 break; | 5264 break; |
5059 | 5265 |
5060 case TOKcast: // cast(type) expression | 5266 case TOKcast: // cast(type) expression |
5061 { Type *t; | 5267 { |
5062 | |
5063 nextToken(); | 5268 nextToken(); |
5064 check(TOKlparen); | 5269 check(TOKlparen); |
5065 /* Look for cast(const) and cast(invariant) | 5270 /* Look for cast(), cast(const), cast(immutable), |
5271 * cast(shared), cast(shared const) | |
5066 */ | 5272 */ |
5067 if ((token.value == TOKconst || token.value == TOKinvariant || token.value == TOKimmutable) && | 5273 unsigned m; |
5068 peek(&token)->value == TOKrparen) | 5274 if (token.value == TOKrparen) |
5069 { enum TOK tok = token.value; | 5275 { |
5070 nextToken(); | 5276 m = 0; |
5277 goto Lmod1; | |
5278 } | |
5279 else if (token.value == TOKconst && peekNext() == TOKrparen) | |
5280 { | |
5281 m = MODconst; | |
5282 goto Lmod2; | |
5283 } | |
5284 else if ((token.value == TOKimmutable || token.value == TOKinvariant) && peekNext() == TOKrparen) | |
5285 { | |
5286 m = MODinvariant; | |
5287 goto Lmod2; | |
5288 } | |
5289 else if (token.value == TOKshared && peekNext() == TOKrparen) | |
5290 { | |
5291 m = MODshared; | |
5292 goto Lmod2; | |
5293 } | |
5294 else if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() == TOKrparen || | |
5295 token.value == TOKshared && peekNext() == TOKconst && peekNext2() == TOKrparen) | |
5296 { | |
5297 m = MODshared | MODconst; | |
5298 nextToken(); | |
5299 Lmod2: | |
5300 nextToken(); | |
5301 Lmod1: | |
5071 nextToken(); | 5302 nextToken(); |
5072 e = parseUnaryExp(); | 5303 e = parseUnaryExp(); |
5073 e = new CastExp(loc, e, tok); | 5304 e = new CastExp(loc, e, m); |
5074 } | 5305 } |
5075 else | 5306 else |
5076 { | 5307 { |
5077 t = parseType(); // ( type ) | 5308 Type *t = parseType(); // ( type ) |
5078 check(TOKrparen); | 5309 check(TOKrparen); |
5079 e = parseUnaryExp(); | 5310 e = parseUnaryExp(); |
5080 e = new CastExp(loc, e, t); | 5311 e = new CastExp(loc, e, t); |
5081 } | 5312 } |
5082 break; | 5313 break; |
5151 nextToken(); | 5382 nextToken(); |
5152 if (token.value != TOKidentifier) | 5383 if (token.value != TOKidentifier) |
5153 { error("Identifier expected following (type)."); | 5384 { error("Identifier expected following (type)."); |
5154 return NULL; | 5385 return NULL; |
5155 } | 5386 } |
5156 e = new TypeDotIdExp(loc, t, token.ident); | 5387 e = typeDotIdExp(loc, t, token.ident); |
5157 nextToken(); | 5388 nextToken(); |
5158 e = parsePostExp(e); | 5389 e = parsePostExp(e); |
5159 } | 5390 } |
5160 else | 5391 else |
5161 { | 5392 { |