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 '../scanner.dart' show | 7 import '../scanner.dart' show |
8 ErrorToken; | 8 ErrorToken; |
9 | 9 |
10 import '../scanner/recover.dart' show | 10 import '../scanner/recover.dart' show |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 /** | 93 /** |
94 * An event generating parser of Dart programs. This parser expects | 94 * An event generating parser of Dart programs. This parser expects |
95 * all tokens in a linked list (aka a token stream). | 95 * all tokens in a linked list (aka a token stream). |
96 * | 96 * |
97 * The class [Scanner] is used to generate a token stream. See the | 97 * The class [Scanner] is used to generate a token stream. See the |
98 * file scanner.dart. | 98 * file scanner.dart. |
99 * | 99 * |
100 * Subclasses of the class [Listener] are used to listen to events. | 100 * Subclasses of the class [Listener] are used to listen to events. |
101 * | 101 * |
102 * Most methods of this class belong in one of two major categories: | 102 * Most methods of this class belong in one of two major categories: |
103 * parse methods and peek methods. Parse methods all have the prefix | 103 * parse metods and peek methods. Parse methods all have the prefix |
104 * parse, and peek methods all have the prefix peek. | 104 * parse, and peek methods all have the prefix peek. |
105 * | 105 * |
106 * Parse methods generate events (by calling methods on [listener]) | 106 * Parse methods generate events (by calling methods on [listener]) |
107 * and return the next token to parse. Peek methods do not generate | 107 * and return the next token to parse. Peek methods do not generate |
108 * events (except for errors) and may return null. | 108 * events (except for errors) and may return null. |
109 * | 109 * |
110 * Parse methods are generally named parseGrammarProductionSuffix. The | 110 * Parse methods are generally named parseGrammarProductionSuffix. The |
111 * suffix can be one of "opt", or "star". "opt" means zero or one | 111 * suffix can be one of "opt", or "star". "opt" means zero or one |
112 * matches, "star" means zero or more matches. For example, | 112 * matches, "star" means zero or more matches. For example, |
113 * [parseMetadataStar] corresponds to this grammar snippet: [: | 113 * [parseMetadataStar] corresponds to this grammar snippet: [: |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 token = parseIdentifier(token.next); | 378 token = parseIdentifier(token.next); |
379 } | 379 } |
380 token = parseArgumentsOpt(token); | 380 token = parseArgumentsOpt(token); |
381 listener.endMetadata(atToken, period, token); | 381 listener.endMetadata(atToken, period, token); |
382 return token; | 382 return token; |
383 } | 383 } |
384 | 384 |
385 Token parseTypedef(Token token) { | 385 Token parseTypedef(Token token) { |
386 Token typedefKeyword = token; | 386 Token typedefKeyword = token; |
387 listener.beginFunctionTypeAlias(token); | 387 listener.beginFunctionTypeAlias(token); |
388 Token equals; | 388 token = parseReturnTypeOpt(token.next); |
389 if (optional('=', peekAfterNominalType(token.next))) { | 389 token = parseIdentifier(token); |
390 token = parseIdentifier(token.next); | 390 token = parseTypeVariablesOpt(token); |
391 token = parseTypeVariablesOpt(token); | 391 token = parseFormalParameters(token); |
392 equals = token; | 392 listener.endFunctionTypeAlias(typedefKeyword, token); |
393 token = expect('=', token); | |
394 token = parseType(token); | |
395 } else { | |
396 token = parseReturnTypeOpt(token.next); | |
397 token = parseIdentifier(token); | |
398 token = parseTypeVariablesOpt(token); | |
399 token = parseFormalParameters(token); | |
400 } | |
401 listener.endFunctionTypeAlias(typedefKeyword, equals, token); | |
402 return expect(';', token); | 393 return expect(';', token); |
403 } | 394 } |
404 | 395 |
405 Token parseMixinApplication(Token token) { | 396 Token parseMixinApplication(Token token) { |
406 listener.beginMixinApplication(token); | 397 listener.beginMixinApplication(token); |
407 token = parseType(token); | 398 token = parseType(token); |
408 token = expect('with', token); | 399 token = expect('with', token); |
409 token = parseTypeList(token); | 400 token = parseTypeList(token); |
410 listener.endMixinApplication(); | 401 listener.endMixinApplication(); |
411 return token; | 402 return token; |
412 } | 403 } |
413 | 404 |
414 Token parseReturnTypeOpt(Token token) { | 405 Token parseReturnTypeOpt(Token token) { |
415 if (identical(token.stringValue, 'void')) { | 406 if (identical(token.stringValue, 'void')) { |
416 if (isGeneralizedFunctionType(token.next)) { | 407 listener.handleVoidKeyword(token); |
417 return parseType(token); | 408 return token.next; |
418 } else { | |
419 listener.handleVoidKeyword(token); | |
420 return token.next; | |
421 } | |
422 } else { | 409 } else { |
423 return parseTypeOpt(token); | 410 return parseTypeOpt(token); |
424 } | 411 } |
425 } | 412 } |
426 | 413 |
427 Token parseFormalParametersOpt(Token token) { | 414 Token parseFormalParametersOpt(Token token) { |
428 if (optional('(', token)) { | 415 if (optional('(', token)) { |
429 return parseFormalParameters(token); | 416 return parseFormalParameters(token); |
430 } else { | 417 } else { |
431 listener.handleNoFormalParameters(token); | 418 listener.handleNoFormalParameters(token); |
(...skipping 11 matching lines...) Expand all Loading... |
443 } | 430 } |
444 return reportUnrecoverableError( | 431 return reportUnrecoverableError( |
445 token, ErrorKind.ExpectedButGot, {"expected": "("}); | 432 token, ErrorKind.ExpectedButGot, {"expected": "("}); |
446 } | 433 } |
447 BeginGroupToken beginGroupToken = token; | 434 BeginGroupToken beginGroupToken = token; |
448 Token endToken = beginGroupToken.endGroup; | 435 Token endToken = beginGroupToken.endGroup; |
449 listener.endFormalParameters(0, token, endToken); | 436 listener.endFormalParameters(0, token, endToken); |
450 return endToken.next; | 437 return endToken.next; |
451 } | 438 } |
452 | 439 |
453 /// Parses the formal parameter list of a function. | 440 Token parseFormalParameters(Token token) { |
454 /// | |
455 /// If [inFunctionType] is true, then the names may be omitted (except for | |
456 /// named arguments). If it is false, then the types may be omitted. | |
457 Token parseFormalParameters(Token token, {bool inFunctionType: false}) { | |
458 Token begin = token; | 441 Token begin = token; |
459 listener.beginFormalParameters(begin); | 442 listener.beginFormalParameters(begin); |
460 expect('(', token); | 443 expect('(', token); |
461 int parameterCount = 0; | 444 int parameterCount = 0; |
462 do { | 445 do { |
463 token = token.next; | 446 token = token.next; |
464 if (optional(')', token)) { | 447 if (optional(')', token)) { |
465 break; | 448 break; |
466 } | 449 } |
467 ++parameterCount; | 450 ++parameterCount; |
468 String value = token.stringValue; | 451 String value = token.stringValue; |
469 if (identical(value, '[')) { | 452 if (identical(value, '[')) { |
470 token = parseOptionalFormalParameters( | 453 token = parseOptionalFormalParameters(token, false); |
471 token, false, inFunctionType: inFunctionType); | |
472 break; | 454 break; |
473 } else if (identical(value, '{')) { | 455 } else if (identical(value, '{')) { |
474 token = parseOptionalFormalParameters( | 456 token = parseOptionalFormalParameters(token, true); |
475 token, true, inFunctionType: inFunctionType); | |
476 break; | 457 break; |
477 } | 458 } |
478 token = parseFormalParameter(token, FormalParameterType.REQUIRED, | 459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); |
479 inFunctionType: inFunctionType); | |
480 } while (optional(',', token)); | 460 } while (optional(',', token)); |
481 listener.endFormalParameters(parameterCount, begin, token); | 461 listener.endFormalParameters(parameterCount, begin, token); |
482 return expect(')', token); | 462 return expect(')', token); |
483 } | 463 } |
484 | 464 |
485 Token parseFormalParameter(Token token, FormalParameterType type, | 465 Token parseFormalParameter(Token token, FormalParameterType type) { |
486 {bool inFunctionType}) { | |
487 token = parseMetadataStar(token, forParameter: true); | 466 token = parseMetadataStar(token, forParameter: true); |
488 listener.beginFormalParameter(token); | 467 listener.beginFormalParameter(token); |
489 | 468 |
490 // Skip over `covariant` token, if the next token is an identifier or | 469 // Skip over `covariant` token, if the next token is an identifier or |
491 // modifier. | 470 // modifier. |
492 // This enables the case where `covariant` is the name of the parameter: | 471 // This enables the case where `covariant` is the name of the parameter: |
493 // void foo(covariant); | 472 // void foo(covariant); |
494 if (identical(token.stringValue, 'covariant') && | 473 if (identical(token.stringValue, 'covariant') && |
495 (token.next.isIdentifier() || isModifier(token.next))) { | 474 (token.next.isIdentifier() || isModifier(token.next))) { |
496 token = token.next; | 475 token = token.next; |
497 } | 476 } |
498 token = parseModifiers(token); | 477 token = parseModifiers(token); |
499 bool isNamedParameter = type == FormalParameterType.NAMED; | 478 // TODO(ahe): Validate that there are formal parameters if void. |
500 | 479 token = parseReturnTypeOpt(token); |
501 Token thisKeyword = null; | 480 Token thisKeyword = null; |
502 if (inFunctionType && isNamedParameter) { | 481 if (optional('this', token)) { |
503 token = parseType(token); | 482 thisKeyword = token; |
504 token = parseIdentifier(token); | 483 // TODO(ahe): Validate field initializers are only used in |
505 } else if (inFunctionType) { | 484 // constructors, and not for function-typed arguments. |
506 token = parseType(token); | 485 token = expect('.', token.next); |
507 if (token.isIdentifier()) { | |
508 token = parseIdentifier(token); | |
509 } else { | |
510 listener.handleNoName(token); | |
511 } | |
512 } else { | |
513 token = parseReturnTypeOpt(token); | |
514 if (optional('this', token)) { | |
515 thisKeyword = token; | |
516 token = expect('.', token.next); | |
517 } | |
518 token = parseIdentifier(token); | |
519 } | 486 } |
520 | 487 token = parseIdentifier(token); |
521 // Generalized function types don't allow inline function types. | |
522 // The following isn't allowed: | |
523 // int Function(int bar(String x)). | |
524 if (optional('(', token)) { | 488 if (optional('(', token)) { |
525 Token inlineFunctionTypeStart = token; | |
526 listener.beginFunctionTypedFormalParameter(token); | 489 listener.beginFunctionTypedFormalParameter(token); |
527 listener.handleNoTypeVariables(token); | 490 listener.handleNoTypeVariables(token); |
528 token = parseFormalParameters(token); | 491 token = parseFormalParameters(token); |
529 listener.endFunctionTypedFormalParameter(token); | 492 listener.endFunctionTypedFormalParameter(token); |
530 if (inFunctionType) { | |
531 reportRecoverableError( | |
532 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); | |
533 } | |
534 } else if (optional('<', token)) { | 493 } else if (optional('<', token)) { |
535 Token inlineFunctionTypeStart = token; | |
536 listener.beginFunctionTypedFormalParameter(token); | 494 listener.beginFunctionTypedFormalParameter(token); |
537 token = parseTypeVariablesOpt(token); | 495 token = parseTypeVariablesOpt(token); |
538 token = parseFormalParameters(token); | 496 token = parseFormalParameters(token); |
539 listener.endFunctionTypedFormalParameter(token); | 497 listener.endFunctionTypedFormalParameter(token); |
540 if (inFunctionType) { | |
541 reportRecoverableError( | |
542 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); | |
543 } | |
544 } | 498 } |
545 String value = token.stringValue; | 499 String value = token.stringValue; |
546 if ((identical('=', value)) || (identical(':', value))) { | 500 if ((identical('=', value)) || (identical(':', value))) { |
547 // TODO(ahe): Validate that these are only used for optional parameters. | 501 // TODO(ahe): Validate that these are only used for optional parameters. |
548 Token equal = token; | 502 Token equal = token; |
549 token = parseExpression(token.next); | 503 token = parseExpression(token.next); |
550 listener.handleValuedFormalParameter(equal, token); | 504 listener.handleValuedFormalParameter(equal, token); |
551 if (type.isRequired) { | 505 if (type.isRequired) { |
552 reportRecoverableError( | 506 reportRecoverableError( |
553 equal, ErrorKind.RequiredParameterWithDefault); | 507 equal, ErrorKind.RequiredParameterWithDefault); |
554 } else if (type.isPositional && identical(':', value)) { | 508 } else if (type.isPositional && identical(':', value)) { |
555 reportRecoverableError( | 509 reportRecoverableError( |
556 equal, ErrorKind.PositionalParameterWithEquals); | 510 equal, ErrorKind.PositionalParameterWithEquals); |
557 } | 511 } |
558 } | 512 } |
559 listener.endFormalParameter(thisKeyword); | 513 listener.endFormalParameter(thisKeyword); |
560 return token; | 514 return token; |
561 } | 515 } |
562 | 516 |
563 Token parseOptionalFormalParameters(Token token, bool isNamed, | 517 Token parseOptionalFormalParameters(Token token, bool isNamed) { |
564 {bool inFunctionType}) { | |
565 Token begin = token; | 518 Token begin = token; |
566 listener.beginOptionalFormalParameters(begin); | 519 listener.beginOptionalFormalParameters(begin); |
567 assert((isNamed && optional('{', token)) || optional('[', token)); | 520 assert((isNamed && optional('{', token)) || optional('[', token)); |
568 int parameterCount = 0; | 521 int parameterCount = 0; |
569 do { | 522 do { |
570 token = token.next; | 523 token = token.next; |
571 if (isNamed && optional('}', token)) { | 524 if (isNamed && optional('}', token)) { |
572 break; | 525 break; |
573 } else if (!isNamed && optional(']', token)) { | 526 } else if (!isNamed && optional(']', token)) { |
574 break; | 527 break; |
575 } | 528 } |
576 var type = | 529 var type = |
577 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 530 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
578 token = | 531 token = parseFormalParameter(token, type); |
579 parseFormalParameter(token, type, inFunctionType: inFunctionType); | |
580 ++parameterCount; | 532 ++parameterCount; |
581 } while (optional(',', token)); | 533 } while (optional(',', token)); |
582 if (parameterCount == 0) { | 534 if (parameterCount == 0) { |
583 reportRecoverableError( | 535 reportRecoverableError( |
584 token, | 536 token, |
585 isNamed | 537 isNamed |
586 ? ErrorKind.EmptyNamedParameterList | 538 ? ErrorKind.EmptyNamedParameterList |
587 : ErrorKind.EmptyOptionalParameterList); | 539 : ErrorKind.EmptyOptionalParameterList); |
588 } | 540 } |
589 listener.endOptionalFormalParameters(parameterCount, begin, token); | 541 listener.endOptionalFormalParameters(parameterCount, begin, token); |
590 if (isNamed) { | 542 if (isNamed) { |
591 return expect('}', token); | 543 return expect('}', token); |
592 } else { | 544 } else { |
593 return expect(']', token); | 545 return expect(']', token); |
594 } | 546 } |
595 } | 547 } |
596 | 548 |
597 Token parseTypeOpt(Token token) { | 549 Token parseTypeOpt(Token token) { |
598 if (isGeneralizedFunctionType(token)) { | |
599 // Function type without return type. | |
600 return parseType(token); | |
601 } | |
602 Token peek = peekAfterIfType(token); | 550 Token peek = peekAfterIfType(token); |
603 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { | 551 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { |
604 return parseType(token); | 552 return parseType(token); |
605 } | 553 } |
606 listener.handleNoType(token); | 554 listener.handleNoType(token); |
607 return token; | 555 return token; |
608 } | 556 } |
609 | 557 |
610 bool isValidTypeReference(Token token) { | 558 bool isValidTypeReference(Token token) { |
611 final kind = token.kind; | 559 final kind = token.kind; |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 token = token.next; | 714 token = token.next; |
767 classKeyword = token; | 715 classKeyword = token; |
768 } | 716 } |
769 assert(optional('class', classKeyword)); | 717 assert(optional('class', classKeyword)); |
770 int modifierCount = 0; | 718 int modifierCount = 0; |
771 if (abstractKeyword != null) { | 719 if (abstractKeyword != null) { |
772 parseModifier(abstractKeyword); | 720 parseModifier(abstractKeyword); |
773 modifierCount++; | 721 modifierCount++; |
774 } | 722 } |
775 listener.handleModifiers(modifierCount); | 723 listener.handleModifiers(modifierCount); |
776 bool isMixinApplication = optional('=', peekAfterNominalType(token)); | 724 bool isMixinApplication = optional('=', peekAfterType(token)); |
777 Token name = token.next; | 725 Token name = token.next; |
778 token = parseIdentifier(name); | 726 token = parseIdentifier(name); |
779 | 727 |
780 if (isMixinApplication) { | 728 if (isMixinApplication) { |
781 listener.beginNamedMixinApplication(begin, name); | 729 listener.beginNamedMixinApplication(begin, name); |
782 } else { | 730 } else { |
783 listener.beginClassDeclaration(begin, name); | 731 listener.beginClassDeclaration(begin, name); |
784 } | 732 } |
785 | 733 |
786 token = parseTypeVariablesOpt(token); | 734 token = parseTypeVariablesOpt(token); |
(...skipping 18 matching lines...) Expand all Loading... |
805 } | 753 } |
806 listener.endNamedMixinApplication(begin, classKeyword, equals, | 754 listener.endNamedMixinApplication(begin, classKeyword, equals, |
807 implementsKeyword, token); | 755 implementsKeyword, token); |
808 return expect(';', token); | 756 return expect(';', token); |
809 } | 757 } |
810 | 758 |
811 Token parseClass(Token token, Token begin, Token classKeyword, Token name) { | 759 Token parseClass(Token token, Token begin, Token classKeyword, Token name) { |
812 Token extendsKeyword; | 760 Token extendsKeyword; |
813 if (optional('extends', token)) { | 761 if (optional('extends', token)) { |
814 extendsKeyword = token; | 762 extendsKeyword = token; |
815 if (optional('with', peekAfterNominalType(token.next))) { | 763 if (optional('with', peekAfterType(token.next))) { |
816 token = parseMixinApplication(token.next); | 764 token = parseMixinApplication(token.next); |
817 } else { | 765 } else { |
818 token = parseType(token.next); | 766 token = parseType(token.next); |
819 } | 767 } |
820 } else { | 768 } else { |
821 extendsKeyword = null; | 769 extendsKeyword = null; |
822 listener.handleNoType(token); | 770 listener.handleNoType(token); |
823 } | 771 } |
824 Token implementsKeyword; | 772 Token implementsKeyword; |
825 int interfacesCount = 0; | 773 int interfacesCount = 0; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 value2 == stringValue || | 845 value2 == stringValue || |
898 value3 == stringValue || | 846 value3 == stringValue || |
899 value4 == stringValue; | 847 value4 == stringValue; |
900 } | 848 } |
901 | 849 |
902 bool notEofOrValue(String value, Token token) { | 850 bool notEofOrValue(String value, Token token) { |
903 return !identical(token.kind, EOF_TOKEN) && | 851 return !identical(token.kind, EOF_TOKEN) && |
904 !identical(value, token.stringValue); | 852 !identical(value, token.stringValue); |
905 } | 853 } |
906 | 854 |
907 bool isGeneralizedFunctionType(Token token) { | |
908 return optional('Function', token) && | |
909 (optional('<', token.next) || optional('(', token.next)); | |
910 } | |
911 | |
912 Token parseType(Token token) { | 855 Token parseType(Token token) { |
913 Token begin = token; | 856 Token begin = token; |
914 if (isGeneralizedFunctionType(token)) { | 857 if (isValidTypeReference(token)) { |
915 // A function type without return type. | 858 token = parseIdentifier(token); |
916 // Push the non-existing return type first. The loop below will | 859 token = parseQualifiedRestOpt(token); |
917 // generate the full type. | |
918 listener.handleNoType(token); | |
919 } else if (identical(token.stringValue, 'void') && | |
920 isGeneralizedFunctionType(token.next)) { | |
921 listener.handleVoidKeyword(token); | |
922 token = token.next; | |
923 } else { | 860 } else { |
924 if (isValidTypeReference(token)) { | 861 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); |
925 token = parseIdentifier(token); | 862 listener.handleInvalidTypeReference(token); |
926 token = parseQualifiedRestOpt(token); | |
927 } else { | |
928 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); | |
929 listener.handleInvalidTypeReference(token); | |
930 } | |
931 token = parseTypeArgumentsOpt(token); | |
932 listener.handleType(begin, token); | |
933 } | 863 } |
934 | 864 token = parseTypeArgumentsOpt(token); |
935 // While we see a `Function(` treat the pushed type as return type. | 865 listener.endType(begin, token); |
936 // For example: `int Function() Function(int) Function(String x)`. | |
937 while (isGeneralizedFunctionType(token)) { | |
938 token = parseFunctionType(token); | |
939 } | |
940 return token; | 866 return token; |
941 } | 867 } |
942 | 868 |
943 /// Parses a generalized function type. | |
944 /// | |
945 /// The return type must already be pushed. | |
946 Token parseFunctionType(Token token) { | |
947 assert(optional('Function', token)); | |
948 Token functionToken = token; | |
949 token = token.next; | |
950 token = parseTypeVariablesOpt(token); | |
951 token = parseFormalParameters(token, inFunctionType: true); | |
952 listener.handleFunctionType(functionToken, token); | |
953 return token; | |
954 } | |
955 | |
956 Token parseTypeArgumentsOpt(Token token) { | 869 Token parseTypeArgumentsOpt(Token token) { |
957 return parseStuff( | 870 return parseStuff( |
958 token, | 871 token, |
959 (t) => listener.beginTypeArguments(t), | 872 (t) => listener.beginTypeArguments(t), |
960 (t) => parseType(t), | 873 (t) => parseType(t), |
961 (c, bt, et) => listener.endTypeArguments(c, bt, et), | 874 (c, bt, et) => listener.endTypeArguments(c, bt, et), |
962 (t) => listener.handleNoTypeArguments(t)); | 875 (t) => listener.handleNoTypeArguments(t)); |
963 } | 876 } |
964 | 877 |
965 Token parseTypeVariablesOpt(Token token) { | 878 Token parseTypeVariablesOpt(Token token) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 | 1075 |
1163 if (getOrSet != null) { | 1076 if (getOrSet != null) { |
1164 var kind = (hasModifier || hasType) | 1077 var kind = (hasModifier || hasType) |
1165 ? ErrorKind.ExtraneousModifier | 1078 ? ErrorKind.ExtraneousModifier |
1166 : ErrorKind.ExtraneousModifierReplace; | 1079 : ErrorKind.ExtraneousModifierReplace; |
1167 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); | 1080 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); |
1168 } | 1081 } |
1169 | 1082 |
1170 if (!hasType) { | 1083 if (!hasType) { |
1171 listener.handleNoType(name); | 1084 listener.handleNoType(name); |
1172 } else if (optional('void', type) && | 1085 } else if (optional('void', type)) { |
1173 !isGeneralizedFunctionType(type.next)) { | |
1174 listener.handleNoType(name); | 1086 listener.handleNoType(name); |
1175 // TODO(ahe): This error is reported twice, second time is from | 1087 // TODO(ahe): This error is reported twice, second time is from |
1176 // [parseVariablesDeclarationMaybeSemicolon] via | 1088 // [parseVariablesDeclarationMaybeSemicolon] via |
1177 // [PartialFieldListElement.parseNode]. | 1089 // [PartialFieldListElement.parseNode]. |
1178 reportRecoverableError(type, ErrorKind.InvalidVoid); | 1090 reportRecoverableError(type, ErrorKind.InvalidVoid); |
1179 } else { | 1091 } else { |
1180 parseType(type); | 1092 parseType(type); |
1181 if (isVar) { | 1093 if (isVar) { |
1182 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, | 1094 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, |
1183 {'modifier': modifiers.head}); | 1095 {'modifier': modifiers.head}); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1299 return listener.handleMemberName(identifiers); | 1211 return listener.handleMemberName(identifiers); |
1300 } else if (optional("=", token) || optional(";", token) || | 1212 } else if (optional("=", token) || optional(";", token) || |
1301 optional(",", token)) { | 1213 optional(",", token)) { |
1302 // A field or abstract getter. | 1214 // A field or abstract getter. |
1303 identifiers = identifiers.prepend(token); | 1215 identifiers = identifiers.prepend(token); |
1304 return listener.handleMemberName(identifiers); | 1216 return listener.handleMemberName(identifiers); |
1305 } else if (isGetter) { | 1217 } else if (isGetter) { |
1306 hasName = true; | 1218 hasName = true; |
1307 } | 1219 } |
1308 identifiers = identifiers.prepend(token); | 1220 identifiers = identifiers.prepend(token); |
1309 | 1221 if (isValidTypeReference(token)) { |
1310 if (!isGeneralizedFunctionType(token)) { | 1222 // type ... |
1311 // Read a potential return type. | 1223 if (optional('.', token.next)) { |
1312 if (isValidTypeReference(token)) { | 1224 // type '.' ... |
1313 // type ... | 1225 if (token.next.next.isIdentifier()) { |
1314 if (optional('.', token.next)) { | 1226 // type '.' identifier |
1315 // type '.' ... | 1227 token = token.next.next; |
1316 if (token.next.next.isIdentifier()) { | |
1317 // type '.' identifier | |
1318 token = token.next.next; | |
1319 } | |
1320 } | 1228 } |
1321 if (optional('<', token.next)) { | 1229 } |
1322 if (token.next is BeginGroupToken) { | 1230 if (optional('<', token.next)) { |
1323 BeginGroupToken beginGroup = token.next; | 1231 if (token.next is BeginGroupToken) { |
1324 if (beginGroup.endGroup == null) { | 1232 BeginGroupToken beginGroup = token.next; |
1325 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | 1233 if (beginGroup.endGroup == null) { |
1326 } else { | 1234 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); |
1327 token = beginGroup.endGroup; | 1235 } else { |
1328 } | 1236 token = beginGroup.endGroup; |
1329 } | 1237 } |
1330 } | 1238 } |
1331 } | 1239 } |
1332 token = token.next; | |
1333 } | 1240 } |
1334 while (isGeneralizedFunctionType(token)) { | 1241 token = token.next; |
1335 token = token.next; | |
1336 if (optional('<', token)) { | |
1337 if (token is BeginGroupToken) { | |
1338 BeginGroupToken beginGroup = token; | |
1339 if (beginGroup.endGroup == null) { | |
1340 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | |
1341 } else { | |
1342 token = beginGroup.endGroup.next; | |
1343 } | |
1344 } | |
1345 } | |
1346 if (!optional('(', token)) { | |
1347 if (optional(';', token)) { | |
1348 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); | |
1349 } | |
1350 token = expect("(", token); | |
1351 } | |
1352 if (token is BeginGroupToken) { | |
1353 BeginGroupToken beginGroup = token; | |
1354 if (beginGroup.endGroup == null) { | |
1355 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | |
1356 } else { | |
1357 token = beginGroup.endGroup.next; | |
1358 } | |
1359 } | |
1360 } | |
1361 } | 1242 } |
1362 return listener.handleMemberName(const Link<Token>()); | 1243 return listener.handleMemberName(const Link<Token>()); |
1363 } | 1244 } |
1364 | 1245 |
1365 Token parseFieldInitializerOpt(Token token) { | 1246 Token parseFieldInitializerOpt(Token token) { |
1366 if (optional('=', token)) { | 1247 if (optional('=', token)) { |
1367 Token assignment = token; | 1248 Token assignment = token; |
1368 listener.beginFieldInitializer(token); | 1249 listener.beginFieldInitializer(token); |
1369 token = parseExpression(token.next); | 1250 token = parseExpression(token.next); |
1370 listener.endFieldInitializer(assignment); | 1251 listener.endFieldInitializer(assignment); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 if (!isModifier(token)) break; | 1346 if (!isModifier(token)) break; |
1466 token = parseModifier(token); | 1347 token = parseModifier(token); |
1467 count++; | 1348 count++; |
1468 } | 1349 } |
1469 listener.handleModifiers(count); | 1350 listener.handleModifiers(count); |
1470 return token; | 1351 return token; |
1471 } | 1352 } |
1472 | 1353 |
1473 /** | 1354 /** |
1474 * Returns the first token after the type starting at [token]. | 1355 * Returns the first token after the type starting at [token]. |
1475 * | |
1476 * This method assumes that [token] is an identifier (or void). | 1356 * This method assumes that [token] is an identifier (or void). |
1477 * Use [peekAfterIfType] if [token] isn't known to be an identifier. | 1357 * Use [peekAfterIfType] if [token] isn't known to be an identifier. |
1478 */ | 1358 */ |
1479 Token peekAfterType(Token token) { | 1359 Token peekAfterType(Token token) { |
1480 // We are looking at "identifier ...". | 1360 // We are looking at "identifier ...". |
1481 Token peek = token; | |
1482 if (!isGeneralizedFunctionType(token)) { | |
1483 peek = peekAfterNominalType(token); | |
1484 } | |
1485 | |
1486 // We might have just skipped over the return value of the function type. | |
1487 // Check again, if we are now at a function type position. | |
1488 while (isGeneralizedFunctionType(peek)) { | |
1489 peek = peekAfterFunctionType(peek.next); | |
1490 } | |
1491 return peek; | |
1492 } | |
1493 | |
1494 /** | |
1495 * Returns the first token after the nominal type starting at [token]. | |
1496 * | |
1497 * This method assumes that [token] is an identifier (or void). | |
1498 */ | |
1499 Token peekAfterNominalType(Token token) { | |
1500 Token peek = token.next; | 1361 Token peek = token.next; |
1501 if (identical(peek.kind, PERIOD_TOKEN)) { | 1362 if (identical(peek.kind, PERIOD_TOKEN)) { |
1502 if (peek.next.isIdentifier()) { | 1363 if (peek.next.isIdentifier()) { |
1503 // Look past a library prefix. | 1364 // Look past a library prefix. |
1504 peek = peek.next.next; | 1365 peek = peek.next.next; |
1505 } | 1366 } |
1506 } | 1367 } |
1507 // We are looking at "qualified ...". | 1368 // We are looking at "qualified ...". |
1508 if (identical(peek.kind, LT_TOKEN)) { | 1369 if (identical(peek.kind, LT_TOKEN)) { |
1509 // Possibly generic type. | 1370 // Possibly generic type. |
1510 // We are looking at "qualified '<'". | 1371 // We are looking at "qualified '<'". |
1511 BeginGroupToken beginGroupToken = peek; | 1372 BeginGroupToken beginGroupToken = peek; |
1512 Token gtToken = beginGroupToken.endGroup; | 1373 Token gtToken = beginGroupToken.endGroup; |
1513 if (gtToken != null) { | 1374 if (gtToken != null) { |
1514 // We are looking at "qualified '<' ... '>' ...". | 1375 // We are looking at "qualified '<' ... '>' ...". |
1515 peek = gtToken.next; | 1376 return gtToken.next; |
1516 } | 1377 } |
1517 } | 1378 } |
1518 return peek; | 1379 return peek; |
1519 } | 1380 } |
1520 | 1381 |
1521 /** | |
1522 * Returns the first token after the function type starting at [token]. | |
1523 * | |
1524 * The token must be at the token *after* the `Function` token position. That | |
1525 * is, the return type and the `Function` token must have already been | |
1526 * skipped. | |
1527 * | |
1528 * This function only skips over one function type syntax. | |
1529 * If necessary, this function must be called multiple times. | |
1530 * | |
1531 * Example: | |
1532 * ``` | |
1533 * int Function() Function<T>(int) | |
1534 * ^ ^ | |
1535 * A call to this function must be either at `(` or at `<`. | |
1536 * If `token` pointed to the first `(`, then the returned | |
1537 * token points to the second `Function` token. | |
1538 */ | |
1539 Token peekAfterFunctionType(Token token) { | |
1540 // Possible inputs are: | |
1541 // ( ... ) | |
1542 // < ... >( ... ) | |
1543 | |
1544 Token peek = token; | |
1545 // If there is a generic argument to the function, skip over that one first. | |
1546 if (identical(peek.kind, LT_TOKEN)) { | |
1547 BeginGroupToken beginGroupToken = peek; | |
1548 Token closeToken = beginGroupToken.endGroup; | |
1549 if (closeToken != null) { | |
1550 peek = closeToken.next; | |
1551 } | |
1552 } | |
1553 | |
1554 // Now we just need to skip over the formals. | |
1555 expect('(', peek); | |
1556 | |
1557 BeginGroupToken beginGroupToken = peek; | |
1558 Token closeToken = beginGroupToken.endGroup; | |
1559 if (closeToken != null) { | |
1560 peek = closeToken.next; | |
1561 } | |
1562 | |
1563 return peek; | |
1564 } | |
1565 | |
1566 /** | 1382 /** |
1567 * If [token] is the start of a type, returns the token after that type. | 1383 * If [token] is the start of a type, returns the token after that type. |
1568 * If [token] is not the start of a type, null is returned. | 1384 * If [token] is not the start of a type, null is returned. |
1569 */ | 1385 */ |
1570 Token peekAfterIfType(Token token) { | 1386 Token peekAfterIfType(Token token) { |
1571 if (!optional('void', token) && !token.isIdentifier()) { | 1387 if (!optional('void', token) && !token.isIdentifier()) { |
1572 return null; | 1388 return null; |
1573 } | 1389 } |
1574 return peekAfterType(token); | 1390 return peekAfterType(token); |
1575 } | 1391 } |
(...skipping 1931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3507 break; | 3323 break; |
3508 } | 3324 } |
3509 if (isRecoverable) { | 3325 if (isRecoverable) { |
3510 listener.handleRecoverableError(token, kind, arguments); | 3326 listener.handleRecoverableError(token, kind, arguments); |
3511 return null; | 3327 return null; |
3512 } else { | 3328 } else { |
3513 return listener.handleUnrecoverableError(token, kind, arguments); | 3329 return listener.handleUnrecoverableError(token, kind, arguments); |
3514 } | 3330 } |
3515 } | 3331 } |
3516 } | 3332 } |
OLD | NEW |