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

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

Issue 2985673002: Parse type variables of local functions before return type. (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
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 } 1169 }
1170 continue optional; 1170 continue optional;
1171 1171
1172 case TypeContinuation.ExpressionStatementOrDeclaration: 1172 case TypeContinuation.ExpressionStatementOrDeclaration:
1173 assert(begin.isIdentifier || identical(begin.stringValue, 'void')); 1173 assert(begin.isIdentifier || identical(begin.stringValue, 'void'));
1174 if (!inPlainSync && optional("await", begin)) { 1174 if (!inPlainSync && optional("await", begin)) {
1175 return parseExpressionStatement(begin); 1175 return parseExpressionStatement(begin);
1176 } 1176 }
1177 1177
1178 if (looksLikeType && token.isIdentifier) { 1178 if (looksLikeType && token.isIdentifier) {
1179 // If the identifier token has a type substitution comment /*=T*/,
1180 // then the set of tokens type tokens should be replaced with the
1181 // tokens parsed from the comment.
1182 Token afterId = token.next; 1179 Token afterId = token.next;
1183 1180
1184 begin =
1185 listener.replaceTokenWithGenericCommentTypeAssign(begin, token);
ahe 2017/07/21 16:02:19 This has already been called when we analyze the t
1186
1187 int afterIdKind = afterId.kind; 1181 int afterIdKind = afterId.kind;
1188 if (looksLikeVariableDeclarationEnd(afterIdKind)) { 1182 if (looksLikeVariableDeclarationEnd(afterIdKind)) {
1189 // We are looking at `type identifier` followed by 1183 // We are looking at `type identifier` followed by
1190 // `(',' | '=' | ';')`. 1184 // `(',' | '=' | ';')`.
1191 1185
1192 // TODO(ahe): Generate type events and call 1186 // TODO(ahe): Generate type events and call
1193 // parseVariablesDeclarationRest instead. 1187 // parseVariablesDeclarationRest instead.
1194 return parseVariablesDeclaration(begin); 1188 return parseVariablesDeclaration(begin);
1195 } else if (OPEN_PAREN_TOKEN == afterIdKind) { 1189 } else if (OPEN_PAREN_TOKEN == afterIdKind) {
1196 // We are looking at `type identifier '('`. 1190 // We are looking at `type identifier '('`.
1197 if (looksLikeFunctionBody(closeBraceTokenFor(afterId).next)) { 1191 if (looksLikeFunctionBody(closeBraceTokenFor(afterId).next)) {
1198 // We are looking at `type identifier '(' ... ')'` followed 1192 // We are looking at `type identifier '(' ... ')'` followed
1199 // `( '{' | '=>' | 'async' | 'sync' )`. 1193 // `( '{' | '=>' | 'async' | 'sync' )`.
1200 return parseLocalFunctionDeclaration(begin); 1194
1195 // Although it looks like there are no type variables here, they
1196 // may get injected from a comment.
1197 Token formals = parseTypeVariablesOpt(afterId);
1198
1199 listener.beginLocalFunctionDeclaration(begin);
1200 listener.handleModifiers(0);
1201 if (voidToken != null) {
1202 listener.handleVoidKeyword(voidToken);
1203 } else {
1204 commitType();
1205 }
1206 listener.beginFunctionName(token);
1207 token = parseIdentifier(
1208 token, IdentifierContext.localFunctionDeclaration);
1209 listener.endFunctionName(begin, token);
1210 return parseLocalFunctionDeclarationFromFormals(formals);
1201 } 1211 }
1202 } else if (identical(afterIdKind, LT_TOKEN)) { 1212 } else if (identical(afterIdKind, LT_TOKEN)) {
1203 // We are looking at `type identifier '<'`. 1213 // We are looking at `type identifier '<'`.
1204 Token afterTypeVariables = closeBraceTokenFor(afterId)?.next; 1214 Token formals = closeBraceTokenFor(afterId)?.next;
1205 if (afterTypeVariables != null && 1215 if (formals != null && optional("(", formals)) {
1206 optional("(", afterTypeVariables)) { 1216 if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) {
1207 if (looksLikeFunctionBody(
1208 closeBraceTokenFor(afterTypeVariables).next)) {
1209 // We are looking at "type identifier '<' ... '>' '(' ... ')'" 1217 // We are looking at "type identifier '<' ... '>' '(' ... ')'"
1210 // followed by '{', '=>', 'async', or 'sync'. 1218 // followed by '{', '=>', 'async', or 'sync'.
1211 return parseLocalFunctionDeclaration(begin); 1219 parseTypeVariablesOpt(afterId);
1220 listener.beginLocalFunctionDeclaration(begin);
1221 listener.handleModifiers(0);
1222 if (voidToken != null) {
1223 listener.handleVoidKeyword(voidToken);
1224 } else {
1225 commitType();
1226 }
1227 listener.beginFunctionName(token);
1228 token = parseIdentifier(
1229 token, IdentifierContext.localFunctionDeclaration);
1230 listener.endFunctionName(begin, token);
1231 return parseLocalFunctionDeclarationFromFormals(formals);
1212 } 1232 }
1213 } 1233 }
1214 } 1234 }
1215 // Fall-through to expression statement. 1235 // Fall-through to expression statement.
1216 } else { 1236 } else {
1217 token = begin; 1237 token = begin;
1218 if (optional(':', token.next)) { 1238 if (optional(':', token.next)) {
1219 return parseLabeledStatement(token); 1239 return parseLabeledStatement(token);
1220 } else if (optional('(', token.next)) { 1240 } else if (optional('(', token.next)) {
1221 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) { 1241 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) {
1222 return parseLocalFunctionDeclaration(token); 1242 // We are looking at `identifier '(' ... ')'` followed by `'{'`,
1243 // `'=>'`, `'async'`, or `'sync'`.
1244
1245 // Although it looks like there are no type variables here, they
1246 // may get injected from a comment.
1247 Token formals = parseTypeVariablesOpt(token.next);
1248
1249 listener.beginLocalFunctionDeclaration(token);
1250 listener.handleModifiers(0);
1251 listener.handleNoType(token);
1252 listener.beginFunctionName(token);
1253 token = parseIdentifier(
1254 token, IdentifierContext.localFunctionDeclaration);
1255 listener.endFunctionName(begin, token);
1256 return parseLocalFunctionDeclarationFromFormals(formals);
1223 } 1257 }
1224 } else if (optional('<', token.next)) { 1258 } else if (optional('<', token.next)) {
1225 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next; 1259 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next;
1226 if (afterTypeVariables != null && 1260 if (afterTypeVariables != null &&
1227 optional("(", afterTypeVariables)) { 1261 optional("(", afterTypeVariables)) {
1228 if (looksLikeFunctionBody( 1262 if (looksLikeFunctionBody(
1229 closeBraceTokenFor(afterTypeVariables).next)) { 1263 closeBraceTokenFor(afterTypeVariables).next)) {
1230 return parseLocalFunctionDeclaration(token); 1264 // We are looking at `identifier '<' ... '>' '(' ... ')'`
1265 // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`.
1266 parseTypeVariablesOpt(token.next);
1267 listener.beginLocalFunctionDeclaration(token);
1268 listener.handleModifiers(0);
1269 listener.handleNoType(token);
1270 listener.beginFunctionName(token);
danrubel 2017/07/21 17:11:20 From this line down to the return statement looks
ahe 2017/08/07 11:45:27 You inspired me to go a bit further, and I decided
1271 token = parseIdentifier(
1272 token, IdentifierContext.localFunctionDeclaration);
1273 listener.endFunctionName(begin, token);
1274 return parseLocalFunctionDeclarationFromFormals(
1275 afterTypeVariables);
1231 } 1276 }
1232 } 1277 }
1233 // Fall through to expression statement. 1278 // Fall through to expression statement.
1234 } 1279 }
1235 } 1280 }
1236 return parseExpressionStatement(begin); 1281 return parseExpressionStatement(begin);
1237 1282
1238 case TypeContinuation.ExpressionStatementOrConstDeclaration: 1283 case TypeContinuation.ExpressionStatementOrConstDeclaration:
1239 Token identifier; 1284 Token identifier;
1240 if (looksLikeType && token.isIdentifier) { 1285 if (looksLikeType && token.isIdentifier) {
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 token = parseFormalParameters(token, MemberKind.Local); 2373 token = parseFormalParameters(token, MemberKind.Local);
2329 AsyncModifier savedAsyncModifier = asyncState; 2374 AsyncModifier savedAsyncModifier = asyncState;
2330 token = parseAsyncModifier(token); 2375 token = parseAsyncModifier(token);
2331 bool isBlock = optional('{', token); 2376 bool isBlock = optional('{', token);
2332 token = parseFunctionBody(token, true, false); 2377 token = parseFunctionBody(token, true, false);
2333 asyncState = savedAsyncModifier; 2378 asyncState = savedAsyncModifier;
2334 listener.endFunctionExpression(beginToken, token); 2379 listener.endFunctionExpression(beginToken, token);
2335 return isBlock ? token.next : token; 2380 return isBlock ? token.next : token;
2336 } 2381 }
2337 2382
2338 Token parseLocalFunctionDeclaration(Token token) { 2383 /// Parses the rest of a local function declaration starting from formal
2339 listener.beginLocalFunctionDeclaration(token); 2384 /// parameters.
2340 Token beginToken = token; 2385 ///
2341 token = parseModifiers(token, MemberKind.Local); 2386 /// Precondition: the parser has previously generated these events:
2342 listener.beginFunctionName(token); 2387 ///
2343 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration); 2388 /// - Type variables.
2344 token = parseQualifiedRestOpt( 2389 /// - beginLocalFunctionDeclaration.
2345 token, IdentifierContext.localFunctionDeclarationContinuation); 2390 /// - Modifiers.
2346 listener.endFunctionName(beginToken, token); 2391 /// - Return type.
2347 token = parseTypeVariablesOpt(token); 2392 /// - Function name.
2393 Token parseLocalFunctionDeclarationFromFormals(Token token) {
2348 token = parseFormalParametersOpt(token, MemberKind.Local); 2394 token = parseFormalParametersOpt(token, MemberKind.Local);
2349 token = parseInitializersOpt(token); 2395 token = parseInitializersOpt(token);
2350 AsyncModifier savedAsyncModifier = asyncState; 2396 AsyncModifier savedAsyncModifier = asyncState;
2351 token = parseAsyncModifier(token); 2397 token = parseAsyncModifier(token);
2352 token = parseFunctionBody(token, false, true); 2398 token = parseFunctionBody(token, false, true);
2353 asyncState = savedAsyncModifier; 2399 asyncState = savedAsyncModifier;
2354 token = token.next; 2400 token = token.next;
2355 listener.endLocalFunctionDeclaration(token); 2401 listener.endLocalFunctionDeclaration(token);
2356 return token; 2402 return token;
2357 } 2403 }
(...skipping 1645 matching lines...) Expand 10 before | Expand all | Expand 10 after
4003 } 4049 }
4004 4050
4005 Token reportUnexpectedToken(Token token) { 4051 Token reportUnexpectedToken(Token token) {
4006 return reportUnrecoverableErrorWithToken( 4052 return reportUnrecoverableErrorWithToken(
4007 token, fasta.templateUnexpectedToken); 4053 token, fasta.templateUnexpectedToken);
4008 } 4054 }
4009 } 4055 }
4010 4056
4011 // TODO(ahe): Remove when analyzer supports generalized function syntax. 4057 // TODO(ahe): Remove when analyzer supports generalized function syntax.
4012 typedef _MessageWithArgument<T> = Message Function(T); 4058 typedef _MessageWithArgument<T> = Message Function(T);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698