Mercurial > projects > dil
comparison trunk/src/dil/Parser.d @ 505:3bb94ba21490
Refactored a great amount of code.
Changed many declaration types from Token* to Identifier*.
Fix in parseStructInitializer(): append null to idents in else body.
Fixed class Parameter and parseParameterList().
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Wed, 12 Dec 2007 02:25:42 +0100 |
parents | 9076c4cea2a4 |
children | 996041463028 |
comparison
equal
deleted
inserted
replaced
504:9076c4cea2a4 | 505:3bb94ba21490 |
---|---|
158 auto begin = token; | 158 auto begin = token; |
159 ModuleFQN moduleFQN; | 159 ModuleFQN moduleFQN; |
160 do | 160 do |
161 { | 161 { |
162 nT(); | 162 nT(); |
163 moduleFQN ~= requireIdentifier("expected module identifier, not '{}'"); | 163 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); |
164 } while (token.type == T.Dot) | 164 } while (token.type == T.Dot) |
165 require(T.Semicolon); | 165 require(T.Semicolon); |
166 return set(new ModuleDeclaration(moduleFQN), begin); | 166 return set(new ModuleDeclaration(moduleFQN), begin); |
167 } | 167 } |
168 | 168 |
364 nT(); | 364 nT(); |
365 while (!token.isDeclDefStart && | 365 while (!token.isDeclDefStart && |
366 token.type != T.RBrace && | 366 token.type != T.RBrace && |
367 token.type != T.EOF) | 367 token.type != T.EOF) |
368 auto text = Token.textSpan(begin, this.prevToken); | 368 auto text = Token.textSpan(begin, this.prevToken); |
369 error(begin, "illegal Declaration found: " ~ text); | 369 error(begin, MSG.IllegalDeclaration ~ text); |
370 } | 370 } |
371 decl.setProtection(this.protection); | 371 decl.setProtection(this.protection); |
372 decl.setStorageClass(this.storageClass); | 372 decl.setStorageClass(this.storageClass); |
373 assert(!isNodeSet(decl)); | 373 assert(!isNodeSet(decl)); |
374 set(decl, begin); | 374 set(decl, begin); |
430 bool testAutoDeclaration = false, | 430 bool testAutoDeclaration = false, |
431 bool optionalParameterList = true) | 431 bool optionalParameterList = true) |
432 { | 432 { |
433 auto begin = token; | 433 auto begin = token; |
434 Type type; | 434 Type type; |
435 Token* ident; | 435 Identifier* ident; |
436 | 436 |
437 // Check for AutoDeclaration: StorageClasses Identifier = | 437 // Check for AutoDeclaration: StorageClasses Identifier = |
438 if (testAutoDeclaration && | 438 if (testAutoDeclaration && |
439 token.type == T.Identifier && | 439 token.type == T.Identifier && |
440 peekNext() == T.Assign) | 440 peekNext() == T.Assign) |
441 { | 441 { |
442 ident = token; | 442 ident = token.ident; |
443 nT(); | 443 nT(); |
444 } | 444 } |
445 else | 445 else |
446 { | 446 { |
447 type = parseType(); | 447 type = parseType(); |
460 // something(*p); | 460 // something(*p); |
461 type = parseCFunctionPointerType(type, ident, optionalParameterList); | 461 type = parseCFunctionPointerType(type, ident, optionalParameterList); |
462 } | 462 } |
463 else | 463 else |
464 { | 464 { |
465 ident = requireId(); | 465 ident = requireIdentifier(MSG.ExpectedFunctionName); |
466 // Type FunctionName ( ParameterList ) FunctionBody | 466 // Type FunctionName ( ParameterList ) FunctionBody |
467 if (token.type == T.LParen) | 467 if (token.type == T.LParen) |
468 { | 468 { |
469 // It's a function declaration | 469 // It's a function declaration |
470 TemplateParameters tparams; | 470 TemplateParameters tparams; |
501 type = parseDeclaratorSuffix(type); | 501 type = parseDeclaratorSuffix(type); |
502 } | 502 } |
503 } | 503 } |
504 | 504 |
505 // It's a variable declaration. | 505 // It's a variable declaration. |
506 Token*[] idents = [ident]; | 506 Identifier*[] idents = [ident]; |
507 Expression[] values; | 507 Expression[] values; |
508 goto LenterLoop; // We've already parsed an identifier. Jump to if statement and check for initializer. | 508 goto LenterLoop; // We've already parsed an identifier. Jump to if statement and check for initializer. |
509 while (token.type == T.Comma) | 509 while (token.type == T.Comma) |
510 { | 510 { |
511 nT(); | 511 nT(); |
512 idents ~= requireId(); | 512 idents ~= requireIdentifier(MSG.ExpectedVariableName); |
513 LenterLoop: | 513 LenterLoop: |
514 if (token.type == T.Assign) | 514 if (token.type == T.Assign) |
515 nT(), (values ~= parseInitializer()); | 515 nT(), (values ~= parseInitializer()); |
516 else | 516 else |
517 values ~= null; | 517 values ~= null; |
579 // StructInitializer: | 579 // StructInitializer: |
580 // { } | 580 // { } |
581 // { StructMemberInitializers } | 581 // { StructMemberInitializers } |
582 Expression parseStructInitializer() | 582 Expression parseStructInitializer() |
583 { | 583 { |
584 Token*[] idents; | 584 Identifier*[] idents; |
585 Expression[] values; | 585 Expression[] values; |
586 | 586 |
587 nT(); | 587 nT(); |
588 while (token.type != T.RBrace) | 588 while (token.type != T.RBrace) |
589 { | 589 { |
590 if (token.type == T.Identifier) | 590 if (token.type == T.Identifier && |
591 // Peek for colon to see if this is a member identifier. | |
592 peekNext() == T.Colon) | |
591 { | 593 { |
592 // Peek for colon to see if this is a member identifier. | 594 idents ~= token.ident; |
593 if (peekNext() == T.Colon) | 595 nT(), nT(); // Skip Identifier : |
594 { | |
595 idents ~= token; | |
596 nT(); | |
597 nT(); | |
598 } | |
599 } | 596 } |
597 else | |
598 idents ~= null; | |
599 | |
600 // NonVoidInitializer | 600 // NonVoidInitializer |
601 values ~= parseNonVoidInitializer(); | 601 values ~= parseNonVoidInitializer(); |
602 | 602 |
603 if (token.type != T.Comma) | 603 if (token.type != T.Comma) |
604 break; | 604 break; |
649 error(MID.OutContract); | 649 error(MID.OutContract); |
650 nT(); | 650 nT(); |
651 if (token.type == T.LParen) | 651 if (token.type == T.LParen) |
652 { | 652 { |
653 nT(); | 653 nT(); |
654 func.outIdent = requireId(); | 654 func.outIdent = requireIdentifier(MSG.ExpectedAnIdentifier); |
655 require(T.RParen); | 655 require(T.RParen); |
656 } | 656 } |
657 func.outBody = parseStatements(); | 657 func.outBody = parseStatements(); |
658 continue; | 658 continue; |
659 case T.Body: | 659 case T.Body: |
660 nT(); | 660 nT(); |
661 goto case T.LBrace; | 661 goto case T.LBrace; |
662 default: | 662 default: |
663 error(MID.ExpectedButFound, "FunctionBody", token.srcText); | 663 error(token, MSG.ExpectedFunctionBody, token.srcText); |
664 } | 664 } |
665 break; // Exit loop. | 665 break; // Exit loop. |
666 } | 666 } |
667 set(func, begin); | 667 set(func, begin); |
668 func.finishConstruction(); | 668 func.finishConstruction(); |
721 { | 721 { |
722 if (prev_lt == LinkageType.None) | 722 if (prev_lt == LinkageType.None) |
723 prev_lt = lt; | 723 prev_lt = lt; |
724 else | 724 else |
725 // TODO: create new msg RedundantLinkageType. | 725 // TODO: create new msg RedundantLinkageType. |
726 error(begin, "redundant linkage type: " ~ Token.textSpan(begin, this.prevToken)); | 726 error(begin, MSG.RedundantLinkageType ~ Token.textSpan(begin, this.prevToken)); |
727 } | 727 } |
728 | 728 |
729 Declaration parseStorageAttribute() | 729 Declaration parseStorageAttribute() |
730 { | 730 { |
731 StorageClass stc, stc_tmp; | 731 StorageClass stc, stc_tmp; |
865 case T.Pragma: | 865 case T.Pragma: |
866 // Pragma: | 866 // Pragma: |
867 // pragma ( Identifier ) | 867 // pragma ( Identifier ) |
868 // pragma ( Identifier , ExpressionList ) | 868 // pragma ( Identifier , ExpressionList ) |
869 nT(); | 869 nT(); |
870 Token* ident; | 870 Identifier* ident; |
871 Expression[] args; | 871 Expression[] args; |
872 Declaration decls; | |
873 | 872 |
874 require(T.LParen); | 873 require(T.LParen); |
875 ident = requireId(); | 874 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier); |
876 | 875 |
877 if (token.type == T.Comma) | 876 if (token.type == T.Comma) |
878 { | 877 nT(), (args = parseExpressionList()); |
879 nT(); | |
880 args = parseExpressionList(); | |
881 } | |
882 require(T.RParen); | 878 require(T.RParen); |
883 | 879 |
884 if (token.type == T.Semicolon) | 880 decl = new PragmaDeclaration(ident, args, parseDeclarationsBlock()); |
885 { | |
886 nT(); | |
887 // TODO: call set()? | |
888 decls = new EmptyDeclaration(); | |
889 } | |
890 else | |
891 decls = parseDeclarationsBlock(); | |
892 | |
893 decl = new PragmaDeclaration(ident, args, decls); | |
894 break; | 881 break; |
895 default: | 882 default: |
896 // Protection attributes | 883 // Protection attributes |
897 Protection prot; | 884 Protection prot; |
898 switch (token.type) | 885 switch (token.type) |
945 Identifier* moduleAlias; | 932 Identifier* moduleAlias; |
946 | 933 |
947 // AliasName = ModuleName | 934 // AliasName = ModuleName |
948 if (peekNext() == T.Assign) | 935 if (peekNext() == T.Assign) |
949 { | 936 { |
950 moduleAlias = requireIdentifier("expected alias module name, not '{}'"); | 937 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName); |
951 nT(); // Skip = | 938 nT(); // Skip = |
952 } | 939 } |
953 | 940 |
954 // Identifier(.Identifier)* | 941 // Identifier(.Identifier)* |
955 while (1) | 942 while (1) |
956 { | 943 { |
957 moduleFQN ~= requireIdentifier("expected module identifier, not '{}'"); | 944 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); |
958 if (token.type != T.Dot) | 945 if (token.type != T.Dot) |
959 break; | 946 break; |
960 nT(); | 947 nT(); |
961 } | 948 } |
962 | 949 |
978 nT(); | 965 nT(); |
979 Identifier* bindAlias; | 966 Identifier* bindAlias; |
980 // BindAlias = BindName | 967 // BindAlias = BindName |
981 if (peekNext() == T.Assign) | 968 if (peekNext() == T.Assign) |
982 { | 969 { |
983 bindAlias = requireIdentifier("expected alias name, not '{}'"); | 970 bindAlias = requireIdentifier(MSG.ExpectedAliasImportName); |
984 nT(); // Skip = | 971 nT(); // Skip = |
985 } | 972 } |
986 // Push identifiers. | 973 // Push identifiers. |
987 bindNames ~= requireIdentifier("expected an identifier, not '{}'"); | 974 bindNames ~= requireIdentifier(MSG.ExpectedImportName); |
988 bindAliases ~= bindAlias; | 975 bindAliases ~= bindAlias; |
989 } while (token.type == T.Comma) | 976 } while (token.type == T.Comma) |
990 } | 977 } |
991 | 978 |
992 require(T.Semicolon); | 979 require(T.Semicolon); |
996 | 983 |
997 Declaration parseEnumDeclaration() | 984 Declaration parseEnumDeclaration() |
998 { | 985 { |
999 assert(token.type == T.Enum); | 986 assert(token.type == T.Enum); |
1000 | 987 |
1001 Token* enumName; | 988 Identifier* enumName; |
1002 Type baseType; | 989 Type baseType; |
1003 EnumMember[] members; | 990 EnumMember[] members; |
1004 bool hasBody; | 991 bool hasBody; |
1005 | 992 |
1006 nT(); // Skip enum keyword. | 993 nT(); // Skip enum keyword. |
1007 | 994 |
1008 if (token.type == T.Identifier) | 995 enumName = optionalIdentifier(); |
1009 { | |
1010 enumName = token; | |
1011 nT(); | |
1012 } | |
1013 | 996 |
1014 if (token.type == T.Colon) | 997 if (token.type == T.Colon) |
1015 { | 998 { |
1016 nT(); | 999 nT(); |
1017 baseType = parseBasicType(); | 1000 baseType = parseBasicType(); |
1028 hasBody = true; | 1011 hasBody = true; |
1029 nT(); // Skip { | 1012 nT(); // Skip { |
1030 while (token.type != T.RBrace) | 1013 while (token.type != T.RBrace) |
1031 { | 1014 { |
1032 auto begin = token; | 1015 auto begin = token; |
1033 auto memberName = requireId(); | 1016 auto name = requireIdentifier(MSG.ExpectedEnumMember); |
1034 Expression value; | 1017 Expression value; |
1035 | 1018 |
1036 if (token.type == T.Assign) | 1019 if (token.type == T.Assign) |
1037 { | 1020 nT(), (value = parseAssignExpression()); |
1038 nT(); | |
1039 value = parseAssignExpression(); | |
1040 } | |
1041 else | 1021 else |
1042 value = null; | 1022 value = null; |
1043 | 1023 |
1044 members ~= set(new EnumMember(memberName, value), begin); | 1024 members ~= set(new EnumMember(name, value), begin); |
1045 | 1025 |
1046 if (token.type != T.Comma) | 1026 if (token.type != T.Comma) |
1047 break; | 1027 break; |
1048 nT(); // Skip , | 1028 nT(); // Skip , |
1049 } | 1029 } |
1050 require(T.RBrace); | 1030 require(T.RBrace); |
1051 } | 1031 } |
1052 else | 1032 else |
1053 error(MID.ExpectedButFound, "enum declaration", token.srcText); | 1033 error(token, MSG.ExpectedEnumBody, token.srcText); |
1054 | 1034 |
1055 return new EnumDeclaration(enumName, baseType, members, hasBody); | 1035 return new EnumDeclaration(enumName, baseType, members, hasBody); |
1056 } | 1036 } |
1057 | 1037 |
1058 Declaration parseClassDeclaration() | 1038 Declaration parseClassDeclaration() |
1059 { | 1039 { |
1060 assert(token.type == T.Class); | 1040 assert(token.type == T.Class); |
1061 | 1041 |
1062 Token* className; | 1042 Identifier* className; |
1063 TemplateParameters tparams; | 1043 TemplateParameters tparams; |
1064 BaseClass[] bases; | 1044 BaseClass[] bases; |
1065 Declarations decls; | 1045 Declarations decls; |
1066 | 1046 |
1067 nT(); // Skip class keyword. | 1047 nT(); // Skip class keyword. |
1068 className = requireId(); | 1048 className = requireIdentifier(MSG.ExpectedClassName); |
1069 | 1049 |
1070 if (token.type == T.LParen) | 1050 if (token.type == T.LParen) |
1071 tparams = parseTemplateParameterList(); | 1051 tparams = parseTemplateParameterList(); |
1072 | 1052 |
1073 if (token.type == T.Colon) | 1053 if (token.type == T.Colon) |
1080 nT(); | 1060 nT(); |
1081 } | 1061 } |
1082 else if (token.type == T.LBrace) | 1062 else if (token.type == T.LBrace) |
1083 decls = parseDeclarationDefinitionsBody(); | 1063 decls = parseDeclarationDefinitionsBody(); |
1084 else | 1064 else |
1085 expected(T.LBrace); // TODO: better error msg | 1065 error(token, MSG.ExpectedClassBody, token.srcText); |
1086 | 1066 |
1087 return new ClassDeclaration(className, tparams, bases, decls); | 1067 return new ClassDeclaration(className, tparams, bases, decls); |
1088 } | 1068 } |
1089 | 1069 |
1090 BaseClass[] parseBaseClasses(bool colonLeadsOff = true) | 1070 BaseClass[] parseBaseClasses(bool colonLeadsOff = true) |
1127 | 1107 |
1128 Declaration parseInterfaceDeclaration() | 1108 Declaration parseInterfaceDeclaration() |
1129 { | 1109 { |
1130 assert(token.type == T.Interface); | 1110 assert(token.type == T.Interface); |
1131 | 1111 |
1132 Token* name; | 1112 Identifier* name; |
1133 TemplateParameters tparams; | 1113 TemplateParameters tparams; |
1134 BaseClass[] bases; | 1114 BaseClass[] bases; |
1135 Declarations decls; | 1115 Declarations decls; |
1136 | 1116 |
1137 nT(); // Skip interface keyword. | 1117 nT(); // Skip interface keyword. |
1138 name = requireId(); | 1118 name = requireIdentifier(MSG.ExpectedInterfaceName); |
1139 | 1119 |
1140 if (token.type == T.LParen) | 1120 if (token.type == T.LParen) |
1141 tparams = parseTemplateParameterList(); | 1121 tparams = parseTemplateParameterList(); |
1142 | 1122 |
1143 if (token.type == T.Colon) | 1123 if (token.type == T.Colon) |
1145 | 1125 |
1146 if (token.type == T.Semicolon) | 1126 if (token.type == T.Semicolon) |
1147 { | 1127 { |
1148 if (bases.length != 0) | 1128 if (bases.length != 0) |
1149 error(MID.BaseClassInForwardDeclaration); | 1129 error(MID.BaseClassInForwardDeclaration); |
1130 nT(); | |
1131 } | |
1132 else if (token.type == T.LBrace) | |
1133 decls = parseDeclarationDefinitionsBody(); | |
1134 else | |
1135 error(token, MSG.ExpectedInterfaceBody, token.srcText); | |
1136 | |
1137 return new InterfaceDeclaration(name, tparams, bases, decls); | |
1138 } | |
1139 | |
1140 Declaration parseAggregateDeclaration() | |
1141 { | |
1142 assert(token.type == T.Struct || token.type == T.Union); | |
1143 | |
1144 TOK tok = token.type; | |
1145 | |
1146 Identifier* name; | |
1147 TemplateParameters tparams; | |
1148 Declarations decls; | |
1149 | |
1150 nT(); // Skip struct or union keyword. | |
1151 | |
1152 name = optionalIdentifier(); | |
1153 | |
1154 if (name && token.type == T.LParen) | |
1155 tparams = parseTemplateParameterList(); | |
1156 | |
1157 if (token.type == T.Semicolon) | |
1158 { | |
1159 //if (name.length == 0) | |
1160 // TODO: error: forward declarations must have a name. | |
1150 nT(); | 1161 nT(); |
1151 } | 1162 } |
1152 else if (token.type == T.LBrace) | 1163 else if (token.type == T.LBrace) |
1153 decls = parseDeclarationDefinitionsBody(); | 1164 decls = parseDeclarationDefinitionsBody(); |
1154 else | 1165 else |
1155 expected(T.LBrace); // TODO: better error msg | 1166 expected(T.LBrace); // TODO: better error msg |
1156 | 1167 |
1157 return new InterfaceDeclaration(name, tparams, bases, decls); | |
1158 } | |
1159 | |
1160 Declaration parseAggregateDeclaration() | |
1161 { | |
1162 assert(token.type == T.Struct || token.type == T.Union); | |
1163 | |
1164 TOK tok = token.type; | |
1165 | |
1166 Token* name; | |
1167 TemplateParameters tparams; | |
1168 Declarations decls; | |
1169 | |
1170 nT(); // Skip struct or union keyword. | |
1171 // name is optional. | |
1172 if (token.type == T.Identifier) | |
1173 { | |
1174 name = token; | |
1175 nT(); | |
1176 if (token.type == T.LParen) | |
1177 tparams = parseTemplateParameterList(); | |
1178 } | |
1179 | |
1180 if (token.type == T.Semicolon) | |
1181 { | |
1182 //if (name.length == 0) | |
1183 // TODO: error: forward declarations must have a name. | |
1184 nT(); | |
1185 } | |
1186 else if (token.type == T.LBrace) | |
1187 decls = parseDeclarationDefinitionsBody(); | |
1188 else | |
1189 expected(T.LBrace); // TODO: better error msg | |
1190 | |
1191 if (tok == T.Struct) | 1168 if (tok == T.Struct) |
1192 { | 1169 { |
1193 auto d = new StructDeclaration(name, tparams, decls); | 1170 auto sd = new StructDeclaration(name, tparams, decls); |
1194 d.setAlignSize(this.alignSize); | 1171 sd.setAlignSize(this.alignSize); |
1195 return d; | 1172 return sd; |
1196 } | 1173 } |
1197 else | 1174 else |
1198 return new UnionDeclaration(name, tparams, decls); | 1175 return new UnionDeclaration(name, tparams, decls); |
1199 } | 1176 } |
1200 | 1177 |
1425 | 1402 |
1426 Declaration parseTemplateDeclaration() | 1403 Declaration parseTemplateDeclaration() |
1427 { | 1404 { |
1428 assert(token.type == T.Template); | 1405 assert(token.type == T.Template); |
1429 nT(); // Skip template keyword. | 1406 nT(); // Skip template keyword. |
1430 auto templateName = requireId(); | 1407 auto templateName = requireIdentifier(MSG.ExpectedTemplateName); |
1431 auto templateParams = parseTemplateParameterList(); | 1408 auto templateParams = parseTemplateParameterList(); |
1432 auto decls = parseDeclarationDefinitionsBody(); | 1409 auto decls = parseDeclarationDefinitionsBody(); |
1433 return new TemplateDeclaration(templateName, templateParams, decls); | 1410 return new TemplateDeclaration(templateName, templateParams, decls); |
1434 } | 1411 } |
1435 | 1412 |
1510 } | 1487 } |
1511 | 1488 |
1512 while (1) | 1489 while (1) |
1513 { | 1490 { |
1514 begin = token; | 1491 begin = token; |
1515 auto ident = requireId(); | 1492 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
1516 Expression e; | 1493 Expression e; |
1517 if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments ) | 1494 if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments ) |
1518 { | 1495 { |
1519 nT(); // Skip !. | 1496 nT(); // Skip !. |
1520 e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin); | 1497 auto tparams = parseTemplateArguments(); |
1498 e = new TemplateInstanceExpression(ident, tparams); | |
1521 } | 1499 } |
1522 else // Identifier | 1500 else // Identifier |
1523 e = set(new IdentifierExpression(ident), begin); | 1501 e = new IdentifierExpression(ident); |
1524 | 1502 |
1525 identList ~= e; | 1503 identList ~= set(e, begin); |
1526 | 1504 |
1527 LnewExpressionLoop: | 1505 LnewExpressionLoop: |
1528 if (token.type != T.Dot) | 1506 if (token.type != T.Dot) |
1529 break; | 1507 break; |
1530 nT(); // Skip dot. | 1508 nT(); // Skip dot. |
1573 } | 1551 } |
1574 | 1552 |
1575 while (1) | 1553 while (1) |
1576 { | 1554 { |
1577 begin = token; | 1555 begin = token; |
1578 auto ident = requireId(); | 1556 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
1557 Type t; | |
1579 // NB.: Currently Types can't be followed by "!=" so we don't need to peek for "(" when parsing TemplateInstances. | 1558 // NB.: Currently Types can't be followed by "!=" so we don't need to peek for "(" when parsing TemplateInstances. |
1580 if (token.type == T.Not/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments ) | 1559 if (token.type == T.Not/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments ) |
1581 { | 1560 { |
1582 nT(); // Skip !. | 1561 nT(); // Skip !. |
1583 identList ~= set(new TemplateInstanceType(ident, parseTemplateArguments()), begin); | 1562 t = new TemplateInstanceType(ident, parseTemplateArguments()); |
1584 } | 1563 } |
1585 else // Identifier | 1564 else // Identifier |
1586 identList ~= set(new IdentifierType(ident), begin); | 1565 t = new IdentifierType(ident); |
1566 | |
1567 identList ~= set(t, begin); | |
1587 | 1568 |
1588 if (token.type != T.Dot) | 1569 if (token.type != T.Dot) |
1589 break; | 1570 break; |
1590 nT(); | 1571 nT(); |
1591 } | 1572 } |
1602 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; | 1583 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; |
1603 */ | 1584 */ |
1604 Class parseMixin(Class)() | 1585 Class parseMixin(Class)() |
1605 { | 1586 { |
1606 assert(token.type == T.Mixin); | 1587 assert(token.type == T.Mixin); |
1607 auto begin = token; | |
1608 nT(); // Skip mixin keyword. | 1588 nT(); // Skip mixin keyword. |
1609 | 1589 |
1610 static if (is(Class == MixinDeclaration)) | 1590 static if (is(Class == MixinDeclaration)) |
1611 { | 1591 { |
1612 if (token.type == T.LParen) | 1592 if (token.type == T.LParen) |
1618 require(T.Semicolon); | 1598 require(T.Semicolon); |
1619 return new MixinDeclaration(e); | 1599 return new MixinDeclaration(e); |
1620 } | 1600 } |
1621 } | 1601 } |
1622 | 1602 |
1603 auto begin = token; | |
1623 Expression[] templateIdent; | 1604 Expression[] templateIdent; |
1624 Token* mixinIdent; | 1605 Identifier* mixinIdent; |
1625 | 1606 |
1626 // This code is similar to parseDotListType(). | 1607 // This code is similar to parseDotListType(). |
1627 if (token.type == T.Dot) | 1608 if (token.type == T.Dot) |
1628 { | 1609 { |
1629 nT(); | 1610 nT(); |
1631 } | 1612 } |
1632 | 1613 |
1633 while (1) | 1614 while (1) |
1634 { | 1615 { |
1635 begin = token; | 1616 begin = token; |
1636 auto ident = requireId(); | 1617 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
1637 Expression e; | 1618 Expression e; |
1638 if (token.type == T.Not) // Identifier !( TemplateArguments ) | 1619 if (token.type == T.Not) // Identifier !( TemplateArguments ) |
1639 { | 1620 { |
1640 // No need to peek for T.LParen. This must be a template instance. | 1621 // No need to peek for T.LParen. This must be a template instance. |
1641 nT(); | 1622 nT(); |
1642 e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin); | 1623 auto tparams = parseTemplateArguments(); |
1624 e = new TemplateInstanceExpression(ident, tparams); | |
1643 } | 1625 } |
1644 else // Identifier | 1626 else // Identifier |
1645 e = set(new IdentifierExpression(ident), begin); | 1627 e = new IdentifierExpression(ident); |
1646 | 1628 |
1647 templateIdent ~= e; | 1629 templateIdent ~= set(e, begin); |
1648 | 1630 |
1649 if (token.type != T.Dot) | 1631 if (token.type != T.Dot) |
1650 break; | 1632 break; |
1651 nT(); | 1633 nT(); |
1652 } | 1634 } |
1653 | 1635 |
1654 if (token.type == T.Identifier) | 1636 mixinIdent = optionalIdentifier(); |
1655 { | |
1656 mixinIdent = token; | |
1657 nT(); | |
1658 } | |
1659 | |
1660 require(T.Semicolon); | 1637 require(T.Semicolon); |
1661 | 1638 |
1662 return new Class(templateIdent, mixinIdent); | 1639 return new Class(templateIdent, mixinIdent); |
1663 } | 1640 } |
1664 | 1641 |
1720 s = parseAttributeStatement(); | 1697 s = parseAttributeStatement(); |
1721 return s; | 1698 return s; |
1722 case T.Identifier: | 1699 case T.Identifier: |
1723 if (peekNext() == T.Colon) | 1700 if (peekNext() == T.Colon) |
1724 { | 1701 { |
1725 auto ident = token; | 1702 auto ident = token.ident; |
1726 nT(); // Skip Identifier | 1703 nT(), nT(); // Skip Identifier : |
1727 nT(); // Skip : | |
1728 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement()); | 1704 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement()); |
1729 break; | 1705 break; |
1730 } | 1706 } |
1731 goto case T.Dot; | 1707 goto case T.Dot; |
1732 case T.Dot, T.Typeof: | 1708 case T.Dot, T.Typeof: |
1932 nT(); | 1908 nT(); |
1933 while (!token.isStatementStart && | 1909 while (!token.isStatementStart && |
1934 token.type != T.RBrace && | 1910 token.type != T.RBrace && |
1935 token.type != T.EOF) | 1911 token.type != T.EOF) |
1936 auto text = Token.textSpan(begin, this.prevToken); | 1912 auto text = Token.textSpan(begin, this.prevToken); |
1937 error(begin, "illegal Statement found: " ~ text); | 1913 error(begin, MSG.IllegalStatement ~ text); |
1938 } | 1914 } |
1939 assert(s !is null); | 1915 assert(s !is null); |
1940 set(s, begin); | 1916 set(s, begin); |
1941 return s; | 1917 return s; |
1942 } | 1918 } |
1971 require(T.RBrace); | 1947 require(T.RBrace); |
1972 s = set(ss, begin); | 1948 s = set(ss, begin); |
1973 } | 1949 } |
1974 else if (token.type == T.Semicolon) | 1950 else if (token.type == T.Semicolon) |
1975 { | 1951 { |
1976 error(MID.ExpectedButFound, "non-empty statement", ";"); | 1952 error(token, MSG.ExpectedNonEmptyStatement); |
1977 nT(); | 1953 nT(); |
1978 s = set(new EmptyStatement(), begin); | 1954 s = set(new EmptyStatement(), begin); |
1979 } | 1955 } |
1980 else | 1956 else |
1981 s = parseStatement(); | 1957 s = parseStatement(); |
2083 Expression condition; | 2059 Expression condition; |
2084 Statement ifBody, elseBody; | 2060 Statement ifBody, elseBody; |
2085 | 2061 |
2086 require(T.LParen); | 2062 require(T.LParen); |
2087 | 2063 |
2088 Token* ident; | 2064 Identifier* ident; |
2089 auto begin = token; // For start of AutoDeclaration or normal Declaration. | 2065 auto begin = token; // For start of AutoDeclaration or normal Declaration. |
2090 // auto Identifier = Expression | 2066 // auto Identifier = Expression |
2091 if (token.type == T.Auto) | 2067 if (token.type == T.Auto) |
2092 { | 2068 { |
2093 nT(); | 2069 nT(); |
2094 ident = requireId(); | 2070 ident = requireIdentifier(MSG.ExpectedVariableName); |
2095 require(T.Assign); | 2071 require(T.Assign); |
2096 auto init = parseExpression(); | 2072 auto init = parseExpression(); |
2097 auto v = new VariableDeclaration(null, [ident], [init]); | 2073 auto v = new VariableDeclaration(null, [ident], [init]); |
2098 set(v, ident); | 2074 set(v, begin.nextNWS); |
2099 auto d = new StorageClassDeclaration(StorageClass.Auto, T.Auto, v); | 2075 auto d = new StorageClassDeclaration(StorageClass.Auto, T.Auto, v); |
2100 set(d, begin); | 2076 set(d, begin); |
2101 variable = new DeclarationStatement(d); | 2077 variable = new DeclarationStatement(d); |
2102 set(variable, begin); | 2078 set(variable, begin); |
2103 } | 2079 } |
2189 | 2165 |
2190 require(T.LParen); | 2166 require(T.LParen); |
2191 while (1) | 2167 while (1) |
2192 { | 2168 { |
2193 auto paramBegin = token; | 2169 auto paramBegin = token; |
2194 Token* stcTok; | 2170 StorageClass stc; |
2195 Type type; | 2171 Type type; |
2196 Token* ident; | 2172 Identifier* ident; |
2197 | 2173 |
2198 switch (token.type) | 2174 switch (token.type) |
2199 { | 2175 { |
2200 case T.Ref, T.Inout: | 2176 case T.Ref, T.Inout: |
2201 stcTok = token; | 2177 stc = StorageClass.Ref; |
2202 nT(); | 2178 nT(); |
2203 // fall through | 2179 // fall through |
2204 case T.Identifier: | 2180 case T.Identifier: |
2205 auto next = peekNext(); | 2181 auto next = peekNext(); |
2206 if (next == T.Comma || next == T.Semicolon || next == T.RParen) | 2182 if (next == T.Comma || next == T.Semicolon || next == T.RParen) |
2207 { | 2183 { |
2208 ident = token; | 2184 ident = requireIdentifier(MSG.ExpectedVariableName); |
2209 nT(); | 2185 nT(); |
2210 break; | 2186 break; |
2211 } | 2187 } |
2212 // fall through | 2188 // fall through |
2213 default: | 2189 default: |
2214 type = parseDeclarator(ident); | 2190 type = parseDeclarator(ident); |
2215 } | 2191 } |
2216 | 2192 |
2217 params ~= set(new Parameter(stcTok, type, ident, null), paramBegin); | 2193 params ~= set(new Parameter(stc, type, ident, null), paramBegin); |
2218 | 2194 |
2219 if (token.type != T.Comma) | 2195 if (token.type != T.Comma) |
2220 break; | 2196 break; |
2221 nT(); | 2197 nT(); |
2222 } | 2198 } |
2291 | 2267 |
2292 Statement parseContinueStatement() | 2268 Statement parseContinueStatement() |
2293 { | 2269 { |
2294 assert(token.type == T.Continue); | 2270 assert(token.type == T.Continue); |
2295 nT(); | 2271 nT(); |
2296 Token* ident; | 2272 auto ident = optionalIdentifier(); |
2297 if (token.type == T.Identifier) | |
2298 { | |
2299 ident = token; | |
2300 nT(); | |
2301 } | |
2302 require(T.Semicolon); | 2273 require(T.Semicolon); |
2303 return new ContinueStatement(ident); | 2274 return new ContinueStatement(ident); |
2304 } | 2275 } |
2305 | 2276 |
2306 Statement parseBreakStatement() | 2277 Statement parseBreakStatement() |
2307 { | 2278 { |
2308 assert(token.type == T.Break); | 2279 assert(token.type == T.Break); |
2309 nT(); | 2280 nT(); |
2310 Token* ident; | 2281 auto ident = optionalIdentifier(); |
2311 if (token.type == T.Identifier) | |
2312 { | |
2313 ident = token; | |
2314 nT(); | |
2315 } | |
2316 require(T.Semicolon); | |
2317 return new BreakStatement(ident); | 2282 return new BreakStatement(ident); |
2318 } | 2283 } |
2319 | 2284 |
2320 Statement parseReturnStatement() | 2285 Statement parseReturnStatement() |
2321 { | 2286 { |
2330 | 2295 |
2331 Statement parseGotoStatement() | 2296 Statement parseGotoStatement() |
2332 { | 2297 { |
2333 assert(token.type == T.Goto); | 2298 assert(token.type == T.Goto); |
2334 nT(); | 2299 nT(); |
2335 Token* ident; | 2300 Identifier* ident; |
2336 Expression caseExpr; | 2301 Expression caseExpr; |
2337 switch (token.type) | 2302 switch (token.type) |
2338 { | 2303 { |
2339 case T.Case: | 2304 case T.Case: |
2340 nT(); | 2305 nT(); |
2344 break; | 2309 break; |
2345 case T.Default: | 2310 case T.Default: |
2346 nT(); | 2311 nT(); |
2347 break; | 2312 break; |
2348 default: | 2313 default: |
2349 ident = requireId(); | 2314 ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
2350 } | 2315 } |
2351 require(T.Semicolon); | 2316 require(T.Semicolon); |
2352 return new GotoStatement(ident, caseExpr); | 2317 return new GotoStatement(ident, caseExpr); |
2353 } | 2318 } |
2354 | 2319 |
2392 Parameter param; | 2357 Parameter param; |
2393 if (token.type == T.LParen) | 2358 if (token.type == T.LParen) |
2394 { | 2359 { |
2395 nT(); | 2360 nT(); |
2396 auto begin = token; | 2361 auto begin = token; |
2397 Token* ident; | 2362 Identifier* ident; |
2398 auto type = parseDeclarator(ident, true); | 2363 auto type = parseDeclarator(ident, true); |
2399 param = new Parameter(null, type, ident, null); | 2364 param = new Parameter(StorageClass.None, type, ident, null); |
2400 set(param, begin); | 2365 set(param, begin); |
2401 require(T.RParen); | 2366 require(T.RParen); |
2402 } | 2367 } |
2403 catchBodies ~= new CatchBody(param, parseNoScopeStatement()); | 2368 catchBodies ~= new CatchBody(param, parseNoScopeStatement()); |
2404 if (param is null) | 2369 if (param is null) |
2434 { | 2399 { |
2435 assert(token.type == T.Scope); | 2400 assert(token.type == T.Scope); |
2436 nT(); | 2401 nT(); |
2437 assert(token.type == T.LParen); | 2402 assert(token.type == T.LParen); |
2438 nT(); | 2403 nT(); |
2439 | 2404 auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier); |
2440 Token* condition = requireId(); | |
2441 if (condition) | 2405 if (condition) |
2442 switch (condition.ident.identID) | 2406 switch (condition.identID) |
2443 { | 2407 { |
2444 case ID.exit, ID.success, ID.failure: | 2408 case ID.exit, ID.success, ID.failure: |
2445 break; | 2409 break; |
2446 default: | 2410 default: |
2447 // TODO: create MID.InvalidScopeIdentifier | 2411 // TODO: create MID.InvalidScopeIdentifier |
2448 error(condition, "'exit', 'success', 'failure' are valid scope identifiers, but not '{}';", condition.srcText); | 2412 error(this.prevToken, MSG.InvalidScopeIdentifier, this.prevToken.srcText); |
2449 } | 2413 } |
2450 require(T.RParen); | 2414 require(T.RParen); |
2451 Statement scopeBody; | 2415 Statement scopeBody; |
2452 if (token.type == T.LBrace) | 2416 if (token.type == T.LBrace) |
2453 scopeBody = parseScopeStatement(); | 2417 scopeBody = parseScopeStatement(); |
2473 Statement parsePragmaStatement() | 2437 Statement parsePragmaStatement() |
2474 { | 2438 { |
2475 assert(token.type == T.Pragma); | 2439 assert(token.type == T.Pragma); |
2476 nT(); | 2440 nT(); |
2477 | 2441 |
2478 Token* ident; | 2442 Identifier* ident; |
2479 Expression[] args; | 2443 Expression[] args; |
2480 Statement pragmaBody; | 2444 Statement pragmaBody; |
2481 | 2445 |
2482 require(T.LParen); | 2446 require(T.LParen); |
2483 ident = requireId(); | 2447 ident = requireIdentifier(MSG.ExpectedPragmaIdentifier); |
2484 | 2448 |
2485 if (token.type == T.Comma) | 2449 if (token.type == T.Comma) |
2486 { | 2450 { |
2487 nT(); | 2451 nT(); |
2488 args = parseExpressionList(); | 2452 args = parseExpressionList(); |
2662 | 2626 |
2663 Statement parseAsmInstruction() | 2627 Statement parseAsmInstruction() |
2664 { | 2628 { |
2665 auto begin = token; | 2629 auto begin = token; |
2666 Statement s; | 2630 Statement s; |
2667 typeof(token) ident; | 2631 Identifier* ident; |
2668 switch (token.type) | 2632 switch (token.type) |
2669 { | 2633 { |
2670 // Keywords that are valid opcodes. | 2634 // Keywords that are valid opcodes. |
2671 case T.In, T.Int, T.Out: | 2635 case T.In, T.Int, T.Out: |
2672 ident = token; | 2636 ident = token.ident; |
2673 nT(); | 2637 nT(); |
2674 goto LOpcode; | 2638 goto LOpcode; |
2675 case T.Identifier: | 2639 case T.Identifier: |
2676 ident = token; | 2640 ident = token.ident; |
2677 nT(); // Skip Identifier | 2641 nT(); // Skip Identifier |
2678 if (token.type == T.Colon) | 2642 if (token.type == T.Colon) |
2679 { | 2643 { |
2680 // Identifier : AsmInstruction | 2644 // Identifier : AsmInstruction |
2681 nT(); // Skip : | 2645 nT(); // Skip : |
2701 } | 2665 } |
2702 require(T.Semicolon); | 2666 require(T.Semicolon); |
2703 s = new AsmInstruction(ident, es); | 2667 s = new AsmInstruction(ident, es); |
2704 break; | 2668 break; |
2705 case T.Align: | 2669 case T.Align: |
2706 nT(); | 2670 // align Integer; |
2707 auto number = token; | 2671 nT(); |
2708 switch (token.type) | 2672 int number = -1; |
2709 { | 2673 if (token.type == T.Int32) |
2710 case T.Int32, T.Int64, T.Uint32, T.Uint64: | 2674 (number = token.int_), nT(); |
2711 number = token; nT(); break; | 2675 else |
2712 default: | 2676 error(token, MSG.ExpectedIntegerAfterAlign, token.srcText); |
2713 if (token.type != T.Semicolon) | |
2714 nT(); | |
2715 number = null; | |
2716 // TODO: report error: number expected after asm align statement. | |
2717 error(token, "expected an integer after align, not '{}'", token.srcText); | |
2718 } | |
2719 require(T.Semicolon); | 2677 require(T.Semicolon); |
2720 s = new AsmAlignStatement(number); | 2678 s = new AsmAlignStatement(number); |
2721 break; | 2679 break; |
2722 case T.Semicolon: | 2680 case T.Semicolon: |
2723 s = new EmptyStatement(); | 2681 s = new EmptyStatement(); |
2730 nT(); | 2688 nT(); |
2731 while (!token.isAsmInstructionStart && | 2689 while (!token.isAsmInstructionStart && |
2732 token.type != T.RBrace && | 2690 token.type != T.RBrace && |
2733 token.type != T.EOF) | 2691 token.type != T.EOF) |
2734 auto text = Token.textSpan(begin, this.prevToken); | 2692 auto text = Token.textSpan(begin, this.prevToken); |
2735 error(begin, "illegal AsmInstruction found: " ~ text); | 2693 error(begin, MSG.IllegalAsmInstructino ~ text); |
2736 } | 2694 } |
2737 set(s, begin); | 2695 set(s, begin); |
2738 return s; | 2696 return s; |
2739 } | 2697 } |
2740 | 2698 |
3076 // DotIdentifier | 3034 // DotIdentifier |
3077 Expression[] identList; | 3035 Expression[] identList; |
3078 while (1) | 3036 while (1) |
3079 { | 3037 { |
3080 auto begin2 = token; | 3038 auto begin2 = token; |
3081 auto ident = requireId(); | 3039 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
3082 e = new IdentifierExpression(ident); | 3040 e = new IdentifierExpression(ident); |
3083 set(e, begin2); | 3041 set(e, begin2); |
3084 identList ~= e; | 3042 identList ~= e; |
3085 if (token.type != T.Dot) | 3043 if (token.type != T.Dot) |
3086 break; | 3044 break; |
3509 } | 3467 } |
3510 bool success; | 3468 bool success; |
3511 auto type = try_(&parseType_, success); | 3469 auto type = try_(&parseType_, success); |
3512 if (success) | 3470 if (success) |
3513 { | 3471 { |
3514 auto ident = requireId(); | 3472 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot); |
3515 e = new TypeDotIdExpression(type, ident); | 3473 e = new TypeDotIdExpression(type, ident); |
3516 break; | 3474 break; |
3517 } | 3475 } |
3518 goto default; | 3476 goto default; |
3519 default: | 3477 default: |
3669 break; | 3627 break; |
3670 case T.Is: | 3628 case T.Is: |
3671 requireNext(T.LParen); | 3629 requireNext(T.LParen); |
3672 | 3630 |
3673 Type type, specType; | 3631 Type type, specType; |
3674 Token* ident; // optional Identifier | 3632 Identifier* ident; // optional Identifier |
3675 Token* opTok, specTok; | 3633 Token* opTok, specTok; |
3676 | 3634 |
3677 type = parseDeclarator(ident, true); | 3635 type = parseDeclarator(ident, true); |
3678 | 3636 |
3679 switch (token.type) | 3637 switch (token.type) |
3744 T.Cfloat, T.Cdouble, T.Creal, T.Void: | 3702 T.Cfloat, T.Cdouble, T.Creal, T.Void: |
3745 auto type = new IntegralType(token.type); | 3703 auto type = new IntegralType(token.type); |
3746 nT(); | 3704 nT(); |
3747 set(type, begin); | 3705 set(type, begin); |
3748 require(T.Dot); | 3706 require(T.Dot); |
3749 auto ident = requireId(); | 3707 auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot); |
3750 | 3708 |
3751 e = new TypeDotIdExpression(type, ident); | 3709 e = new TypeDotIdExpression(type, ident); |
3752 break; | 3710 break; |
3753 version(D2) | 3711 version(D2) |
3754 { | 3712 { |
3755 case T.Traits: | 3713 case T.Traits: |
3756 nT(); | 3714 nT(); |
3757 require(T.LParen); | 3715 require(T.LParen); |
3758 auto id = requireId(); | 3716 auto id = requireIdentifier(MSG.ExpectedAnIdentifier); |
3759 TemplateArguments args; | 3717 TemplateArguments args; |
3760 if (token.type == T.Comma) | 3718 if (token.type == T.Comma) |
3761 args = parseTemplateArguments2(); | 3719 args = parseTemplateArguments2(); |
3762 else | 3720 else |
3763 require(T.RParen); | 3721 require(T.RParen); |
4012 } | 3970 } |
4013 set(t, begin); | 3971 set(t, begin); |
4014 return t; | 3972 return t; |
4015 } | 3973 } |
4016 | 3974 |
4017 Type parseCFunctionPointerType(Type type, ref Token* ident, bool optionalParamList) | 3975 Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList) |
4018 { | 3976 { |
4019 assert(token.type == T.LParen); | 3977 assert(token.type == T.LParen); |
4020 assert(type !is null); | 3978 assert(type !is null); |
4021 auto begin = token; | 3979 auto begin = token; |
4022 nT(); // Skip ( | 3980 nT(); // Skip ( |
4027 type = parseCFunctionPointerType(type, ident, true); | 3985 type = parseCFunctionPointerType(type, ident, true); |
4028 } | 3986 } |
4029 else if (token.type == T.Identifier) | 3987 else if (token.type == T.Identifier) |
4030 { | 3988 { |
4031 // The identifier of the function pointer and the declaration. | 3989 // The identifier of the function pointer and the declaration. |
4032 ident = token; | 3990 ident = token.ident; |
4033 nT(); | 3991 nT(); |
4034 type = parseDeclaratorSuffix(type); | 3992 type = parseDeclaratorSuffix(type); |
4035 } | 3993 } |
4036 require(T.RParen); | 3994 require(T.RParen); |
4037 | 3995 |
4043 | 4001 |
4044 type = set(new CFuncPointerType(type, params), begin); | 4002 type = set(new CFuncPointerType(type, params), begin); |
4045 return type; | 4003 return type; |
4046 } | 4004 } |
4047 | 4005 |
4048 Type parseDeclarator(ref Token* ident, bool identOptional = false) | 4006 Type parseDeclarator(ref Identifier* ident, bool identOptional = false) |
4049 { | 4007 { |
4050 auto t = parseType(); | 4008 auto t = parseType(); |
4051 | 4009 |
4052 if (token.type == T.LParen) | 4010 if (token.type == T.LParen) |
4053 { | 4011 { |
4054 t = parseCFunctionPointerType(t, ident, true); | 4012 t = parseCFunctionPointerType(t, ident, true); |
4055 } | 4013 } |
4056 else if (token.type == T.Identifier) | 4014 else if (token.type == T.Identifier) |
4057 { | 4015 { |
4058 ident = token; | 4016 ident = token.ident; |
4059 nT(); | 4017 nT(); |
4060 t = parseDeclaratorSuffix(t); | 4018 t = parseDeclaratorSuffix(t); |
4061 } | 4019 } |
4062 | 4020 |
4063 if (ident is null && !identOptional) | 4021 if (ident is null && !identOptional) |
4064 expected(T.Identifier); | 4022 error(token, MSG.ExpectedDeclaratorIdentifier, token.srcText); |
4065 | 4023 |
4066 return t; | 4024 return t; |
4067 } | 4025 } |
4068 | 4026 |
4069 /++ | 4027 /++ |
4122 { | 4080 { |
4123 nT(); | 4081 nT(); |
4124 return set(params, begin); | 4082 return set(params, begin); |
4125 } | 4083 } |
4126 | 4084 |
4085 Loop: | |
4127 while (1) | 4086 while (1) |
4128 { | 4087 { |
4129 auto paramBegin = token; | 4088 auto paramBegin = token; |
4130 Token* stcTok; | |
4131 StorageClass stc, tmp; | 4089 StorageClass stc, tmp; |
4090 Type type; | |
4091 Identifier* ident; | |
4092 Expression defValue; | |
4093 | |
4094 void pushParameter() | |
4095 { | |
4096 params ~= set(new Parameter(stc, type, ident, defValue), paramBegin); | |
4097 } | |
4132 | 4098 |
4133 if (token.type == T.Ellipses) | 4099 if (token.type == T.Ellipses) |
4134 { | 4100 { |
4135 nT(); | 4101 nT(); |
4136 params ~= set(new Parameter(null, null, null, null), paramBegin); | 4102 stc = StorageClass.Variadic; |
4137 break; // Exit loop. | 4103 pushParameter(); // type, ident and defValue will be null. |
4104 break Loop; | |
4138 } | 4105 } |
4139 | 4106 |
4140 Lstc_loop: | 4107 Lstc_loop: |
4141 switch (token.type) | 4108 switch (token.type) |
4142 { | 4109 { |
4143 version(D2) | 4110 version(D2) |
4144 { | 4111 { |
4145 case T.Invariant: // D2.0 | 4112 case T.Invariant: // D2.0 |
4146 if (peekNext() == T.LParen) | 4113 if (peekNext() == T.LParen) |
4147 goto default; | 4114 goto default; |
4148 tmp = StorageClass.Invariant; | 4115 tmp = StorageClass.Invariant; |
4149 goto Lcommon; | 4116 goto Lcommon; |
4159 tmp = StorageClass.Scope; | 4126 tmp = StorageClass.Scope; |
4160 goto Lcommon; | 4127 goto Lcommon; |
4161 case T.Static: // D2.0 | 4128 case T.Static: // D2.0 |
4162 tmp = StorageClass.Static; | 4129 tmp = StorageClass.Static; |
4163 goto Lcommon; | 4130 goto Lcommon; |
4131 } | |
4164 case T.In: | 4132 case T.In: |
4165 tmp = StorageClass.In; | 4133 tmp = StorageClass.In; |
4166 goto Lcommon; | 4134 goto Lcommon; |
4167 case T.Out: | 4135 case T.Out: |
4168 tmp = StorageClass.Out; | 4136 tmp = StorageClass.Out; |
4172 goto Lcommon; | 4140 goto Lcommon; |
4173 case T.Lazy: | 4141 case T.Lazy: |
4174 tmp = StorageClass.Lazy; | 4142 tmp = StorageClass.Lazy; |
4175 goto Lcommon; | 4143 goto Lcommon; |
4176 Lcommon: | 4144 Lcommon: |
4145 // Check for redundancy. | |
4177 if (stc & tmp) | 4146 if (stc & tmp) |
4178 error(MID.RedundantStorageClass, token.srcText); | 4147 error(MID.RedundantStorageClass, token.srcText); |
4179 else | 4148 else |
4180 stc |= tmp; | 4149 stc |= tmp; |
4181 nT(); | 4150 nT(); |
4151 version(D2) | |
4182 goto Lstc_loop; | 4152 goto Lstc_loop; |
4183 } | 4153 else |
4184 else // else body of version(D2) | 4154 goto default; // In D1.0 only one stc per parameter is allowed. |
4185 { | |
4186 case T.In, T.Out, T.Inout, T.Ref, T.Lazy: | |
4187 stcTok = token; | |
4188 nT(); | |
4189 goto default; | |
4190 } | |
4191 default: | 4155 default: |
4192 version(D2) | 4156 type = parseDeclarator(ident, true); |
4193 { | 4157 |
4194 if (stc != StorageClass.None) | |
4195 stcTok = begin; | |
4196 } | |
4197 Token* ident; | |
4198 auto type = parseDeclarator(ident, true); | |
4199 | |
4200 Expression assignExpr; | |
4201 if (token.type == T.Assign) | 4158 if (token.type == T.Assign) |
4159 nT(), (defValue = parseAssignExpression()); | |
4160 | |
4161 if (token.type == T.Ellipses) | |
4202 { | 4162 { |
4203 nT(); | 4163 nT(); |
4204 assignExpr = parseAssignExpression(); | 4164 stc |= StorageClass.Variadic; |
4165 pushParameter(); | |
4166 break Loop; | |
4205 } | 4167 } |
4206 | 4168 |
4207 if (token.type == T.Ellipses) | 4169 pushParameter(); |
4208 { | |
4209 auto p = set(new Parameter(stcTok, type, ident, assignExpr), paramBegin); | |
4210 p.stc |= StorageClass.Variadic; | |
4211 params ~= p; | |
4212 nT(); | |
4213 break; // Exit loop. | |
4214 } | |
4215 | |
4216 params ~= set(new Parameter(stcTok, type, ident, assignExpr), paramBegin); | |
4217 | 4170 |
4218 if (token.type != T.Comma) | 4171 if (token.type != T.Comma) |
4219 break; // Exit loop. | 4172 break Loop; |
4220 nT(); | 4173 nT(); |
4221 continue; | 4174 } |
4222 } | |
4223 break; // Exit loop. | |
4224 } | 4175 } |
4225 require(T.RParen); | 4176 require(T.RParen); |
4226 return set(params, begin); | 4177 return set(params, begin); |
4227 } | 4178 } |
4228 | 4179 |
4229 TemplateArguments parseTemplateArguments() | 4180 TemplateArguments parseTemplateArguments() |
4230 { | 4181 { |
4231 TemplateArguments targs; | 4182 TemplateArguments targs; |
4232 require(T.LParen); | 4183 require(T.LParen); |
4233 if (token.type != T.RParen) | 4184 if (token.type != T.RParen) |
4234 targs = parseTemplateArguments_(); | 4185 targs = parseTemplateArguments_(); |
4235 require(T.RParen); | 4186 require(T.RParen); |
4236 return targs; | 4187 return targs; |
4237 } | 4188 } |
4238 | 4189 |
4239 version(D2) | 4190 version(D2) |
4244 nT(); | 4195 nT(); |
4245 TemplateArguments targs; | 4196 TemplateArguments targs; |
4246 if (token.type != T.RParen) | 4197 if (token.type != T.RParen) |
4247 targs = parseTemplateArguments_(); | 4198 targs = parseTemplateArguments_(); |
4248 else | 4199 else |
4249 error(MID.ExpectedButFound, "Type/Expression", ")"); | 4200 error(token, MSG.ExpectedTypeOrExpression); |
4250 require(T.RParen); | 4201 require(T.RParen); |
4251 return targs; | 4202 return targs; |
4252 } | 4203 } |
4253 } // version(D2) | 4204 } // version(D2) |
4254 | 4205 |
4303 nT(); | 4254 nT(); |
4304 TemplateParameters tparams; | 4255 TemplateParameters tparams; |
4305 if (token.type != T.RParen) | 4256 if (token.type != T.RParen) |
4306 tparams = parseTemplateParameterList_(); | 4257 tparams = parseTemplateParameterList_(); |
4307 else | 4258 else |
4308 error(MID.ExpectedButFound, "Type/Expression", ")"); | 4259 error(token, MSG.ExpectedTemplateParameters); |
4309 return tparams; | 4260 return tparams; |
4310 } | 4261 } |
4311 } // version(D2) | 4262 } // version(D2) |
4312 | 4263 |
4313 TemplateParameters parseTemplateParameterList_() | 4264 TemplateParameters parseTemplateParameterList_() |
4317 | 4268 |
4318 while (1) | 4269 while (1) |
4319 { | 4270 { |
4320 auto paramBegin = token; | 4271 auto paramBegin = token; |
4321 TemplateParameter tp; | 4272 TemplateParameter tp; |
4322 Token* ident; | 4273 Identifier* ident; |
4323 Type specType, defType; | 4274 Type specType, defType; |
4324 | 4275 |
4325 void parseSpecAndOrDefaultType() | 4276 void parseSpecAndOrDefaultType() |
4326 { | 4277 { |
4327 // : SpecializationType | 4278 // : SpecializationType |
4342 { | 4293 { |
4343 case T.Alias: | 4294 case T.Alias: |
4344 // TemplateAliasParameter: | 4295 // TemplateAliasParameter: |
4345 // alias Identifier | 4296 // alias Identifier |
4346 nT(); // Skip alias keyword. | 4297 nT(); // Skip alias keyword. |
4347 ident = requireId(); | 4298 ident = requireIdentifier(MSG.ExpectedAliasTemplateParam); |
4348 parseSpecAndOrDefaultType(); | 4299 parseSpecAndOrDefaultType(); |
4349 tp = new TemplateAliasParameter(ident, specType, defType); | 4300 tp = new TemplateAliasParameter(ident, specType, defType); |
4350 break; | 4301 break; |
4351 case T.Identifier: | 4302 case T.Identifier: |
4352 ident = token; | 4303 ident = token.ident; |
4353 switch (peekNext()) | 4304 switch (peekNext()) |
4354 { | 4305 { |
4355 case T.Ellipses: | 4306 case T.Ellipses: |
4356 // TemplateTupleParameter: | 4307 // TemplateTupleParameter: |
4357 // Identifier ... | 4308 // Identifier ... |
4379 { | 4330 { |
4380 case T.This: | 4331 case T.This: |
4381 // TemplateThisParameter | 4332 // TemplateThisParameter |
4382 // this TemplateTypeParameter | 4333 // this TemplateTypeParameter |
4383 nT(); // Skip 'this' keyword. | 4334 nT(); // Skip 'this' keyword. |
4384 ident = requireId(); | 4335 ident = requireIdentifier(MSG.ExpectedNameForThisTempParam); |
4385 parseSpecAndOrDefaultType(); | 4336 parseSpecAndOrDefaultType(); |
4386 tp = new TemplateThisParameter(ident, specType, defType); | 4337 tp = new TemplateThisParameter(ident, specType, defType); |
4387 break; | 4338 break; |
4388 } | 4339 } |
4389 default: | 4340 default: |
4436 { | 4387 { |
4437 nT(); | 4388 nT(); |
4438 require(tok); | 4389 require(tok); |
4439 } | 4390 } |
4440 | 4391 |
4392 Identifier* optionalIdentifier() | |
4393 { | |
4394 Identifier* id; | |
4395 if (token.type == T.Identifier) | |
4396 (id = token.ident), nT(); | |
4397 return id; | |
4398 } | |
4399 | |
4441 Identifier* requireIdentifier() | 4400 Identifier* requireIdentifier() |
4442 { | 4401 { |
4443 Identifier* id; | 4402 Identifier* id; |
4444 if (token.type == T.Identifier) | 4403 if (token.type == T.Identifier) |
4445 (id = token.ident), nT(); | 4404 (id = token.ident), nT(); |
4483 else | 4442 else |
4484 error(MID.ExpectedButFound, "Identifier", token.srcText); | 4443 error(MID.ExpectedButFound, "Identifier", token.srcText); |
4485 return null; | 4444 return null; |
4486 } | 4445 } |
4487 | 4446 |
4447 Token* requireIdToken(char[] errorMsg) | |
4448 { | |
4449 Token* idtok; | |
4450 if (token.type == T.Identifier) | |
4451 (idtok = token), nT(); | |
4452 else | |
4453 error(token, errorMsg, token.srcText); | |
4454 return idtok; | |
4455 } | |
4456 | |
4488 /// Reports an error that has no message ID yet. | 4457 /// Reports an error that has no message ID yet. |
4489 void error(Token* token, char[] formatMsg, ...) | 4458 void error(Token* token, char[] formatMsg, ...) |
4490 { | 4459 { |
4491 error_(token, MID.min, formatMsg, _arguments, _argptr); | 4460 error_(token, MID.min, formatMsg, _arguments, _argptr); |
4492 } | 4461 } |
4505 } | 4474 } |
4506 auto location = token.getLocation(); | 4475 auto location = token.getLocation(); |
4507 auto msg = Format(_arguments, _argptr, formatMsg); | 4476 auto msg = Format(_arguments, _argptr, formatMsg); |
4508 errors ~= new Information(InfoType.Parser, mid, location, msg); | 4477 errors ~= new Information(InfoType.Parser, mid, location, msg); |
4509 } | 4478 } |
4479 | |
4480 /// Collection of error messages with no MID yet. | |
4481 private struct MSG | |
4482 { | |
4483 static: | |
4484 auto ExpectedIdAfterTypeDot = "expected identifier after '(Type).', not '{}'"; | |
4485 auto ExpectedModuleIdentifier = "expected module identifier, not '{}'"; | |
4486 auto IllegalDeclaration = "illegal Declaration found: {}"; | |
4487 auto ExpectedFunctionName = "expected function name, not '{}'"; | |
4488 auto ExpectedVariableName = "expected variable name, not '{}'"; | |
4489 auto ExpectedFunctionBody = "expected function body, not '{}'"; | |
4490 auto RedundantLinkageType = "redundant linkage type: "; | |
4491 auto ExpectedPragmaIdentifier = "expected pragma identifier, not '{}'"; | |
4492 auto ExpectedAliasModuleName = "expected alias module name, not '{}'"; | |
4493 auto ExpectedAliasImportName = "expected alias name, not '{}'"; | |
4494 auto ExpectedImportName = "expected an identifier, not '{}'"; | |
4495 auto ExpectedEnumMember = "expected enum member, not '{}'"; | |
4496 auto ExpectedEnumBody = "expected enum body, not '{}'"; | |
4497 auto ExpectedClassName = "expected class name, not '{}'"; | |
4498 auto ExpectedClassBody = "expected class body, not '{}'"; | |
4499 auto ExpectedInterfaceName = "expected interface name, not '{}'"; | |
4500 auto ExpectedInterfaceBody = "expected interface body, not '{}'"; | |
4501 auto ExpectedTemplateName = "expected template name, not '{}'"; | |
4502 auto ExpectedAnIdentifier = "expected an identifier, not '{}'"; | |
4503 auto IllegalStatement = "illegal Statement found: "; | |
4504 auto ExpectedNonEmptyStatement = "didn't expect ';', use { } instead"; | |
4505 auto ExpectedScopeIdentifier = "expected 'exit', 'success' or 'failure', not '{}'"; | |
4506 auto InvalidScopeIdentifier = "'exit', 'success', 'failure' are valid scope identifiers, but not '{}';"; | |
4507 auto ExpectedIntegerAfterAlign = "expected an integer after align, not '{}'"; | |
4508 auto IllegalAsmInstructino = "illegal AsmInstruction found: "; | |
4509 auto ExpectedDeclaratorIdentifier = "expected declarator identifier, not '{}'"; | |
4510 auto ExpectedTemplateParameters = "expected one or more template parameters not ')'"; | |
4511 auto ExpectedTypeOrExpression = "expected a type or and expression not ')'"; | |
4512 auto ExpectedAliasTemplateParam = "expected name for alias template parameter, not '{}'"; | |
4513 auto ExpectedNameForThisTempParam = "expected name for 'this' template parameter, not '{}'"; | |
4514 } | |
4510 } | 4515 } |