| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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. | 7 * all tokens in a linked list. |
| 8 */ | 8 */ |
| 9 class Parser { | 9 class Parser { |
| 10 final Listener listener; | 10 final Listener listener; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 if (value === 'default') return true; | 181 if (value === 'default') return true; |
| 182 if (value === 'factory') { | 182 if (value === 'factory') { |
| 183 listener.recoverableError("expected 'default'", token: token); | 183 listener.recoverableError("expected 'default'", token: token); |
| 184 return true; | 184 return true; |
| 185 } | 185 } |
| 186 return false; | 186 return false; |
| 187 } | 187 } |
| 188 | 188 |
| 189 Token skipBlock(Token token) { | 189 Token skipBlock(Token token) { |
| 190 if (!optional('{', token)) { | 190 if (!optional('{', token)) { |
| 191 return listener.expectedBlock(token); | 191 return listener.unexpected(token); |
| 192 } | 192 } |
| 193 BeginGroupToken beginGroupToken = token; | 193 BeginGroupToken beginGroupToken = token; |
| 194 assert(beginGroupToken.endGroup === null || | 194 assert(beginGroupToken.endGroup === null || |
| 195 beginGroupToken.endGroup.kind === $CLOSE_CURLY_BRACKET); | 195 beginGroupToken.endGroup.kind === $CLOSE_CURLY_BRACKET); |
| 196 return beginGroupToken.endGroup; | 196 return beginGroupToken.endGroup; |
| 197 } | 197 } |
| 198 | 198 |
| 199 Token parseClass(Token token) { | 199 Token parseClass(Token token) { |
| 200 Token begin = token; | 200 Token begin = token; |
| 201 listener.beginClassDeclaration(token); | 201 listener.beginClassDeclaration(token); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 isField = false; | 362 isField = false; |
| 363 break; | 363 break; |
| 364 } else if ((value === '=') || (value === ';') || (value === ',')) { | 364 } else if ((value === '=') || (value === ';') || (value === ',')) { |
| 365 isField = true; | 365 isField = true; |
| 366 break; | 366 break; |
| 367 } else { | 367 } else { |
| 368 token = listener.unexpected(token); | 368 token = listener.unexpected(token); |
| 369 if (token.kind === EOF_TOKEN) { | 369 if (token.kind === EOF_TOKEN) { |
| 370 // TODO(ahe): This is a hack. It would be better to tell the | 370 // TODO(ahe): This is a hack. It would be better to tell the |
| 371 // listener more explicitly that it must pop an identifier. | 371 // listener more explicitly that it must pop an identifier. |
| 372 listener.endTopLevelFields(0, start, token); | 372 listener.endTopLevelFields(1, start, token); |
| 373 return token; | 373 return token; |
| 374 } | 374 } |
| 375 } | 375 } |
| 376 } | 376 } |
| 377 if (isField) { | 377 if (isField) { |
| 378 int fieldCount = 1; | 378 int fieldCount = 1; |
| 379 token = parseVariableInitializerOpt(token); | 379 token = parseVariableInitializerOpt(token); |
| 380 while (optional(',', token)) { | 380 while (optional(',', token)) { |
| 381 token = parseIdentifier(token.next); | 381 token = parseIdentifier(token.next); |
| 382 token = parseVariableInitializerOpt(token); | 382 token = parseVariableInitializerOpt(token); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 token = parseModifier(token); | 472 token = parseModifier(token); |
| 473 count++; | 473 count++; |
| 474 } | 474 } |
| 475 listener.handleModifiers(count); | 475 listener.handleModifiers(count); |
| 476 return token; | 476 return token; |
| 477 } | 477 } |
| 478 | 478 |
| 479 Token peekAfterType(Token token) { | 479 Token peekAfterType(Token token) { |
| 480 // TODO(ahe): Also handle var? | 480 // TODO(ahe): Also handle var? |
| 481 if ('void' !== token.stringValue && !isIdentifier(token)) { | 481 if ('void' !== token.stringValue && !isIdentifier(token)) { |
| 482 listener.expectedIdentifier(token); | 482 listener.unexpected(token); |
| 483 } | 483 } |
| 484 // We are looking at "identifier ...". | 484 // We are looking at "identifier ...". |
| 485 Token peek = token.next; | 485 Token peek = token.next; |
| 486 if (peek.kind === PERIOD_TOKEN) { | 486 if (peek.kind === PERIOD_TOKEN) { |
| 487 if (isIdentifier(peek.next)) { | 487 if (isIdentifier(peek.next)) { |
| 488 // Look past a library prefix. | 488 // Look past a library prefix. |
| 489 peek = peek.next.next; | 489 peek = peek.next.next; |
| 490 } | 490 } |
| 491 } | 491 } |
| 492 // We are looking at "qualified ...". | 492 // We are looking at "qualified ...". |
| 493 if (peek.kind === LT_TOKEN) { | 493 if (peek.kind === LT_TOKEN) { |
| 494 // Possibly generic type. | 494 // Possibly generic type. |
| 495 // We are looking at "qualified '<'". | 495 // We are looking at "qualified '<'". |
| 496 BeginGroupToken beginGroupToken = peek; | 496 BeginGroupToken beginGroupToken = peek; |
| 497 Token gtToken = beginGroupToken.endGroup; | 497 Token gtToken = beginGroupToken.endGroup; |
| 498 if (gtToken !== null) { | 498 if (gtToken !== null) { |
| 499 // We are looking at "qualified '<' ... '>' ...". | 499 // We are looking at "qualified '<' ... '>' ...". |
| 500 return gtToken.next; | 500 return gtToken.next; |
| 501 } | 501 } |
| 502 } | 502 } |
| 503 return peek; | 503 return peek; |
| 504 } | 504 } |
| 505 | 505 |
| 506 Token parseClassBody(Token token) { | 506 Token parseClassBody(Token token) { |
| 507 Token begin = token; | 507 Token begin = token; |
| 508 listener.beginClassBody(token); | 508 listener.beginClassBody(token); |
| 509 if (!optional('{', token)) { | 509 if (!optional('{', token)) { |
| 510 return listener.expectedBlock(token); | 510 token = listener.unexpected(token); |
| 511 listener.endClassBody(0, begin, null); |
| 512 return token; |
| 511 } | 513 } |
| 512 token = token.next; | 514 token = token.next; |
| 513 int count = 0; | 515 int count = 0; |
| 514 while (notEofOrValue('}', token)) { | 516 while (notEofOrValue('}', token)) { |
| 515 token = parseMember(token); | 517 token = parseMember(token); |
| 516 ++count; | 518 ++count; |
| 517 } | 519 } |
| 518 listener.endClassBody(count, begin, token); | 520 listener.endClassBody(count, begin, token); |
| 519 return token; | 521 return token; |
| 520 } | 522 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 542 // error handling. | 544 // error handling. |
| 543 final String value = token.stringValue; | 545 final String value = token.stringValue; |
| 544 if ((value === '(') || (value === '.')) { | 546 if ((value === '(') || (value === '.')) { |
| 545 isField = false; | 547 isField = false; |
| 546 break; | 548 break; |
| 547 } else if ((value === '=') || (value === ';') || (value === ',')) { | 549 } else if ((value === '=') || (value === ';') || (value === ',')) { |
| 548 isField = true; | 550 isField = true; |
| 549 break; | 551 break; |
| 550 } else { | 552 } else { |
| 551 token = listener.unexpected(token); | 553 token = listener.unexpected(token); |
| 554 if (token.kind === EOF_TOKEN) { |
| 555 // TODO(ahe): This is a hack, see parseTopLevelMember. |
| 556 listener.endFields(1, start, token); |
| 557 return token; |
| 558 } |
| 552 } | 559 } |
| 553 } | 560 } |
| 554 if (isField) { | 561 if (isField) { |
| 555 int fieldCount = 1; | 562 int fieldCount = 1; |
| 556 token = parseVariableInitializerOpt(token); | 563 token = parseVariableInitializerOpt(token); |
| 557 while (optional(',', token)) { | 564 while (optional(',', token)) { |
| 558 // TODO(ahe): Count these. | 565 // TODO(ahe): Count these. |
| 559 token = parseIdentifier(token.next); | 566 token = parseIdentifier(token.next); |
| 560 token = parseVariableInitializerOpt(token); | 567 token = parseVariableInitializerOpt(token); |
| 561 ++fieldCount; | 568 ++fieldCount; |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 token = parseParenthesizedExpression(token); | 995 token = parseParenthesizedExpression(token); |
| 989 mayParseFunctionExpressions = old; | 996 mayParseFunctionExpressions = old; |
| 990 return token; | 997 return token; |
| 991 } | 998 } |
| 992 } | 999 } |
| 993 | 1000 |
| 994 Token parseParenthesizedExpression(Token token) { | 1001 Token parseParenthesizedExpression(Token token) { |
| 995 BeginGroupToken begin = token; | 1002 BeginGroupToken begin = token; |
| 996 token = expect('(', token); | 1003 token = expect('(', token); |
| 997 token = parseExpression(token); | 1004 token = parseExpression(token); |
| 998 assert(begin.endGroup === token); | 1005 if (begin.endGroup !== token) { |
| 1006 listener.unexpected(token); |
| 1007 token = begin.endGroup; |
| 1008 } |
| 999 listener.handleParenthesizedExpression(begin); | 1009 listener.handleParenthesizedExpression(begin); |
| 1000 return expect(')', token); | 1010 return expect(')', token); |
| 1001 } | 1011 } |
| 1002 | 1012 |
| 1003 Token parseThisExpression(Token token) { | 1013 Token parseThisExpression(Token token) { |
| 1004 listener.handleThisExpression(token); | 1014 listener.handleThisExpression(token); |
| 1005 token = token.next; | 1015 token = token.next; |
| 1006 if (optional('(', token)) { | 1016 if (optional('(', token)) { |
| 1007 // Constructor forwarding. | 1017 // Constructor forwarding. |
| 1008 token = parseArguments(token); | 1018 token = parseArguments(token); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 | 1113 |
| 1104 Token parseNewExpression(Token token) { | 1114 Token parseNewExpression(Token token) { |
| 1105 Token newKeyword = token; | 1115 Token newKeyword = token; |
| 1106 token = expect('new', token); | 1116 token = expect('new', token); |
| 1107 token = parseType(token); | 1117 token = parseType(token); |
| 1108 bool named = false; | 1118 bool named = false; |
| 1109 if (optional('.', token)) { | 1119 if (optional('.', token)) { |
| 1110 named = true; | 1120 named = true; |
| 1111 token = parseIdentifier(token.next); | 1121 token = parseIdentifier(token.next); |
| 1112 } | 1122 } |
| 1113 token = parseArguments(token); | 1123 if (optional('(', token)) { |
| 1124 token = parseArguments(token); |
| 1125 } else { |
| 1126 listener.handleNoArguments(token); |
| 1127 token = listener.unexpected(token); |
| 1128 } |
| 1114 listener.handleNewExpression(newKeyword, named); | 1129 listener.handleNewExpression(newKeyword, named); |
| 1115 return token; | 1130 return token; |
| 1116 } | 1131 } |
| 1117 | 1132 |
| 1118 Token parseConstExpression(Token token) { | 1133 Token parseConstExpression(Token token) { |
| 1119 Token constKeyword = token; | 1134 Token constKeyword = token; |
| 1120 token = expect('const', token); | 1135 token = expect('const', token); |
| 1121 final String value = token.stringValue; | 1136 final String value = token.stringValue; |
| 1122 if ((value === '<') || | 1137 if ((value === '<') || |
| 1123 (value === '[') || | 1138 (value === '[') || |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 } | 1468 } |
| 1454 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 1469 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 1455 return expectSemicolon(token); | 1470 return expectSemicolon(token); |
| 1456 } | 1471 } |
| 1457 | 1472 |
| 1458 Token parseEmptyStatement(Token token) { | 1473 Token parseEmptyStatement(Token token) { |
| 1459 listener.handleEmptyStatement(token); | 1474 listener.handleEmptyStatement(token); |
| 1460 return expectSemicolon(token); | 1475 return expectSemicolon(token); |
| 1461 } | 1476 } |
| 1462 } | 1477 } |
| OLD | NEW |