| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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); |
| OLD | NEW |