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. |
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); |