| 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |