| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 12920)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -6373,33 +6373,30 @@
|
| } else if (CurrentToken() == Token::kSEMICOLON) {
|
| // Empty statement, nothing to do.
|
| ConsumeToken();
|
| - } else if (CurrentToken() == Token::kTHROW) {
|
| + } else if ((CurrentToken() == Token::kTHROW) &&
|
| + (LookaheadToken(1) == Token::kSEMICOLON)) {
|
| + // Rethrow of current exception. Throwing of an exception object
|
| + // is an expression and is handled in ParseExpr().
|
| ConsumeToken();
|
| - AstNode* expr = NULL;
|
| - if (CurrentToken() != Token::kSEMICOLON) {
|
| - expr = ParseExpr(kAllowConst, kConsumeCascades);
|
| - ExpectSemicolon();
|
| - statement = new ThrowNode(statement_pos, expr, NULL);
|
| - } else { // No exception object seen so must be a rethrow.
|
| - // Check if it is ok to do a rethrow.
|
| - SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel();
|
| - if (label == NULL ||
|
| - label->FunctionLevel() != current_block_->scope->function_level()) {
|
| - ErrorMsg("rethrow of an exception is not valid here");
|
| - }
|
| - ASSERT(label->owner() != NULL);
|
| - LocalScope* scope = label->owner()->parent();
|
| - ASSERT(scope != NULL);
|
| - LocalVariable* excp_var = scope->LocalLookupVariable(
|
| - String::ZoneHandle(Symbols::ExceptionVar()));
|
| - ASSERT(excp_var != NULL);
|
| - LocalVariable* trace_var = scope->LocalLookupVariable(
|
| - String::ZoneHandle(Symbols::StacktraceVar()));
|
| - ASSERT(trace_var != NULL);
|
| - statement = new ThrowNode(statement_pos,
|
| - new LoadLocalNode(statement_pos, excp_var),
|
| - new LoadLocalNode(statement_pos, trace_var));
|
| + ExpectSemicolon();
|
| + // Check if it is ok to do a rethrow.
|
| + SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel();
|
| + if (label == NULL ||
|
| + label->FunctionLevel() != current_block_->scope->function_level()) {
|
| + ErrorMsg(statement_pos, "rethrow of an exception is not valid here");
|
| }
|
| + ASSERT(label->owner() != NULL);
|
| + LocalScope* scope = label->owner()->parent();
|
| + ASSERT(scope != NULL);
|
| + LocalVariable* excp_var = scope->LocalLookupVariable(
|
| + String::ZoneHandle(Symbols::ExceptionVar()));
|
| + ASSERT(excp_var != NULL);
|
| + LocalVariable* trace_var = scope->LocalLookupVariable(
|
| + String::ZoneHandle(Symbols::StacktraceVar()));
|
| + ASSERT(trace_var != NULL);
|
| + statement = new ThrowNode(statement_pos,
|
| + new LoadLocalNode(statement_pos, excp_var),
|
| + new LoadLocalNode(statement_pos, trace_var));
|
| } else {
|
| statement = ParseExpr(kAllowConst, kConsumeCascades);
|
| ExpectSemicolon();
|
| @@ -7007,6 +7004,13 @@
|
| bool consume_cascades) {
|
| TRACE_PARSER("ParseExpr");
|
| const intptr_t expr_pos = TokenPos();
|
| +
|
| + if (CurrentToken() == Token::kTHROW) {
|
| + ConsumeToken();
|
| + ASSERT(CurrentToken() != Token::kSEMICOLON);
|
| + AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
|
| + return new ThrowNode(expr_pos, expr, NULL);
|
| + }
|
| AstNode* expr = ParseConditionalExpr();
|
| if (!Token::IsAssignmentOperator(CurrentToken())) {
|
| if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
|
| @@ -9666,6 +9670,9 @@
|
|
|
|
|
| void Parser::SkipExpr() {
|
| + while (CurrentToken() == Token::kTHROW) {
|
| + ConsumeToken();
|
| + }
|
| SkipConditionalExpr();
|
| if (CurrentToken() == Token::kCASCADE) {
|
| SkipSelectors();
|
|
|