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 |