Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2978073002: Add closeBraceTokenFor and use it instead of BeginToken. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' show Code, Message, Template; 7 import '../fasta_codes.dart' show Code, Message, Template;
8 8
9 import '../fasta_codes.dart' as fasta; 9 import '../fasta_codes.dart' as fasta;
10 10
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 64
65 import 'identifier_context.dart' show IdentifierContext; 65 import 'identifier_context.dart' show IdentifierContext;
66 66
67 import 'listener.dart' show Listener; 67 import 'listener.dart' show Listener;
68 68
69 import 'member_kind.dart' show MemberKind; 69 import 'member_kind.dart' show MemberKind;
70 70
71 import 'type_continuation.dart' 71 import 'type_continuation.dart'
72 show TypeContinuation, typeContiunationFromFormalParameterKind; 72 show TypeContinuation, typeContiunationFromFormalParameterKind;
73 73
74 import 'util.dart' show optional; 74 import 'util.dart' show closeBraceTokenFor, optional;
75 75
76 /// An event generating parser of Dart programs. This parser expects all tokens 76 /// An event generating parser of Dart programs. This parser expects all tokens
77 /// in a linked list (aka a token stream). 77 /// in a linked list (aka a token stream).
78 /// 78 ///
79 /// The class [Scanner] is used to generate a token stream. See the file 79 /// The class [Scanner] is used to generate a token stream. See the file
80 /// [scanner.dart](../scanner.dart). 80 /// [scanner.dart](../scanner.dart).
81 /// 81 ///
82 /// Subclasses of the class [Listener] are used to listen to events. 82 /// Subclasses of the class [Listener] are used to listen to events.
83 /// 83 ///
84 /// Most methods of this class belong in one of three major categories: parse 84 /// Most methods of this class belong in one of three major categories: parse
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 listener.beginOptionalFormalParameters(token); 552 listener.beginOptionalFormalParameters(token);
553 if (!optional('(', token)) { 553 if (!optional('(', token)) {
554 if (optional(';', token)) { 554 if (optional(';', token)) {
555 reportRecoverableError(token, fasta.messageExpectedOpenParens); 555 reportRecoverableError(token, fasta.messageExpectedOpenParens);
556 return token; 556 return token;
557 } 557 }
558 return reportUnrecoverableError( 558 return reportUnrecoverableError(
559 token, fasta.templateExpectedButGot.withArguments("(")) 559 token, fasta.templateExpectedButGot.withArguments("("))
560 .next; 560 .next;
561 } 561 }
562 BeginToken beginGroupToken = token; 562 Token closeBrace = closeBraceTokenFor(token);
563 Token endToken = beginGroupToken.endGroup; 563 listener.endFormalParameters(0, token, closeBrace, kind);
564 listener.endFormalParameters(0, token, endToken, kind); 564 return closeBrace.next;
565 return endToken.next;
566 } 565 }
567 566
568 /// Parses the formal parameter list of a function. 567 /// Parses the formal parameter list of a function.
569 /// 568 ///
570 /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be 569 /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
571 /// omitted (except for named arguments). Otherwise, types may be omitted. 570 /// omitted (except for named arguments). Otherwise, types may be omitted.
572 Token parseFormalParameters(Token token, MemberKind kind) { 571 Token parseFormalParameters(Token token, MemberKind kind) {
573 Token begin = token; 572 Token begin = token;
574 listener.beginFormalParameters(begin, kind); 573 listener.beginFormalParameters(begin, kind);
575 expect('(', token); 574 expect('(', token);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 /// possible other constructs will pass (e.g., 'a < C, D > 3'). 659 /// possible other constructs will pass (e.g., 'a < C, D > 3').
661 bool isValidMethodTypeArguments(Token token) { 660 bool isValidMethodTypeArguments(Token token) {
662 Token Function(Token token) tryParseType; 661 Token Function(Token token) tryParseType;
663 662
664 /// Returns token after match if [token] matches '<' type (',' type)* '>' 663 /// Returns token after match if [token] matches '<' type (',' type)* '>'
665 /// '(', and otherwise returns null. Does not produce listener events. With 664 /// '(', and otherwise returns null. Does not produce listener events. With
666 /// respect to the final '(', please see the description of 665 /// respect to the final '(', please see the description of
667 /// [isValidMethodTypeArguments]. 666 /// [isValidMethodTypeArguments].
668 Token tryParseMethodTypeArguments(Token token) { 667 Token tryParseMethodTypeArguments(Token token) {
669 if (!identical(token.kind, LT_TOKEN)) return null; 668 if (!identical(token.kind, LT_TOKEN)) return null;
670 BeginToken beginToken = token; 669 Token endToken = closeBraceTokenFor(token);
671 Token endToken = beginToken.endGroup;
672 if (endToken == null || 670 if (endToken == null ||
673 !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) { 671 !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) {
674 return null; 672 return null;
675 } 673 }
676 token = tryParseType(token.next); 674 token = tryParseType(token.next);
677 while (token != null && identical(token.kind, COMMA_TOKEN)) { 675 while (token != null && identical(token.kind, COMMA_TOKEN)) {
678 token = tryParseType(token.next); 676 token = tryParseType(token.next);
679 } 677 }
680 if (token == null || !identical(token.kind, GT_TOKEN)) return null; 678 if (token == null || !identical(token.kind, GT_TOKEN)) return null;
681 return token.next; 679 return token.next;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 token = parseIdentifier(token.next, context); 754 token = parseIdentifier(token.next, context);
757 listener.handleQualified(period); 755 listener.handleQualified(period);
758 return token; 756 return token;
759 } 757 }
760 758
761 Token skipBlock(Token token) { 759 Token skipBlock(Token token) {
762 if (!optional('{', token)) { 760 if (!optional('{', token)) {
763 return reportUnrecoverableError(token, fasta.messageExpectedBlockToSkip) 761 return reportUnrecoverableError(token, fasta.messageExpectedBlockToSkip)
764 .next; 762 .next;
765 } 763 }
766 BeginToken beginGroupToken = token; 764 Token closeBrace = closeBraceTokenFor(token);
767 Token endGroup = beginGroupToken.endGroup; 765 if (closeBrace == null ||
768 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { 766 !identical(closeBrace.kind, $CLOSE_CURLY_BRACKET)) {
769 return reportUnmatchedToken(beginGroupToken).next; 767 return reportUnmatchedToken(token).next;
770 } 768 }
771 return beginGroupToken.endGroup; 769 return closeBrace;
772 } 770 }
773 771
774 Token parseEnum(Token token) { 772 Token parseEnum(Token token) {
775 listener.beginEnum(token); 773 listener.beginEnum(token);
776 Token enumKeyword = token; 774 Token enumKeyword = token;
777 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration); 775 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration);
778 token = expect('{', token); 776 token = expect('{', token);
779 int count = 0; 777 int count = 0;
780 if (!optional('}', token)) { 778 if (!optional('}', token)) {
781 token = parseIdentifier(token, IdentifierContext.enumValueDeclaration); 779 token = parseIdentifier(token, IdentifierContext.enumValueDeclaration);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 } 954 }
957 955
958 /// Parse a type, if it is appropriate to do so. 956 /// Parse a type, if it is appropriate to do so.
959 /// 957 ///
960 /// If this method can parse a type, it will return the next (non-null) token 958 /// If this method can parse a type, it will return the next (non-null) token
961 /// after the type. Otherwise, it returns null. 959 /// after the type. Otherwise, it returns null.
962 Token parseType(Token token, 960 Token parseType(Token token,
963 [TypeContinuation continuation = TypeContinuation.Required, 961 [TypeContinuation continuation = TypeContinuation.Required,
964 IdentifierContext continuationContext, 962 IdentifierContext continuationContext,
965 MemberKind memberKind]) { 963 MemberKind memberKind]) {
966 /// Returns the close brace, bracket, or parenthesis of [left]. For '<', it
967 /// may return null.
968 Token getClose(BeginToken left) => left.endToken;
969
970 /// True if we've seen the `var` keyword. 964 /// True if we've seen the `var` keyword.
971 bool hasVar = false; 965 bool hasVar = false;
972 966
973 /// Where the type begins. 967 /// Where the type begins.
974 Token begin; 968 Token begin;
975 969
976 /// Non-null if 'void' is the first token. 970 /// Non-null if 'void' is the first token.
977 Token voidToken; 971 Token voidToken;
978 972
979 /// True if the tokens at [begin] looks like a type. 973 /// True if the tokens at [begin] looks like a type.
980 bool looksLikeType = false; 974 bool looksLikeType = false;
981 975
982 /// True if a type that could be a return type for a generalized function 976 /// True if a type that could be a return type for a generalized function
983 /// type was seen during analysis. 977 /// type was seen during analysis.
984 bool hasReturnType = false; 978 bool hasReturnType = false;
985 979
986 /// The identifier context to use for parsing the type. 980 /// The identifier context to use for parsing the type.
987 IdentifierContext context = IdentifierContext.typeReference; 981 IdentifierContext context = IdentifierContext.typeReference;
988 982
989 /// Non-null if type arguments were seen during analysis. 983 /// Non-null if type arguments were seen during analysis.
990 BeginToken typeArguments; 984 Token typeArguments;
991 985
992 /// The number of function types seen during analysis. 986 /// The number of function types seen during analysis.
993 int functionTypes = 0; 987 int functionTypes = 0;
994 988
995 /// The start of type variables of function types seen during 989 /// The start of type variables of function types seen during
996 /// analysis. Notice that the tokens in this list might be either `'<'` or 990 /// analysis. Notice that the tokens in this list might be either `'<'` or
997 /// `'('` as not all function types have type parameters. Also, it is safe 991 /// `'('` as not all function types have type parameters. Also, it is safe
998 /// to assume that [getClose] will return non-null for all these tokens. 992 /// to assume that [closeBraceTokenFor] will return non-null for all these t okens.
999 Link<Token> typeVariableStarters = const Link<Token>(); 993 Link<Token> typeVariableStarters = const Link<Token>();
1000 994
1001 { 995 {
1002 // Analyse the next tokens to see if they could be a type. 996 // Analyse the next tokens to see if they could be a type.
1003 997
1004 if (continuation == 998 if (continuation ==
1005 TypeContinuation.ExpressionStatementOrConstDeclaration) { 999 TypeContinuation.ExpressionStatementOrConstDeclaration) {
1006 // This is a special case. The first token is `const` and we need to 1000 // This is a special case. The first token is `const` and we need to
1007 // analyze the tokens following the const keyword. 1001 // analyze the tokens following the const keyword.
1008 assert(optional("const", token)); 1002 assert(optional("const", token));
(...skipping 15 matching lines...) Expand all
1024 !isGeneralizedFunctionType(token)) { 1018 !isGeneralizedFunctionType(token)) {
1025 // We're looking at an identifier that could be a type (or `dynamic`). 1019 // We're looking at an identifier that could be a type (or `dynamic`).
1026 looksLikeType = true; 1020 looksLikeType = true;
1027 token = token.next; 1021 token = token.next;
1028 if (optional(".", token) && isValidTypeReference(token.next)) { 1022 if (optional(".", token) && isValidTypeReference(token.next)) {
1029 // We're looking at `prefix '.' identifier`. 1023 // We're looking at `prefix '.' identifier`.
1030 context = IdentifierContext.prefixedTypeReference; 1024 context = IdentifierContext.prefixedTypeReference;
1031 token = token.next.next; 1025 token = token.next.next;
1032 } 1026 }
1033 if (optional("<", token)) { 1027 if (optional("<", token)) {
1034 Token close = getClose(token); 1028 Token close = closeBraceTokenFor(token);
1035 if (close != null && 1029 if (close != null &&
1036 (optional(">", close) || optional(">>", close))) { 1030 (optional(">", close) || optional(">>", close))) {
1037 // We found some type arguments. 1031 // We found some type arguments.
1038 typeArguments = token; 1032 typeArguments = token;
1039 token = close.next; 1033 token = close.next;
1040 } 1034 }
1041 } 1035 }
1042 } 1036 }
1043 1037
1044 // If what we have seen so far looks like a type, that could be a return 1038 // If what we have seen so far looks like a type, that could be a return
1045 // type for a generalized function type. 1039 // type for a generalized function type.
1046 hasReturnType = looksLikeType; 1040 hasReturnType = looksLikeType;
1047 1041
1048 while (optional("Function", token)) { 1042 while (optional("Function", token)) {
1049 Token typeVariableStart = token.next; 1043 Token typeVariableStart = token.next;
1050 if (optional("<", token.next)) { 1044 if (optional("<", token.next)) {
1051 Token close = getClose(token.next); 1045 Token close = closeBraceTokenFor(token.next);
1052 if (close != null && optional(">", close)) { 1046 if (close != null && optional(">", close)) {
1053 token = close; 1047 token = close;
1054 } else { 1048 } else {
1055 break; // Not a function type. 1049 break; // Not a function type.
1056 } 1050 }
1057 } 1051 }
1058 if (optional("(", token.next)) { 1052 if (optional("(", token.next)) {
1059 // This is a function type. 1053 // This is a function type.
1060 Token close = getClose(token.next); 1054 Token close = closeBraceTokenFor(token.next);
1061 assert(optional(")", close)); 1055 assert(optional(")", close));
1062 looksLikeType = true; 1056 looksLikeType = true;
1063 functionTypes++; 1057 functionTypes++;
1064 typeVariableStarters = 1058 typeVariableStarters =
1065 typeVariableStarters.prepend(typeVariableStart); 1059 typeVariableStarters.prepend(typeVariableStart);
1066 token = close.next; 1060 token = close.next;
1067 } else { 1061 } else {
1068 break; // Not a funtion type. 1062 break; // Not a funtion type.
1069 } 1063 }
1070 } 1064 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 return parseType(newBegin); 1102 return parseType(newBegin);
1109 } 1103 }
1110 } 1104 }
1111 1105
1112 for (int i = 0; i < functionTypes; i++) { 1106 for (int i = 0; i < functionTypes; i++) {
1113 assert(optional('Function', token)); 1107 assert(optional('Function', token));
1114 Token functionToken = token; 1108 Token functionToken = token;
1115 token = token.next; 1109 token = token.next;
1116 if (optional("<", token)) { 1110 if (optional("<", token)) {
1117 // Skip type parameters, they were parsed above. 1111 // Skip type parameters, they were parsed above.
1118 token = getClose(token).next; 1112 token = closeBraceTokenFor(token).next;
1119 } 1113 }
1120 token = 1114 token =
1121 parseFormalParameters(token, MemberKind.GeneralizedFunctionType); 1115 parseFormalParameters(token, MemberKind.GeneralizedFunctionType);
1122 listener.endFunctionType(functionToken, token); 1116 listener.endFunctionType(functionToken, token);
1123 } 1117 }
1124 1118
1125 if (hasVar) { 1119 if (hasVar) {
1126 reportRecoverableError(begin, fasta.messageTypeAfterVar); 1120 reportRecoverableError(begin, fasta.messageTypeAfterVar);
1127 } 1121 }
1128 1122
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 int afterIdKind = afterId.kind; 1187 int afterIdKind = afterId.kind;
1194 if (looksLikeVariableDeclarationEnd(afterIdKind)) { 1188 if (looksLikeVariableDeclarationEnd(afterIdKind)) {
1195 // We are looking at `type identifier` followed by 1189 // We are looking at `type identifier` followed by
1196 // `(',' | '=' | ';')`. 1190 // `(',' | '=' | ';')`.
1197 1191
1198 // TODO(ahe): Generate type events and call 1192 // TODO(ahe): Generate type events and call
1199 // parseVariablesDeclarationRest instead. 1193 // parseVariablesDeclarationRest instead.
1200 return parseVariablesDeclaration(begin); 1194 return parseVariablesDeclaration(begin);
1201 } else if (OPEN_PAREN_TOKEN == afterIdKind) { 1195 } else if (OPEN_PAREN_TOKEN == afterIdKind) {
1202 // We are looking at `type identifier '('`. 1196 // We are looking at `type identifier '('`.
1203 if (looksLikeFunctionBody(getClose(afterId).next)) { 1197 if (looksLikeFunctionBody(closeBraceTokenFor(afterId).next)) {
1204 // We are looking at `type identifier '(' ... ')'` followed 1198 // We are looking at `type identifier '(' ... ')'` followed
1205 // `( '{' | '=>' | 'async' | 'sync' )`. 1199 // `( '{' | '=>' | 'async' | 'sync' )`.
1206 return parseLocalFunctionDeclaration(begin); 1200 return parseLocalFunctionDeclaration(begin);
1207 } 1201 }
1208 } else if (identical(afterIdKind, LT_TOKEN)) { 1202 } else if (identical(afterIdKind, LT_TOKEN)) {
1209 // We are looking at `type identifier '<'`. 1203 // We are looking at `type identifier '<'`.
1210 Token afterTypeVariables = getClose(afterId)?.next; 1204 Token afterTypeVariables = closeBraceTokenFor(afterId)?.next;
1211 if (afterTypeVariables != null && 1205 if (afterTypeVariables != null &&
1212 optional("(", afterTypeVariables)) { 1206 optional("(", afterTypeVariables)) {
1213 if (looksLikeFunctionBody(getClose(afterTypeVariables).next)) { 1207 if (looksLikeFunctionBody(
1208 closeBraceTokenFor(afterTypeVariables).next)) {
1214 // We are looking at "type identifier '<' ... '>' '(' ... ')'" 1209 // We are looking at "type identifier '<' ... '>' '(' ... ')'"
1215 // followed by '{', '=>', 'async', or 'sync'. 1210 // followed by '{', '=>', 'async', or 'sync'.
1216 return parseLocalFunctionDeclaration(begin); 1211 return parseLocalFunctionDeclaration(begin);
1217 } 1212 }
1218 } 1213 }
1219 } 1214 }
1220 // Fall-through to expression statement. 1215 // Fall-through to expression statement.
1221 } else { 1216 } else {
1222 token = begin; 1217 token = begin;
1223 if (optional(':', token.next)) { 1218 if (optional(':', token.next)) {
1224 return parseLabeledStatement(token); 1219 return parseLabeledStatement(token);
1225 } else if (optional('(', token.next)) { 1220 } else if (optional('(', token.next)) {
1226 if (looksLikeFunctionBody(getClose(token.next).next)) { 1221 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) {
1227 return parseLocalFunctionDeclaration(token); 1222 return parseLocalFunctionDeclaration(token);
1228 } 1223 }
1229 } else if (optional('<', token.next)) { 1224 } else if (optional('<', token.next)) {
1230 Token afterTypeVariables = getClose(token.next)?.next; 1225 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next;
1231 if (afterTypeVariables != null && 1226 if (afterTypeVariables != null &&
1232 optional("(", afterTypeVariables)) { 1227 optional("(", afterTypeVariables)) {
1233 if (looksLikeFunctionBody(getClose(afterTypeVariables).next)) { 1228 if (looksLikeFunctionBody(
1229 closeBraceTokenFor(afterTypeVariables).next)) {
1234 return parseLocalFunctionDeclaration(token); 1230 return parseLocalFunctionDeclaration(token);
1235 } 1231 }
1236 } 1232 }
1237 // Fall through to expression statement. 1233 // Fall through to expression statement.
1238 } 1234 }
1239 } 1235 }
1240 return parseExpressionStatement(begin); 1236 return parseExpressionStatement(begin);
1241 1237
1242 case TypeContinuation.ExpressionStatementOrConstDeclaration: 1238 case TypeContinuation.ExpressionStatementOrConstDeclaration:
1243 Token identifier; 1239 Token identifier;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 } 1332 }
1337 if (isNamedParameter && nameToken.lexeme.startsWith("_")) { 1333 if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
1338 // TODO(ahe): Move this to after commiting the type. 1334 // TODO(ahe): Move this to after commiting the type.
1339 reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter); 1335 reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter);
1340 } 1336 }
1341 1337
1342 token = listener.injectGenericCommentTypeList(token); 1338 token = listener.injectGenericCommentTypeList(token);
1343 1339
1344 Token inlineFunctionTypeStart; 1340 Token inlineFunctionTypeStart;
1345 if (optional("<", token)) { 1341 if (optional("<", token)) {
1346 Token closer = getClose(token); 1342 Token closer = closeBraceTokenFor(token);
1347 if (closer != null) { 1343 if (closer != null) {
1348 if (optional("(", closer.next)) { 1344 if (optional("(", closer.next)) {
1349 inlineFunctionTypeStart = token; 1345 inlineFunctionTypeStart = token;
1350 token = token.next; 1346 token = token.next;
1351 } 1347 }
1352 } 1348 }
1353 } else if (optional("(", token)) { 1349 } else if (optional("(", token)) {
1354 inlineFunctionTypeStart = token; 1350 inlineFunctionTypeStart = token;
1355 token = getClose(token).next; 1351 token = closeBraceTokenFor(token).next;
1356 } 1352 }
1357 1353
1358 if (inlineFunctionTypeStart != null) { 1354 if (inlineFunctionTypeStart != null) {
1359 token = parseTypeVariablesOpt(inlineFunctionTypeStart); 1355 token = parseTypeVariablesOpt(inlineFunctionTypeStart);
1360 listener.beginFunctionTypedFormalParameter(inlineFunctionTypeStart); 1356 listener.beginFunctionTypedFormalParameter(inlineFunctionTypeStart);
1361 if (!untyped) { 1357 if (!untyped) {
1362 if (voidToken != null) { 1358 if (voidToken != null) {
1363 listener.handleVoidKeyword(voidToken); 1359 listener.handleVoidKeyword(voidToken);
1364 } else { 1360 } else {
1365 Token saved = token; 1361 Token saved = token;
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 // type ... 1717 // type ...
1722 if (optional('.', token.next)) { 1718 if (optional('.', token.next)) {
1723 // type '.' ... 1719 // type '.' ...
1724 if (token.next.next.isIdentifier) { 1720 if (token.next.next.isIdentifier) {
1725 // type '.' identifier 1721 // type '.' identifier
1726 token = token.next.next; 1722 token = token.next.next;
1727 } 1723 }
1728 } 1724 }
1729 if (optional('<', token.next)) { 1725 if (optional('<', token.next)) {
1730 if (token.next is BeginToken) { 1726 if (token.next is BeginToken) {
1731 BeginToken beginGroup = token.next; 1727 token = token.next;
1732 if (beginGroup.endGroup == null) { 1728 Token closeBrace = closeBraceTokenFor(token);
1733 token = reportUnmatchedToken(beginGroup).next; 1729 if (closeBrace == null) {
1730 token = reportUnmatchedToken(token).next;
1734 } else { 1731 } else {
1735 token = beginGroup.endGroup; 1732 token = closeBrace;
1736 } 1733 }
1737 } 1734 }
1738 } 1735 }
1739 // If the next token after a type has a type substitution comment 1736 // If the next token after a type has a type substitution comment
1740 // /*=T*/, then the previous type tokens and the reference to them 1737 // /*=T*/, then the previous type tokens and the reference to them
1741 // from the link should be replaced. 1738 // from the link should be replaced.
1742 { 1739 {
1743 Token newType = listener.replaceTokenWithGenericCommentTypeAssign( 1740 Token newType = listener.replaceTokenWithGenericCommentTypeAssign(
1744 type, token.next); 1741 type, token.next);
1745 if (!identical(newType, type)) { 1742 if (!identical(newType, type)) {
1746 identifiers = identifiers.tail; 1743 identifiers = identifiers.tail;
1747 token = newType; 1744 token = newType;
1748 continue; 1745 continue;
1749 } 1746 }
1750 } 1747 }
1751 } 1748 }
1752 token = token.next; 1749 token = token.next;
1753 } 1750 }
1754 while (isGeneralizedFunctionType(token)) { 1751 while (isGeneralizedFunctionType(token)) {
1755 token = token.next; 1752 token = token.next;
1756 if (optional('<', token)) { 1753 if (optional('<', token)) {
1757 if (token is BeginToken) { 1754 if (token is BeginToken) {
1758 BeginToken beginGroup = token; 1755 Token closeBrace = closeBraceTokenFor(token);
1759 if (beginGroup.endGroup == null) { 1756 if (closeBrace == null) {
1760 token = reportUnmatchedToken(beginGroup).next; 1757 token = reportUnmatchedToken(token).next;
1761 } else { 1758 } else {
1762 token = beginGroup.endGroup.next; 1759 token = closeBrace.next;
1763 } 1760 }
1764 } 1761 }
1765 } 1762 }
1766 if (!optional('(', token)) { 1763 if (!optional('(', token)) {
1767 if (optional(';', token)) { 1764 if (optional(';', token)) {
1768 reportRecoverableError(token, fasta.messageExpectedOpenParens); 1765 reportRecoverableError(token, fasta.messageExpectedOpenParens);
1769 } 1766 }
1770 token = expect("(", token); 1767 token = expect("(", token);
1771 } 1768 }
1772 if (token is BeginToken) { 1769 if (token is BeginToken) {
1773 BeginToken beginGroup = token; 1770 Token closeBrace = closeBraceTokenFor(token);
1774 if (beginGroup.endGroup == null) { 1771 if (closeBrace == null) {
1775 token = reportUnmatchedToken(beginGroup).next; 1772 token = reportUnmatchedToken(token).next;
1776 } else { 1773 } else {
1777 token = beginGroup.endGroup.next; 1774 token = closeBrace.next;
1778 } 1775 }
1779 } 1776 }
1780 } 1777 }
1781 } 1778 }
1782 return listener.handleMemberName(const Link<Token>()); 1779 return listener.handleMemberName(const Link<Token>());
1783 } 1780 }
1784 1781
1785 Token parseFieldInitializerOpt( 1782 Token parseFieldInitializerOpt(
1786 Token token, Token name, Token varFinalOrConst, bool isTopLevel) { 1783 Token token, Token name, Token varFinalOrConst, bool isTopLevel) {
1787 if (optional('=', token)) { 1784 if (optional('=', token)) {
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 token = parseType(token, typeContinuation, null, memberKind); 2031 token = parseType(token, typeContinuation, null, memberKind);
2035 return token; 2032 return token;
2036 } 2033 }
2037 2034
2038 Token skipClassBody(Token token) { 2035 Token skipClassBody(Token token) {
2039 if (!optional('{', token)) { 2036 if (!optional('{', token)) {
2040 return reportUnrecoverableErrorWithToken( 2037 return reportUnrecoverableErrorWithToken(
2041 token, fasta.templateExpectedClassBodyToSkip) 2038 token, fasta.templateExpectedClassBodyToSkip)
2042 .next; 2039 .next;
2043 } 2040 }
2044 BeginToken beginGroupToken = token; 2041 Token closeBrace = closeBraceTokenFor(token);
2045 Token endGroup = beginGroupToken.endGroup; 2042 if (closeBrace == null ||
2046 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { 2043 !identical(closeBrace.kind, $CLOSE_CURLY_BRACKET)) {
2047 return reportUnmatchedToken(beginGroupToken).next; 2044 return reportUnmatchedToken(token).next;
2048 } 2045 }
2049 return endGroup; 2046 return closeBrace;
2050 } 2047 }
2051 2048
2052 Token parseClassBody(Token token) { 2049 Token parseClassBody(Token token) {
2053 Token begin = token; 2050 Token begin = token;
2054 listener.beginClassBody(token); 2051 listener.beginClassBody(token);
2055 if (!optional('{', token)) { 2052 if (!optional('{', token)) {
2056 token = reportUnrecoverableErrorWithToken( 2053 token = reportUnrecoverableErrorWithToken(
2057 token, fasta.templateExpectedClassBody) 2054 token, fasta.templateExpectedClassBody)
2058 .next; 2055 .next;
2059 } 2056 }
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
2725 token = token.next; 2722 token = token.next;
2726 nextValue = token.next.stringValue; 2723 nextValue = token.next.stringValue;
2727 } 2724 }
2728 if (identical(nextValue, '{')) { 2725 if (identical(nextValue, '{')) {
2729 // Handle cases like this: 2726 // Handle cases like this:
2730 // class Foo { 2727 // class Foo {
2731 // var map; 2728 // var map;
2732 // Foo() : map = {}; 2729 // Foo() : map = {};
2733 // Foo.x() : map = true ? {} : {}; 2730 // Foo.x() : map = true ? {} : {};
2734 // } 2731 // }
2735 BeginToken begin = token.next; 2732 token = closeBraceTokenFor(token) ?? token;
2736 token = (begin.endGroup != null) ? begin.endGroup : token;
2737 token = token.next; 2733 token = token.next;
2738 continue; 2734 continue;
2739 } 2735 }
2740 if (identical(nextValue, '<')) { 2736 if (identical(nextValue, '<')) {
2741 // Handle cases like this: 2737 // Handle cases like this:
2742 // class Foo { 2738 // class Foo {
2743 // var map; 2739 // var map;
2744 // Foo() : map = <String, Foo>{}; 2740 // Foo() : map = <String, Foo>{};
2745 // Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{}; 2741 // Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{};
2746 // } 2742 // }
2747 BeginToken begin = token.next; 2743 token = closeBraceTokenFor(token.next) ?? token;
2748 token = (begin.endGroup != null) ? begin.endGroup : token;
2749 token = token.next; 2744 token = token.next;
2750 if (identical(token.stringValue, '{')) { 2745 if (identical(token.stringValue, '{')) {
2751 begin = token; 2746 token = closeBraceTokenFor(token) ?? token;
2752 token = (begin.endGroup != null) ? begin.endGroup : token;
2753 token = token.next; 2747 token = token.next;
2754 } 2748 }
2755 continue; 2749 continue;
2756 } 2750 }
2757 } 2751 }
2758 if (!mayParseFunctionExpressions && identical(value, '{')) { 2752 if (!mayParseFunctionExpressions && identical(value, '{')) {
2759 break; 2753 break;
2760 } 2754 }
2761 if (token is BeginToken) { 2755 if (token is BeginToken) {
2762 BeginToken begin = token; 2756 token = closeBraceTokenFor(token) ?? token;
2763 token = (begin.endGroup != null) ? begin.endGroup : token;
2764 } else if (token is ErrorToken) { 2757 } else if (token is ErrorToken) {
2765 reportErrorToken(token, false).next; 2758 reportErrorToken(token, false).next;
2766 } 2759 }
2767 token = token.next; 2760 token = token.next;
2768 } 2761 }
2769 return token; 2762 return token;
2770 } 2763 }
2771 2764
2772 Token parseRecoverExpression(Token token, Message message) { 2765 Token parseRecoverExpression(Token token, Message message) {
2773 return parseExpression(token); 2766 return parseExpression(token);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
3020 3013
3021 Token expressionExpected(Token token) { 3014 Token expressionExpected(Token token) {
3022 token = reportUnrecoverableErrorWithToken( 3015 token = reportUnrecoverableErrorWithToken(
3023 token, fasta.templateExpectedExpression) 3016 token, fasta.templateExpectedExpression)
3024 .next; 3017 .next;
3025 listener.handleInvalidExpression(token); 3018 listener.handleInvalidExpression(token);
3026 return token; 3019 return token;
3027 } 3020 }
3028 3021
3029 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { 3022 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
3030 BeginToken beginGroup = token; 3023 Token nextToken = closeBraceTokenFor(token).next;
3031 Token nextToken = beginGroup.endGroup.next;
3032 int kind = nextToken.kind; 3024 int kind = nextToken.kind;
3033 if (mayParseFunctionExpressions && 3025 if (mayParseFunctionExpressions &&
3034 (identical(kind, FUNCTION_TOKEN) || 3026 (identical(kind, FUNCTION_TOKEN) ||
3035 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || 3027 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
3036 (identical(kind, KEYWORD_TOKEN) && 3028 (identical(kind, KEYWORD_TOKEN) &&
3037 (optional('async', nextToken) || 3029 (optional('async', nextToken) ||
3038 optional('sync', nextToken))))) { 3030 optional('sync', nextToken))))) {
3039 listener.handleNoTypeVariables(token); 3031 listener.handleNoTypeVariables(token);
3040 return parseFunctionExpression(token); 3032 return parseFunctionExpression(token);
3041 } else { 3033 } else {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
3142 listener.handleLiteralMap(count, beginToken, constKeyword, token); 3134 listener.handleLiteralMap(count, beginToken, constKeyword, token);
3143 return expect('}', token); 3135 return expect('}', token);
3144 } 3136 }
3145 3137
3146 /// formalParameterList functionBody. 3138 /// formalParameterList functionBody.
3147 /// 3139 ///
3148 /// This is a suffix parser because it is assumed that type arguments have 3140 /// This is a suffix parser because it is assumed that type arguments have
3149 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed. 3141 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
3150 Token parseLiteralFunctionSuffix(Token token) { 3142 Token parseLiteralFunctionSuffix(Token token) {
3151 assert(optional('(', token)); 3143 assert(optional('(', token));
3152 BeginToken beginGroup = token; 3144 Token closeBrace = closeBraceTokenFor(token);
3153 if (beginGroup.endGroup != null) { 3145 if (closeBrace != null) {
3154 Token nextToken = beginGroup.endGroup.next; 3146 Token nextToken = closeBrace.next;
3155 int kind = nextToken.kind; 3147 int kind = nextToken.kind;
3156 if (identical(kind, FUNCTION_TOKEN) || 3148 if (identical(kind, FUNCTION_TOKEN) ||
3157 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || 3149 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
3158 (identical(kind, KEYWORD_TOKEN) && 3150 (identical(kind, KEYWORD_TOKEN) &&
3159 (optional('async', nextToken) || optional('sync', nextToken)))) { 3151 (optional('async', nextToken) || optional('sync', nextToken)))) {
3160 return parseFunctionExpression(token); 3152 return parseFunctionExpression(token);
3161 } 3153 }
3162 // Fall through. 3154 // Fall through.
3163 } 3155 }
3164 return reportUnexpectedToken(token).next; 3156 return reportUnexpectedToken(token).next;
3165 } 3157 }
3166 3158
3167 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. 3159 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
3168 /// 3160 ///
3169 /// Where 3161 /// Where
3170 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' 3162 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']'
3171 /// genericMapLiteral ::= 3163 /// genericMapLiteral ::=
3172 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' 3164 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
3173 /// genericFunctionLiteral ::= 3165 /// genericFunctionLiteral ::=
3174 /// typeParameters formalParameterList functionBody 3166 /// typeParameters formalParameterList functionBody
3175 /// Provide token for [constKeyword] if preceded by 'const', null if not. 3167 /// Provide token for [constKeyword] if preceded by 'const', null if not.
3176 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { 3168 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) {
3177 assert(optional('<', token)); 3169 assert(optional('<', token));
3178 BeginToken begin = token; 3170 Token closeBrace = closeBraceTokenFor(token);
3179 if (constKeyword == null && 3171 if (constKeyword == null &&
3180 begin.endGroup != null && 3172 closeBrace != null &&
3181 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { 3173 identical(closeBrace.next.kind, OPEN_PAREN_TOKEN)) {
3182 token = parseTypeVariablesOpt(token); 3174 token = parseTypeVariablesOpt(token);
3183 return parseLiteralFunctionSuffix(token); 3175 return parseLiteralFunctionSuffix(token);
3184 } else { 3176 } else {
3185 token = parseTypeArgumentsOpt(token); 3177 token = parseTypeArgumentsOpt(token);
3186 if (optional('{', token)) { 3178 if (optional('{', token)) {
3187 return parseLiteralMapSuffix(token, constKeyword); 3179 return parseLiteralMapSuffix(token, constKeyword);
3188 } else if ((optional('[', token)) || (optional('[]', token))) { 3180 } else if ((optional('[', token)) || (optional('[]', token))) {
3189 return parseLiteralListSuffix(token, constKeyword); 3181 return parseLiteralListSuffix(token, constKeyword);
3190 } 3182 }
3191 return reportUnexpectedToken(token).next; 3183 return reportUnexpectedToken(token).next;
(...skipping 14 matching lines...) Expand all
3206 Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) { 3198 Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) {
3207 if (!mayParseFunctionExpressions) { 3199 if (!mayParseFunctionExpressions) {
3208 return parseSend(token, context); 3200 return parseSend(token, context);
3209 } else { 3201 } else {
3210 return parseType(token, TypeContinuation.SendOrFunctionLiteral, context); 3202 return parseType(token, TypeContinuation.SendOrFunctionLiteral, context);
3211 } 3203 }
3212 } 3204 }
3213 3205
3214 bool isFunctionDeclaration(Token token) { 3206 bool isFunctionDeclaration(Token token) {
3215 if (optional('<', token)) { 3207 if (optional('<', token)) {
3216 BeginToken begin = token; 3208 Token closeBrace = closeBraceTokenFor(token);
3217 if (begin.endGroup == null) return false; 3209 if (closeBrace == null) return false;
3218 token = begin.endGroup.next; 3210 token = closeBrace.next;
3219 } 3211 }
3220 if (optional('(', token)) { 3212 if (optional('(', token)) {
3221 BeginToken begin = token; 3213 String afterParens = closeBraceTokenFor(token).next.stringValue;
3222 String afterParens = begin.endGroup.next.stringValue;
3223 if (identical(afterParens, '{') || 3214 if (identical(afterParens, '{') ||
3224 identical(afterParens, '=>') || 3215 identical(afterParens, '=>') ||
3225 identical(afterParens, 'async') || 3216 identical(afterParens, 'async') ||
3226 identical(afterParens, 'sync')) { 3217 identical(afterParens, 'sync')) {
3227 return true; 3218 return true;
3228 } 3219 }
3229 } 3220 }
3230 return false; 3221 return false;
3231 } 3222 }
3232 3223
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 listener.handleNoTypeArguments(token); 3373 listener.handleNoTypeArguments(token);
3383 } 3374 }
3384 token = parseArgumentsOpt(token); 3375 token = parseArgumentsOpt(token);
3385 listener.handleSend(beginToken, token); 3376 listener.handleSend(beginToken, token);
3386 return token; 3377 return token;
3387 } 3378 }
3388 3379
3389 Token skipArgumentsOpt(Token token) { 3380 Token skipArgumentsOpt(Token token) {
3390 listener.handleNoArguments(token); 3381 listener.handleNoArguments(token);
3391 if (optional('(', token)) { 3382 if (optional('(', token)) {
3392 BeginToken begin = token; 3383 return closeBraceTokenFor(token).next;
3393 return begin.endGroup.next;
3394 } else { 3384 } else {
3395 return token; 3385 return token;
3396 } 3386 }
3397 } 3387 }
3398 3388
3399 Token parseArgumentsOpt(Token token) { 3389 Token parseArgumentsOpt(Token token) {
3400 if (!optional('(', token)) { 3390 if (!optional('(', token)) {
3401 listener.handleNoArguments(token); 3391 listener.handleNoArguments(token);
3402 return token; 3392 return token;
3403 } else { 3393 } else {
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
4013 } 4003 }
4014 4004
4015 Token reportUnexpectedToken(Token token) { 4005 Token reportUnexpectedToken(Token token) {
4016 return reportUnrecoverableErrorWithToken( 4006 return reportUnrecoverableErrorWithToken(
4017 token, fasta.templateUnexpectedToken); 4007 token, fasta.templateUnexpectedToken);
4018 } 4008 }
4019 } 4009 }
4020 4010
4021 // TODO(ahe): Remove when analyzer supports generalized function syntax. 4011 // TODO(ahe): Remove when analyzer supports generalized function syntax.
4022 typedef _MessageWithArgument<T> = Message Function(T); 4012 typedef _MessageWithArgument<T> = Message Function(T);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | pkg/front_end/lib/src/fasta/parser/util.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698