Mercurial > projects > dil
comparison trunk/src/dil/parser/Parser.d @ 774:846044180d22
Added method skip() to class Parser.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 18 Feb 2008 20:03:44 +0100 |
parents | 5e3ef1b2011c |
children | c1d5cfd7aa44 |
comparison
equal
deleted
inserted
replaced
773:6dbbb403fc58 | 774:846044180d22 |
---|---|
163 bool consumed()(TOK k) // Templatized, so it's inlined. | 163 bool consumed()(TOK k) // Templatized, so it's inlined. |
164 { | 164 { |
165 return token.kind == k ? (nT(), true) : false; | 165 return token.kind == k ? (nT(), true) : false; |
166 } | 166 } |
167 | 167 |
168 /// Asserts that the current token is of kind expectedKind, | |
169 /// and then moves to the next token. | |
170 void skip()(TOK expectedKind) | |
171 { | |
172 assert(token.kind == expectedKind /+|| *(int*).init+/, token.srcText()); | |
173 nT(); | |
174 } | |
175 | |
168 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 176 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
169 | Declaration parsing methods | | 177 | Declaration parsing methods | |
170 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ | 178 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
171 | 179 |
172 Declaration parseModuleDeclaration() | 180 Declaration parseModuleDeclaration() |
173 { | 181 { |
174 assert(token.kind == T.Module); | 182 skip(T.Module); |
175 auto begin = token; | 183 auto begin = token; |
176 ModuleFQN moduleFQN; | 184 ModuleFQN moduleFQN; |
177 do | 185 do |
178 { | |
179 nT(); | |
180 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); | 186 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); |
181 } while (token.kind == T.Dot) | 187 while (consumed(T.Dot)) |
182 require(T.Semicolon); | 188 require(T.Semicolon); |
183 return set(new ModuleDeclaration(moduleFQN), begin); | 189 return set(new ModuleDeclaration(moduleFQN), begin); |
184 } | 190 } |
185 | 191 |
186 /++ | 192 /++ |
447 bool testAutoDeclaration = false, | 453 bool testAutoDeclaration = false, |
448 bool optionalParameterList = true) | 454 bool optionalParameterList = true) |
449 { | 455 { |
450 auto begin = token; | 456 auto begin = token; |
451 Type type; | 457 Type type; |
452 Identifier* ident; | 458 Identifier* name; |
453 | 459 |
454 // Check for AutoDeclaration: StorageClasses Identifier = | 460 // Check for AutoDeclaration: StorageClasses Identifier = |
455 if (testAutoDeclaration && | 461 if (testAutoDeclaration && |
456 token.kind == T.Identifier && | 462 token.kind == T.Identifier && |
457 peekNext() == T.Assign) | 463 peekNext() == T.Assign) |
458 { | 464 { |
459 ident = token.ident; | 465 name = token.ident; |
460 nT(); | 466 skip(T.Identifier); |
461 } | 467 } |
462 else | 468 else |
463 { | 469 { |
464 type = parseType(); // VariableType or ReturnType | 470 type = parseType(); // VariableType or ReturnType |
465 if (token.kind == T.LParen) | 471 if (token.kind == T.LParen) |
473 // // In the following case precedence is given to a CallExpression. | 479 // // In the following case precedence is given to a CallExpression. |
474 // something(*p); // 'something' may be a function/method or an object having opCall overloaded. | 480 // something(*p); // 'something' may be a function/method or an object having opCall overloaded. |
475 // } | 481 // } |
476 // // A pointer to a function taking no parameters and returning 'something'. | 482 // // A pointer to a function taking no parameters and returning 'something'. |
477 // something(*p); | 483 // something(*p); |
478 type = parseCFunctionPointerType(type, ident, optionalParameterList); | 484 type = parseCFunctionPointerType(type, name, optionalParameterList); |
479 } | 485 } |
480 else if (peekNext() == T.LParen) | 486 else if (peekNext() == T.LParen) |
481 { // Type FunctionName ( ParameterList ) FunctionBody | 487 { // Type FunctionName ( ParameterList ) FunctionBody |
482 ident = requireIdentifier(MSG.ExpectedFunctionName); | 488 name = requireIdentifier(MSG.ExpectedFunctionName); |
483 ident || nT(); // Skip non-identifier token. | 489 name || nT(); // Skip non-identifier token. |
484 assert(token.kind == T.LParen); | 490 assert(token.kind == T.LParen); |
485 // It's a function declaration | 491 // It's a function declaration |
486 TemplateParameters tparams; | 492 TemplateParameters tparams; |
487 if (tokenAfterParenIs(T.LParen)) | 493 if (tokenAfterParenIs(T.LParen)) |
488 // ( TemplateParameterList ) ( ParameterList ) | 494 // ( TemplateParameterList ) ( ParameterList ) |
504 default: | 510 default: |
505 } | 511 } |
506 } | 512 } |
507 // ReturnType FunctionName ( ParameterList ) | 513 // ReturnType FunctionName ( ParameterList ) |
508 auto funcBody = parseFunctionBody(); | 514 auto funcBody = parseFunctionBody(); |
509 auto fd = new FunctionDeclaration(type, ident,/+ tparams,+/ params, funcBody); | 515 auto fd = new FunctionDeclaration(type, name,/+ tparams,+/ params, funcBody); |
510 fd.setStorageClass(stc); | 516 fd.setStorageClass(stc); |
511 fd.setLinkageType(linkType); | 517 fd.setLinkageType(linkType); |
512 fd.setProtection(protection); | 518 fd.setProtection(protection); |
513 if (tparams) | 519 if (tparams) |
514 { | 520 { |
515 auto d = putInsideTemplateDeclaration(begin, ident, fd, tparams); | 521 auto d = putInsideTemplateDeclaration(begin, name, fd, tparams); |
516 d.setStorageClass(stc); | 522 d.setStorageClass(stc); |
517 d.setProtection(protection); | 523 d.setProtection(protection); |
518 return set(d, begin); | 524 return set(d, begin); |
519 } | 525 } |
520 return set(fd, begin); | 526 return set(fd, begin); |
521 } | 527 } |
522 else | 528 else |
523 { | 529 { // Type VariableName DeclaratorSuffix |
524 // Type VariableName DeclaratorSuffix | 530 name = requireIdentifier(MSG.ExpectedVariableName); |
525 ident = requireIdentifier(MSG.ExpectedVariableName); | |
526 type = parseDeclaratorSuffix(type); | 531 type = parseDeclaratorSuffix(type); |
527 } | 532 } |
528 } | 533 } |
529 | 534 |
530 // It's a variable declaration. | 535 // It's a variables declaration. |
531 Identifier*[] idents = [ident]; | 536 Identifier*[] names = [name]; // One identifier has been parsed already. |
532 Expression[] values; | 537 Expression[] values; |
533 goto LenterLoop; // We've already parsed an identifier. Jump to if statement and check for initializer. | 538 goto LenterLoop; // Enter the loop and check for an initializer. |
534 while (consumed(T.Comma)) | 539 while (consumed(T.Comma)) |
535 { | 540 { |
536 idents ~= requireIdentifier(MSG.ExpectedVariableName); | 541 names ~= requireIdentifier(MSG.ExpectedVariableName); |
537 LenterLoop: | 542 LenterLoop: |
538 if (consumed(T.Assign)) | 543 if (consumed(T.Assign)) |
539 values ~= parseInitializer(); | 544 values ~= parseInitializer(); |
540 else | 545 else |
541 values ~= null; | 546 values ~= null; |
542 } | 547 } |
543 require(T.Semicolon); | 548 require(T.Semicolon); |
544 auto d = new VariablesDeclaration(type, idents, values); | 549 auto d = new VariablesDeclaration(type, names, values); |
545 d.setStorageClass(stc); | 550 d.setStorageClass(stc); |
546 d.setLinkageType(linkType); | 551 d.setLinkageType(linkType); |
547 d.setProtection(protection); | 552 d.setProtection(protection); |
548 return set(d, begin); | 553 return set(d, begin); |
549 } | 554 } |
554 { | 559 { |
555 auto begin = token; | 560 auto begin = token; |
556 auto next = peekNext(); | 561 auto next = peekNext(); |
557 if (next == T.Comma || next == T.Semicolon) | 562 if (next == T.Comma || next == T.Semicolon) |
558 { | 563 { |
559 nT(); | 564 skip(T.Void); |
560 return set(new VoidInitExpression(), begin); | 565 return set(new VoidInitExpression(), begin); |
561 } | 566 } |
562 } | 567 } |
563 return parseNonVoidInitializer(); | 568 return parseNonVoidInitializer(); |
564 } | 569 } |
574 // [ ] | 579 // [ ] |
575 // [ ArrayMemberInitializations ] | 580 // [ ArrayMemberInitializations ] |
576 Expression[] keys; | 581 Expression[] keys; |
577 Expression[] values; | 582 Expression[] values; |
578 | 583 |
579 nT(); | 584 skip(T.LBracket); |
580 while (token.kind != T.RBracket) | 585 while (token.kind != T.RBracket) |
581 { | 586 { |
582 auto e = parseNonVoidInitializer(); | 587 auto e = parseNonVoidInitializer(); |
583 if (consumed(T.Colon)) | 588 if (consumed(T.Colon)) |
584 { | 589 { |
589 { | 594 { |
590 keys ~= null; | 595 keys ~= null; |
591 values ~= e; | 596 values ~= e; |
592 } | 597 } |
593 | 598 |
594 if (token.kind != T.Comma) | 599 if (!consumed(T.Comma)) |
595 break; | 600 break; |
596 nT(); | |
597 } | 601 } |
598 require(T.RBracket); | 602 require(T.RBracket); |
599 init = new ArrayInitExpression(keys, values); | 603 init = new ArrayInitExpression(keys, values); |
600 break; | 604 break; |
601 case T.LBrace: | 605 case T.LBrace: |
605 Expression parseStructInitializer() | 609 Expression parseStructInitializer() |
606 { | 610 { |
607 Identifier*[] idents; | 611 Identifier*[] idents; |
608 Expression[] values; | 612 Expression[] values; |
609 | 613 |
610 nT(); | 614 skip(T.LBrace); |
611 while (token.kind != T.RBrace) | 615 while (token.kind != T.RBrace) |
612 { | 616 { |
613 if (token.kind == T.Identifier && | 617 if (token.kind == T.Identifier && |
614 // Peek for colon to see if this is a member identifier. | 618 // Peek for colon to see if this is a member identifier. |
615 peekNext() == T.Colon) | 619 peekNext() == T.Colon) |
616 { | 620 { |
617 idents ~= token.ident; | 621 idents ~= token.ident; |
618 nT(), nT(); // Skip Identifier : | 622 skip(T.Identifier), skip(T.Colon); |
619 } | 623 } |
620 else | 624 else |
621 idents ~= null; | 625 idents ~= null; |
622 | 626 |
623 // NonVoidInitializer | 627 // NonVoidInitializer |
624 values ~= parseNonVoidInitializer(); | 628 values ~= parseNonVoidInitializer(); |
625 | 629 |
626 if (token.kind != T.Comma) | 630 if (!consumed(T.Comma)) |
627 break; | 631 break; |
628 nT(); | |
629 } | 632 } |
630 require(T.RBrace); | 633 require(T.RBrace); |
631 return new StructInitExpression(idents, values); | 634 return new StructInitExpression(idents, values); |
632 } | 635 } |
633 | 636 |
692 } | 695 } |
693 | 696 |
694 LinkageType parseLinkageType() | 697 LinkageType parseLinkageType() |
695 { | 698 { |
696 LinkageType linkageType; | 699 LinkageType linkageType; |
697 if (token.kind != T.LParen) | 700 |
701 if (!consumed(T.LParen)) | |
698 return linkageType; | 702 return linkageType; |
699 | 703 |
700 nT(); // Skip ( | 704 if (consumed(T.RParen)) |
701 if (token.kind == T.RParen) | 705 { // extern() |
702 { | |
703 nT(); | |
704 error(MID.MissingLinkageType); | 706 error(MID.MissingLinkageType); |
705 return linkageType; | 707 return linkageType; |
706 } | 708 } |
707 | 709 |
708 auto identTok = requireId(); | 710 auto identTok = requireId(); |
851 return parse(); | 853 return parse(); |
852 } | 854 } |
853 | 855 |
854 uint parseAlignAttribute() | 856 uint parseAlignAttribute() |
855 { | 857 { |
856 assert(token.kind == T.Align); | 858 skip(T.Align); |
857 nT(); // Skip align keyword. | |
858 uint size = DEFAULT_ALIGN_SIZE; // Global default. | 859 uint size = DEFAULT_ALIGN_SIZE; // Global default. |
859 if (consumed(T.LParen)) | 860 if (consumed(T.LParen)) |
860 { | 861 { |
861 if (token.kind == T.Int32) | 862 if (token.kind == T.Int32) |
862 (size = token.int_), nT(); | 863 (size = token.int_), skip(T.Int32); |
863 else | 864 else |
864 expected(T.Int32); | 865 expected(T.Int32); |
865 require(T.RParen); | 866 require(T.RParen); |
866 } | 867 } |
867 return size; | 868 return size; |
924 return decl; | 925 return decl; |
925 } | 926 } |
926 | 927 |
927 Declaration parseImportDeclaration() | 928 Declaration parseImportDeclaration() |
928 { | 929 { |
929 assert(token.kind == T.Import || token.kind == T.Static); | |
930 bool isStatic = consumed(T.Static); | 930 bool isStatic = consumed(T.Static); |
931 assert(token.kind == T.Import); | 931 skip(T.Import); |
932 nT(); // Skip import keyword. | |
933 | 932 |
934 ModuleFQN[] moduleFQNs; | 933 ModuleFQN[] moduleFQNs; |
935 Identifier*[] moduleAliases; | 934 Identifier*[] moduleAliases; |
936 Identifier*[] bindNames; | 935 Identifier*[] bindNames; |
937 Identifier*[] bindAliases; | 936 Identifier*[] bindAliases; |
942 Identifier* moduleAlias; | 941 Identifier* moduleAlias; |
943 // AliasName = ModuleName | 942 // AliasName = ModuleName |
944 if (peekNext() == T.Assign) | 943 if (peekNext() == T.Assign) |
945 { | 944 { |
946 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName); | 945 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName); |
947 nT(); // Skip = | 946 skip(T.Assign); |
948 } | 947 } |
949 // Identifier ("." Identifier)* | 948 // Identifier ("." Identifier)* |
950 do | 949 do |
951 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); | 950 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); |
952 while (consumed(T.Dot)) | 951 while (consumed(T.Dot)) |
953 // Push identifiers. | 952 // Push identifiers. |
954 moduleFQNs ~= moduleFQN; | 953 moduleFQNs ~= moduleFQN; |
955 moduleAliases ~= moduleAlias; | 954 moduleAliases ~= moduleAlias; |
956 } while (consumed(T.Comma)) | 955 } while (consumed(T.Comma)) |
957 | 956 |
958 if (token.kind == T.Colon) | 957 if (consumed(T.Colon)) |
959 { | 958 { // BindAlias "=" BindName ("," BindAlias "=" BindName)*; |
960 // BindAlias = BindName(, BindAlias = BindName)*; | 959 // BindName ("," BindName)*; |
961 // BindName(, BindName)*; | |
962 do | 960 do |
963 { | 961 { |
964 nT(); | |
965 Identifier* bindAlias; | 962 Identifier* bindAlias; |
966 // BindAlias = BindName | 963 // BindAlias = BindName |
967 if (peekNext() == T.Assign) | 964 if (peekNext() == T.Assign) |
968 { | 965 { |
969 bindAlias = requireIdentifier(MSG.ExpectedAliasImportName); | 966 bindAlias = requireIdentifier(MSG.ExpectedAliasImportName); |
970 nT(); // Skip = | 967 skip(T.Assign); |
971 } | 968 } |
972 // Push identifiers. | 969 // Push identifiers. |
973 bindNames ~= requireIdentifier(MSG.ExpectedImportName); | 970 bindNames ~= requireIdentifier(MSG.ExpectedImportName); |
974 bindAliases ~= bindAlias; | 971 bindAliases ~= bindAlias; |
975 } while (token.kind == T.Comma) | 972 } while (consumed(T.Comma)) |
976 } | 973 } |
977 | |
978 require(T.Semicolon); | 974 require(T.Semicolon); |
979 | 975 |
980 return new ImportDeclaration(moduleFQNs, moduleAliases, bindNames, bindAliases, isStatic); | 976 return new ImportDeclaration(moduleFQNs, moduleAliases, bindNames, bindAliases, isStatic); |
981 } | 977 } |
982 | 978 |
983 Declaration parseEnumDeclaration() | 979 Declaration parseEnumDeclaration() |
984 { | 980 { |
985 assert(token.kind == T.Enum); | 981 skip(T.Enum); |
986 nT(); // Skip enum keyword. | |
987 | 982 |
988 Identifier* enumName; | 983 Identifier* enumName; |
989 Type baseType; | 984 Type baseType; |
990 EnumMemberDeclaration[] members; | 985 EnumMemberDeclaration[] members; |
991 bool hasBody; | 986 bool hasBody; |
1011 else | 1006 else |
1012 value = null; | 1007 value = null; |
1013 | 1008 |
1014 members ~= set(new EnumMemberDeclaration(name, value), begin); | 1009 members ~= set(new EnumMemberDeclaration(name, value), begin); |
1015 | 1010 |
1016 if (token.kind != T.Comma) | 1011 if (!consumed(T.Comma)) |
1017 break; | 1012 break; |
1018 nT(); // Skip , | |
1019 } | 1013 } |
1020 require(T.RBrace); | 1014 require(T.RBrace); |
1021 } | 1015 } |
1022 else | 1016 else |
1023 error(token, MSG.ExpectedEnumBody, token.srcText); | 1017 error(token, MSG.ExpectedEnumBody, token.srcText); |
1043 return new TemplateDeclaration(name, tparams, cd); | 1037 return new TemplateDeclaration(name, tparams, cd); |
1044 } | 1038 } |
1045 | 1039 |
1046 Declaration parseClassDeclaration() | 1040 Declaration parseClassDeclaration() |
1047 { | 1041 { |
1048 assert(token.kind == T.Class); | 1042 auto begin = token; |
1049 auto begin = token; | 1043 skip(T.Class); |
1050 nT(); // Skip class keyword. | |
1051 | 1044 |
1052 Identifier* className; | 1045 Identifier* className; |
1053 TemplateParameters tparams; | 1046 TemplateParameters tparams; |
1054 BaseClassType[] bases; | 1047 BaseClassType[] bases; |
1055 CompoundDeclaration decls; | 1048 CompoundDeclaration decls; |
1075 return d; | 1068 return d; |
1076 } | 1069 } |
1077 | 1070 |
1078 BaseClassType[] parseBaseClasses(bool colonLeadsOff = true) | 1071 BaseClassType[] parseBaseClasses(bool colonLeadsOff = true) |
1079 { | 1072 { |
1080 if (colonLeadsOff) | 1073 colonLeadsOff && skip(T.Colon); |
1081 { | |
1082 assert(token.kind == T.Colon); | |
1083 nT(); // Skip colon | |
1084 } | |
1085 | 1074 |
1086 BaseClassType[] bases; | 1075 BaseClassType[] bases; |
1087 | |
1088 do | 1076 do |
1089 { | 1077 { |
1090 Protection prot = Protection.Public; | 1078 Protection prot = Protection.Public; |
1091 switch (token.kind) | 1079 switch (token.kind) |
1092 { | 1080 { |
1108 return bases; | 1096 return bases; |
1109 } | 1097 } |
1110 | 1098 |
1111 Declaration parseInterfaceDeclaration() | 1099 Declaration parseInterfaceDeclaration() |
1112 { | 1100 { |
1113 assert(token.kind == T.Interface); | 1101 auto begin = token; |
1114 auto begin = token; | 1102 skip(T.Interface); |
1115 nT(); // Skip interface keyword. | |
1116 | 1103 |
1117 Identifier* name; | 1104 Identifier* name; |
1118 TemplateParameters tparams; | 1105 TemplateParameters tparams; |
1119 BaseClassType[] bases; | 1106 BaseClassType[] bases; |
1120 CompoundDeclaration decls; | 1107 CompoundDeclaration decls; |
1142 | 1129 |
1143 Declaration parseStructOrUnionDeclaration() | 1130 Declaration parseStructOrUnionDeclaration() |
1144 { | 1131 { |
1145 assert(token.kind == T.Struct || token.kind == T.Union); | 1132 assert(token.kind == T.Struct || token.kind == T.Union); |
1146 auto begin = token; | 1133 auto begin = token; |
1147 nT(); // Skip struct or union keyword. | 1134 skip(token.kind); |
1148 | 1135 |
1149 Identifier* name; | 1136 Identifier* name; |
1150 TemplateParameters tparams; | 1137 TemplateParameters tparams; |
1151 CompoundDeclaration decls; | 1138 CompoundDeclaration decls; |
1152 | 1139 |
1179 return d; | 1166 return d; |
1180 } | 1167 } |
1181 | 1168 |
1182 Declaration parseConstructorDeclaration() | 1169 Declaration parseConstructorDeclaration() |
1183 { | 1170 { |
1184 assert(token.kind == T.This); | 1171 skip(T.This); |
1185 nT(); // Skip 'this' keyword. | |
1186 auto parameters = parseParameterList(); | 1172 auto parameters = parseParameterList(); |
1187 auto funcBody = parseFunctionBody(); | 1173 auto funcBody = parseFunctionBody(); |
1188 return new ConstructorDeclaration(parameters, funcBody); | 1174 return new ConstructorDeclaration(parameters, funcBody); |
1189 } | 1175 } |
1190 | 1176 |
1191 Declaration parseDestructorDeclaration() | 1177 Declaration parseDestructorDeclaration() |
1192 { | 1178 { |
1193 assert(token.kind == T.Tilde); | 1179 skip(T.Tilde); |
1194 nT(); // Skip ~ | |
1195 require(T.This); | 1180 require(T.This); |
1196 require(T.LParen); | 1181 require(T.LParen); |
1197 require(T.RParen); | 1182 require(T.RParen); |
1198 auto funcBody = parseFunctionBody(); | 1183 auto funcBody = parseFunctionBody(); |
1199 return new DestructorDeclaration(funcBody); | 1184 return new DestructorDeclaration(funcBody); |
1200 } | 1185 } |
1201 | 1186 |
1202 Declaration parseStaticConstructorDeclaration() | 1187 Declaration parseStaticConstructorDeclaration() |
1203 { | 1188 { |
1204 assert(token.kind == T.Static); | 1189 skip(T.Static); |
1205 nT(); // Skip static keyword. | 1190 skip(T.This); |
1206 nT(); // Skip 'this' keyword. | |
1207 require(T.LParen); | 1191 require(T.LParen); |
1208 require(T.RParen); | 1192 require(T.RParen); |
1209 auto funcBody = parseFunctionBody(); | 1193 auto funcBody = parseFunctionBody(); |
1210 return new StaticConstructorDeclaration(funcBody); | 1194 return new StaticConstructorDeclaration(funcBody); |
1211 } | 1195 } |
1212 | 1196 |
1213 Declaration parseStaticDestructorDeclaration() | 1197 Declaration parseStaticDestructorDeclaration() |
1214 { | 1198 { |
1215 assert(token.kind == T.Static); | 1199 skip(T.Static); |
1216 nT(); // Skip static keyword. | 1200 skip(T.Tilde); |
1217 nT(); // Skip ~ | |
1218 require(T.This); | 1201 require(T.This); |
1219 require(T.LParen); | 1202 require(T.LParen); |
1220 require(T.RParen); | 1203 require(T.RParen); |
1221 auto funcBody = parseFunctionBody(); | 1204 auto funcBody = parseFunctionBody(); |
1222 return new StaticDestructorDeclaration(funcBody); | 1205 return new StaticDestructorDeclaration(funcBody); |
1223 } | 1206 } |
1224 | 1207 |
1225 Declaration parseInvariantDeclaration() | 1208 Declaration parseInvariantDeclaration() |
1226 { | 1209 { |
1227 assert(token.kind == T.Invariant); | 1210 skip(T.Invariant); |
1228 nT(); // Skip invariant keyword. | |
1229 // Optional () for getting ready porting to D 2.0 | 1211 // Optional () for getting ready porting to D 2.0 |
1230 if (token.kind == T.LParen) | 1212 if (consumed(T.LParen)) |
1231 requireNext(T.RParen); | 1213 require(T.RParen); |
1232 auto funcBody = parseFunctionBody(); | 1214 auto funcBody = parseFunctionBody(); |
1233 return new InvariantDeclaration(funcBody); | 1215 return new InvariantDeclaration(funcBody); |
1234 } | 1216 } |
1235 | 1217 |
1236 Declaration parseUnittestDeclaration() | 1218 Declaration parseUnittestDeclaration() |
1237 { | 1219 { |
1238 assert(token.kind == T.Unittest); | 1220 skip(T.Unittest); |
1239 nT(); // Skip unittest keyword. | |
1240 auto funcBody = parseFunctionBody(); | 1221 auto funcBody = parseFunctionBody(); |
1241 return new UnittestDeclaration(funcBody); | 1222 return new UnittestDeclaration(funcBody); |
1242 } | 1223 } |
1243 | 1224 |
1244 Token* parseIdentOrInt() | 1225 Token* parseIdentOrInt() |
1249 return null; | 1230 return null; |
1250 } | 1231 } |
1251 | 1232 |
1252 Declaration parseDebugDeclaration() | 1233 Declaration parseDebugDeclaration() |
1253 { | 1234 { |
1254 assert(token.kind == T.Debug); | 1235 skip(T.Debug); |
1255 nT(); // Skip debug keyword. | |
1256 | 1236 |
1257 Token* spec; | 1237 Token* spec; |
1258 Token* cond; | 1238 Token* cond; |
1259 Declaration decls, elseDecls; | 1239 Declaration decls, elseDecls; |
1260 | 1240 |
1282 return new DebugDeclaration(spec, cond, decls, elseDecls); | 1262 return new DebugDeclaration(spec, cond, decls, elseDecls); |
1283 } | 1263 } |
1284 | 1264 |
1285 Declaration parseVersionDeclaration() | 1265 Declaration parseVersionDeclaration() |
1286 { | 1266 { |
1287 assert(token.kind == T.Version); | 1267 skip(T.Version); |
1288 nT(); // Skip version keyword. | |
1289 | 1268 |
1290 Token* spec; | 1269 Token* spec; |
1291 Token* cond; | 1270 Token* cond; |
1292 Declaration decls, elseDecls; | 1271 Declaration decls, elseDecls; |
1293 | 1272 |
1312 return new VersionDeclaration(spec, cond, decls, elseDecls); | 1291 return new VersionDeclaration(spec, cond, decls, elseDecls); |
1313 } | 1292 } |
1314 | 1293 |
1315 Declaration parseStaticIfDeclaration() | 1294 Declaration parseStaticIfDeclaration() |
1316 { | 1295 { |
1317 assert(token.kind == T.Static); | 1296 skip(T.Static); |
1318 nT(); // Skip static keyword. | 1297 skip(T.If); |
1319 nT(); // Skip if keyword. | |
1320 | 1298 |
1321 Expression condition; | 1299 Expression condition; |
1322 Declaration ifDecls, elseDecls; | 1300 Declaration ifDecls, elseDecls; |
1323 | 1301 |
1324 require(T.LParen); | 1302 require(T.LParen); |
1333 return new StaticIfDeclaration(condition, ifDecls, elseDecls); | 1311 return new StaticIfDeclaration(condition, ifDecls, elseDecls); |
1334 } | 1312 } |
1335 | 1313 |
1336 Declaration parseStaticAssertDeclaration() | 1314 Declaration parseStaticAssertDeclaration() |
1337 { | 1315 { |
1338 assert(token.kind == T.Static); | 1316 skip(T.Static); |
1339 nT(); // Skip static keyword. | 1317 skip(T.Assert); |
1340 nT(); // Skip assert keyword. | |
1341 Expression condition, message; | 1318 Expression condition, message; |
1342 require(T.LParen); | 1319 require(T.LParen); |
1343 condition = parseAssignExpression(); | 1320 condition = parseAssignExpression(); |
1344 if (consumed(T.Comma)) | 1321 if (consumed(T.Comma)) |
1345 message = parseAssignExpression(); | 1322 message = parseAssignExpression(); |
1348 return new StaticAssertDeclaration(condition, message); | 1325 return new StaticAssertDeclaration(condition, message); |
1349 } | 1326 } |
1350 | 1327 |
1351 Declaration parseTemplateDeclaration() | 1328 Declaration parseTemplateDeclaration() |
1352 { | 1329 { |
1353 assert(token.kind == T.Template); | 1330 skip(T.Template); |
1354 nT(); // Skip template keyword. | |
1355 auto templateName = requireIdentifier(MSG.ExpectedTemplateName); | 1331 auto templateName = requireIdentifier(MSG.ExpectedTemplateName); |
1356 auto templateParams = parseTemplateParameterList(); | 1332 auto templateParams = parseTemplateParameterList(); |
1357 auto decls = parseDeclarationDefinitionsBody(); | 1333 auto decls = parseDeclarationDefinitionsBody(); |
1358 return new TemplateDeclaration(templateName, templateParams, decls); | 1334 return new TemplateDeclaration(templateName, templateParams, decls); |
1359 } | 1335 } |
1360 | 1336 |
1361 Declaration parseNewDeclaration() | 1337 Declaration parseNewDeclaration() |
1362 { | 1338 { |
1363 assert(token.kind == T.New); | 1339 skip(T.New); |
1364 nT(); // Skip new keyword. | |
1365 auto parameters = parseParameterList(); | 1340 auto parameters = parseParameterList(); |
1366 auto funcBody = parseFunctionBody(); | 1341 auto funcBody = parseFunctionBody(); |
1367 return new NewDeclaration(parameters, funcBody); | 1342 return new NewDeclaration(parameters, funcBody); |
1368 } | 1343 } |
1369 | 1344 |
1370 Declaration parseDeleteDeclaration() | 1345 Declaration parseDeleteDeclaration() |
1371 { | 1346 { |
1372 assert(token.kind == T.Delete); | 1347 skip(T.Delete); |
1373 nT(); // Skip delete keyword. | |
1374 auto parameters = parseParameterList(); | 1348 auto parameters = parseParameterList(); |
1375 auto funcBody = parseFunctionBody(); | 1349 auto funcBody = parseFunctionBody(); |
1376 return new DeleteDeclaration(parameters, funcBody); | 1350 return new DeleteDeclaration(parameters, funcBody); |
1377 } | 1351 } |
1378 | 1352 |
1379 Type parseTypeofType() | 1353 Type parseTypeofType() |
1380 { | 1354 { |
1381 assert(token.kind == T.Typeof); | 1355 auto begin = token; |
1382 auto begin = token; | 1356 skip(T.Typeof); |
1357 require(T.LParen); | |
1383 Type type; | 1358 Type type; |
1384 requireNext(T.LParen); | |
1385 switch (token.kind) | 1359 switch (token.kind) |
1386 { | 1360 { |
1387 version(D2) | 1361 version(D2) |
1388 { | 1362 { |
1389 case T.Return: | 1363 case T.Return: |
1408 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; | 1382 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; |
1409 +/ | 1383 +/ |
1410 Class parseMixin(Class)() | 1384 Class parseMixin(Class)() |
1411 { | 1385 { |
1412 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement)); | 1386 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement)); |
1413 assert(token.kind == T.Mixin); | 1387 skip(T.Mixin); |
1414 nT(); // Skip mixin keyword. | |
1415 | 1388 |
1416 static if (is(Class == MixinDeclaration)) | 1389 static if (is(Class == MixinDeclaration)) |
1417 { | 1390 { |
1418 if (consumed(T.LParen)) | 1391 if (consumed(T.LParen)) |
1419 { | 1392 { |
1501 return s; | 1474 return s; |
1502 case T.Identifier: | 1475 case T.Identifier: |
1503 if (peekNext() == T.Colon) | 1476 if (peekNext() == T.Colon) |
1504 { | 1477 { |
1505 auto ident = token.ident; | 1478 auto ident = token.ident; |
1506 nT(), nT(); // Skip Identifier : | 1479 skip(T.Identifier); skip(T.Colon); |
1507 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement()); | 1480 s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement()); |
1508 break; | 1481 break; |
1509 } | 1482 } |
1510 goto case T.Dot; | 1483 goto case T.Dot; |
1511 case T.Dot, T.Typeof: | 1484 case T.Dot, T.Typeof: |
1819 return new DeclarationStatement(parse()); | 1792 return new DeclarationStatement(parse()); |
1820 } | 1793 } |
1821 | 1794 |
1822 Statement parseIfStatement() | 1795 Statement parseIfStatement() |
1823 { | 1796 { |
1824 assert(token.kind == T.If); | 1797 skip(T.If); |
1825 nT(); | |
1826 | 1798 |
1827 Statement variable; | 1799 Statement variable; |
1828 Expression condition; | 1800 Expression condition; |
1829 Statement ifBody, elseBody; | 1801 Statement ifBody, elseBody; |
1830 | 1802 |
1844 set(d, begin); | 1816 set(d, begin); |
1845 variable = new DeclarationStatement(d); | 1817 variable = new DeclarationStatement(d); |
1846 set(variable, begin); | 1818 set(variable, begin); |
1847 } | 1819 } |
1848 else | 1820 else |
1849 { | 1821 { // Declarator = Expression |
1850 // Declarator = Expression | |
1851 Type parseDeclaratorAssign() | 1822 Type parseDeclaratorAssign() |
1852 { | 1823 { |
1853 auto type = parseDeclarator(ident); | 1824 auto type = parseDeclarator(ident); |
1854 require(T.Assign); | 1825 require(T.Assign); |
1855 return type; | 1826 return type; |
1874 return new IfStatement(variable, condition, ifBody, elseBody); | 1845 return new IfStatement(variable, condition, ifBody, elseBody); |
1875 } | 1846 } |
1876 | 1847 |
1877 Statement parseWhileStatement() | 1848 Statement parseWhileStatement() |
1878 { | 1849 { |
1879 assert(token.kind == T.While); | 1850 skip(T.While); |
1880 nT(); | |
1881 require(T.LParen); | 1851 require(T.LParen); |
1882 auto condition = parseExpression(); | 1852 auto condition = parseExpression(); |
1883 require(T.RParen); | 1853 require(T.RParen); |
1884 return new WhileStatement(condition, parseScopeStatement()); | 1854 return new WhileStatement(condition, parseScopeStatement()); |
1885 } | 1855 } |
1886 | 1856 |
1887 Statement parseDoWhileStatement() | 1857 Statement parseDoWhileStatement() |
1888 { | 1858 { |
1889 assert(token.kind == T.Do); | 1859 skip(T.Do); |
1890 nT(); | |
1891 auto doBody = parseScopeStatement(); | 1860 auto doBody = parseScopeStatement(); |
1892 require(T.While); | 1861 require(T.While); |
1893 require(T.LParen); | 1862 require(T.LParen); |
1894 auto condition = parseExpression(); | 1863 auto condition = parseExpression(); |
1895 require(T.RParen); | 1864 require(T.RParen); |
1896 return new DoWhileStatement(condition, doBody); | 1865 return new DoWhileStatement(condition, doBody); |
1897 } | 1866 } |
1898 | 1867 |
1899 Statement parseForStatement() | 1868 Statement parseForStatement() |
1900 { | 1869 { |
1901 assert(token.kind == T.For); | 1870 skip(T.For); |
1902 nT(); | |
1903 require(T.LParen); | |
1904 | 1871 |
1905 Statement init, forBody; | 1872 Statement init, forBody; |
1906 Expression condition, increment; | 1873 Expression condition, increment; |
1907 | 1874 |
1908 if (token.kind != T.Semicolon) | 1875 require(T.LParen); |
1876 if (!consumed(T.Semicolon)) | |
1909 init = parseNoScopeStatement(); | 1877 init = parseNoScopeStatement(); |
1910 else | |
1911 nT(); // Skip ; | |
1912 if (token.kind != T.Semicolon) | 1878 if (token.kind != T.Semicolon) |
1913 condition = parseExpression(); | 1879 condition = parseExpression(); |
1914 require(T.Semicolon); | 1880 require(T.Semicolon); |
1915 if (token.kind != T.RParen) | 1881 if (token.kind != T.RParen) |
1916 increment = parseExpression(); | 1882 increment = parseExpression(); |
1978 return new ForeachStatement(tok, params, e, forBody); | 1944 return new ForeachStatement(tok, params, e, forBody); |
1979 } | 1945 } |
1980 | 1946 |
1981 Statement parseSwitchStatement() | 1947 Statement parseSwitchStatement() |
1982 { | 1948 { |
1983 assert(token.kind == T.Switch); | 1949 skip(T.Switch); |
1984 nT(); | |
1985 require(T.LParen); | 1950 require(T.LParen); |
1986 auto condition = parseExpression(); | 1951 auto condition = parseExpression(); |
1987 require(T.RParen); | 1952 require(T.RParen); |
1988 auto switchBody = parseScopeStatement(); | 1953 auto switchBody = parseScopeStatement(); |
1989 return new SwitchStatement(condition, switchBody); | 1954 return new SwitchStatement(condition, switchBody); |
1990 } | 1955 } |
1991 | 1956 |
1992 /++ | 1957 /// Helper function for parsing the body of a default or case statement. |
1993 Helper function for parsing the body of | |
1994 a default or case statement. | |
1995 +/ | |
1996 Statement parseCaseOrDefaultBody() | 1958 Statement parseCaseOrDefaultBody() |
1997 { | 1959 { |
1998 // This function is similar to parseNoScopeStatement() | 1960 // This function is similar to parseNoScopeStatement() |
1999 auto begin = token; | 1961 auto begin = token; |
2000 auto s = new CompoundStatement(); | 1962 auto s = new CompoundStatement(); |
2007 return set(new ScopeStatement(s), begin); | 1969 return set(new ScopeStatement(s), begin); |
2008 } | 1970 } |
2009 | 1971 |
2010 Statement parseCaseStatement() | 1972 Statement parseCaseStatement() |
2011 { | 1973 { |
2012 assert(token.kind == T.Case); | 1974 skip(T.Case); |
2013 nT(); | |
2014 auto values = parseExpressionList(); | 1975 auto values = parseExpressionList(); |
2015 require(T.Colon); | 1976 require(T.Colon); |
2016 auto caseBody = parseCaseOrDefaultBody(); | 1977 auto caseBody = parseCaseOrDefaultBody(); |
2017 return new CaseStatement(values, caseBody); | 1978 return new CaseStatement(values, caseBody); |
2018 } | 1979 } |
2019 | 1980 |
2020 Statement parseDefaultStatement() | 1981 Statement parseDefaultStatement() |
2021 { | 1982 { |
2022 assert(token.kind == T.Default); | 1983 skip(T.Default); |
2023 nT(); | |
2024 require(T.Colon); | 1984 require(T.Colon); |
2025 auto defaultBody = parseCaseOrDefaultBody(); | 1985 auto defaultBody = parseCaseOrDefaultBody(); |
2026 return new DefaultStatement(defaultBody); | 1986 return new DefaultStatement(defaultBody); |
2027 } | 1987 } |
2028 | 1988 |
2029 Statement parseContinueStatement() | 1989 Statement parseContinueStatement() |
2030 { | 1990 { |
2031 assert(token.kind == T.Continue); | 1991 skip(T.Continue); |
2032 nT(); | |
2033 auto ident = optionalIdentifier(); | 1992 auto ident = optionalIdentifier(); |
2034 require(T.Semicolon); | 1993 require(T.Semicolon); |
2035 return new ContinueStatement(ident); | 1994 return new ContinueStatement(ident); |
2036 } | 1995 } |
2037 | 1996 |
2038 Statement parseBreakStatement() | 1997 Statement parseBreakStatement() |
2039 { | 1998 { |
2040 assert(token.kind == T.Break); | 1999 skip(T.Break); |
2041 nT(); | |
2042 auto ident = optionalIdentifier(); | 2000 auto ident = optionalIdentifier(); |
2043 require(T.Semicolon); | 2001 require(T.Semicolon); |
2044 return new BreakStatement(ident); | 2002 return new BreakStatement(ident); |
2045 } | 2003 } |
2046 | 2004 |
2047 Statement parseReturnStatement() | 2005 Statement parseReturnStatement() |
2048 { | 2006 { |
2049 assert(token.kind == T.Return); | 2007 skip(T.Return); |
2050 nT(); | |
2051 Expression expr; | 2008 Expression expr; |
2052 if (token.kind != T.Semicolon) | 2009 if (token.kind != T.Semicolon) |
2053 expr = parseExpression(); | 2010 expr = parseExpression(); |
2054 require(T.Semicolon); | 2011 require(T.Semicolon); |
2055 return new ReturnStatement(expr); | 2012 return new ReturnStatement(expr); |
2056 } | 2013 } |
2057 | 2014 |
2058 Statement parseGotoStatement() | 2015 Statement parseGotoStatement() |
2059 { | 2016 { |
2060 assert(token.kind == T.Goto); | 2017 skip(T.Goto); |
2061 nT(); | |
2062 Identifier* ident; | 2018 Identifier* ident; |
2063 Expression caseExpr; | 2019 Expression caseExpr; |
2064 switch (token.kind) | 2020 switch (token.kind) |
2065 { | 2021 { |
2066 case T.Case: | 2022 case T.Case: |
2023 ident = token.ident; | |
2067 nT(); | 2024 nT(); |
2068 if (token.kind == T.Semicolon) | 2025 if (token.kind == T.Semicolon) |
2069 break; | 2026 break; |
2070 caseExpr = parseExpression(); | 2027 caseExpr = parseExpression(); |
2071 break; | 2028 break; |
2072 case T.Default: | 2029 case T.Default: |
2030 ident = token.ident; | |
2073 nT(); | 2031 nT(); |
2074 break; | 2032 break; |
2075 default: | 2033 default: |
2076 ident = requireIdentifier(MSG.ExpectedAnIdentifier); | 2034 ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
2077 } | 2035 } |
2079 return new GotoStatement(ident, caseExpr); | 2037 return new GotoStatement(ident, caseExpr); |
2080 } | 2038 } |
2081 | 2039 |
2082 Statement parseWithStatement() | 2040 Statement parseWithStatement() |
2083 { | 2041 { |
2084 assert(token.kind == T.With); | 2042 skip(T.With); |
2085 nT(); | |
2086 require(T.LParen); | 2043 require(T.LParen); |
2087 auto expr = parseExpression(); | 2044 auto expr = parseExpression(); |
2088 require(T.RParen); | 2045 require(T.RParen); |
2089 return new WithStatement(expr, parseScopeStatement()); | 2046 return new WithStatement(expr, parseScopeStatement()); |
2090 } | 2047 } |
2091 | 2048 |
2092 Statement parseSynchronizedStatement() | 2049 Statement parseSynchronizedStatement() |
2093 { | 2050 { |
2094 assert(token.kind == T.Synchronized); | 2051 skip(T.Synchronized); |
2095 nT(); | |
2096 Expression expr; | 2052 Expression expr; |
2097 if (consumed(T.LParen)) | 2053 if (consumed(T.LParen)) |
2098 { | 2054 { |
2099 expr = parseExpression(); | 2055 expr = parseExpression(); |
2100 require(T.RParen); | 2056 require(T.RParen); |
2102 return new SynchronizedStatement(expr, parseScopeStatement()); | 2058 return new SynchronizedStatement(expr, parseScopeStatement()); |
2103 } | 2059 } |
2104 | 2060 |
2105 Statement parseTryStatement() | 2061 Statement parseTryStatement() |
2106 { | 2062 { |
2107 assert(token.kind == T.Try); | 2063 auto begin = token; |
2108 auto begin = token; | 2064 skip(T.Try); |
2109 nT(); | |
2110 | 2065 |
2111 auto tryBody = parseScopeStatement(); | 2066 auto tryBody = parseScopeStatement(); |
2112 CatchStatement[] catchBodies; | 2067 CatchStatement[] catchBodies; |
2113 FinallyStatement finBody; | 2068 FinallyStatement finBody; |
2114 | 2069 |
2139 return new TryStatement(tryBody, catchBodies, finBody); | 2094 return new TryStatement(tryBody, catchBodies, finBody); |
2140 } | 2095 } |
2141 | 2096 |
2142 Statement parseThrowStatement() | 2097 Statement parseThrowStatement() |
2143 { | 2098 { |
2144 assert(token.kind == T.Throw); | 2099 skip(T.Throw); |
2145 nT(); | |
2146 auto expr = parseExpression(); | 2100 auto expr = parseExpression(); |
2147 require(T.Semicolon); | 2101 require(T.Semicolon); |
2148 return new ThrowStatement(expr); | 2102 return new ThrowStatement(expr); |
2149 } | 2103 } |
2150 | 2104 |
2151 Statement parseScopeGuardStatement() | 2105 Statement parseScopeGuardStatement() |
2152 { | 2106 { |
2153 assert(token.kind == T.Scope); | 2107 skip(T.Scope); |
2154 nT(); | 2108 skip(T.LParen); |
2155 assert(token.kind == T.LParen); | |
2156 nT(); | |
2157 auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier); | 2109 auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier); |
2158 if (condition) | 2110 if (condition) |
2159 switch (condition.idKind) | 2111 switch (condition.idKind) |
2160 { | 2112 { |
2161 case IDK.exit, IDK.success, IDK.failure: | 2113 case IDK.exit, IDK.success, IDK.failure: |
2172 return new ScopeGuardStatement(condition, scopeBody); | 2124 return new ScopeGuardStatement(condition, scopeBody); |
2173 } | 2125 } |
2174 | 2126 |
2175 Statement parseVolatileStatement() | 2127 Statement parseVolatileStatement() |
2176 { | 2128 { |
2177 assert(token.kind == T.Volatile); | 2129 skip(T.Volatile); |
2178 nT(); | |
2179 Statement volatileBody; | 2130 Statement volatileBody; |
2180 if (token.kind == T.Semicolon) | 2131 if (token.kind == T.Semicolon) |
2181 nT(); | 2132 nT(); |
2182 else if (token.kind == T.LBrace) | 2133 else if (token.kind == T.LBrace) |
2183 volatileBody = parseScopeStatement(); | 2134 volatileBody = parseScopeStatement(); |
2186 return new VolatileStatement(volatileBody); | 2137 return new VolatileStatement(volatileBody); |
2187 } | 2138 } |
2188 | 2139 |
2189 Statement parsePragmaStatement() | 2140 Statement parsePragmaStatement() |
2190 { | 2141 { |
2191 assert(token.kind == T.Pragma); | 2142 skip(T.Pragma); |
2192 nT(); | |
2193 | 2143 |
2194 Identifier* ident; | 2144 Identifier* ident; |
2195 Expression[] args; | 2145 Expression[] args; |
2196 Statement pragmaBody; | 2146 Statement pragmaBody; |
2197 | 2147 |
2207 return new PragmaStatement(ident, args, pragmaBody); | 2157 return new PragmaStatement(ident, args, pragmaBody); |
2208 } | 2158 } |
2209 | 2159 |
2210 Statement parseStaticIfStatement() | 2160 Statement parseStaticIfStatement() |
2211 { | 2161 { |
2212 assert(token.kind == T.Static); | 2162 skip(T.Static); |
2213 nT(); | 2163 skip(T.If); |
2214 assert(token.kind == T.If); | |
2215 nT(); | |
2216 Expression condition; | 2164 Expression condition; |
2217 Statement ifBody, elseBody; | 2165 Statement ifBody, elseBody; |
2218 | 2166 |
2219 require(T.LParen); | 2167 require(T.LParen); |
2220 condition = parseExpression(); | 2168 condition = parseExpression(); |
2225 return new StaticIfStatement(condition, ifBody, elseBody); | 2173 return new StaticIfStatement(condition, ifBody, elseBody); |
2226 } | 2174 } |
2227 | 2175 |
2228 Statement parseStaticAssertStatement() | 2176 Statement parseStaticAssertStatement() |
2229 { | 2177 { |
2230 assert(token.kind == T.Static); | 2178 skip(T.Static); |
2231 nT(); | 2179 skip(T.Assert); |
2232 assert(token.kind == T.Assert); | |
2233 nT(); | |
2234 Expression condition, message; | 2180 Expression condition, message; |
2181 | |
2235 require(T.LParen); | 2182 require(T.LParen); |
2236 condition = parseAssignExpression(); // Condition. | 2183 condition = parseAssignExpression(); // Condition. |
2237 if (consumed(T.Comma)) | 2184 if (consumed(T.Comma)) |
2238 message = parseAssignExpression(); // Error message. | 2185 message = parseAssignExpression(); // Error message. |
2239 require(T.RParen); | 2186 require(T.RParen); |
2241 return new StaticAssertStatement(condition, message); | 2188 return new StaticAssertStatement(condition, message); |
2242 } | 2189 } |
2243 | 2190 |
2244 Statement parseDebugStatement() | 2191 Statement parseDebugStatement() |
2245 { | 2192 { |
2246 assert(token.kind == T.Debug); | 2193 skip(T.Debug); |
2247 nT(); // Skip debug keyword. | |
2248 | |
2249 Token* cond; | 2194 Token* cond; |
2250 Statement debugBody, elseBody; | 2195 Statement debugBody, elseBody; |
2251 | 2196 |
2252 // ( Condition ) | 2197 // ( Condition ) |
2253 if (consumed(T.LParen)) | 2198 if (consumed(T.LParen)) |
2265 return new DebugStatement(cond, debugBody, elseBody); | 2210 return new DebugStatement(cond, debugBody, elseBody); |
2266 } | 2211 } |
2267 | 2212 |
2268 Statement parseVersionStatement() | 2213 Statement parseVersionStatement() |
2269 { | 2214 { |
2270 assert(token.kind == T.Version); | 2215 skip(T.Version); |
2271 nT(); // Skip version keyword. | |
2272 | |
2273 Token* cond; | 2216 Token* cond; |
2274 Statement versionBody, elseBody; | 2217 Statement versionBody, elseBody; |
2275 | 2218 |
2276 // ( Condition ) | 2219 // ( Condition ) |
2277 require(T.LParen); | 2220 require(T.LParen); |
2290 | Assembler parsing methods | | 2233 | Assembler parsing methods | |
2291 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ | 2234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
2292 | 2235 |
2293 Statement parseAsmBlockStatement() | 2236 Statement parseAsmBlockStatement() |
2294 { | 2237 { |
2295 assert(token.kind == T.Asm); | 2238 skip(T.Asm); |
2296 nT(); // Skip asm keyword. | |
2297 require(T.LBrace); | 2239 require(T.LBrace); |
2298 auto ss = new CompoundStatement; | 2240 auto ss = new CompoundStatement; |
2299 while (token.kind != T.RBrace && token.kind != T.EOF) | 2241 while (token.kind != T.RBrace && token.kind != T.EOF) |
2300 ss ~= parseAsmStatement(); | 2242 ss ~= parseAsmStatement(); |
2301 require(T.RBrace); | 2243 require(T.RBrace); |
2314 ident = token.ident; | 2256 ident = token.ident; |
2315 nT(); | 2257 nT(); |
2316 goto LOpcode; | 2258 goto LOpcode; |
2317 case T.Identifier: | 2259 case T.Identifier: |
2318 ident = token.ident; | 2260 ident = token.ident; |
2319 nT(); // Skip Identifier | 2261 nT(); |
2320 if (consumed(T.Colon)) | 2262 if (consumed(T.Colon)) |
2321 { // Identifier : AsmStatement | 2263 { // Identifier : AsmStatement |
2322 s = new LabeledStatement(ident, parseAsmStatement()); | 2264 s = new LabeledStatement(ident, parseAsmStatement()); |
2323 break; | 2265 break; |
2324 } | 2266 } |
2339 case T.Align: | 2281 case T.Align: |
2340 // align Integer; | 2282 // align Integer; |
2341 nT(); | 2283 nT(); |
2342 int number = -1; | 2284 int number = -1; |
2343 if (token.kind == T.Int32) | 2285 if (token.kind == T.Int32) |
2344 (number = token.int_), nT(); | 2286 (number = token.int_), skip(T.Int32); |
2345 else | 2287 else |
2346 error(token, MSG.ExpectedIntegerAfterAlign, token.srcText); | 2288 error(token, MSG.ExpectedIntegerAfterAlign, token.srcText); |
2347 require(T.Semicolon); | 2289 require(T.Semicolon); |
2348 s = new AsmAlignStatement(number); | 2290 s = new AsmAlignStatement(number); |
2349 break; | 2291 break; |
2574 case IDK.near, IDK.far,/* "byte", "short", "int",*/ | 2516 case IDK.near, IDK.far,/* "byte", "short", "int",*/ |
2575 IDK.word, IDK.dword, IDK.qword/*, "float", "double", "real"*/: | 2517 IDK.word, IDK.dword, IDK.qword/*, "float", "double", "real"*/: |
2576 LAsmTypePrefix: | 2518 LAsmTypePrefix: |
2577 nT(); | 2519 nT(); |
2578 if (token.kind == T.Identifier && token.ident is Ident.ptr) | 2520 if (token.kind == T.Identifier && token.ident is Ident.ptr) |
2579 nT(); | 2521 skip(T.Identifier); |
2580 else | 2522 else |
2581 error(MID.ExpectedButFound, "ptr", token.srcText); | 2523 error(MID.ExpectedButFound, "ptr", token.srcText); |
2582 e = new AsmTypeExpression(parseAsmExpression()); | 2524 e = new AsmTypeExpression(parseAsmExpression()); |
2583 break; | 2525 break; |
2584 case IDK.offset: | 2526 case IDK.offset: |
2665 // (1) - (7) | 2607 // (1) - (7) |
2666 int number = -1; | 2608 int number = -1; |
2667 if (consumed(T.LParen)) | 2609 if (consumed(T.LParen)) |
2668 { | 2610 { |
2669 if (token.kind == T.Int32) | 2611 if (token.kind == T.Int32) |
2670 (number = token.int_), nT(); | 2612 (number = token.int_), skip(T.Int32); |
2671 else | 2613 else |
2672 expected(T.Int32); | 2614 expected(T.Int32); |
2673 require(T.RParen); | 2615 require(T.RParen); |
2674 } | 2616 } |
2675 e = new AsmRegisterExpression(register, number); | 2617 e = new AsmRegisterExpression(register, number); |
2680 int number = -1; | 2622 int number = -1; |
2681 if (consumed(T.Colon)) | 2623 if (consumed(T.Colon)) |
2682 { | 2624 { |
2683 // :0, :4, :8 | 2625 // :0, :4, :8 |
2684 if (token.kind == T.Int32) | 2626 if (token.kind == T.Int32) |
2685 (number = token.int_), nT(); | 2627 (number = token.int_), skip(T.Int32); |
2686 if (number != 0 && number != 4 && number != 8) | 2628 if (number != 0 && number != 4 && number != 8) |
2687 error(MID.ExpectedButFound, "0, 4 or 8", token.srcText); | 2629 error(MID.ExpectedButFound, "0, 4 or 8", token.srcText); |
2688 } | 2630 } |
2689 e = new AsmRegisterExpression(register, number); | 2631 e = new AsmRegisterExpression(register, number); |
2690 break; | 2632 break; |
3108 break; | 3050 break; |
3109 case T.LParen: | 3051 case T.LParen: |
3110 // ( Type ) . Identifier | 3052 // ( Type ) . Identifier |
3111 Type parseType_() | 3053 Type parseType_() |
3112 { | 3054 { |
3113 nT(); | 3055 skip(T.LParen); |
3114 auto type = parseType(); | 3056 auto type = parseType(); |
3115 require(T.RParen); | 3057 require(T.RParen); |
3116 require(T.Dot); | 3058 require(T.Dot); |
3117 return type; | 3059 return type; |
3118 } | 3060 } |
3151 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); | 3093 auto ident = requireIdentifier(MSG.ExpectedAnIdentifier); |
3152 Expression e; | 3094 Expression e; |
3153 // Peek for '(' to avoid matching: id !is id | 3095 // Peek for '(' to avoid matching: id !is id |
3154 if (token.kind == T.Not && peekNext() == T.LParen) | 3096 if (token.kind == T.Not && peekNext() == T.LParen) |
3155 { // Identifier !( TemplateArguments ) | 3097 { // Identifier !( TemplateArguments ) |
3156 nT(); // Skip !. | 3098 skip(T.Not); |
3157 auto tparams = parseTemplateArguments(); | 3099 auto tparams = parseTemplateArguments(); |
3158 e = new TemplateInstanceExpression(ident, tparams); | 3100 e = new TemplateInstanceExpression(ident, tparams); |
3159 } | 3101 } |
3160 else // Identifier | 3102 else // Identifier |
3161 e = new IdentifierExpression(ident); | 3103 e = new IdentifierExpression(ident); |
3369 auto funcBody = parseFunctionBody(); | 3311 auto funcBody = parseFunctionBody(); |
3370 e = new FunctionLiteralExpression(null, parameters, funcBody); | 3312 e = new FunctionLiteralExpression(null, parameters, funcBody); |
3371 } | 3313 } |
3372 else | 3314 else |
3373 { // ( Expression ) | 3315 { // ( Expression ) |
3374 nT(); | 3316 skip(T.LParen); |
3375 e = parseExpression(); | 3317 e = parseExpression(); |
3376 require(T.RParen); | 3318 require(T.RParen); |
3377 e = new ParenExpression(e); | 3319 e = new ParenExpression(e); |
3378 } | 3320 } |
3379 break; | 3321 break; |
3380 version(D2) | 3322 version(D2) |
3381 { | 3323 { |
3382 case T.Traits: | 3324 case T.Traits: |
3383 nT(); | 3325 requireNext(T.LParen); |
3384 require(T.LParen); | |
3385 auto id = requireIdentifier(MSG.ExpectedAnIdentifier); | 3326 auto id = requireIdentifier(MSG.ExpectedAnIdentifier); |
3386 TemplateArguments args; | 3327 TemplateArguments args; |
3387 if (token.kind == T.Comma) | 3328 if (token.kind == T.Comma) |
3388 args = parseTemplateArguments2(); | 3329 args = parseTemplateArguments2(); |
3389 else | 3330 else |
3422 } | 3363 } |
3423 | 3364 |
3424 Expression parseNewExpression(/*Expression e*/) | 3365 Expression parseNewExpression(/*Expression e*/) |
3425 { | 3366 { |
3426 auto begin = token; | 3367 auto begin = token; |
3427 assert(token.kind == T.New); | 3368 skip(T.New); |
3428 nT(); // Skip new keyword. | |
3429 | 3369 |
3430 Expression[] newArguments; | 3370 Expression[] newArguments; |
3431 Expression[] ctorArguments; | 3371 Expression[] ctorArguments; |
3432 | 3372 |
3433 if (token.kind == T.LParen) | 3373 if (token.kind == T.LParen) |
3513 return t; | 3453 return t; |
3514 version(D2) | 3454 version(D2) |
3515 { | 3455 { |
3516 case T.Const: | 3456 case T.Const: |
3517 // const ( Type ) | 3457 // const ( Type ) |
3518 nT(); | 3458 requireNext(T.LParen); |
3519 require(T.LParen); | |
3520 t = parseType(); | 3459 t = parseType(); |
3521 require(T.RParen); | 3460 require(T.RParen); |
3522 t = new ConstType(t); | 3461 t = new ConstType(t); |
3523 break; | 3462 break; |
3524 case T.Invariant: | 3463 case T.Invariant: |
3525 // invariant ( Type ) | 3464 // invariant ( Type ) |
3526 nT(); | 3465 requireNext(T.LParen); |
3527 require(T.LParen); | |
3528 t = parseType(); | 3466 t = parseType(); |
3529 require(T.RParen); | 3467 require(T.RParen); |
3530 t = new InvariantType(t); | 3468 t = new InvariantType(t); |
3531 break; | 3469 break; |
3532 } // version(D2) | 3470 } // version(D2) |
3538 return set(t, begin); | 3476 return set(t, begin); |
3539 } | 3477 } |
3540 | 3478 |
3541 Type parseBasicType2(Type t) | 3479 Type parseBasicType2(Type t) |
3542 { | 3480 { |
3543 typeof(token) begin; | |
3544 while (1) | 3481 while (1) |
3545 { | 3482 { |
3546 begin = token; | 3483 auto begin = token; |
3547 switch (token.kind) | 3484 switch (token.kind) |
3548 { | 3485 { |
3549 case T.Mul: | 3486 case T.Mul: |
3550 t = new PointerType(t); | 3487 t = new PointerType(t); |
3551 nT(); | 3488 nT(); |
3570 assert(0); | 3507 assert(0); |
3571 } | 3508 } |
3572 | 3509 |
3573 bool tokenAfterParenIs(TOK tok) | 3510 bool tokenAfterParenIs(TOK tok) |
3574 { | 3511 { |
3575 // We count nested parentheses tokens because template types may appear inside parameter lists; e.g. (int x, Foo!(int) y). | 3512 // We count nested parentheses tokens because template types |
3513 // may appear inside parameter lists. E.g.: (int x, Foo!(int) y) | |
3576 assert(token.kind == T.LParen); | 3514 assert(token.kind == T.LParen); |
3577 Token* next = token; | 3515 Token* next = token; |
3578 uint level = 1; | 3516 uint level = 1; |
3579 Loop: | 3517 Loop: |
3580 while (1) | 3518 while (1) |
3615 if (token.kind != T.LBracket) | 3553 if (token.kind != T.LBracket) |
3616 return lhsType; // Break recursion; return Type on the left hand side of the Identifier. | 3554 return lhsType; // Break recursion; return Type on the left hand side of the Identifier. |
3617 | 3555 |
3618 auto begin = token; | 3556 auto begin = token; |
3619 Type t; | 3557 Type t; |
3620 nT(); | 3558 skip(T.LBracket); |
3621 if (consumed(T.RBracket)) | 3559 if (consumed(T.RBracket)) |
3622 t = new ArrayType(parseNext()); // [ ] | 3560 t = new ArrayType(parseNext()); // [ ] |
3623 else | 3561 else |
3624 { | 3562 { |
3625 bool success; | 3563 bool success; |
3647 return parseNext(); | 3585 return parseNext(); |
3648 } | 3586 } |
3649 | 3587 |
3650 Type parseArrayType(Type t) | 3588 Type parseArrayType(Type t) |
3651 { | 3589 { |
3652 assert(token.kind == T.LBracket); | 3590 auto begin = token; |
3653 auto begin = token; | 3591 skip(T.LBracket); |
3654 nT(); | |
3655 if (consumed(T.RBracket)) | 3592 if (consumed(T.RBracket)) |
3656 t = new ArrayType(t); | 3593 t = new ArrayType(t); |
3657 else | 3594 else |
3658 { | 3595 { |
3659 bool success; | 3596 bool success; |
3679 return t; | 3616 return t; |
3680 } | 3617 } |
3681 | 3618 |
3682 Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList) | 3619 Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList) |
3683 { | 3620 { |
3684 assert(token.kind == T.LParen); | |
3685 assert(type !is null); | 3621 assert(type !is null); |
3686 auto begin = token; | 3622 auto begin = token; |
3687 nT(); // Skip ( | 3623 skip(T.LParen); |
3624 | |
3688 type = parseBasicType2(type); | 3625 type = parseBasicType2(type); |
3689 if (token.kind == T.LParen) | 3626 if (token.kind == T.LParen) |
3690 { | 3627 { // Can be nested. |
3691 // Can be nested. | |
3692 type = parseCFunctionPointerType(type, ident, true); | 3628 type = parseCFunctionPointerType(type, ident, true); |
3693 } | 3629 } |
3694 else if (token.kind == T.Identifier) | 3630 else if (token.kind == T.Identifier) |
3695 { | 3631 { // The identifier of the function pointer and the declaration. |
3696 // The identifier of the function pointer and the declaration. | |
3697 ident = token.ident; | 3632 ident = token.ident; |
3698 nT(); | 3633 nT(); |
3699 type = parseDeclaratorSuffix(type); | 3634 type = parseDeclaratorSuffix(type); |
3700 } | 3635 } |
3701 require(T.RParen); | 3636 require(T.RParen); |
3749 ( ) | 3684 ( ) |
3750 ( ExpressionList ) | 3685 ( ExpressionList ) |
3751 +/ | 3686 +/ |
3752 Expression[] parseArguments() | 3687 Expression[] parseArguments() |
3753 { | 3688 { |
3754 assert(token.kind == T.LParen); | 3689 skip(T.LParen); |
3755 nT(); | |
3756 Expression[] args; | 3690 Expression[] args; |
3757 if (token.kind != TOK.RParen) | 3691 if (token.kind != T.RParen) |
3758 args = parseExpressionList(); | 3692 args = parseExpressionList(); |
3759 require(TOK.RParen); | 3693 require(T.RParen); |
3760 return args; | 3694 return args; |
3761 } | 3695 } |
3762 | 3696 |
3763 Parameters parseParameterList() | 3697 Parameters parseParameterList() |
3764 out(params) | 3698 out(params) |
3883 | 3817 |
3884 version(D2) | 3818 version(D2) |
3885 { | 3819 { |
3886 TemplateArguments parseTemplateArguments2() | 3820 TemplateArguments parseTemplateArguments2() |
3887 { | 3821 { |
3888 assert(token.kind == T.Comma); | 3822 skip(T.Comma); |
3889 nT(); | |
3890 TemplateArguments targs; | 3823 TemplateArguments targs; |
3891 if (token.kind != T.RParen) | 3824 if (token.kind != T.RParen) |
3892 targs = parseTemplateArguments_(); | 3825 targs = parseTemplateArguments_(); |
3893 else | 3826 else |
3894 error(token, MSG.ExpectedTypeOrExpression); | 3827 error(token, MSG.ExpectedTypeOrExpression); |
3906 Type parseType_() | 3839 Type parseType_() |
3907 { | 3840 { |
3908 auto type = parseType(); | 3841 auto type = parseType(); |
3909 if (token.kind == T.Comma || token.kind == T.RParen) | 3842 if (token.kind == T.Comma || token.kind == T.RParen) |
3910 return type; | 3843 return type; |
3911 ++errorCount; // Cause try_() to fail. | 3844 errorCount++; // Cause try_() to fail. |
3912 return null; | 3845 return null; |
3913 } | 3846 } |
3914 bool success; | 3847 bool success; |
3915 auto typeArgument = try_(&parseType_, success); | 3848 auto typeArgument = try_(&parseType_, success); |
3916 if (success) | 3849 if (success) |
3940 | 3873 |
3941 version(D2) | 3874 version(D2) |
3942 { | 3875 { |
3943 TemplateParameters parseTemplateParameterList2() | 3876 TemplateParameters parseTemplateParameterList2() |
3944 { | 3877 { |
3945 assert(token.kind == T.Comma); | 3878 skip(T.Comma); |
3946 nT(); | |
3947 auto begin = token; | 3879 auto begin = token; |
3948 auto tparams = new TemplateParameters; | 3880 auto tparams = new TemplateParameters; |
3949 if (token.kind != T.RParen) | 3881 if (token.kind != T.RParen) |
3950 parseTemplateParameterList_(tparams); | 3882 parseTemplateParameterList_(tparams); |
3951 else | 3883 else |
3976 switch (token.kind) | 3908 switch (token.kind) |
3977 { | 3909 { |
3978 case T.Alias: | 3910 case T.Alias: |
3979 // TemplateAliasParameter: | 3911 // TemplateAliasParameter: |
3980 // alias Identifier | 3912 // alias Identifier |
3981 nT(); // Skip alias keyword. | 3913 skip(T.Alias); |
3982 ident = requireIdentifier(MSG.ExpectedAliasTemplateParam); | 3914 ident = requireIdentifier(MSG.ExpectedAliasTemplateParam); |
3983 parseSpecAndOrDefaultType(); | 3915 parseSpecAndOrDefaultType(); |
3984 tp = new TemplateAliasParameter(ident, specType, defType); | 3916 tp = new TemplateAliasParameter(ident, specType, defType); |
3985 break; | 3917 break; |
3986 case T.Identifier: | 3918 case T.Identifier: |
3988 switch (peekNext()) | 3920 switch (peekNext()) |
3989 { | 3921 { |
3990 case T.Ellipses: | 3922 case T.Ellipses: |
3991 // TemplateTupleParameter: | 3923 // TemplateTupleParameter: |
3992 // Identifier ... | 3924 // Identifier ... |
3993 nT(); // Skip Identifier. | 3925 skip(T.Identifier); skip(T.Ellipses); |
3994 nT(); // Skip Ellipses. | |
3995 if (token.kind == T.Comma) | 3926 if (token.kind == T.Comma) |
3996 error(MID.TemplateTupleParameter); | 3927 error(MID.TemplateTupleParameter); |
3997 tp = new TemplateTupleParameter(ident); | 3928 tp = new TemplateTupleParameter(ident); |
3998 break; | 3929 break; |
3999 case T.Comma, T.RParen, T.Colon, T.Assign: | 3930 case T.Comma, T.RParen, T.Colon, T.Assign: |
4000 // TemplateTypeParameter: | 3931 // TemplateTypeParameter: |
4001 // Identifier | 3932 // Identifier |
4002 nT(); // Skip Identifier. | 3933 skip(T.Identifier); |
4003 parseSpecAndOrDefaultType(); | 3934 parseSpecAndOrDefaultType(); |
4004 tp = new TemplateTypeParameter(ident, specType, defType); | 3935 tp = new TemplateTypeParameter(ident, specType, defType); |
4005 break; | 3936 break; |
4006 default: | 3937 default: |
4007 // TemplateValueParameter: | 3938 // TemplateValueParameter: |
4013 version(D2) | 3944 version(D2) |
4014 { | 3945 { |
4015 case T.This: | 3946 case T.This: |
4016 // TemplateThisParameter | 3947 // TemplateThisParameter |
4017 // this TemplateTypeParameter | 3948 // this TemplateTypeParameter |
4018 nT(); // Skip 'this' keyword. | 3949 skip(T.This); |
4019 ident = requireIdentifier(MSG.ExpectedNameForThisTempParam); | 3950 ident = requireIdentifier(MSG.ExpectedNameForThisTempParam); |
4020 parseSpecAndOrDefaultType(); | 3951 parseSpecAndOrDefaultType(); |
4021 tp = new TemplateThisParameter(ident, specType, defType); | 3952 tp = new TemplateThisParameter(ident, specType, defType); |
4022 break; | 3953 break; |
4023 } | 3954 } |
4064 | 3995 |
4065 Identifier* optionalIdentifier() | 3996 Identifier* optionalIdentifier() |
4066 { | 3997 { |
4067 Identifier* id; | 3998 Identifier* id; |
4068 if (token.kind == T.Identifier) | 3999 if (token.kind == T.Identifier) |
4069 (id = token.ident), nT(); | 4000 (id = token.ident), skip(T.Identifier); |
4070 return id; | 4001 return id; |
4071 } | 4002 } |
4072 | 4003 |
4073 Identifier* requireIdentifier() | 4004 Identifier* requireIdentifier() |
4074 { | 4005 { |
4075 Identifier* id; | 4006 Identifier* id; |
4076 if (token.kind == T.Identifier) | 4007 if (token.kind == T.Identifier) |
4077 (id = token.ident), nT(); | 4008 (id = token.ident), skip(T.Identifier); |
4078 else | 4009 else |
4079 error(MID.ExpectedButFound, "Identifier", token.srcText); | 4010 error(MID.ExpectedButFound, "Identifier", token.srcText); |
4080 return id; | 4011 return id; |
4081 } | 4012 } |
4082 | 4013 |
4083 /++ | 4014 /// Params: |
4084 Params: | 4015 /// errorMsg = an error that has no message ID yet. |
4085 errorMsg = an error that has no message ID yet. | |
4086 +/ | |
4087 Identifier* requireIdentifier(char[] errorMsg) | 4016 Identifier* requireIdentifier(char[] errorMsg) |
4088 { | 4017 { |
4089 Identifier* id; | 4018 Identifier* id; |
4090 if (token.kind == T.Identifier) | 4019 if (token.kind == T.Identifier) |
4091 (id = token.ident), nT(); | 4020 (id = token.ident), skip(T.Identifier); |
4092 else | 4021 else |
4093 error(token, errorMsg, token.srcText); | 4022 error(token, errorMsg, token.srcText); |
4094 return id; | 4023 return id; |
4095 } | 4024 } |
4096 | 4025 |
4097 Identifier* requireIdentifier(MID mid) | 4026 Identifier* requireIdentifier(MID mid) |
4098 { | 4027 { |
4099 Identifier* id; | 4028 Identifier* id; |
4100 if (token.kind == T.Identifier) | 4029 if (token.kind == T.Identifier) |
4101 (id = token.ident), nT(); | 4030 (id = token.ident), skip(T.Identifier); |
4102 else | 4031 else |
4103 error(mid, token.srcText); | 4032 error(mid, token.srcText); |
4104 return id; | 4033 return id; |
4105 } | 4034 } |
4106 | 4035 |
4119 | 4048 |
4120 Token* requireIdToken(char[] errorMsg) | 4049 Token* requireIdToken(char[] errorMsg) |
4121 { | 4050 { |
4122 Token* idtok; | 4051 Token* idtok; |
4123 if (token.kind == T.Identifier) | 4052 if (token.kind == T.Identifier) |
4124 (idtok = token), nT(); | 4053 (idtok = token), skip(T.Identifier); |
4125 else | 4054 else |
4126 error(token, errorMsg, token.srcText); | 4055 error(token, errorMsg, token.srcText); |
4127 return idtok; | 4056 return idtok; |
4128 } | 4057 } |
4129 | 4058 |