Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Unified Diff: runtime/vm/parser.cc

Issue 63033003: Fix try-catch for sure (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/try_catch_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/try_catch_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698