Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 29984) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -861,9 +861,7 @@ |
| RawArray* Parser::EvaluateMetadata() { |
| - if (CurrentToken() != Token::kAT) { |
| - ErrorMsg("Metadata character '@' expected"); |
| - } |
| + CheckToken(Token::kAT, "Metadata character '@' expected"); |
| GrowableObjectArray& meta_values = |
| GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| while (CurrentToken() == Token::kAT) { |
| @@ -1690,13 +1688,9 @@ |
| evaluate_metadata, |
| params); |
| if (params->has_optional_positional_parameters) { |
| - if (CurrentToken() != Token::kRBRACK) { |
| - ErrorMsg("',' or ']' expected"); |
| - } |
| + CheckToken(Token::kRBRACK, "',' or ']' expected"); |
| } else { |
| - if (CurrentToken() != Token::kRBRACE) { |
| - ErrorMsg("',' or '}' expected"); |
| - } |
| + CheckToken(Token::kRBRACE, "',' or '}' expected"); |
| } |
| ConsumeToken(); // ']' or '}'. |
| } |
| @@ -1716,9 +1710,7 @@ |
| TRACE_PARSER("ParseNativeDeclaration"); |
| ASSERT(IsLiteral("native")); |
| ConsumeToken(); |
| - if (CurrentToken() != Token::kSTRING) { |
| - ErrorMsg("string literal expected"); |
| - } |
| + CheckToken(Token::kSTRING, "string literal expected"); |
| String& native_name = *CurrentLiteral(); |
| ConsumeToken(); |
| return native_name; |
| @@ -2119,9 +2111,7 @@ |
| ctor_name = String::Concat(ctor_name, |
| *ExpectIdentifier("constructor name expected")); |
| } |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("parameter list expected"); |
| - } |
| + CheckToken(Token::kLPAREN, "parameter list expected"); |
| ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| // 'this' parameter is the first argument to super class constructor. |
| @@ -2380,9 +2370,7 @@ |
| ctor_name = String::Concat(ctor_name, |
| *ExpectIdentifier("constructor name expected")); |
| } |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("parameter list expected"); |
| - } |
| + CheckToken(Token::kLPAREN, "parameter list expected"); |
| ArgumentListNode* arguments = new ArgumentListNode(call_pos); |
| // 'this' parameter is the first argument to constructor. |
| @@ -3002,9 +2990,7 @@ |
| ConsumeToken(); |
| ExpectIdentifier("identifier expected"); |
| } |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| SkipToMatchingParenthesis(); |
| } else { |
| SkipIf(Token::kTHIS); |
| @@ -3215,9 +3201,7 @@ |
| *ExpectIdentifier("constructor name expected")); |
| } |
| method->redirect_name = &redir_name; |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| SkipToMatchingParenthesis(); |
| } else { |
| SkipInitializers(); |
| @@ -3684,9 +3668,7 @@ |
| // Ensure that names are symbols. |
| *member.name = Symbols::New(*member.name); |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("left parenthesis expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| } else if ((CurrentToken() == Token::kGET) && !member.has_var && |
| (LookaheadToken(1) != Token::kLPAREN) && |
| (LookaheadToken(1) != Token::kASSIGN) && |
| @@ -3706,9 +3688,7 @@ |
| member.kind = RawFunction::kSetterFunction; |
| member.name_pos = this->TokenPos(); |
| member.name = ExpectIdentifier("identifier expected"); |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| // The grammar allows a return type, so member.type is not always NULL here. |
| // If no return type is specified, the return type of the setter is dynamic. |
| if (member.type == NULL) { |
| @@ -3941,9 +3921,7 @@ |
| if (is_mixin_declaration) { |
| ExpectSemicolon(); |
| } else { |
| - if (CurrentToken() != Token::kLBRACE) { |
| - ErrorMsg("{ expected"); |
| - } |
| + CheckToken(Token::kLBRACE); |
| SkipBlock(); |
| ExpectToken(Token::kRBRACE); |
| } |
| @@ -4107,9 +4085,7 @@ |
| String::Handle(type.UserVisibleName()).ToCString()); |
| } |
| - if (CurrentToken() != Token::kWITH) { |
| - ErrorMsg("mixin application 'with Type' expected"); |
| - } |
| + CheckToken(Token::kWITH, "mixin application 'with Type' expected"); |
| type = ParseMixins(type); |
| mixin_application.set_super_type(type); |
| @@ -4226,9 +4202,7 @@ |
| &result_type); |
| } |
| // Parse the formal parameters of the function type. |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("formal parameter list expected"); |
| - } |
| + CheckToken(Token::kLPAREN, "formal parameter list expected"); |
| ParamList func_params; |
| // Add implicit closure object parameter. |
| @@ -4654,9 +4628,7 @@ |
| // A setter named x= may co-exist with a function named x, thus we do |
| // not need to check setters. |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| const intptr_t function_pos = TokenPos(); |
| ParamList params; |
| const bool allow_explicit_default_values = true; |
| @@ -4913,9 +4885,7 @@ |
| ASSERT(is_import || is_export); |
| const intptr_t import_pos = TokenPos(); |
| ConsumeToken(); |
| - if (CurrentToken() != Token::kSTRING) { |
| - ErrorMsg("library url expected"); |
| - } |
| + CheckToken(Token::kSTRING, "library url expected"); |
| AstNode* url_literal = ParseStringLiteral(false); |
| ASSERT(url_literal->IsLiteralNode()); |
| ASSERT(url_literal->AsLiteralNode()->literal().IsString()); |
| @@ -5004,9 +4974,7 @@ |
| void Parser::ParseLibraryPart() { |
| const intptr_t source_pos = TokenPos(); |
| ConsumeToken(); // Consume "part". |
| - if (CurrentToken() != Token::kSTRING) { |
| - ErrorMsg("url expected"); |
| - } |
| + CheckToken(Token::kSTRING, "url expected"); |
| AstNode* url_literal = ParseStringLiteral(false); |
| ASSERT(url_literal->IsLiteralNode()); |
| ASSERT(url_literal->AsLiteralNode()->literal().IsString()); |
| @@ -5072,9 +5040,7 @@ |
| void Parser::ParsePartHeader() { |
| SkipMetadata(); |
| - if (CurrentToken() != Token::kPART) { |
| - ErrorMsg("'part of' expected"); |
| - } |
| + CheckToken(Token::kPART, "'part of' expected"); |
| ConsumeToken(); |
| if (!IsLiteral("of")) { |
| ErrorMsg("'part of' expected"); |
| @@ -5584,11 +5550,8 @@ |
| line_number); |
| } |
| } |
| + CheckToken(Token::kLPAREN); |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| - |
| // Check whether we have parsed this closure function before, in a previous |
| // compilation. If so, reuse the function object, else create a new one |
| // and register it in the current class. |
| @@ -6835,8 +6798,7 @@ |
| // Now parse the 'try' block. |
| OpenBlock(); |
| - Block* current_try_block = current_block_; |
| - PushTryBlock(current_try_block); |
| + PushTryBlock(current_block_); |
| ExpectToken(Token::kLBRACE); |
| ParseStatementSequence(); |
| ExpectToken(Token::kRBRACE); |
| @@ -6871,8 +6833,7 @@ |
| exception_param.type = &AbstractType::ZoneHandle( |
| ParseType(ClassFinalizer::kCanonicalize)); |
| } else { |
| - exception_param.type = |
| - &AbstractType::ZoneHandle(Type::DynamicType()); |
| + exception_param.type = &AbstractType::ZoneHandle(Type::DynamicType()); |
| } |
| if (CurrentToken() == Token::kCATCH) { |
| ConsumeToken(); // Consume the 'catch'. |
| @@ -6890,9 +6851,12 @@ |
| ExpectToken(Token::kRPAREN); |
| } |
| - // Parse the individual catch handler code and add an unconditional |
| - // JUMP to the end of the try block. |
| - ExpectToken(Token::kLBRACE); |
| + // Create a block containing the catch clause parameters and |
| + // the following code: |
| + // 1) Store exception object and stack trace object into user-defined |
| + // variables (as needed). |
| + // 2) Nested block with source code from catch clause block. |
| + // 3) unconditional JUMP to the end of the try block. |
|
regis
2013/11/06 21:59:55
Upper-case u.
hausner
2013/11/06 22:07:11
Done.
|
| OpenBlock(); |
| AddCatchParamsToScope(exception_param, |
| stack_trace_param, |
| @@ -6927,18 +6891,21 @@ |
| no_args)); |
| } |
| - ParseStatementSequence(); // Parse the catch handler code. |
| + // Add nested block with user-defined code. |
| + CheckToken(Token::kLBRACE); |
| + current_block_->statements->Add(ParseNestedStatement(false, NULL)); |
| + |
| + // Add unconditional jump to end of catch clause list. |
| current_block_->statements->Add( |
| new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); |
| - SequenceNode* catch_handler = CloseBlock(); |
| - ExpectToken(Token::kRBRACE); |
| + SequenceNode* catch_clause = CloseBlock(); |
| + |
| const bool is_bad_type = exception_param.type->IsMalformed() || |
| exception_param.type->IsMalbounded(); |
| if (!is_bad_type && !exception_param.type->IsDynamicType()) { |
| // Has a type specification that is not malformed or malbounded. |
| - // Now form an 'if type check' as an exception type exists in the |
| - // catch specifier. |
| + // Now form an 'if type check' to guard the catch handler code. |
| if (!exception_param.type->IsInstantiated() && |
| (current_block_->scope->function_level() > 0)) { |
| // Make sure that the instantiator is captured. |
| @@ -6952,7 +6919,7 @@ |
| AstNode* type_cond_expr = new ComparisonNode( |
| catch_pos, Token::kIS, exception_var, exception_type); |
| current_block_->statements->Add( |
| - new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); |
| + new IfNode(catch_pos, type_cond_expr, catch_clause, NULL)); |
| // Do not add uninstantiated types (e.g. type parameter T or |
| // generic type List<T>), since the debugger won't be able to |
| @@ -6970,9 +6937,9 @@ |
| *exception_param.type)); |
| // We still add the dead code below to satisfy the code generator. |
| } |
| - // No exception type exists in the catch specifier so execute the |
| + // No exception type exists in the catch clause so execute the |
| // catch handler code unconditionally. |
| - current_block_->statements->Add(catch_handler); |
| + current_block_->statements->Add(catch_clause); |
| generic_catch_seen = true; |
| // This catch clause will handle all exceptions. We can safely forget |
| // all previous catch clause types. |
| @@ -6980,6 +6947,7 @@ |
| handler_types.Add(*exception_param.type); |
| } |
| } |
| + |
| SequenceNode* catch_handler_list = CloseBlock(); |
| TryBlocks* inner_try_block = PopTryBlock(); |
| const intptr_t try_index = inner_try_block->try_index(); |
| @@ -7401,6 +7369,17 @@ |
| } |
| +void Parser::CheckToken(Token::Kind token_expected, const char* msg) { |
| + if (CurrentToken() != token_expected) { |
| + if (msg != NULL) { |
| + ErrorMsg("%s", msg); |
| + } else { |
| + ErrorMsg("'%s' expected", Token::Str(token_expected)); |
| + } |
| + } |
| +} |
| + |
| + |
| void Parser::ExpectToken(Token::Kind token_expected) { |
| if (CurrentToken() != token_expected) { |
| ErrorMsg("'%s' expected", Token::Str(token_expected)); |
| @@ -8202,9 +8181,7 @@ |
| AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) { |
| TRACE_PARSER("ParseInstanceCall"); |
| const intptr_t call_pos = TokenPos(); |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg(call_pos, "left parenthesis expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
| return new InstanceCallNode(call_pos, receiver, func_name, arguments); |
| } |
| @@ -9278,9 +9255,7 @@ |
| RawAbstractType* Parser::ParseType( |
| ClassFinalizer::FinalizationKind finalization) { |
| TRACE_PARSER("ParseType"); |
| - if (CurrentToken() != Token::kIDENT) { |
| - ErrorMsg("type name expected"); |
| - } |
| + CheckToken(Token::kIDENT, "type name expected"); |
| QualIdent type_name; |
| if (finalization == ClassFinalizer::kIgnore) { |
| if (!is_top_level_ && (current_block_ != NULL)) { |
| @@ -9897,9 +9872,7 @@ |
| } |
| // Parse constructor parameters. |
| - if (CurrentToken() != Token::kLPAREN) { |
| - ErrorMsg("'(' expected"); |
| - } |
| + CheckToken(Token::kLPAREN); |
| intptr_t call_pos = TokenPos(); |
| ArgumentListNode* arguments = ParseActualParameters(NULL, is_const); |