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

Side by Side Diff: dart/lib/compiler/implementation/scanner/parser.dart

Issue 10913153: Parse methods named 'get' or 'set' (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Store type annotations Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 listener.endOptionalFormalParameters(parameterCount, begin, token); 278 listener.endOptionalFormalParameters(parameterCount, begin, token);
279 if (isNamed) { 279 if (isNamed) {
280 return expect('}', token); 280 return expect('}', token);
281 } else { 281 } else {
282 return expect(']', token); 282 return expect(']', token);
283 } 283 }
284 } 284 }
285 285
286 Token parseTypeOpt(Token token) { 286 Token parseTypeOpt(Token token) {
287 String value = token.stringValue; 287 String value = token.stringValue;
288 if (value === 'var') return parseType(token);
289 if (value !== 'this') { 288 if (value !== 'this') {
290 Token peek = peekAfterExpectedType(token); 289 Token peek = peekAfterExpectedType(token);
291 if (isIdentifier(peek) || optional('this', peek)) { 290 if (isIdentifier(peek) || optional('this', peek)) {
292 return parseType(token); 291 return parseType(token);
293 } 292 }
294 } 293 }
295 listener.handleNoType(token); 294 listener.handleNoType(token);
296 return token; 295 return token;
297 } 296 }
298 297
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 endStuff(count, begin, token); 498 endStuff(count, begin, token);
500 return expect('>', token); 499 return expect('>', token);
501 } 500 }
502 handleNoStuff(token); 501 handleNoStuff(token);
503 return token; 502 return token;
504 } 503 }
505 504
506 Token parseTopLevelMember(Token token) { 505 Token parseTopLevelMember(Token token) {
507 Token start = token; 506 Token start = token;
508 listener.beginTopLevelMember(token); 507 listener.beginTopLevelMember(token);
509 token = parseModifiers(token); 508
510 Token getOrSet = findGetOrSet(token); 509 Link<Token> identifiers = findMemberName(token);
511 if (token === getOrSet) token = token.next; 510 if (identifiers.isEmpty()) {
512 Token peek = peekAfterExpectedType(token); 511 return listener.unexpected(start);
513 if (isIdentifier(peek)) {
514 // Skip type.
515 token = peek;
516 } 512 }
517 if (token === getOrSet) token = token.next; 513 Token name = identifiers.head;
518 token = parseIdentifier(token); 514 identifiers = identifiers.tail;
515 if (!identifiers.isEmpty()) {
516 if (optional('operator', identifiers.head)) {
ngeoffray 2012/09/10 14:24:49 'operator' does not apply to top level methods.
ahe 2012/09/10 19:03:02 Done.
517 name = identifiers.head;
518 identifiers = identifiers.tail;
519 }
520 }
521 Token getOrSet;
522 if (!identifiers.isEmpty()) {
523 String value = identifiers.head.stringValue;
524 if ((value === 'get') || (value === 'set')) {
525 getOrSet = identifiers.head;
526 identifiers = identifiers.tail;
527 }
528 }
529 Token type;
530 if (!identifiers.isEmpty()) {
531 if (isValidTypeReference(identifiers.head)) {
532 type = identifiers.head;
533 identifiers = identifiers.tail;
534 }
535 }
536 parseModifierList(identifiers.reverse());
537 if (type === null) {
538 listener.handleNoType(token);
539 } else {
540 parseReturnTypeOpt(type);
541 }
542 token = parseIdentifier(name);
543
519 bool isField; 544 bool isField;
520 while (true) { 545 while (true) {
521 // Loop to allow the listener to rewrite the token stream for 546 // Loop to allow the listener to rewrite the token stream for
522 // error handling. 547 // error handling.
523 final String value = token.stringValue; 548 final String value = token.stringValue;
524 if ((value === '(') || (value === '{') || (value === '=>')) { 549 if ((value === '(') || (value === '{') || (value === '=>')) {
525 isField = false; 550 isField = false;
526 break; 551 break;
527 } else if ((value === '=') || (value === ';') || (value === ',')) { 552 } else if ((value === '=') || (value === ';') || (value === ',')) {
528 isField = true; 553 isField = true;
(...skipping 19 matching lines...) Expand all
548 expectSemicolon(token); 573 expectSemicolon(token);
549 listener.endTopLevelFields(fieldCount, start, token); 574 listener.endTopLevelFields(fieldCount, start, token);
550 } else { 575 } else {
551 token = parseFormalParametersOpt(token); 576 token = parseFormalParametersOpt(token);
552 token = parseFunctionBody(token, false); 577 token = parseFunctionBody(token, false);
553 listener.endTopLevelMethod(start, getOrSet, token); 578 listener.endTopLevelMethod(start, getOrSet, token);
554 } 579 }
555 return token.next; 580 return token.next;
556 } 581 }
557 582
583 Link<Token> findMemberName(Token token) {
584 Link<Token> identifiers = const EmptyLink<Token>();
585 while (token.kind !== EOF_TOKEN) {
586 String value = token.stringValue;
587 if ((value === '(') || (value === '{') || (value === '=>')) {
588 // A method.
589 return identifiers;
590 } else if ((value === '=') || (value === ';') || (value === ',')) {
591 // A field or abstract getter.
592 return identifiers;
593 }
594 identifiers = identifiers.prepend(token);
595 if (isValidTypeReference(token)) {
596 // type ...
597 if (optional('.', token.next)) {
598 // type '.' ...
599 if (isIdentifier(token.next.next)) {
600 // type '.' identifier
601 token = token.next.next;
602 }
603 }
604 if (optional('<', token.next)) {
605 if (token.next is BeginGroupToken) {
606 BeginGroupToken beginGroup = token.next;
607 token = beginGroup.endGroup;
608 }
609 }
610 }
611 token = token.next;
612 }
613 return listener.unexpected(token);
614 }
615
558 Token parseVariableInitializerOpt(Token token) { 616 Token parseVariableInitializerOpt(Token token) {
559 if (optional('=', token)) { 617 if (optional('=', token)) {
560 Token assignment = token; 618 Token assignment = token;
561 listener.beginInitializer(token); 619 listener.beginInitializer(token);
562 token = parseExpression(token.next); 620 token = parseExpression(token.next);
563 listener.endInitializer(assignment); 621 listener.endInitializer(assignment);
564 } 622 }
565 return token; 623 return token;
566 } 624 }
567 625
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 ('static' === value) || 688 ('static' === value) ||
631 ('external' === value); 689 ('external' === value);
632 } 690 }
633 691
634 Token parseModifier(Token token) { 692 Token parseModifier(Token token) {
635 assert(isModifier(token)); 693 assert(isModifier(token));
636 listener.handleModifier(token); 694 listener.handleModifier(token);
637 return token.next; 695 return token.next;
638 } 696 }
639 697
698 void parseModifierList(Link<Token> tokens) {
699 int count = 0;
700 for (; !tokens.isEmpty(); tokens = tokens.tail) {
701 Token token = tokens.head;
702 if (isModifier(token)) {
703 parseModifier(token);
704 } else {
705 listener.unexpected(token);
706 }
707 count++;
708 }
709 listener.handleModifiers(count);
710 }
711
640 Token parseModifiers(Token token) { 712 Token parseModifiers(Token token) {
641 int count = 0; 713 int count = 0;
642 while (token.kind === KEYWORD_TOKEN) { 714 while (token.kind === KEYWORD_TOKEN) {
643 if (!isModifier(token)) 715 if (!isModifier(token))
644 break; 716 break;
645 token = parseModifier(token); 717 token = parseModifier(token);
646 count++; 718 count++;
647 } 719 }
648 listener.handleModifiers(count); 720 listener.handleModifiers(count);
649 return token; 721 return token;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 } 770 }
699 listener.endClassBody(count, begin, token); 771 listener.endClassBody(count, begin, token);
700 return token; 772 return token;
701 } 773 }
702 774
703 bool isGetOrSet(Token token) { 775 bool isGetOrSet(Token token) {
704 final String value = token.stringValue; 776 final String value = token.stringValue;
705 return (value === 'get') || (value === 'set'); 777 return (value === 'get') || (value === 'set');
706 } 778 }
707 779
708 Token findGetOrSet(Token token) {
709 if (isGetOrSet(token)) {
710 if (optional('<', token.next)) {
711 // For example: get<T> ...
712 final Token peek = peekAfterExpectedType(token);
713 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
714 // For example: get<T> get identifier
715 return peek;
716 }
717 } else {
718 // For example: get ...
719 if (isGetOrSet(token.next) && isIdentifier(token.next.next)) {
720 // For example: get get identifier
721 return token.next;
722 } else {
723 // For example: get identifier
724 return token;
725 }
726 }
727 } else if (token.stringValue !== 'operator') {
728 final Token peek = peekAfterExpectedType(token);
729 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
730 // type? get identifier
731 return peek;
732 }
733 }
734 return null;
735 }
736
737 Token parseMember(Token token) { 780 Token parseMember(Token token) {
738 token = parseMetadataStar(token); 781 token = parseMetadataStar(token);
739 String value = token.stringValue; 782 String value = token.stringValue;
740 if (value === 'factory' || 783 if (value === 'factory' ||
741 (value === 'external' && optional('factory', token.next))) { 784 (value === 'external' && optional('factory', token.next))) {
742 return parseFactoryMethod(token); 785 return parseFactoryMethod(token);
743 } 786 }
744 Token start = token; 787 Token start = token;
745 listener.beginMember(token); 788 listener.beginMember(token);
746 token = parseModifiers(token); 789
747 Token getOrSet = findGetOrSet(token); 790 Link<Token> identifiers = findMemberName(token);
748 if (token === getOrSet) token = token.next; 791 if (identifiers.isEmpty()) {
749 Token peek = peekAfterExpectedType(token); 792 return listener.unexpected(start);
750 if (isIdentifier(peek) && token.stringValue !== 'operator') {
751 // Skip type.
752 token = peek;
753 } 793 }
754 if (token === getOrSet) token = token.next; 794 Token name = identifiers.head;
755 if (optional('operator', token)) { 795 identifiers = identifiers.tail;
756 token = parseOperatorName(token); 796 if (!identifiers.isEmpty()) {
797 if (optional('operator', identifiers.head)) {
798 name = identifiers.head;
799 identifiers = identifiers.tail;
800 }
801 }
802 Token getOrSet;
803 if (!identifiers.isEmpty()) {
804 if (isGetOrSet(identifiers.head)) {
805 getOrSet = identifiers.head;
806 identifiers = identifiers.tail;
807 }
808 }
809 Token type;
810 if (!identifiers.isEmpty()) {
811 if (isValidTypeReference(identifiers.head)) {
812 type = identifiers.head;
813 identifiers = identifiers.tail;
814 }
815 }
816 parseModifierList(identifiers.reverse());
817 if (type === null) {
818 listener.handleNoType(token);
757 } else { 819 } else {
758 token = parseIdentifier(token); 820 parseReturnTypeOpt(type);
821 }
822
823 if (optional('operator', name)) {
824 token = parseOperatorName(name);
825 } else {
826 token = parseIdentifier(name);
759 } 827 }
760 bool isField; 828 bool isField;
761 while (true) { 829 while (true) {
762 // Loop to allow the listener to rewrite the token stream for 830 // Loop to allow the listener to rewrite the token stream for
763 // error handling. 831 // error handling.
764 final String value = token.stringValue; 832 final String value = token.stringValue;
765 if ((value === '(') || (value === '.') || (value === '{') || 833 if ((value === '(') || (value === '.') || (value === '{') ||
766 (value === '=>')) { 834 (value === '=>')) {
767 isField = false; 835 isField = false;
768 break; 836 break;
(...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1962 } 2030 }
1963 listener.handleContinueStatement(hasTarget, continueKeyword, token); 2031 listener.handleContinueStatement(hasTarget, continueKeyword, token);
1964 return expectSemicolon(token); 2032 return expectSemicolon(token);
1965 } 2033 }
1966 2034
1967 Token parseEmptyStatement(Token token) { 2035 Token parseEmptyStatement(Token token) {
1968 listener.handleEmptyStatement(token); 2036 listener.handleEmptyStatement(token);
1969 return expectSemicolon(token); 2037 return expectSemicolon(token);
1970 } 2038 }
1971 } 2039 }
OLDNEW
« no previous file with comments | « dart/lib/compiler/implementation/scanner/listener.dart ('k') | dart/tests/co19/co19-dart2js.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698