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 metods and peek methods. Parse methods all have the prefix | 103 * parse methods 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 = parseReturnTypeOpt(token.next); | 388 Token equals; |
389 token = parseIdentifier(token); | 389 if (optional('=', peekAfterNominalType(token.next))) { |
390 token = parseTypeVariablesOpt(token); | 390 token = parseIdentifier(token.next); |
391 token = parseFormalParameters(token); | 391 token = parseTypeVariablesOpt(token); |
392 listener.endFunctionTypeAlias(typedefKeyword, token); | 392 equals = token; |
| 393 token = expect('=', token); |
| 394 token = parseType(token); |
| 395 } else { |
| 396 token = parseTypeOpt(token.next); |
| 397 token = parseIdentifier(token); |
| 398 token = parseTypeVariablesOpt(token); |
| 399 token = parseFormalParameters(token); |
| 400 } |
| 401 listener.endFunctionTypeAlias(typedefKeyword, equals, token); |
393 return expect(';', token); | 402 return expect(';', token); |
394 } | 403 } |
395 | 404 |
396 Token parseMixinApplication(Token token) { | 405 Token parseMixinApplication(Token token) { |
397 listener.beginMixinApplication(token); | 406 listener.beginMixinApplication(token); |
398 token = parseType(token); | 407 token = parseType(token); |
399 token = expect('with', token); | 408 token = expect('with', token); |
400 token = parseTypeList(token); | 409 token = parseTypeList(token); |
401 listener.endMixinApplication(); | 410 listener.endMixinApplication(); |
402 return token; | 411 return token; |
403 } | 412 } |
404 | 413 |
405 Token parseReturnTypeOpt(Token token) { | |
406 if (identical(token.stringValue, 'void')) { | |
407 listener.handleVoidKeyword(token); | |
408 return token.next; | |
409 } else { | |
410 return parseTypeOpt(token); | |
411 } | |
412 } | |
413 | |
414 Token parseFormalParametersOpt(Token token) { | 414 Token parseFormalParametersOpt(Token token) { |
415 if (optional('(', token)) { | 415 if (optional('(', token)) { |
416 return parseFormalParameters(token); | 416 return parseFormalParameters(token); |
417 } else { | 417 } else { |
418 listener.handleNoFormalParameters(token); | 418 listener.handleNoFormalParameters(token); |
419 return token; | 419 return token; |
420 } | 420 } |
421 } | 421 } |
422 | 422 |
423 Token skipFormalParameters(Token token) { | 423 Token skipFormalParameters(Token token) { |
424 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 424 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
425 listener.beginOptionalFormalParameters(token); | 425 listener.beginOptionalFormalParameters(token); |
426 if (!optional('(', token)) { | 426 if (!optional('(', token)) { |
427 if (optional(';', token)) { | 427 if (optional(';', token)) { |
428 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); | 428 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); |
429 return token; | 429 return token; |
430 } | 430 } |
431 return reportUnrecoverableError( | 431 return reportUnrecoverableError( |
432 token, ErrorKind.ExpectedButGot, {"expected": "("}); | 432 token, ErrorKind.ExpectedButGot, {"expected": "("}); |
433 } | 433 } |
434 BeginGroupToken beginGroupToken = token; | 434 BeginGroupToken beginGroupToken = token; |
435 Token endToken = beginGroupToken.endGroup; | 435 Token endToken = beginGroupToken.endGroup; |
436 listener.endFormalParameters(0, token, endToken); | 436 listener.endFormalParameters(0, token, endToken); |
437 return endToken.next; | 437 return endToken.next; |
438 } | 438 } |
439 | 439 |
440 Token parseFormalParameters(Token token) { | 440 /// Parses the formal parameter list of a function. |
| 441 /// |
| 442 /// If [inFunctionType] is true, then the names may be omitted (except for |
| 443 /// named arguments). If it is false, then the types may be omitted. |
| 444 Token parseFormalParameters(Token token, {bool inFunctionType: false}) { |
441 Token begin = token; | 445 Token begin = token; |
442 listener.beginFormalParameters(begin); | 446 listener.beginFormalParameters(begin); |
443 expect('(', token); | 447 expect('(', token); |
444 int parameterCount = 0; | 448 int parameterCount = 0; |
445 do { | 449 do { |
446 token = token.next; | 450 token = token.next; |
447 if (optional(')', token)) { | 451 if (optional(')', token)) { |
448 break; | 452 break; |
449 } | 453 } |
450 ++parameterCount; | 454 ++parameterCount; |
451 String value = token.stringValue; | 455 String value = token.stringValue; |
452 if (identical(value, '[')) { | 456 if (identical(value, '[')) { |
453 token = parseOptionalFormalParameters(token, false); | 457 token = parseOptionalFormalParameters( |
| 458 token, false, inFunctionType: inFunctionType); |
454 break; | 459 break; |
455 } else if (identical(value, '{')) { | 460 } else if (identical(value, '{')) { |
456 token = parseOptionalFormalParameters(token, true); | 461 token = parseOptionalFormalParameters( |
| 462 token, true, inFunctionType: inFunctionType); |
457 break; | 463 break; |
458 } | 464 } |
459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); | 465 token = parseFormalParameter(token, FormalParameterType.REQUIRED, |
| 466 inFunctionType: inFunctionType); |
460 } while (optional(',', token)); | 467 } while (optional(',', token)); |
461 listener.endFormalParameters(parameterCount, begin, token); | 468 listener.endFormalParameters(parameterCount, begin, token); |
462 return expect(')', token); | 469 return expect(')', token); |
463 } | 470 } |
464 | 471 |
465 Token parseFormalParameter(Token token, FormalParameterType type) { | 472 Token parseFormalParameter(Token token, FormalParameterType type, |
| 473 {bool inFunctionType}) { |
466 token = parseMetadataStar(token, forParameter: true); | 474 token = parseMetadataStar(token, forParameter: true); |
467 listener.beginFormalParameter(token); | 475 listener.beginFormalParameter(token); |
468 | 476 |
469 // Skip over `covariant` token, if the next token is an identifier or | 477 // Skip over `covariant` token, if the next token is an identifier or |
470 // modifier. | 478 // modifier. |
471 // This enables the case where `covariant` is the name of the parameter: | 479 // This enables the case where `covariant` is the name of the parameter: |
472 // void foo(covariant); | 480 // void foo(covariant); |
473 if (identical(token.stringValue, 'covariant') && | 481 if (identical(token.stringValue, 'covariant') && |
474 (token.next.isIdentifier() || isModifier(token.next))) { | 482 (token.next.isIdentifier() || isModifier(token.next))) { |
475 token = token.next; | 483 token = token.next; |
476 } | 484 } |
477 token = parseModifiers(token); | 485 token = parseModifiers(token); |
478 // TODO(ahe): Validate that there are formal parameters if void. | 486 bool isNamedParameter = type == FormalParameterType.NAMED; |
479 token = parseReturnTypeOpt(token); | 487 |
480 Token thisKeyword = null; | 488 Token thisKeyword = null; |
481 if (optional('this', token)) { | 489 if (inFunctionType && isNamedParameter) { |
482 thisKeyword = token; | 490 token = parseType(token); |
483 // TODO(ahe): Validate field initializers are only used in | 491 token = parseIdentifier(token); |
484 // constructors, and not for function-typed arguments. | 492 } else if (inFunctionType) { |
485 token = expect('.', token.next); | 493 token = parseType(token); |
| 494 if (token.isIdentifier()) { |
| 495 token = parseIdentifier(token); |
| 496 } else { |
| 497 listener.handleNoName(token); |
| 498 } |
| 499 } else { |
| 500 token = parseTypeOpt(token); |
| 501 if (optional('this', token)) { |
| 502 thisKeyword = token; |
| 503 token = expect('.', token.next); |
| 504 } |
| 505 token = parseIdentifier(token); |
486 } | 506 } |
487 token = parseIdentifier(token); | 507 |
| 508 // Generalized function types don't allow inline function types. |
| 509 // The following isn't allowed: |
| 510 // int Function(int bar(String x)). |
488 if (optional('(', token)) { | 511 if (optional('(', token)) { |
| 512 Token inlineFunctionTypeStart = token; |
489 listener.beginFunctionTypedFormalParameter(token); | 513 listener.beginFunctionTypedFormalParameter(token); |
490 listener.handleNoTypeVariables(token); | 514 listener.handleNoTypeVariables(token); |
491 token = parseFormalParameters(token); | 515 token = parseFormalParameters(token); |
492 listener.endFunctionTypedFormalParameter(token); | 516 listener.endFunctionTypedFormalParameter(token); |
| 517 if (inFunctionType) { |
| 518 reportRecoverableError( |
| 519 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); |
| 520 } |
493 } else if (optional('<', token)) { | 521 } else if (optional('<', token)) { |
| 522 Token inlineFunctionTypeStart = token; |
494 listener.beginFunctionTypedFormalParameter(token); | 523 listener.beginFunctionTypedFormalParameter(token); |
495 token = parseTypeVariablesOpt(token); | 524 token = parseTypeVariablesOpt(token); |
496 token = parseFormalParameters(token); | 525 token = parseFormalParameters(token); |
497 listener.endFunctionTypedFormalParameter(token); | 526 listener.endFunctionTypedFormalParameter(token); |
| 527 if (inFunctionType) { |
| 528 reportRecoverableError( |
| 529 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); |
| 530 } |
498 } | 531 } |
499 String value = token.stringValue; | 532 String value = token.stringValue; |
500 if ((identical('=', value)) || (identical(':', value))) { | 533 if ((identical('=', value)) || (identical(':', value))) { |
501 // TODO(ahe): Validate that these are only used for optional parameters. | 534 // TODO(ahe): Validate that these are only used for optional parameters. |
502 Token equal = token; | 535 Token equal = token; |
503 token = parseExpression(token.next); | 536 token = parseExpression(token.next); |
504 listener.handleValuedFormalParameter(equal, token); | 537 listener.handleValuedFormalParameter(equal, token); |
505 if (type.isRequired) { | 538 if (type.isRequired) { |
506 reportRecoverableError( | 539 reportRecoverableError( |
507 equal, ErrorKind.RequiredParameterWithDefault); | 540 equal, ErrorKind.RequiredParameterWithDefault); |
508 } else if (type.isPositional && identical(':', value)) { | 541 } else if (type.isPositional && identical(':', value)) { |
509 reportRecoverableError( | 542 reportRecoverableError( |
510 equal, ErrorKind.PositionalParameterWithEquals); | 543 equal, ErrorKind.PositionalParameterWithEquals); |
511 } | 544 } |
512 } | 545 } |
513 listener.endFormalParameter(thisKeyword); | 546 listener.endFormalParameter(thisKeyword); |
514 return token; | 547 return token; |
515 } | 548 } |
516 | 549 |
517 Token parseOptionalFormalParameters(Token token, bool isNamed) { | 550 Token parseOptionalFormalParameters(Token token, bool isNamed, |
| 551 {bool inFunctionType}) { |
518 Token begin = token; | 552 Token begin = token; |
519 listener.beginOptionalFormalParameters(begin); | 553 listener.beginOptionalFormalParameters(begin); |
520 assert((isNamed && optional('{', token)) || optional('[', token)); | 554 assert((isNamed && optional('{', token)) || optional('[', token)); |
521 int parameterCount = 0; | 555 int parameterCount = 0; |
522 do { | 556 do { |
523 token = token.next; | 557 token = token.next; |
524 if (isNamed && optional('}', token)) { | 558 if (isNamed && optional('}', token)) { |
525 break; | 559 break; |
526 } else if (!isNamed && optional(']', token)) { | 560 } else if (!isNamed && optional(']', token)) { |
527 break; | 561 break; |
528 } | 562 } |
529 var type = | 563 var type = |
530 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 564 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
531 token = parseFormalParameter(token, type); | 565 token = |
| 566 parseFormalParameter(token, type, inFunctionType: inFunctionType); |
532 ++parameterCount; | 567 ++parameterCount; |
533 } while (optional(',', token)); | 568 } while (optional(',', token)); |
534 if (parameterCount == 0) { | 569 if (parameterCount == 0) { |
535 reportRecoverableError( | 570 reportRecoverableError( |
536 token, | 571 token, |
537 isNamed | 572 isNamed |
538 ? ErrorKind.EmptyNamedParameterList | 573 ? ErrorKind.EmptyNamedParameterList |
539 : ErrorKind.EmptyOptionalParameterList); | 574 : ErrorKind.EmptyOptionalParameterList); |
540 } | 575 } |
541 listener.endOptionalFormalParameters(parameterCount, begin, token); | 576 listener.endOptionalFormalParameters(parameterCount, begin, token); |
542 if (isNamed) { | 577 if (isNamed) { |
543 return expect('}', token); | 578 return expect('}', token); |
544 } else { | 579 } else { |
545 return expect(']', token); | 580 return expect(']', token); |
546 } | 581 } |
547 } | 582 } |
548 | 583 |
549 Token parseTypeOpt(Token token) { | 584 Token parseTypeOpt(Token token) { |
| 585 if (isGeneralizedFunctionType(token)) { |
| 586 // Function type without return type. |
| 587 return parseType(token); |
| 588 } |
550 Token peek = peekAfterIfType(token); | 589 Token peek = peekAfterIfType(token); |
551 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { | 590 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { |
552 return parseType(token); | 591 return parseType(token); |
553 } | 592 } |
554 listener.handleNoType(token); | 593 listener.handleNoType(token); |
555 return token; | 594 return token; |
556 } | 595 } |
557 | 596 |
558 bool isValidTypeReference(Token token) { | 597 bool isValidTypeReference(Token token) { |
559 final kind = token.kind; | 598 final kind = token.kind; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 } | 745 } |
707 | 746 |
708 Token parseClassOrNamedMixinApplication(Token token) { | 747 Token parseClassOrNamedMixinApplication(Token token) { |
709 Token begin = token; | 748 Token begin = token; |
710 Token abstractKeyword; | 749 Token abstractKeyword; |
711 if (optional('abstract', token)) { | 750 if (optional('abstract', token)) { |
712 abstractKeyword = token; | 751 abstractKeyword = token; |
713 token = token.next; | 752 token = token.next; |
714 } | 753 } |
715 Token classKeyword = token; | 754 Token classKeyword = token; |
716 var isMixinApplication = optional('=', peekAfterType(token.next)); | 755 var isMixinApplication = optional('=', peekAfterNominalType(token.next)); |
717 if (isMixinApplication) { | 756 if (isMixinApplication) { |
718 listener.beginNamedMixinApplication(begin); | 757 listener.beginNamedMixinApplication(begin); |
719 } else { | 758 } else { |
720 listener.beginClassDeclaration(begin); | 759 listener.beginClassDeclaration(begin); |
721 } | 760 } |
722 | 761 |
723 int modifierCount = 0; | 762 int modifierCount = 0; |
724 if (abstractKeyword != null) { | 763 if (abstractKeyword != null) { |
725 parseModifier(abstractKeyword); | 764 parseModifier(abstractKeyword); |
726 modifierCount++; | 765 modifierCount++; |
(...skipping 20 matching lines...) Expand all Loading... |
747 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); | 786 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); |
748 return expect(';', token); | 787 return expect(';', token); |
749 } | 788 } |
750 | 789 |
751 Token parseClass(Token begin, Token classKeyword) { | 790 Token parseClass(Token begin, Token classKeyword) { |
752 Token token = parseIdentifier(classKeyword.next); | 791 Token token = parseIdentifier(classKeyword.next); |
753 token = parseTypeVariablesOpt(token); | 792 token = parseTypeVariablesOpt(token); |
754 Token extendsKeyword; | 793 Token extendsKeyword; |
755 if (optional('extends', token)) { | 794 if (optional('extends', token)) { |
756 extendsKeyword = token; | 795 extendsKeyword = token; |
757 if (optional('with', peekAfterType(token.next))) { | 796 if (optional('with', peekAfterNominalType(token.next))) { |
758 token = parseMixinApplication(token.next); | 797 token = parseMixinApplication(token.next); |
759 } else { | 798 } else { |
760 token = parseType(token.next); | 799 token = parseType(token.next); |
761 } | 800 } |
762 } else { | 801 } else { |
763 extendsKeyword = null; | 802 extendsKeyword = null; |
764 listener.handleNoType(token); | 803 listener.handleNoType(token); |
765 } | 804 } |
766 Token implementsKeyword; | 805 Token implementsKeyword; |
767 int interfacesCount = 0; | 806 int interfacesCount = 0; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 value2 == stringValue || | 877 value2 == stringValue || |
839 value3 == stringValue || | 878 value3 == stringValue || |
840 value4 == stringValue; | 879 value4 == stringValue; |
841 } | 880 } |
842 | 881 |
843 bool notEofOrValue(String value, Token token) { | 882 bool notEofOrValue(String value, Token token) { |
844 return !identical(token.kind, EOF_TOKEN) && | 883 return !identical(token.kind, EOF_TOKEN) && |
845 !identical(value, token.stringValue); | 884 !identical(value, token.stringValue); |
846 } | 885 } |
847 | 886 |
| 887 bool isGeneralizedFunctionType(Token token) { |
| 888 return optional('Function', token) && |
| 889 (optional('<', token.next) || optional('(', token.next)); |
| 890 } |
| 891 |
848 Token parseType(Token token) { | 892 Token parseType(Token token) { |
849 Token begin = token; | 893 Token begin = token; |
850 if (isValidTypeReference(token)) { | 894 if (isGeneralizedFunctionType(token)) { |
851 token = parseIdentifier(token); | 895 // A function type without return type. |
852 token = parseQualifiedRestOpt(token); | 896 // Push the non-existing return type first. The loop below will |
| 897 // generate the full type. |
| 898 listener.handleNoType(token); |
853 } else { | 899 } else { |
854 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); | 900 if (isValidTypeReference(token)) { |
855 listener.handleInvalidTypeReference(token); | 901 token = parseIdentifier(token); |
| 902 token = parseQualifiedRestOpt(token); |
| 903 } else { |
| 904 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); |
| 905 listener.handleInvalidTypeReference(token); |
| 906 } |
| 907 token = parseTypeArgumentsOpt(token); |
| 908 listener.handleType(begin, token); |
856 } | 909 } |
857 token = parseTypeArgumentsOpt(token); | 910 |
858 listener.endType(begin, token); | 911 // While we see a `Function(` treat the pushed type as return type. |
| 912 // For example: `int Function() Function(int) Function(String x)`. |
| 913 while (isGeneralizedFunctionType(token)) { |
| 914 token = parseFunctionType(token); |
| 915 } |
859 return token; | 916 return token; |
860 } | 917 } |
861 | 918 |
| 919 /// Parses a generalized function type. |
| 920 /// |
| 921 /// The return type must already be pushed. |
| 922 Token parseFunctionType(Token token) { |
| 923 assert(optional('Function', token)); |
| 924 Token functionToken = token; |
| 925 token = token.next; |
| 926 token = parseTypeVariablesOpt(token); |
| 927 token = parseFormalParameters(token, inFunctionType: true); |
| 928 listener.handleFunctionType(functionToken, token); |
| 929 return token; |
| 930 } |
| 931 |
862 Token parseTypeArgumentsOpt(Token token) { | 932 Token parseTypeArgumentsOpt(Token token) { |
863 return parseStuff( | 933 return parseStuff( |
864 token, | 934 token, |
865 (t) => listener.beginTypeArguments(t), | 935 (t) => listener.beginTypeArguments(t), |
866 (t) => parseType(t), | 936 (t) => parseType(t), |
867 (c, bt, et) => listener.endTypeArguments(c, bt, et), | 937 (c, bt, et) => listener.endTypeArguments(c, bt, et), |
868 (t) => listener.handleNoTypeArguments(t)); | 938 (t) => listener.handleNoTypeArguments(t)); |
869 } | 939 } |
870 | 940 |
871 Token parseTypeVariablesOpt(Token token) { | 941 Token parseTypeVariablesOpt(Token token) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 | 1138 |
1069 if (getOrSet != null) { | 1139 if (getOrSet != null) { |
1070 var kind = (hasModifier || hasType) | 1140 var kind = (hasModifier || hasType) |
1071 ? ErrorKind.ExtraneousModifier | 1141 ? ErrorKind.ExtraneousModifier |
1072 : ErrorKind.ExtraneousModifierReplace; | 1142 : ErrorKind.ExtraneousModifierReplace; |
1073 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); | 1143 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); |
1074 } | 1144 } |
1075 | 1145 |
1076 if (!hasType) { | 1146 if (!hasType) { |
1077 listener.handleNoType(name); | 1147 listener.handleNoType(name); |
1078 } else if (optional('void', type)) { | |
1079 listener.handleNoType(name); | |
1080 // TODO(ahe): This error is reported twice, second time is from | |
1081 // [parseVariablesDeclarationMaybeSemicolon] via | |
1082 // [PartialFieldListElement.parseNode]. | |
1083 reportRecoverableError(type, ErrorKind.InvalidVoid); | |
1084 } else { | 1148 } else { |
1085 parseType(type); | 1149 parseType(type); |
1086 if (isVar) { | 1150 if (isVar) { |
1087 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, | 1151 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, |
1088 {'modifier': modifiers.head}); | 1152 {'modifier': modifiers.head}); |
1089 } | 1153 } |
1090 } | 1154 } |
1091 | 1155 |
1092 Token token = parseIdentifier(name); | 1156 Token token = parseIdentifier(name); |
1093 | 1157 |
(...skipping 30 matching lines...) Expand all Loading... |
1124 if (externalModifier != null) { | 1188 if (externalModifier != null) { |
1125 parseModifier(externalModifier); | 1189 parseModifier(externalModifier); |
1126 listener.handleModifiers(1); | 1190 listener.handleModifiers(1); |
1127 } else { | 1191 } else { |
1128 listener.handleModifiers(0); | 1192 listener.handleModifiers(0); |
1129 } | 1193 } |
1130 | 1194 |
1131 if (type == null) { | 1195 if (type == null) { |
1132 listener.handleNoType(name); | 1196 listener.handleNoType(name); |
1133 } else { | 1197 } else { |
1134 parseReturnTypeOpt(type); | 1198 parseTypeOpt(type); |
1135 } | 1199 } |
1136 Token token = parseIdentifier(name); | 1200 Token token = parseIdentifier(name); |
1137 | 1201 |
1138 if (getOrSet == null) { | 1202 if (getOrSet == null) { |
1139 token = parseTypeVariablesOpt(token); | 1203 token = parseTypeVariablesOpt(token); |
1140 } else { | 1204 } else { |
1141 listener.handleNoTypeVariables(token); | 1205 listener.handleNoTypeVariables(token); |
1142 } | 1206 } |
1143 token = parseFormalParametersOpt(token); | 1207 token = parseFormalParametersOpt(token); |
1144 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1208 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1203 return listener.handleMemberName(identifiers); | 1267 return listener.handleMemberName(identifiers); |
1204 } else if (optional("=", token) || optional(";", token) || | 1268 } else if (optional("=", token) || optional(";", token) || |
1205 optional(",", token)) { | 1269 optional(",", token)) { |
1206 // A field or abstract getter. | 1270 // A field or abstract getter. |
1207 identifiers = identifiers.prepend(token); | 1271 identifiers = identifiers.prepend(token); |
1208 return listener.handleMemberName(identifiers); | 1272 return listener.handleMemberName(identifiers); |
1209 } else if (isGetter) { | 1273 } else if (isGetter) { |
1210 hasName = true; | 1274 hasName = true; |
1211 } | 1275 } |
1212 identifiers = identifiers.prepend(token); | 1276 identifiers = identifiers.prepend(token); |
1213 if (isValidTypeReference(token)) { | 1277 |
1214 // type ... | 1278 if (!isGeneralizedFunctionType(token)) { |
1215 if (optional('.', token.next)) { | 1279 // Read a potential return type. |
1216 // type '.' ... | 1280 if (isValidTypeReference(token)) { |
1217 if (token.next.next.isIdentifier()) { | 1281 // type ... |
1218 // type '.' identifier | 1282 if (optional('.', token.next)) { |
1219 token = token.next.next; | 1283 // type '.' ... |
| 1284 if (token.next.next.isIdentifier()) { |
| 1285 // type '.' identifier |
| 1286 token = token.next.next; |
| 1287 } |
| 1288 } |
| 1289 if (optional('<', token.next)) { |
| 1290 if (token.next is BeginGroupToken) { |
| 1291 BeginGroupToken beginGroup = token.next; |
| 1292 if (beginGroup.endGroup == null) { |
| 1293 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); |
| 1294 } else { |
| 1295 token = beginGroup.endGroup; |
| 1296 } |
| 1297 } |
1220 } | 1298 } |
1221 } | 1299 } |
1222 if (optional('<', token.next)) { | 1300 token = token.next; |
1223 if (token.next is BeginGroupToken) { | 1301 } |
1224 BeginGroupToken beginGroup = token.next; | 1302 while (isGeneralizedFunctionType(token)) { |
| 1303 token = token.next; |
| 1304 if (optional('<', token)) { |
| 1305 if (token is BeginGroupToken) { |
| 1306 BeginGroupToken beginGroup = token; |
1225 if (beginGroup.endGroup == null) { | 1307 if (beginGroup.endGroup == null) { |
1226 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | 1308 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); |
1227 } else { | 1309 } else { |
1228 token = beginGroup.endGroup; | 1310 token = beginGroup.endGroup.next; |
1229 } | 1311 } |
1230 } | 1312 } |
1231 } | 1313 } |
| 1314 if (!optional('(', token)) { |
| 1315 if (optional(';', token)) { |
| 1316 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); |
| 1317 } |
| 1318 token = expect("(", token); |
| 1319 } |
| 1320 if (token is BeginGroupToken) { |
| 1321 BeginGroupToken beginGroup = token; |
| 1322 if (beginGroup.endGroup == null) { |
| 1323 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); |
| 1324 } else { |
| 1325 token = beginGroup.endGroup.next; |
| 1326 } |
| 1327 } |
1232 } | 1328 } |
1233 token = token.next; | |
1234 } | 1329 } |
1235 return listener.handleMemberName(const Link<Token>()); | 1330 return listener.handleMemberName(const Link<Token>()); |
1236 } | 1331 } |
1237 | 1332 |
1238 Token parseFieldInitializerOpt(Token token) { | 1333 Token parseFieldInitializerOpt(Token token) { |
1239 if (optional('=', token)) { | 1334 if (optional('=', token)) { |
1240 Token assignment = token; | 1335 Token assignment = token; |
1241 listener.beginFieldInitializer(token); | 1336 listener.beginFieldInitializer(token); |
1242 token = parseExpression(token.next); | 1337 token = parseExpression(token.next); |
1243 listener.endFieldInitializer(assignment); | 1338 listener.endFieldInitializer(assignment); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 if (!isModifier(token)) break; | 1431 if (!isModifier(token)) break; |
1337 token = parseModifier(token); | 1432 token = parseModifier(token); |
1338 count++; | 1433 count++; |
1339 } | 1434 } |
1340 listener.handleModifiers(count); | 1435 listener.handleModifiers(count); |
1341 return token; | 1436 return token; |
1342 } | 1437 } |
1343 | 1438 |
1344 /** | 1439 /** |
1345 * Returns the first token after the type starting at [token]. | 1440 * Returns the first token after the type starting at [token]. |
| 1441 * |
1346 * This method assumes that [token] is an identifier (or void). | 1442 * This method assumes that [token] is an identifier (or void). |
1347 * Use [peekAfterIfType] if [token] isn't known to be an identifier. | 1443 * Use [peekAfterIfType] if [token] isn't known to be an identifier. |
1348 */ | 1444 */ |
1349 Token peekAfterType(Token token) { | 1445 Token peekAfterType(Token token) { |
1350 // We are looking at "identifier ...". | 1446 // We are looking at "identifier ...". |
| 1447 Token peek = token; |
| 1448 if (!isGeneralizedFunctionType(token)) { |
| 1449 peek = peekAfterNominalType(token); |
| 1450 } |
| 1451 |
| 1452 // We might have just skipped over the return value of the function type. |
| 1453 // Check again, if we are now at a function type position. |
| 1454 while (isGeneralizedFunctionType(peek)) { |
| 1455 peek = peekAfterFunctionType(peek.next); |
| 1456 } |
| 1457 return peek; |
| 1458 } |
| 1459 |
| 1460 /** |
| 1461 * Returns the first token after the nominal type starting at [token]. |
| 1462 * |
| 1463 * This method assumes that [token] is an identifier (or void). |
| 1464 */ |
| 1465 Token peekAfterNominalType(Token token) { |
1351 Token peek = token.next; | 1466 Token peek = token.next; |
1352 if (identical(peek.kind, PERIOD_TOKEN)) { | 1467 if (identical(peek.kind, PERIOD_TOKEN)) { |
1353 if (peek.next.isIdentifier()) { | 1468 if (peek.next.isIdentifier()) { |
1354 // Look past a library prefix. | 1469 // Look past a library prefix. |
1355 peek = peek.next.next; | 1470 peek = peek.next.next; |
1356 } | 1471 } |
1357 } | 1472 } |
1358 // We are looking at "qualified ...". | 1473 // We are looking at "qualified ...". |
1359 if (identical(peek.kind, LT_TOKEN)) { | 1474 if (identical(peek.kind, LT_TOKEN)) { |
1360 // Possibly generic type. | 1475 // Possibly generic type. |
1361 // We are looking at "qualified '<'". | 1476 // We are looking at "qualified '<'". |
1362 BeginGroupToken beginGroupToken = peek; | 1477 BeginGroupToken beginGroupToken = peek; |
1363 Token gtToken = beginGroupToken.endGroup; | 1478 Token gtToken = beginGroupToken.endGroup; |
1364 if (gtToken != null) { | 1479 if (gtToken != null) { |
1365 // We are looking at "qualified '<' ... '>' ...". | 1480 // We are looking at "qualified '<' ... '>' ...". |
1366 return gtToken.next; | 1481 peek = gtToken.next; |
1367 } | 1482 } |
1368 } | 1483 } |
1369 return peek; | 1484 return peek; |
1370 } | 1485 } |
1371 | 1486 |
1372 /** | 1487 /** |
| 1488 * Returns the first token after the function type starting at [token]. |
| 1489 * |
| 1490 * The token must be at the token *after* the `Function` token position. That |
| 1491 * is, the return type and the `Function` token must have already been |
| 1492 * skipped. |
| 1493 * |
| 1494 * This function only skips over one function type syntax. |
| 1495 * If necessary, this function must be called multiple times. |
| 1496 * |
| 1497 * Example: |
| 1498 * ``` |
| 1499 * int Function() Function<T>(int) |
| 1500 * ^ ^ |
| 1501 * A call to this function must be either at `(` or at `<`. |
| 1502 * If `token` pointed to the first `(`, then the returned |
| 1503 * token points to the second `Function` token. |
| 1504 */ |
| 1505 Token peekAfterFunctionType(Token token) { |
| 1506 // Possible inputs are: |
| 1507 // ( ... ) |
| 1508 // < ... >( ... ) |
| 1509 |
| 1510 Token peek = token; |
| 1511 // If there is a generic argument to the function, skip over that one first. |
| 1512 if (identical(peek.kind, LT_TOKEN)) { |
| 1513 BeginGroupToken beginGroupToken = peek; |
| 1514 Token closeToken = beginGroupToken.endGroup; |
| 1515 if (closeToken != null) { |
| 1516 peek = closeToken.next; |
| 1517 } |
| 1518 } |
| 1519 |
| 1520 // Now we just need to skip over the formals. |
| 1521 expect('(', peek); |
| 1522 |
| 1523 BeginGroupToken beginGroupToken = peek; |
| 1524 Token closeToken = beginGroupToken.endGroup; |
| 1525 if (closeToken != null) { |
| 1526 peek = closeToken.next; |
| 1527 } |
| 1528 |
| 1529 return peek; |
| 1530 } |
| 1531 |
| 1532 /** |
1373 * If [token] is the start of a type, returns the token after that type. | 1533 * If [token] is the start of a type, returns the token after that type. |
1374 * If [token] is not the start of a type, null is returned. | 1534 * If [token] is not the start of a type, null is returned. |
1375 */ | 1535 */ |
1376 Token peekAfterIfType(Token token) { | 1536 Token peekAfterIfType(Token token) { |
1377 if (!optional('void', token) && !token.isIdentifier()) { | 1537 if (!token.isIdentifier()) { |
1378 return null; | 1538 return null; |
1379 } | 1539 } |
1380 return peekAfterType(token); | 1540 return peekAfterType(token); |
1381 } | 1541 } |
1382 | 1542 |
1383 Token skipClassBody(Token token) { | 1543 Token skipClassBody(Token token) { |
1384 if (!optional('{', token)) { | 1544 if (!optional('{', token)) { |
1385 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); | 1545 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); |
1386 } | 1546 } |
1387 BeginGroupToken beginGroupToken = token; | 1547 BeginGroupToken beginGroupToken = token; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1552 } | 1712 } |
1553 if (getOrSet != null && constModifier != null) { | 1713 if (getOrSet != null && constModifier != null) { |
1554 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, | 1714 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, |
1555 {'modifier': constModifier}); | 1715 {'modifier': constModifier}); |
1556 } | 1716 } |
1557 parseModifierList(modifiers); | 1717 parseModifierList(modifiers); |
1558 | 1718 |
1559 if (type == null) { | 1719 if (type == null) { |
1560 listener.handleNoType(name); | 1720 listener.handleNoType(name); |
1561 } else { | 1721 } else { |
1562 parseReturnTypeOpt(type); | 1722 parseTypeOpt(type); |
1563 } | 1723 } |
1564 Token token; | 1724 Token token; |
1565 if (optional('operator', name)) { | 1725 if (optional('operator', name)) { |
1566 token = parseOperatorName(name); | 1726 token = parseOperatorName(name); |
1567 if (staticModifier != null) { | 1727 if (staticModifier != null) { |
1568 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, | 1728 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, |
1569 {'modifier': staticModifier}); | 1729 {'modifier': staticModifier}); |
1570 } | 1730 } |
1571 } else { | 1731 } else { |
1572 token = parseIdentifier(name); | 1732 token = parseIdentifier(name); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1644 } else { | 1804 } else { |
1645 token = parseIdentifier(token); | 1805 token = parseIdentifier(token); |
1646 } | 1806 } |
1647 } else if (optional('operator', token)) { | 1807 } else if (optional('operator', token)) { |
1648 // operator <op> (... | 1808 // operator <op> (... |
1649 listener.handleNoType(token); | 1809 listener.handleNoType(token); |
1650 listener.beginFunctionName(token); | 1810 listener.beginFunctionName(token); |
1651 token = parseOperatorName(token); | 1811 token = parseOperatorName(token); |
1652 } else { | 1812 } else { |
1653 // <type>? <get>? <name> | 1813 // <type>? <get>? <name> |
1654 token = parseReturnTypeOpt(token); | 1814 token = parseTypeOpt(token); |
1655 if (identical(getOrSet, token)) { | 1815 if (identical(getOrSet, token)) { |
1656 token = token.next; | 1816 token = token.next; |
1657 } | 1817 } |
1658 listener.beginFunctionName(token); | 1818 listener.beginFunctionName(token); |
1659 if (optional('operator', token)) { | 1819 if (optional('operator', token)) { |
1660 token = parseOperatorName(token); | 1820 token = parseOperatorName(token); |
1661 } else { | 1821 } else { |
1662 token = parseIdentifier(token); | 1822 token = parseIdentifier(token); |
1663 } | 1823 } |
1664 } | 1824 } |
(...skipping 29 matching lines...) Expand all Loading... |
1694 Token parseFunctionDeclaration(Token token) { | 1854 Token parseFunctionDeclaration(Token token) { |
1695 listener.beginFunctionDeclaration(token); | 1855 listener.beginFunctionDeclaration(token); |
1696 token = parseFunction(token, null); | 1856 token = parseFunction(token, null); |
1697 listener.endFunctionDeclaration(token); | 1857 listener.endFunctionDeclaration(token); |
1698 return token; | 1858 return token; |
1699 } | 1859 } |
1700 | 1860 |
1701 Token parseFunctionExpression(Token token) { | 1861 Token parseFunctionExpression(Token token) { |
1702 listener.beginFunction(token); | 1862 listener.beginFunction(token); |
1703 listener.handleModifiers(0); | 1863 listener.handleModifiers(0); |
1704 token = parseReturnTypeOpt(token); | 1864 token = parseTypeOpt(token); |
1705 listener.beginFunctionName(token); | 1865 listener.beginFunctionName(token); |
1706 token = parseIdentifier(token); | 1866 token = parseIdentifier(token); |
1707 listener.endFunctionName(token); | 1867 listener.endFunctionName(token); |
1708 token = parseTypeVariablesOpt(token); | 1868 token = parseTypeVariablesOpt(token); |
1709 token = parseFormalParameters(token); | 1869 token = parseFormalParameters(token); |
1710 listener.handleNoInitializers(); | 1870 listener.handleNoInitializers(); |
1711 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1871 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
1712 token = parseAsyncModifier(token); | 1872 token = parseAsyncModifier(token); |
1713 bool isBlock = optional('{', token); | 1873 bool isBlock = optional('{', token); |
1714 token = parseFunctionBody(token, true, false); | 1874 token = parseFunctionBody(token, true, false); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 } else { | 2055 } else { |
1896 return parseExpressionStatement(token); | 2056 return parseExpressionStatement(token); |
1897 } | 2057 } |
1898 } else if (identical(value, 'for')) { | 2058 } else if (identical(value, 'for')) { |
1899 return parseForStatement(null, token); | 2059 return parseForStatement(null, token); |
1900 } else if (identical(value, 'rethrow')) { | 2060 } else if (identical(value, 'rethrow')) { |
1901 return parseRethrowStatement(token); | 2061 return parseRethrowStatement(token); |
1902 } else if (identical(value, 'throw') && optional(';', token.next)) { | 2062 } else if (identical(value, 'throw') && optional(';', token.next)) { |
1903 // TODO(kasperl): Stop dealing with throw here. | 2063 // TODO(kasperl): Stop dealing with throw here. |
1904 return parseRethrowStatement(token); | 2064 return parseRethrowStatement(token); |
1905 } else if (identical(value, 'void')) { | |
1906 return parseExpressionStatementOrDeclaration(token); | |
1907 } else if (identical(value, 'while')) { | 2065 } else if (identical(value, 'while')) { |
1908 return parseWhileStatement(token); | 2066 return parseWhileStatement(token); |
1909 } else if (identical(value, 'do')) { | 2067 } else if (identical(value, 'do')) { |
1910 return parseDoWhileStatement(token); | 2068 return parseDoWhileStatement(token); |
1911 } else if (identical(value, 'try')) { | 2069 } else if (identical(value, 'try')) { |
1912 return parseTryStatement(token); | 2070 return parseTryStatement(token); |
1913 } else if (identical(value, 'switch')) { | 2071 } else if (identical(value, 'switch')) { |
1914 return parseSwitchStatement(token); | 2072 return parseSwitchStatement(token); |
1915 } else if (identical(value, 'break')) { | 2073 } else if (identical(value, 'break')) { |
1916 return parseBreakStatement(token); | 2074 return parseBreakStatement(token); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 return peek; | 2135 return peek; |
1978 } else if (token.isIdentifier()) { | 2136 } else if (token.isIdentifier()) { |
1979 // We are looking at "identifier". | 2137 // We are looking at "identifier". |
1980 return token; | 2138 return token; |
1981 } else { | 2139 } else { |
1982 return null; | 2140 return null; |
1983 } | 2141 } |
1984 } | 2142 } |
1985 | 2143 |
1986 Token parseExpressionStatementOrDeclaration(Token token) { | 2144 Token parseExpressionStatementOrDeclaration(Token token) { |
1987 assert(token.isIdentifier() || identical(token.stringValue, 'void')); | 2145 assert(token.isIdentifier()); |
1988 Token identifier = peekIdentifierAfterType(token); | 2146 Token identifier = peekIdentifierAfterType(token); |
1989 if (identifier != null) { | 2147 if (identifier != null) { |
1990 assert(identifier.isIdentifier()); | 2148 assert(identifier.isIdentifier()); |
1991 Token afterId = identifier.next; | 2149 Token afterId = identifier.next; |
1992 int afterIdKind = afterId.kind; | 2150 int afterIdKind = afterId.kind; |
1993 if (identical(afterIdKind, EQ_TOKEN) || | 2151 if (identical(afterIdKind, EQ_TOKEN) || |
1994 identical(afterIdKind, SEMICOLON_TOKEN) || | 2152 identical(afterIdKind, SEMICOLON_TOKEN) || |
1995 identical(afterIdKind, COMMA_TOKEN)) { | 2153 identical(afterIdKind, COMMA_TOKEN)) { |
1996 // We are looking at "type identifier" followed by '=', ';', ','. | 2154 // We are looking at "type identifier" followed by '=', ';', ','. |
1997 return parseVariablesDeclaration(token); | 2155 return parseVariablesDeclaration(token); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2389 } else if (value == 'null') { | 2547 } else if (value == 'null') { |
2390 return parseLiteralNull(token); | 2548 return parseLiteralNull(token); |
2391 } else if (value == 'this') { | 2549 } else if (value == 'this') { |
2392 return parseThisExpression(token); | 2550 return parseThisExpression(token); |
2393 } else if (value == 'super') { | 2551 } else if (value == 'super') { |
2394 return parseSuperExpression(token); | 2552 return parseSuperExpression(token); |
2395 } else if (value == 'new') { | 2553 } else if (value == 'new') { |
2396 return parseNewExpression(token); | 2554 return parseNewExpression(token); |
2397 } else if (value == 'const') { | 2555 } else if (value == 'const') { |
2398 return parseConstExpression(token); | 2556 return parseConstExpression(token); |
2399 } else if (value == 'void') { | |
2400 return parseFunctionExpression(token); | |
2401 } else if (asyncAwaitKeywordsEnabled && | 2557 } else if (asyncAwaitKeywordsEnabled && |
2402 (value == 'yield' || value == 'async')) { | 2558 (value == 'yield' || value == 'async')) { |
2403 return expressionExpected(token); | 2559 return expressionExpected(token); |
2404 } else if (token.isIdentifier()) { | 2560 } else if (token.isIdentifier()) { |
2405 return parseSendOrFunctionLiteral(token); | 2561 return parseSendOrFunctionLiteral(token); |
2406 } else { | 2562 } else { |
2407 return expressionExpected(token); | 2563 return expressionExpected(token); |
2408 } | 2564 } |
2409 } else if (kind == OPEN_PAREN_TOKEN) { | 2565 } else if (kind == OPEN_PAREN_TOKEN) { |
2410 return parseParenthesizedExpressionOrFunctionLiteral(token); | 2566 return parseParenthesizedExpressionOrFunctionLiteral(token); |
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 break; | 3468 break; |
3313 } | 3469 } |
3314 if (isRecoverable) { | 3470 if (isRecoverable) { |
3315 listener.handleRecoverableError(token, kind, arguments); | 3471 listener.handleRecoverableError(token, kind, arguments); |
3316 return null; | 3472 return null; |
3317 } else { | 3473 } else { |
3318 return listener.handleUnrecoverableError(token, kind, arguments); | 3474 return listener.handleUnrecoverableError(token, kind, arguments); |
3319 } | 3475 } |
3320 } | 3476 } |
3321 } | 3477 } |
OLD | NEW |