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

Side by Side Diff: pkg/compiler/lib/src/parser/parser.dart

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Remove obsolete named argument. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.parser; 5 library dart2js.parser;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../tokens/keyword.dart' show Keyword; 8 import '../tokens/keyword.dart' show Keyword;
9 import '../tokens/precedence.dart' show PrecedenceInfo; 9 import '../tokens/precedence.dart' show PrecedenceInfo;
10 import '../tokens/precedence_constants.dart' 10 import '../tokens/precedence_constants.dart'
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 period = token; 355 period = token;
356 token = parseIdentifier(token.next); 356 token = parseIdentifier(token.next);
357 } 357 }
358 token = parseArgumentsOpt(token); 358 token = parseArgumentsOpt(token);
359 listener.endMetadata(atToken, period, token); 359 listener.endMetadata(atToken, period, token);
360 return token; 360 return token;
361 } 361 }
362 362
363 Token parseTypedef(Token token) { 363 Token parseTypedef(Token token) {
364 Token typedefKeyword = token; 364 Token typedefKeyword = token;
365 listener.beginFunctionTypeAlias(token); 365 listener.beginTypedef(token);
366 token = parseReturnTypeOpt(token.next); 366 Token equals;
367 token = parseIdentifier(token); 367 if (optional('=', peekAfterNominalType(token.next))) {
368 token = parseTypeVariablesOpt(token); 368 token = parseIdentifier(token.next);
369 token = parseFormalParameters(token); 369 token = parseTypeVariablesOpt(token);
370 listener.endFunctionTypeAlias(typedefKeyword, token); 370 equals = expect('=', token);
Johnni Winther 2017/01/02 12:46:53 We are only using [equals] as a marker, but with t
floitsch 2017/01/02 13:48:48 Right. Good catch. done.
371 token = parseType(equals);
372 } else {
373 token = parseReturnTypeOpt(token.next);
374 token = parseIdentifier(token);
375 token = parseTypeVariablesOpt(token);
376 token = parseFormalParameters(token);
377 }
378 listener.endTypedef(typedefKeyword, equals, token);
371 return expect(';', token); 379 return expect(';', token);
372 } 380 }
373 381
374 Token parseMixinApplication(Token token) { 382 Token parseMixinApplication(Token token) {
375 listener.beginMixinApplication(token); 383 listener.beginMixinApplication(token);
376 token = parseType(token); 384 token = parseType(token);
377 token = expect('with', token); 385 token = expect('with', token);
378 token = parseTypeList(token); 386 token = parseTypeList(token);
379 listener.endMixinApplication(); 387 listener.endMixinApplication();
380 return token; 388 return token;
(...skipping 10 matching lines...) Expand all
391 399
392 Token parseFormalParametersOpt(Token token) { 400 Token parseFormalParametersOpt(Token token) {
393 if (optional('(', token)) { 401 if (optional('(', token)) {
394 return parseFormalParameters(token); 402 return parseFormalParameters(token);
395 } else { 403 } else {
396 listener.handleNoFormalParameters(token); 404 listener.handleNoFormalParameters(token);
397 return token; 405 return token;
398 } 406 }
399 } 407 }
400 408
401 Token parseFormalParameters(Token token) { 409 /// Parses the formal parameter list of a function.
410 ///
411 /// If [inFunctionType] is true, then the names may be omitted (except for
412 /// named arguments). If it is false, then the types may be omitted.
413 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
402 Token begin = token; 414 Token begin = token;
403 listener.beginFormalParameters(begin); 415 listener.beginFormalParameters(begin);
404 expect('(', token); 416 expect('(', token);
405 int parameterCount = 0; 417 int parameterCount = 0;
406 do { 418 do {
407 token = token.next; 419 token = token.next;
408 if (optional(')', token)) { 420 if (optional(')', token)) {
409 break; 421 break;
410 } 422 }
411 ++parameterCount; 423 ++parameterCount;
412 String value = token.stringValue; 424 String value = token.stringValue;
413 if (identical(value, '[')) { 425 if (identical(value, '[')) {
414 token = parseOptionalFormalParameters(token, false); 426 token = parseOptionalFormalParameters(
427 token, false, inFunctionType: inFunctionType);
415 break; 428 break;
416 } else if (identical(value, '{')) { 429 } else if (identical(value, '{')) {
417 token = parseOptionalFormalParameters(token, true); 430 token = parseOptionalFormalParameters(
431 token, true, inFunctionType: inFunctionType);
418 break; 432 break;
419 } 433 }
420 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 434 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
435 inFunctionType: inFunctionType);
421 } while (optional(',', token)); 436 } while (optional(',', token));
422 listener.endFormalParameters(parameterCount, begin, token); 437 listener.endFormalParameters(parameterCount, begin, token);
423 return expect(')', token); 438 return expect(')', token);
424 } 439 }
425 440
426 Token parseFormalParameter(Token token, FormalParameterType type) { 441 Token parseFormalParameter(Token token, FormalParameterType type,
442 {bool inFunctionType}) {
427 token = parseMetadataStar(token, forParameter: true); 443 token = parseMetadataStar(token, forParameter: true);
428 listener.beginFormalParameter(token); 444 listener.beginFormalParameter(token);
429 token = parseModifiers(token); 445 token = parseModifiers(token);
430 // TODO(ahe): Validate that there are formal parameters if void. 446 bool isNamedParameter = type == FormalParameterType.NAMED;
431 token = parseReturnTypeOpt(token); 447
432 Token thisKeyword = null; 448 Token thisKeyword = null;
433 if (optional('this', token)) { 449 if (inFunctionType && isNamedParameter) {
434 thisKeyword = token; 450 token = parseTypeOpt(token);
435 // TODO(ahe): Validate field initializers are only used in 451 token = parseIdentifier(token);
436 // constructors, and not for function-typed arguments. 452 } else if (inFunctionType) {
437 token = expect('.', token.next); 453 token = parseType(token);
454 if (token.isIdentifier()) {
455 token = parseIdentifier(token);
456 } else {
457 listener.handleNoName(token);
458 }
459 } else {
460 // TODO(ahe): Validate that there are formal parameters if void.
Johnni Winther 2017/01/02 12:46:53 Remove. This is checked in resolution.
floitsch 2017/01/02 13:48:48 Done.
461 token = parseReturnTypeOpt(token);
462 if (optional('this', token)) {
463 thisKeyword = token;
464 // TODO(ahe): Validate field initializers are only used in
465 // constructors, and not for function-typed arguments.
Johnni Winther 2017/01/02 12:46:53 Ditto.
floitsch 2017/01/02 13:48:48 Done.
466 token = expect('.', token.next);
467 }
468 token = parseIdentifier(token);
438 } 469 }
439 token = parseIdentifier(token); 470
440 if (optional('(', token)) { 471 // Generalized function types don't allow inline function types.
441 listener.handleNoTypeVariables(token); 472 // The following isn't allowed:
442 token = parseFormalParameters(token); 473 // int Function(int bar(String x)).
443 listener.handleFunctionTypedFormalParameter(token); 474 if (!inFunctionType) {
444 } else if (optional('<', token)) { 475 if (optional('(', token)) {
445 token = parseTypeVariablesOpt(token); 476 listener.handleNoTypeVariables(token);
446 token = parseFormalParameters(token); 477 token = parseFormalParameters(token);
447 listener.handleFunctionTypedFormalParameter(token); 478 listener.handleFunctionTypedFormalParameter(token);
479 } else if (optional('<', token)) {
480 token = parseTypeVariablesOpt(token);
481 token = parseFormalParameters(token);
482 listener.handleFunctionTypedFormalParameter(token);
483 }
448 } 484 }
449 String value = token.stringValue; 485 String value = token.stringValue;
450 if ((identical('=', value)) || (identical(':', value))) { 486 if ((identical('=', value)) || (identical(':', value))) {
451 // TODO(ahe): Validate that these are only used for optional parameters. 487 // TODO(ahe): Validate that these are only used for optional parameters.
452 Token equal = token; 488 Token equal = token;
453 token = parseExpression(token.next); 489 token = parseExpression(token.next);
454 listener.handleValuedFormalParameter(equal, token); 490 listener.handleValuedFormalParameter(equal, token);
455 if (type.isRequired) { 491 if (type.isRequired) {
456 listener.reportError( 492 listener.reportError(
457 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); 493 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT);
458 } else if (type.isPositional && identical(':', value)) { 494 } else if (type.isPositional && identical(':', value)) {
459 listener.reportError( 495 listener.reportError(
460 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); 496 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS);
461 } 497 }
462 } 498 }
463 listener.endFormalParameter(thisKeyword); 499 listener.endFormalParameter(thisKeyword);
464 return token; 500 return token;
465 } 501 }
466 502
467 Token parseOptionalFormalParameters(Token token, bool isNamed) { 503 Token parseOptionalFormalParameters(Token token, bool isNamed,
504 {bool inFunctionType}) {
468 Token begin = token; 505 Token begin = token;
469 listener.beginOptionalFormalParameters(begin); 506 listener.beginOptionalFormalParameters(begin);
470 assert((isNamed && optional('{', token)) || optional('[', token)); 507 assert((isNamed && optional('{', token)) || optional('[', token));
471 int parameterCount = 0; 508 int parameterCount = 0;
472 do { 509 do {
473 token = token.next; 510 token = token.next;
474 if (isNamed && optional('}', token)) { 511 if (isNamed && optional('}', token)) {
475 break; 512 break;
476 } else if (!isNamed && optional(']', token)) { 513 } else if (!isNamed && optional(']', token)) {
477 break; 514 break;
478 } 515 }
479 var type = 516 var type =
480 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 517 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
481 token = parseFormalParameter(token, type); 518 token =
519 parseFormalParameter(token, type, inFunctionType: inFunctionType);
482 ++parameterCount; 520 ++parameterCount;
483 } while (optional(',', token)); 521 } while (optional(',', token));
484 if (parameterCount == 0) { 522 if (parameterCount == 0) {
485 listener.reportError( 523 listener.reportError(
486 token, 524 token,
487 isNamed 525 isNamed
488 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST 526 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST
489 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST); 527 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST);
490 } 528 }
491 listener.endOptionalFormalParameters(parameterCount, begin, token); 529 listener.endOptionalFormalParameters(parameterCount, begin, token);
492 if (isNamed) { 530 if (isNamed) {
493 return expect('}', token); 531 return expect('}', token);
494 } else { 532 } else {
495 return expect(']', token); 533 return expect(']', token);
496 } 534 }
497 } 535 }
498 536
499 Token parseTypeOpt(Token token) { 537 Token parseTypeOpt(Token token) {
538 if (isGeneralizedFunctionType(token)) {
539 // Function type without return type.
540 return parseType(token);
541 }
500 Token peek = peekAfterIfType(token); 542 Token peek = peekAfterIfType(token);
501 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 543 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
502 return parseType(token); 544 return parseType(token);
503 } 545 }
504 listener.handleNoType(token); 546 listener.handleNoType(token);
505 return token; 547 return token;
506 } 548 }
507 549
508 bool isValidTypeReference(Token token) { 550 bool isValidTypeReference(Token token) {
509 final kind = token.kind; 551 final kind = token.kind;
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 } 696 }
655 697
656 Token parseClassOrNamedMixinApplication(Token token) { 698 Token parseClassOrNamedMixinApplication(Token token) {
657 Token begin = token; 699 Token begin = token;
658 Token abstractKeyword; 700 Token abstractKeyword;
659 if (optional('abstract', token)) { 701 if (optional('abstract', token)) {
660 abstractKeyword = token; 702 abstractKeyword = token;
661 token = token.next; 703 token = token.next;
662 } 704 }
663 Token classKeyword = token; 705 Token classKeyword = token;
664 var isMixinApplication = optional('=', peekAfterType(token.next)); 706 var isMixinApplication = optional('=', peekAfterNominalType(token.next));
665 if (isMixinApplication) { 707 if (isMixinApplication) {
666 listener.beginNamedMixinApplication(begin); 708 listener.beginNamedMixinApplication(begin);
667 } else { 709 } else {
668 listener.beginClassDeclaration(begin); 710 listener.beginClassDeclaration(begin);
669 } 711 }
670 712
671 int modifierCount = 0; 713 int modifierCount = 0;
672 if (abstractKeyword != null) { 714 if (abstractKeyword != null) {
673 parseModifier(abstractKeyword); 715 parseModifier(abstractKeyword);
674 modifierCount++; 716 modifierCount++;
(...skipping 20 matching lines...) Expand all
695 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); 737 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token);
696 return expect(';', token); 738 return expect(';', token);
697 } 739 }
698 740
699 Token parseClass(Token begin, Token classKeyword) { 741 Token parseClass(Token begin, Token classKeyword) {
700 Token token = parseIdentifier(classKeyword.next); 742 Token token = parseIdentifier(classKeyword.next);
701 token = parseTypeVariablesOpt(token); 743 token = parseTypeVariablesOpt(token);
702 Token extendsKeyword; 744 Token extendsKeyword;
703 if (optional('extends', token)) { 745 if (optional('extends', token)) {
704 extendsKeyword = token; 746 extendsKeyword = token;
705 if (optional('with', peekAfterType(token.next))) { 747 if (optional('with', peekAfterNominalType(token.next))) {
706 token = parseMixinApplication(token.next); 748 token = parseMixinApplication(token.next);
707 } else { 749 } else {
708 token = parseType(token.next); 750 token = parseType(token.next);
709 } 751 }
710 } else { 752 } else {
711 extendsKeyword = null; 753 extendsKeyword = null;
712 listener.handleNoType(token); 754 listener.handleNoType(token);
713 } 755 }
714 Token implementsKeyword; 756 Token implementsKeyword;
715 int interfacesCount = 0; 757 int interfacesCount = 0;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 value2 == stringValue || 835 value2 == stringValue ||
794 value3 == stringValue || 836 value3 == stringValue ||
795 value4 == stringValue; 837 value4 == stringValue;
796 } 838 }
797 839
798 bool notEofOrValue(String value, Token token) { 840 bool notEofOrValue(String value, Token token) {
799 return !identical(token.kind, EOF_TOKEN) && 841 return !identical(token.kind, EOF_TOKEN) &&
800 !identical(value, token.stringValue); 842 !identical(value, token.stringValue);
801 } 843 }
802 844
845 bool isGeneralizedFunctionType(Token token) {
846 // TODO(floitsch): don't use string comparison, but the keyword-state
847 // table is currently not set up to deal with upper-case characters.
848 return (optional('<', token.next) || optional('(', token.next)) &&
849 token.value == "Function";
850 }
851
803 Token parseType(Token token) { 852 Token parseType(Token token) {
804 Token begin = token; 853 Token begin = token;
805 if (isValidTypeReference(token)) { 854 if (isGeneralizedFunctionType(token)) {
806 token = parseIdentifier(token); 855 // A function type without return type.
807 token = parseQualifiedRestOpt(token); 856 // Push the non-existing return type first. The loop below will
857 // generate the full type.
858 listener.handleNoType(token);
808 } else { 859 } else {
809 token = listener.expectedType(token); 860 if (isValidTypeReference(token)) {
861 token = parseIdentifier(token);
862 token = parseQualifiedRestOpt(token);
863 } else {
864 token = listener.expectedType(token);
865 }
866 token = parseTypeArgumentsOpt(token);
867 listener.endType(begin, token);
810 } 868 }
811 token = parseTypeArgumentsOpt(token); 869
812 listener.endType(begin, token); 870 // While we see a `Function(` treat the pushed type as return type.
871 // For example: `int Function() Function(int) Function(String x)`.
872 while (isGeneralizedFunctionType(token)) {
873 token = parseFunctionType(token);
874 }
813 return token; 875 return token;
814 } 876 }
815 877
878 /// Parses a generalized function type.
879 ///
880 /// The return type must already be pushed.
881 Token parseFunctionType(Token token) {
882 // TODO(floitsch): don't use string comparison, but the keyword-state
883 // table is currently not set up to deal with upper-case characters.
884 if (token.value != "Function") {
885 return listener.expected("Function", token);
886 }
887 Token functionToken = token;
888 token = token.next;
889 token = parseTypeVariablesOpt(token);
890 token = parseFormalParameters(token, inFunctionType: true);
891 listener.endFunctionType(functionToken, token);
892 return token;
893 }
894
816 Token parseTypeArgumentsOpt(Token token) { 895 Token parseTypeArgumentsOpt(Token token) {
817 return parseStuff( 896 return parseStuff(
818 token, 897 token,
819 (t) => listener.beginTypeArguments(t), 898 (t) => listener.beginTypeArguments(t),
820 (t) => parseType(t), 899 (t) => parseType(t),
821 (c, bt, et) => listener.endTypeArguments(c, bt, et), 900 (c, bt, et) => listener.endTypeArguments(c, bt, et),
822 (t) => listener.handleNoTypeArguments(t)); 901 (t) => listener.handleNoTypeArguments(t));
823 } 902 }
824 903
825 Token parseTypeVariablesOpt(Token token) { 904 Token parseTypeVariablesOpt(Token token) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 identifiers = identifiers.prepend(token); 1218 identifiers = identifiers.prepend(token);
1140 return identifiers; 1219 return identifiers;
1141 } else if (value == '=' || value == ';' || value == ',') { 1220 } else if (value == '=' || value == ';' || value == ',') {
1142 // A field or abstract getter. 1221 // A field or abstract getter.
1143 identifiers = identifiers.prepend(token); 1222 identifiers = identifiers.prepend(token);
1144 return identifiers; 1223 return identifiers;
1145 } else if (isGetter) { 1224 } else if (isGetter) {
1146 hasName = true; 1225 hasName = true;
1147 } 1226 }
1148 identifiers = identifiers.prepend(token); 1227 identifiers = identifiers.prepend(token);
1149 if (isValidTypeReference(token)) { 1228
1150 // type ... 1229 if (!isGeneralizedFunctionType(token)) {
1151 if (optional('.', token.next)) { 1230 // Read a potential return type.
1152 // type '.' ... 1231 if (isValidTypeReference(token)) {
1153 if (token.next.next.isIdentifier()) { 1232 // type ...
1154 // type '.' identifier 1233 if (optional('.', token.next)) {
1155 token = token.next.next; 1234 // type '.' ...
1235 if (token.next.next.isIdentifier()) {
1236 // type '.' identifier
1237 token = token.next.next;
1238 }
1239 }
1240 if (optional('<', token.next)) {
1241 if (token.next is BeginGroupToken) {
1242 BeginGroupToken beginGroup = token.next;
1243 if (beginGroup.endGroup == null) {
1244 listener.unmatched(beginGroup);
1245 }
1246 token = beginGroup.endGroup;
1247 }
1156 } 1248 }
1157 } 1249 }
1158 if (optional('<', token.next)) { 1250 token = token.next;
1159 if (token.next is BeginGroupToken) { 1251 }
1160 BeginGroupToken beginGroup = token.next; 1252 while (isGeneralizedFunctionType(token)) {
1253 token = token.next;
1254 if (optional('<', token)) {
1255 if (token is BeginGroupToken) {
1256 BeginGroupToken beginGroup = token;
1161 if (beginGroup.endGroup == null) { 1257 if (beginGroup.endGroup == null) {
1162 listener.unmatched(beginGroup); 1258 listener.unmatched(beginGroup);
1163 } 1259 }
1164 token = beginGroup.endGroup; 1260 token = beginGroup.endGroup.next;
1165 } 1261 }
1166 } 1262 }
1263 if (!optional('(', token)) {
1264 if (optional(';', token)) {
1265 listener.recoverableError(token, "expected '('");
1266 }
1267 token = listener.unexpected(token);
1268 }
1269 if (token is BeginGroupToken) {
1270 BeginGroupToken beginGroup = token;
1271 if (beginGroup.endGroup == null) {
1272 listener.unmatched(beginGroup);
1273 }
1274 token = beginGroup.endGroup.next;
1275 }
1167 } 1276 }
1168 token = token.next;
1169 } 1277 }
1170 return const Link<Token>(); 1278 return const Link<Token>();
1171 } 1279 }
1172 1280
1173 Token parseVariableInitializerOpt(Token token) { 1281 Token parseVariableInitializerOpt(Token token) {
1174 if (optional('=', token)) { 1282 if (optional('=', token)) {
1175 Token assignment = token; 1283 Token assignment = token;
1176 listener.beginInitializer(token); 1284 listener.beginInitializer(token);
1177 token = parseExpression(token.next); 1285 token = parseExpression(token.next);
1178 listener.endInitializer(assignment); 1286 listener.endInitializer(assignment);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 if (!isModifier(token)) break; 1364 if (!isModifier(token)) break;
1257 token = parseModifier(token); 1365 token = parseModifier(token);
1258 count++; 1366 count++;
1259 } 1367 }
1260 listener.handleModifiers(count); 1368 listener.handleModifiers(count);
1261 return token; 1369 return token;
1262 } 1370 }
1263 1371
1264 /** 1372 /**
1265 * Returns the first token after the type starting at [token]. 1373 * Returns the first token after the type starting at [token].
1374 *
1266 * This method assumes that [token] is an identifier (or void). 1375 * This method assumes that [token] is an identifier (or void).
1267 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1376 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1268 */ 1377 */
1269 Token peekAfterType(Token token) { 1378 Token peekAfterType(Token token) {
1270 // We are looking at "identifier ...". 1379 // We are looking at "identifier ...".
1380 Token peek = token;
1381 if (!isGeneralizedFunctionType(token)) {
1382 peek = peekAfterNominalType(token);
1383 }
1384
1385 // We might have just skipped over the return value of the function type.
1386 // Check again, if we are now at a function type position.
1387 while (isGeneralizedFunctionType(peek)) {
1388 peek = peekAfterFunctionType(peek);
1389 }
1390 return peek;
1391 }
1392
1393 /**
1394 * Returns the first token after the nominal type starting at [token].
1395 *
1396 * This method assumes that [token] is an identifier (or void).
1397 */
1398 Token peekAfterNominalType(Token token) {
1271 Token peek = token.next; 1399 Token peek = token.next;
1272 if (identical(peek.kind, PERIOD_TOKEN)) { 1400 if (identical(peek.kind, PERIOD_TOKEN)) {
1273 if (peek.next.isIdentifier()) { 1401 if (peek.next.isIdentifier()) {
1274 // Look past a library prefix. 1402 // Look past a library prefix.
1275 peek = peek.next.next; 1403 peek = peek.next.next;
1276 } 1404 }
1277 } 1405 }
1278 // We are looking at "qualified ...". 1406 // We are looking at "qualified ...".
1279 if (identical(peek.kind, LT_TOKEN)) { 1407 if (identical(peek.kind, LT_TOKEN)) {
1280 // Possibly generic type. 1408 // Possibly generic type.
1281 // We are looking at "qualified '<'". 1409 // We are looking at "qualified '<'".
1282 BeginGroupToken beginGroupToken = peek; 1410 BeginGroupToken beginGroupToken = peek;
1283 Token gtToken = beginGroupToken.endGroup; 1411 Token gtToken = beginGroupToken.endGroup;
1284 if (gtToken != null) { 1412 if (gtToken != null) {
1285 // We are looking at "qualified '<' ... '>' ...". 1413 // We are looking at "qualified '<' ... '>' ...".
1286 return gtToken.next; 1414 peek = gtToken.next;
1287 } 1415 }
1288 } 1416 }
1289 return peek; 1417 return peek;
1290 } 1418 }
1291 1419
1292 /** 1420 /**
1421 * Returns the first token after the function type starting at [token].
1422 *
1423 * The token must be at the `Function` token position. That is, the return
1424 * type must have already been skipped.
1425 *
1426 * This function only skips over one function type syntax.
1427 * If necessary, this function must be called multiple times.
1428 *
1429 * Example:
1430 * ```
1431 * int Function() Function<T>(int)
1432 * ^ ^
1433 * A call to this function must be at one of the `Function` tokens.
1434 * If `token` pointed to the first `Function` token, then the returned
1435 * token points to the second `Function` token.
1436 */
1437 Token peekAfterFunctionType(Token token) {
1438 // Possible inputs are:
1439 // Function( ... )
1440 // Function< ... >( ... )
1441
1442 Token peek = token.next; // Skip over the Function token.
1443 // If there is a generic argument to the function, skip over that one first.
1444 if (identical(peek.kind, LT_TOKEN)) {
1445 BeginGroupToken beginGroupToken = peek;
1446 Token closeToken = beginGroupToken.endGroup;
1447 if (closeToken != null) {
1448 peek = closeToken.next;
1449 }
1450 }
1451
1452 // Now we just need to skip over the formals.
1453 expect('(', peek);
1454
1455 BeginGroupToken beginGroupToken = peek;
1456 Token closeToken = beginGroupToken.endGroup;
1457 if (closeToken != null) {
1458 peek = closeToken.next;
1459 }
1460
1461 return peek;
1462 }
1463
1464 /**
1293 * If [token] is the start of a type, returns the token after that type. 1465 * If [token] is the start of a type, returns the token after that type.
1294 * If [token] is not the start of a type, null is returned. 1466 * If [token] is not the start of a type, null is returned.
1295 */ 1467 */
1296 Token peekAfterIfType(Token token) { 1468 Token peekAfterIfType(Token token) {
1297 if (!optional('void', token) && !token.isIdentifier()) { 1469 if (!optional('void', token) && !token.isIdentifier()) {
1298 return null; 1470 return null;
1299 } 1471 }
1300 return peekAfterType(token); 1472 return peekAfterType(token);
1301 } 1473 }
1302 1474
(...skipping 1666 matching lines...) Expand 10 before | Expand all | Expand 10 after
2969 } 3141 }
2970 listener.handleContinueStatement(hasTarget, continueKeyword, token); 3142 listener.handleContinueStatement(hasTarget, continueKeyword, token);
2971 return expectSemicolon(token); 3143 return expectSemicolon(token);
2972 } 3144 }
2973 3145
2974 Token parseEmptyStatement(Token token) { 3146 Token parseEmptyStatement(Token token) {
2975 listener.handleEmptyStatement(token); 3147 listener.handleEmptyStatement(token);
2976 return expectSemicolon(token); 3148 return expectSemicolon(token);
2977 } 3149 }
2978 } 3150 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698