| 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 /** | 5 /** |
| 6 * An event generating parser of Dart programs. This parser expects | 6 * An event generating parser of Dart programs. This parser expects |
| 7 * all tokens in a linked list (aka a token stream). | 7 * all tokens in a linked list (aka a token stream). |
| 8 * | 8 * |
| 9 * The class [Scanner] is used to generate a token stream. See the | 9 * The class [Scanner] is used to generate a token stream. See the |
| 10 * file scanner.dart. | 10 * file scanner.dart. |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 listener.endOptionalFormalParameters(parameterCount, begin, token); | 197 listener.endOptionalFormalParameters(parameterCount, begin, token); |
| 198 if (isNamed) { | 198 if (isNamed) { |
| 199 return expect('}', token); | 199 return expect('}', token); |
| 200 } else { | 200 } else { |
| 201 return expect(']', token); | 201 return expect(']', token); |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 | 204 |
| 205 Token parseTypeOpt(Token token) { | 205 Token parseTypeOpt(Token token) { |
| 206 String value = token.stringValue; | 206 String value = token.stringValue; |
| 207 if (value === 'var') return parseType(token); | |
| 208 if (value !== 'this') { | 207 if (value !== 'this') { |
| 209 Token peek = peekAfterExpectedType(token); | 208 Token peek = peekAfterExpectedType(token); |
| 210 if (peek.isIdentifier() || optional('this', peek)) { | 209 if (peek.isIdentifier() || optional('this', peek)) { |
| 211 return parseType(token); | 210 return parseType(token); |
| 212 } | 211 } |
| 213 } | 212 } |
| 214 listener.handleNoType(token); | 213 listener.handleNoType(token); |
| 215 return token; | 214 return token; |
| 216 } | 215 } |
| 217 | 216 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 endStuff(count, begin, token); | 400 endStuff(count, begin, token); |
| 402 return expect('>', token); | 401 return expect('>', token); |
| 403 } | 402 } |
| 404 handleNoStuff(token); | 403 handleNoStuff(token); |
| 405 return token; | 404 return token; |
| 406 } | 405 } |
| 407 | 406 |
| 408 Token parseTopLevelMember(Token token) { | 407 Token parseTopLevelMember(Token token) { |
| 409 Token start = token; | 408 Token start = token; |
| 410 listener.beginTopLevelMember(token); | 409 listener.beginTopLevelMember(token); |
| 411 token = parseModifiers(token); | 410 |
| 412 Token getOrSet = findGetOrSet(token); | 411 Link<Token> identifiers = findMemberName(token); |
| 413 if (token === getOrSet) token = token.next; | 412 if (identifiers.isEmpty()) { |
| 414 Token peek = peekAfterExpectedType(token); | 413 return listener.unexpected(start); |
| 415 if (peek.isIdentifier()) { | |
| 416 // Skip type. | |
| 417 token = peek; | |
| 418 } | 414 } |
| 419 if (token === getOrSet) token = token.next; | 415 Token name = identifiers.head; |
| 420 token = parseIdentifier(token); | 416 identifiers = identifiers.tail; |
| 417 Token getOrSet; |
| 418 if (!identifiers.isEmpty()) { |
| 419 String value = identifiers.head.stringValue; |
| 420 if ((value === 'get') || (value === 'set')) { |
| 421 getOrSet = identifiers.head; |
| 422 identifiers = identifiers.tail; |
| 423 } |
| 424 } |
| 425 Token type; |
| 426 if (!identifiers.isEmpty()) { |
| 427 if (isValidTypeReference(identifiers.head)) { |
| 428 type = identifiers.head; |
| 429 identifiers = identifiers.tail; |
| 430 } |
| 431 } |
| 432 parseModifierList(identifiers.reverse()); |
| 433 if (type === null) { |
| 434 listener.handleNoType(token); |
| 435 } else { |
| 436 parseReturnTypeOpt(type); |
| 437 } |
| 438 token = parseIdentifier(name); |
| 439 |
| 421 bool isField; | 440 bool isField; |
| 422 while (true) { | 441 while (true) { |
| 423 // Loop to allow the listener to rewrite the token stream for | 442 // Loop to allow the listener to rewrite the token stream for |
| 424 // error handling. | 443 // error handling. |
| 425 final String value = token.stringValue; | 444 final String value = token.stringValue; |
| 426 if ((value === '(') || (value === '{') || (value === '=>')) { | 445 if ((value === '(') || (value === '{') || (value === '=>')) { |
| 427 isField = false; | 446 isField = false; |
| 428 break; | 447 break; |
| 429 } else if ((value === '=') || (value === ';') || (value === ',')) { | 448 } else if ((value === '=') || (value === ';') || (value === ',')) { |
| 430 isField = true; | 449 isField = true; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 450 expectSemicolon(token); | 469 expectSemicolon(token); |
| 451 listener.endTopLevelFields(fieldCount, start, token); | 470 listener.endTopLevelFields(fieldCount, start, token); |
| 452 } else { | 471 } else { |
| 453 token = parseFormalParametersOpt(token); | 472 token = parseFormalParametersOpt(token); |
| 454 token = parseFunctionBody(token, false); | 473 token = parseFunctionBody(token, false); |
| 455 listener.endTopLevelMethod(start, getOrSet, token); | 474 listener.endTopLevelMethod(start, getOrSet, token); |
| 456 } | 475 } |
| 457 return token.next; | 476 return token.next; |
| 458 } | 477 } |
| 459 | 478 |
| 479 Link<Token> findMemberName(Token token) { |
| 480 Link<Token> identifiers = const EmptyLink<Token>(); |
| 481 while (token.kind !== EOF_TOKEN) { |
| 482 String value = token.stringValue; |
| 483 if ((value === '(') || (value === '{') || (value === '=>')) { |
| 484 // A method. |
| 485 return identifiers; |
| 486 } else if ((value === '=') || (value === ';') || (value === ',')) { |
| 487 // A field or abstract getter. |
| 488 return identifiers; |
| 489 } |
| 490 identifiers = identifiers.prepend(token); |
| 491 if (isValidTypeReference(token)) { |
| 492 // type ... |
| 493 if (optional('.', token.next)) { |
| 494 // type '.' ... |
| 495 if (token.next.next.isIdentifier()) { |
| 496 // type '.' identifier |
| 497 token = token.next.next; |
| 498 } |
| 499 } |
| 500 if (optional('<', token.next)) { |
| 501 if (token.next is BeginGroupToken) { |
| 502 BeginGroupToken beginGroup = token.next; |
| 503 token = beginGroup.endGroup; |
| 504 } |
| 505 } |
| 506 } |
| 507 token = token.next; |
| 508 } |
| 509 return listener.unexpected(token); |
| 510 } |
| 511 |
| 460 Token parseVariableInitializerOpt(Token token) { | 512 Token parseVariableInitializerOpt(Token token) { |
| 461 if (optional('=', token)) { | 513 if (optional('=', token)) { |
| 462 Token assignment = token; | 514 Token assignment = token; |
| 463 listener.beginInitializer(token); | 515 listener.beginInitializer(token); |
| 464 token = parseExpression(token.next); | 516 token = parseExpression(token.next); |
| 465 listener.endInitializer(assignment); | 517 listener.endInitializer(assignment); |
| 466 } | 518 } |
| 467 return token; | 519 return token; |
| 468 } | 520 } |
| 469 | 521 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 ('static' === value) || | 584 ('static' === value) || |
| 533 ('external' === value); | 585 ('external' === value); |
| 534 } | 586 } |
| 535 | 587 |
| 536 Token parseModifier(Token token) { | 588 Token parseModifier(Token token) { |
| 537 assert(isModifier(token)); | 589 assert(isModifier(token)); |
| 538 listener.handleModifier(token); | 590 listener.handleModifier(token); |
| 539 return token.next; | 591 return token.next; |
| 540 } | 592 } |
| 541 | 593 |
| 594 void parseModifierList(Link<Token> tokens) { |
| 595 int count = 0; |
| 596 for (; !tokens.isEmpty(); tokens = tokens.tail) { |
| 597 Token token = tokens.head; |
| 598 if (isModifier(token)) { |
| 599 parseModifier(token); |
| 600 } else { |
| 601 listener.unexpected(token); |
| 602 } |
| 603 count++; |
| 604 } |
| 605 listener.handleModifiers(count); |
| 606 } |
| 607 |
| 542 Token parseModifiers(Token token) { | 608 Token parseModifiers(Token token) { |
| 543 int count = 0; | 609 int count = 0; |
| 544 while (token.kind === KEYWORD_TOKEN) { | 610 while (token.kind === KEYWORD_TOKEN) { |
| 545 if (!isModifier(token)) | 611 if (!isModifier(token)) |
| 546 break; | 612 break; |
| 547 token = parseModifier(token); | 613 token = parseModifier(token); |
| 548 count++; | 614 count++; |
| 549 } | 615 } |
| 550 listener.handleModifiers(count); | 616 listener.handleModifiers(count); |
| 551 return token; | 617 return token; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 666 } |
| 601 listener.endClassBody(count, begin, token); | 667 listener.endClassBody(count, begin, token); |
| 602 return token; | 668 return token; |
| 603 } | 669 } |
| 604 | 670 |
| 605 bool isGetOrSet(Token token) { | 671 bool isGetOrSet(Token token) { |
| 606 final String value = token.stringValue; | 672 final String value = token.stringValue; |
| 607 return (value === 'get') || (value === 'set'); | 673 return (value === 'get') || (value === 'set'); |
| 608 } | 674 } |
| 609 | 675 |
| 610 Token findGetOrSet(Token token) { | |
| 611 if (isGetOrSet(token)) { | |
| 612 if (optional('<', token.next)) { | |
| 613 // For example: get<T> ... | |
| 614 final Token peek = peekAfterExpectedType(token); | |
| 615 if (isGetOrSet(peek) && peek.next.isIdentifier()) { | |
| 616 // For example: get<T> get identifier | |
| 617 return peek; | |
| 618 } | |
| 619 } else { | |
| 620 // For example: get ... | |
| 621 if (isGetOrSet(token.next) && token.next.next.isIdentifier()) { | |
| 622 // For example: get get identifier | |
| 623 return token.next; | |
| 624 } else { | |
| 625 // For example: get identifier | |
| 626 return token; | |
| 627 } | |
| 628 } | |
| 629 } else if (token.stringValue !== 'operator') { | |
| 630 final Token peek = peekAfterExpectedType(token); | |
| 631 if (isGetOrSet(peek) && peek.next.isIdentifier()) { | |
| 632 // type? get identifier | |
| 633 return peek; | |
| 634 } | |
| 635 } | |
| 636 return null; | |
| 637 } | |
| 638 | |
| 639 Token parseMember(Token token) { | 676 Token parseMember(Token token) { |
| 640 token = parseMetadataStar(token); | 677 token = parseMetadataStar(token); |
| 641 String value = token.stringValue; | 678 String value = token.stringValue; |
| 642 if (value === 'factory' || | 679 if (value === 'factory' || |
| 643 (value === 'external' && optional('factory', token.next))) { | 680 (value === 'external' && optional('factory', token.next))) { |
| 644 return parseFactoryMethod(token); | 681 return parseFactoryMethod(token); |
| 645 } | 682 } |
| 646 Token start = token; | 683 Token start = token; |
| 647 listener.beginMember(token); | 684 listener.beginMember(token); |
| 648 token = parseModifiers(token); | 685 |
| 649 Token getOrSet = findGetOrSet(token); | 686 Link<Token> identifiers = findMemberName(token); |
| 650 if (token === getOrSet) token = token.next; | 687 if (identifiers.isEmpty()) { |
| 651 Token peek = peekAfterExpectedType(token); | 688 return listener.unexpected(start); |
| 652 if (peek.isIdentifier() && token.stringValue !== 'operator') { | |
| 653 // Skip type. | |
| 654 token = peek; | |
| 655 } | 689 } |
| 656 if (token === getOrSet) token = token.next; | 690 Token name = identifiers.head; |
| 657 if (optional('operator', token)) { | 691 identifiers = identifiers.tail; |
| 658 token = parseOperatorName(token); | 692 if (!identifiers.isEmpty()) { |
| 693 if (optional('operator', identifiers.head)) { |
| 694 name = identifiers.head; |
| 695 identifiers = identifiers.tail; |
| 696 } |
| 697 } |
| 698 Token getOrSet; |
| 699 if (!identifiers.isEmpty()) { |
| 700 if (isGetOrSet(identifiers.head)) { |
| 701 getOrSet = identifiers.head; |
| 702 identifiers = identifiers.tail; |
| 703 } |
| 704 } |
| 705 Token type; |
| 706 if (!identifiers.isEmpty()) { |
| 707 if (isValidTypeReference(identifiers.head)) { |
| 708 type = identifiers.head; |
| 709 identifiers = identifiers.tail; |
| 710 } |
| 711 } |
| 712 parseModifierList(identifiers.reverse()); |
| 713 if (type === null) { |
| 714 listener.handleNoType(token); |
| 659 } else { | 715 } else { |
| 660 token = parseIdentifier(token); | 716 parseReturnTypeOpt(type); |
| 717 } |
| 718 |
| 719 if (optional('operator', name)) { |
| 720 token = parseOperatorName(name); |
| 721 } else { |
| 722 token = parseIdentifier(name); |
| 661 } | 723 } |
| 662 bool isField; | 724 bool isField; |
| 663 while (true) { | 725 while (true) { |
| 664 // Loop to allow the listener to rewrite the token stream for | 726 // Loop to allow the listener to rewrite the token stream for |
| 665 // error handling. | 727 // error handling. |
| 666 final String value = token.stringValue; | 728 final String value = token.stringValue; |
| 667 if ((value === '(') || (value === '.') || (value === '{') || | 729 if ((value === '(') || (value === '.') || (value === '{') || |
| 668 (value === '=>')) { | 730 (value === '=>')) { |
| 669 isField = false; | 731 isField = false; |
| 670 break; | 732 break; |
| (...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 } | 1926 } |
| 1865 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 1927 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 1866 return expectSemicolon(token); | 1928 return expectSemicolon(token); |
| 1867 } | 1929 } |
| 1868 | 1930 |
| 1869 Token parseEmptyStatement(Token token) { | 1931 Token parseEmptyStatement(Token token) { |
| 1870 listener.handleEmptyStatement(token); | 1932 listener.handleEmptyStatement(token); |
| 1871 return expectSemicolon(token); | 1933 return expectSemicolon(token); |
| 1872 } | 1934 } |
| 1873 } | 1935 } |
| OLD | NEW |