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 }