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

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

Issue 10829334: Const variable declarations accepted in the parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test helper added Created 8 years, 4 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
« no previous file with comments | « no previous file | tests/co19/co19-dart2js.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 ++parameterCount; 143 ++parameterCount;
144 } while (optional(',', token)); 144 } while (optional(',', token));
145 listener.endOptionalFormalParameters(parameterCount, begin, token); 145 listener.endOptionalFormalParameters(parameterCount, begin, token);
146 return expect(']', token); 146 return expect(']', token);
147 } 147 }
148 148
149 Token parseTypeOpt(Token token) { 149 Token parseTypeOpt(Token token) {
150 String value = token.stringValue; 150 String value = token.stringValue;
151 if (value === 'var') return parseType(token); 151 if (value === 'var') return parseType(token);
152 if (value !== 'this') { 152 if (value !== 'this') {
153 Token peek = peekAfterType(token); 153 Token peek = peekAfterExpectedType(token);
154 if (isIdentifier(peek) || optional('this', peek)) { 154 if (isIdentifier(peek) || optional('this', peek)) {
155 return parseType(token); 155 return parseType(token);
156 } 156 }
157 } 157 }
158 listener.handleNoType(token); 158 listener.handleNoType(token);
159 return token; 159 return token;
160 } 160 }
161 161
162 bool isIdentifier(Token token) { 162 bool isIdentifier(Token token) {
163 final kind = token.kind; 163 final kind = token.kind;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 handleNoStuff(token); 344 handleNoStuff(token);
345 return token; 345 return token;
346 } 346 }
347 347
348 Token parseTopLevelMember(Token token) { 348 Token parseTopLevelMember(Token token) {
349 Token start = token; 349 Token start = token;
350 listener.beginTopLevelMember(token); 350 listener.beginTopLevelMember(token);
351 token = parseModifiers(token); 351 token = parseModifiers(token);
352 Token getOrSet = findGetOrSet(token); 352 Token getOrSet = findGetOrSet(token);
353 if (token === getOrSet) token = token.next; 353 if (token === getOrSet) token = token.next;
354 Token peek = peekAfterType(token); 354 Token peek = peekAfterExpectedType(token);
355 if (isIdentifier(peek)) { 355 if (isIdentifier(peek)) {
356 // Skip type. 356 // Skip type.
357 token = peek; 357 token = peek;
358 } 358 }
359 if (token === getOrSet) token = token.next; 359 if (token === getOrSet) token = token.next;
360 token = parseIdentifier(token); 360 token = parseIdentifier(token);
361 bool isField; 361 bool isField;
362 while (true) { 362 while (true) {
363 // Loop to allow the listener to rewrite the token stream for 363 // Loop to allow the listener to rewrite the token stream for
364 // error handling. 364 // error handling.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 } else { 456 } else {
457 listener.recoverableError("unexpected", token: token); 457 listener.recoverableError("unexpected", token: token);
458 return parseExpression(token); 458 return parseExpression(token);
459 } 459 }
460 } 460 }
461 461
462 Token expectSemicolon(Token token) { 462 Token expectSemicolon(Token token) {
463 return expect(';', token); 463 return expect(';', token);
464 } 464 }
465 465
466 bool isModifier(Token token) {
467 final String value = token.stringValue;
468 return ('final' === value) ||
469 ('var' === value) ||
470 ('const' === value) ||
471 ('abstract' === value) ||
472 ('static' === value) ||
473 ('external' === value);
474 }
475
466 Token parseModifier(Token token) { 476 Token parseModifier(Token token) {
467 assert(('final' === token.stringValue) || 477 assert(isModifier(token));
468 ('var' === token.stringValue) ||
469 ('const' === token.stringValue) ||
470 ('abstract' === token.stringValue) ||
471 ('static' === token.stringValue) ||
472 ('external' === token.stringValue));
473 listener.handleModifier(token); 478 listener.handleModifier(token);
474 return token.next; 479 return token.next;
475 } 480 }
476 481
477 Token parseModifiers(Token token) { 482 Token parseModifiers(Token token) {
478 int count = 0; 483 int count = 0;
479 while (token.kind === KEYWORD_TOKEN) { 484 while (token.kind === KEYWORD_TOKEN) {
480 final String value = token.stringValue; 485 if (!isModifier(token))
481 if (('final' !== value) &&
482 ('var' !== value) &&
483 ('const' !== value) &&
484 ('abstract' !== value) &&
485 ('static' !== value) &&
486 ('external' !== value))
487 break; 486 break;
488 token = parseModifier(token); 487 token = parseModifier(token);
489 count++; 488 count++;
490 } 489 }
491 listener.handleModifiers(count); 490 listener.handleModifiers(count);
492 return token; 491 return token;
493 } 492 }
494 493
495 Token peekAfterType(Token token) { 494 Token peekAfterType(Token token) {
496 // TODO(ahe): Also handle var? 495 // TODO(ahe): Also handle var?
497 if ('void' !== token.stringValue && !isIdentifier(token)) {
498 listener.unexpected(token);
499 }
500 // We are looking at "identifier ...". 496 // We are looking at "identifier ...".
501 Token peek = token.next; 497 Token peek = token.next;
502 if (peek.kind === PERIOD_TOKEN) { 498 if (peek.kind === PERIOD_TOKEN) {
503 if (isIdentifier(peek.next)) { 499 if (isIdentifier(peek.next)) {
504 // Look past a library prefix. 500 // Look past a library prefix.
505 peek = peek.next.next; 501 peek = peek.next.next;
506 } 502 }
507 } 503 }
508 // We are looking at "qualified ...". 504 // We are looking at "qualified ...".
509 if (peek.kind === LT_TOKEN) { 505 if (peek.kind === LT_TOKEN) {
510 // Possibly generic type. 506 // Possibly generic type.
511 // We are looking at "qualified '<'". 507 // We are looking at "qualified '<'".
512 BeginGroupToken beginGroupToken = peek; 508 BeginGroupToken beginGroupToken = peek;
513 Token gtToken = beginGroupToken.endGroup; 509 Token gtToken = beginGroupToken.endGroup;
514 if (gtToken !== null) { 510 if (gtToken !== null) {
515 // We are looking at "qualified '<' ... '>' ...". 511 // We are looking at "qualified '<' ... '>' ...".
516 return gtToken.next; 512 return gtToken.next;
517 } 513 }
518 } 514 }
519 return peek; 515 return peek;
520 } 516 }
521 517
518 /**
519 * Returns the token after the type which is expected to begin at [token].
520 * If [token] is not the start of a type, [Listener.unexpectedType] is called.
521 */
522 Token peekAfterExpectedType(Token token) {
523 if ('void' !== token.stringValue && !isIdentifier(token)) {
524 return listener.expectedType(token);
525 }
526 return peekAfterType(token);
527 }
528
522 Token parseClassBody(Token token) { 529 Token parseClassBody(Token token) {
523 Token begin = token; 530 Token begin = token;
524 listener.beginClassBody(token); 531 listener.beginClassBody(token);
525 if (!optional('{', token)) { 532 if (!optional('{', token)) {
526 token = listener.expectedClassBody(token); 533 token = listener.expectedClassBody(token);
527 } 534 }
528 token = token.next; 535 token = token.next;
529 int count = 0; 536 int count = 0;
530 while (notEofOrValue('}', token)) { 537 while (notEofOrValue('}', token)) {
531 token = parseMember(token); 538 token = parseMember(token);
532 ++count; 539 ++count;
533 } 540 }
534 listener.endClassBody(count, begin, token); 541 listener.endClassBody(count, begin, token);
535 return token; 542 return token;
536 } 543 }
537 544
538 bool isGetOrSet(Token token) { 545 bool isGetOrSet(Token token) {
539 final String value = token.stringValue; 546 final String value = token.stringValue;
540 return (value === 'get') || (value === 'set'); 547 return (value === 'get') || (value === 'set');
541 } 548 }
542 549
543 Token findGetOrSet(Token token) { 550 Token findGetOrSet(Token token) {
544 if (isGetOrSet(token)) { 551 if (isGetOrSet(token)) {
545 if (optional('<', token.next)) { 552 if (optional('<', token.next)) {
546 // For example: get<T> ... 553 // For example: get<T> ...
547 final Token peek = peekAfterType(token); 554 final Token peek = peekAfterExpectedType(token);
548 if (isGetOrSet(peek) && isIdentifier(peek.next)) { 555 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
549 // For example: get<T> get identifier 556 // For example: get<T> get identifier
550 return peek; 557 return peek;
551 } 558 }
552 } else { 559 } else {
553 // For example: get ... 560 // For example: get ...
554 if (isGetOrSet(token.next) && isIdentifier(token.next.next)) { 561 if (isGetOrSet(token.next) && isIdentifier(token.next.next)) {
555 // For example: get get identifier 562 // For example: get get identifier
556 return token.next; 563 return token.next;
557 } else { 564 } else {
558 // For example: get identifier 565 // For example: get identifier
559 return token; 566 return token;
560 } 567 }
561 } 568 }
562 } else if (token.stringValue !== 'operator') { 569 } else if (token.stringValue !== 'operator') {
563 final Token peek = peekAfterType(token); 570 final Token peek = peekAfterExpectedType(token);
564 if (isGetOrSet(peek) && isIdentifier(peek.next)) { 571 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
565 // type? get identifier 572 // type? get identifier
566 return peek; 573 return peek;
567 } 574 }
568 } 575 }
569 return null; 576 return null;
570 } 577 }
571 578
572 Token parseMember(Token token) { 579 Token parseMember(Token token) {
573 String value = token.stringValue; 580 String value = token.stringValue;
574 if (value === 'factory' || 581 if (value === 'factory' ||
575 (value === 'external' && optional('factory', token.next))) { 582 (value === 'external' && optional('factory', token.next))) {
576 return parseFactoryMethod(token); 583 return parseFactoryMethod(token);
577 } 584 }
578 Token start = token; 585 Token start = token;
579 listener.beginMember(token); 586 listener.beginMember(token);
580 token = parseModifiers(token); 587 token = parseModifiers(token);
581 Token getOrSet = findGetOrSet(token); 588 Token getOrSet = findGetOrSet(token);
582 if (token === getOrSet) token = token.next; 589 if (token === getOrSet) token = token.next;
583 Token peek = peekAfterType(token); 590 Token peek = peekAfterExpectedType(token);
584 if (isIdentifier(peek) && token.stringValue !== 'operator') { 591 if (isIdentifier(peek) && token.stringValue !== 'operator') {
585 // Skip type. 592 // Skip type.
586 token = peek; 593 token = peek;
587 } 594 }
588 if (token === getOrSet) token = token.next; 595 if (token === getOrSet) token = token.next;
589 if (optional('operator', token)) { 596 if (optional('operator', token)) {
590 token = parseOperatorName(token); 597 token = parseOperatorName(token);
591 } else { 598 } else {
592 token = parseIdentifier(token); 599 token = parseIdentifier(token);
593 } 600 }
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 } else if (value === 'try') { 791 } else if (value === 'try') {
785 return parseTryStatement(token); 792 return parseTryStatement(token);
786 } else if (value === 'switch') { 793 } else if (value === 'switch') {
787 return parseSwitchStatement(token); 794 return parseSwitchStatement(token);
788 } else if (value === 'break') { 795 } else if (value === 'break') {
789 return parseBreakStatement(token); 796 return parseBreakStatement(token);
790 } else if (value === 'continue') { 797 } else if (value === 'continue') {
791 return parseContinueStatement(token); 798 return parseContinueStatement(token);
792 } else if (value === ';') { 799 } else if (value === ';') {
793 return parseEmptyStatement(token); 800 return parseEmptyStatement(token);
801 } else if (value === 'const') {
802 return parseExpressionStatementOrConstDeclaration(token);
794 } else if (isIdentifier(token)) { 803 } else if (isIdentifier(token)) {
795 return parseExpressionStatementOrDeclaration(token); 804 return parseExpressionStatementOrDeclaration(token);
796 } else { 805 } else {
797 return parseExpressionStatement(token); 806 return parseExpressionStatement(token);
798 } 807 }
799 } 808 }
800 809
801 Token parseReturnStatement(Token token) { 810 Token parseReturnStatement(Token token) {
802 Token begin = token; 811 Token begin = token;
803 listener.beginReturnStatement(begin); 812 listener.beginReturnStatement(begin);
(...skipping 11 matching lines...) Expand all
815 Token peekIdentifierAfterType(Token token) { 824 Token peekIdentifierAfterType(Token token) {
816 Token peek = peekAfterType(token); 825 Token peek = peekAfterType(token);
817 if (peek !== null && isIdentifier(peek)) { 826 if (peek !== null && isIdentifier(peek)) {
818 // We are looking at "type identifier". 827 // We are looking at "type identifier".
819 return peek; 828 return peek;
820 } else { 829 } else {
821 return null; 830 return null;
822 } 831 }
823 } 832 }
824 833
834 Token peekIdentifierAfterOptionalType(Token token) {
835 Token peek = peekIdentifierAfterType(token);
836 if (peek !== null) {
837 // We are looking at "type identifier".
838 return peek;
839 } else if (isIdentifier(token)) {
840 // We are looking at "identifier".
841 return token;
842 } else {
843 return null;
844 }
845 }
846
825 Token parseExpressionStatementOrDeclaration(Token token) { 847 Token parseExpressionStatementOrDeclaration(Token token) {
826 assert(isIdentifier(token) || token.stringValue === 'void'); 848 assert(isIdentifier(token) || token.stringValue === 'void');
827 Token identifier = peekIdentifierAfterType(token); 849 Token identifier = peekIdentifierAfterType(token);
828 if (identifier !== null) { 850 if (identifier !== null) {
829 assert(isIdentifier(identifier)); 851 assert(isIdentifier(identifier));
830 Token afterId = identifier.next; 852 Token afterId = identifier.next;
831 int afterIdKind = afterId.kind; 853 int afterIdKind = afterId.kind;
832 if (afterIdKind === EQ_TOKEN || 854 if (afterIdKind === EQ_TOKEN ||
833 afterIdKind === SEMICOLON_TOKEN || 855 afterIdKind === SEMICOLON_TOKEN ||
834 afterIdKind === COMMA_TOKEN) { 856 afterIdKind === COMMA_TOKEN) {
(...skipping 18 matching lines...) Expand all
853 BeginGroupToken begin = token.next; 875 BeginGroupToken begin = token.next;
854 String afterParens = begin.endGroup.next.stringValue; 876 String afterParens = begin.endGroup.next.stringValue;
855 if (afterParens === '{' || afterParens === '=>') { 877 if (afterParens === '{' || afterParens === '=>') {
856 return parseFunctionDeclaration(token); 878 return parseFunctionDeclaration(token);
857 } 879 }
858 } 880 }
859 } 881 }
860 return parseExpressionStatement(token); 882 return parseExpressionStatement(token);
861 } 883 }
862 884
885 Token parseExpressionStatementOrConstDeclaration(Token token) {
886 assert(token.stringValue === 'const');
887 if (isModifier(token.next)) {
888 return parseVariablesDeclaration(token);
889 }
890 Token identifier = peekIdentifierAfterOptionalType(token.next);
891 if (identifier !== null) {
892 assert(isIdentifier(identifier));
893 Token afterId = identifier.next;
894 int afterIdKind = afterId.kind;
895 if (afterIdKind === EQ_TOKEN ||
896 afterIdKind === SEMICOLON_TOKEN ||
897 afterIdKind === COMMA_TOKEN) {
898 // We are looking at "const type identifier" followed by '=', ';', or
899 // ','.
900 return parseVariablesDeclaration(token);
901 }
902 // Fall-through to expression statement.
903 }
904 return parseExpressionStatement(token);
905 }
906
863 Token parseLabel(Token token) { 907 Token parseLabel(Token token) {
864 token = parseIdentifier(token); 908 token = parseIdentifier(token);
865 Token colon = token; 909 Token colon = token;
866 token = expect(':', token); 910 token = expect(':', token);
867 listener.handleLabel(colon); 911 listener.handleLabel(colon);
868 return token; 912 return token;
869 } 913 }
870 914
871 Token parseLabeledStatement(Token token) { 915 Token parseLabeledStatement(Token token) {
872 int labelCount = 0; 916 int labelCount = 0;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 token = parseExpression(token); 1250 token = parseExpression(token);
1207 Token colon = token; 1251 Token colon = token;
1208 token = expect(':', token); 1252 token = expect(':', token);
1209 token = parseExpression(token); 1253 token = parseExpression(token);
1210 listener.endLiteralMapEntry(colon, token); 1254 listener.endLiteralMapEntry(colon, token);
1211 return token; 1255 return token;
1212 } 1256 }
1213 1257
1214 Token parseSendOrFunctionLiteral(Token token) { 1258 Token parseSendOrFunctionLiteral(Token token) {
1215 if (!mayParseFunctionExpressions) return parseSend(token); 1259 if (!mayParseFunctionExpressions) return parseSend(token);
1216 Token peek = peekAfterType(token); 1260 Token peek = peekAfterExpectedType(token);
1217 if (peek.kind === IDENTIFIER_TOKEN && isFunctionDeclaration(peek.next)) { 1261 if (peek.kind === IDENTIFIER_TOKEN && isFunctionDeclaration(peek.next)) {
1218 return parseFunctionExpression(token); 1262 return parseFunctionExpression(token);
1219 } else if (isFunctionDeclaration(token.next)) { 1263 } else if (isFunctionDeclaration(token.next)) {
1220 return parseFunctionExpression(token); 1264 return parseFunctionExpression(token);
1221 } else { 1265 } else {
1222 return parseSend(token); 1266 return parseSend(token);
1223 } 1267 }
1224 } 1268 }
1225 1269
1226 bool isFunctionDeclaration(Token token) { 1270 bool isFunctionDeclaration(Token token) {
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 } 1779 }
1736 listener.handleContinueStatement(hasTarget, continueKeyword, token); 1780 listener.handleContinueStatement(hasTarget, continueKeyword, token);
1737 return expectSemicolon(token); 1781 return expectSemicolon(token);
1738 } 1782 }
1739 1783
1740 Token parseEmptyStatement(Token token) { 1784 Token parseEmptyStatement(Token token) {
1741 listener.handleEmptyStatement(token); 1785 listener.handleEmptyStatement(token);
1742 return expectSemicolon(token); 1786 return expectSemicolon(token);
1743 } 1787 }
1744 } 1788 }
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-dart2js.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698