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

Unified Diff: runtime/vm/parser.cc

Issue 9107070: Proper handling of built-in identifiers (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 11 months 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') | runtime/vm/token.h » ('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 3300)
+++ runtime/vm/parser.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -246,9 +246,6 @@
if (token_kind_ == Token::kERROR) {
ErrorMsg(token_index_, CurrentLiteral()->ToCString());
}
- if (Token::IsPseudoKeyword(token_kind_) && !is_top_level_) {
- token_kind_ = Token::kIDENT;
- }
}
CompilerStats::num_token_checks++;
return token_kind_;
@@ -637,7 +634,7 @@
AddFormalParamsToScope(&params, current_block_->scope);
// Static const fields must have an initializer.
- ExpectToken(Token::kIDENT);
+ ExpectIdentifier("field name expected");
ExpectToken(Token::kASSIGN);
// We don't want to use ParseConstExpr() here because we don't want
@@ -677,7 +674,7 @@
LoadLocalNode* load_receiver = new LoadLocalNode(token_index_, *receiver);
// token_index_ is the function's token position which points to the name of
// the field;
- ASSERT(CurrentToken() == Token::kIDENT);
+ ASSERT(IsIdentifier());
const String& field_name = *CurrentLiteral();
const Class& field_class = Class::Handle(func.owner());
const Field& field =
@@ -813,7 +810,7 @@
if (parameter.type == NULL) {
// At this point, we must see an identifier for the type or the
// function parameter.
- if (CurrentToken() != Token::kIDENT) {
+ if (!IsIdentifier()) {
ErrorMsg("parameter name or type expected");
}
// We have not seen a parameter type yet, so we check if the next
@@ -823,7 +820,7 @@
// We either parse a type or assume that no type is specified.
if ((follower == Token::kLT) || // Parameterized type.
(follower == Token::kPERIOD) || // Qualified class name of type.
- (follower == Token::kIDENT) || // Parameter name following a type.
+ Token::IsIdentifier(follower) || // Parameter name following a type.
(follower == Token::kTHIS)) { // Field parameter following a type.
parameter.type = &AbstractType::ZoneHandle(
ParseType(is_top_level_ ? kCanResolve : kMustResolve));
@@ -837,13 +834,11 @@
this_seen = true;
parameter.is_field_initializer = true;
}
+
// At this point, we must see an identifier for the parameter name.
- if (CurrentToken() != Token::kIDENT) {
- ErrorMsg("parameter name expected");
- }
- parameter.name = CurrentLiteral();
parameter.name_pos = token_index_;
- ConsumeToken();
+ parameter.name = ExpectIdentifier("parameter name expected");
+
if (parameter.is_field_initializer) {
params->has_field_initializer = true;
}
@@ -1386,7 +1381,7 @@
field ^= fields.At(i);
intptr_t field_pos = field.token_index();
SetPosition(field_pos);
- ASSERT(CurrentToken() == Token::kIDENT);
+ ASSERT(IsIdentifier());
ConsumeToken();
ExpectToken(Token::kASSIGN);
AstNode* init_expr = ParseConstExpr();
@@ -1917,7 +1912,7 @@
void Parser::ParseQualIdent(QualIdent* qual_ident) {
- ASSERT(CurrentToken() == Token::kIDENT);
+ ASSERT(IsIdentifier());
if (!is_top_level_) {
bool is_local_ident = ResolveIdentInLocalScope(token_index_,
*CurrentLiteral(),
@@ -2272,11 +2267,13 @@
void Parser::ParseClassMemberDefinition(ClassDesc* members) {
MemberDesc member;
current_member_ = &member;
- if (CurrentToken() == Token::kABSTRACT) {
+ if ((CurrentToken() == Token::kABSTRACT) &&
+ (LookaheadToken(1) != Token::kLPAREN)) {
ConsumeToken();
member.has_abstract = true;
}
- if (CurrentToken() == Token::kSTATIC) {
+ if ((CurrentToken() == Token::kSTATIC) &&
+ (LookaheadToken(1) != Token::kLPAREN)) {
ConsumeToken();
member.has_static = true;
}
@@ -2324,7 +2321,7 @@
(follower == Token::kGET) || // Getter following a type.
(follower == Token::kSET) || // Setter following a type.
(follower == Token::kOPERATOR) || // Operator following a type.
- (follower == Token::kIDENT) || // Member name following a type.
+ (Token::IsIdentifier(follower)) || // Member name following a type.
((follower == Token::kPERIOD) && // Qualified class name of type,
(LookaheadToken(3) != Token::kLPAREN))) { // but not a named constr.
ASSERT(is_top_level_);
@@ -2333,7 +2330,7 @@
}
}
// Optionally parse a (possibly named) constructor name or factory.
- if ((CurrentToken() == Token::kIDENT) &&
+ if (IsIdentifier() &&
(CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) {
member.name = CurrentLiteral();
member.name_pos = this->token_index_;
@@ -2403,13 +2400,15 @@
if (CurrentToken() != Token::kLPAREN) {
ErrorMsg("left parenthesis expected");
}
- } else if (CurrentToken() == Token::kGET) {
+ } else if ((CurrentToken() == Token::kGET) &&
+ (LookaheadToken(1) != Token::kLPAREN) && !member.has_var) {
ConsumeToken();
member.kind = RawFunction::kGetterFunction;
member.name_pos = this->token_index_;
member.name = ExpectIdentifier("identifier expected");
// If the result type was not specified, it will be set to DynamicType.
- } else if (CurrentToken() == Token::kSET) {
+ } else if ((CurrentToken() == Token::kSET) &&
+ (LookaheadToken(1) != Token::kLPAREN) && !member.has_var) {
ConsumeToken();
member.kind = RawFunction::kSetterFunction;
member.name_pos = this->token_index_;
@@ -2419,7 +2418,8 @@
if (member.type == NULL) {
member.type = &Type::ZoneHandle(Type::DynamicType());
}
- } else if (CurrentToken() == Token::kOPERATOR) {
+ } else if ((CurrentToken() == Token::kOPERATOR) &&
+ (LookaheadToken(1) != Token::kLPAREN) && !member.has_var) {
ConsumeToken();
if (!Token::CanBeOverloaded(CurrentToken())) {
ErrorMsg("invalid operator overloading");
@@ -2432,7 +2432,7 @@
member.name =
&String::ZoneHandle(String::NewSymbol(Token::Str(CurrentToken())));
ConsumeToken();
- } else if (CurrentToken() == Token::kIDENT) {
+ } else if (IsIdentifier()) {
member.name = CurrentLiteral();
member.name_pos = token_index_;
ConsumeToken();
@@ -2482,7 +2482,7 @@
const intptr_t class_pos = token_index_;
ExpectToken(Token::kCLASS);
const intptr_t classname_pos = token_index_;
- String& class_name = *ExpectIdentifier("class name expected");
+ String& class_name = *ExpectTypeIdentifier("class name expected");
if (FLAG_trace_parser) {
OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
}
@@ -2624,14 +2624,12 @@
// and the alias name of a function type alias.
// Token position remains unchanged.
bool Parser::IsFunctionTypeAliasName() {
- if ((CurrentToken() == Token::kIDENT) &&
- (LookaheadToken(1) == Token::kLPAREN)) {
+ if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
return true;
}
const intptr_t saved_pos = token_index_;
bool is_alias_name = false;
- if ((CurrentToken() == Token::kIDENT) &&
- (LookaheadToken(1) == Token::kLT)) {
+ if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
ConsumeToken();
if (IsTypeParameter() && (CurrentToken() == Token::kLPAREN)) {
is_alias_name = true;
@@ -2655,12 +2653,9 @@
result_type = ParseType(kDoNotResolve); // No owner class yet.
}
- if (CurrentToken() != Token::kIDENT) {
- ErrorMsg("function alias name expected");
- }
const intptr_t alias_name_pos = token_index_;
- const String* alias_name = CurrentLiteral();
- ConsumeToken();
+ const String* alias_name =
+ ExpectTypeIdentifier("function alias name expected");
// Allocate an interface to hold the type parameters and their 'extends'
// constraints. Make it the owner of the function type descriptor.
@@ -2737,7 +2732,7 @@
const intptr_t interface_pos = token_index_;
ExpectToken(Token::kINTERFACE);
const intptr_t interfacename_pos = token_index_;
- String& interface_name = *ExpectIdentifier("interface name expected");
+ String& interface_name = *ExpectTypeIdentifier("interface name expected");
if (FLAG_trace_parser) {
OS::Print("TopLevel parsing interface '%s'\n", interface_name.ToCString());
}
@@ -3280,9 +3275,7 @@
String& prefix = String::Handle();
if (CurrentToken() == Token::kCOMMA) {
ConsumeToken();
- const String& kPrefix = String::Handle(String::NewSymbol("prefix"));
- if ((CurrentToken() != Token::kIDENT) ||
- !kPrefix.Equals(*CurrentLiteral())) {
+ if (!IsLiteral("prefix")) {
ErrorMsg("prefix: expected");
}
ConsumeToken();
@@ -3381,7 +3374,8 @@
set_current_class(Class::Handle()); // No current class.
if (CurrentToken() == Token::kCLASS) {
ParseClassDefinition(&classes);
- } else if (CurrentToken() == Token::kTYPEDEF) {
+ } else if ((CurrentToken() == Token::kTYPEDEF) &&
+ (LookaheadToken(1) != Token::kLPAREN)) {
ParseFunctionTypeAlias(&classes);
} else if (CurrentToken() == Token::kINTERFACE) {
ParseInterfaceDefinition(&classes);
@@ -3618,7 +3612,7 @@
AstNode* Parser::ParseVariableDeclaration(
const AbstractType& type, bool is_final) {
TRACE_PARSER("ParseVariableDeclaration");
- ASSERT(CurrentToken() == Token::kIDENT);
+ ASSERT(IsIdentifier());
const intptr_t ident_pos = token_index_;
LocalVariable* variable =
new LocalVariable(ident_pos, *CurrentLiteral(), type);
@@ -3671,7 +3665,7 @@
if (type_specification == kIsOptional) {
return Type::DynamicType();
} else {
- ErrorMsg("identifier expected");
+ ErrorMsg("type name expected");
}
}
if (type_specification == kIsOptional) {
@@ -3680,7 +3674,7 @@
// We either parse a type or return now.
if ((follower != Token::kLT) && // Parameterized type.
(follower != Token::kPERIOD) && // Qualified class name of type.
- (follower != Token::kIDENT) && // Variable name following a type.
+ !Token::IsIdentifier(follower) && // Variable name following a type.
(follower != Token::kTHIS)) { // Field parameter following a type.
return Type::DynamicType();
}
@@ -3697,7 +3691,7 @@
bool is_final = (CurrentToken() == Token::kFINAL);
const AbstractType& type = AbstractType::ZoneHandle(
ParseFinalVarOrType(kIsMandatory, kMustResolve));
- if (CurrentToken() != Token::kIDENT) {
+ if (!IsIdentifier()) {
ErrorMsg("identifier expected");
}
@@ -3705,7 +3699,7 @@
ASSERT(initializers != NULL);
while (CurrentToken() == Token::kCOMMA) {
ConsumeToken();
- if (CurrentToken() != Token::kIDENT) {
+ if (!IsIdentifier()) {
ErrorMsg("identifier expected after comma");
}
// We have a second initializer. Allocate a sequence node now.
@@ -3735,7 +3729,7 @@
result_type = ParseType(kMustResolve);
}
const intptr_t ident_pos = token_index_;
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
variable_name = CurrentLiteral();
function_name = variable_name;
ConsumeToken();
@@ -3926,6 +3920,12 @@
}
+// Returns true if the current token is kIDENT or a pseudo-keyword.
+bool Parser::IsIdentifier() {
+ return Token::IsIdentifier(CurrentToken());
+}
+
+
// Returns true if the next tokens can be parsed as a type with optional
// type parameters. Current token position is not restored.
bool Parser::IsOptionalType() {
@@ -3969,12 +3969,13 @@
return true;
}
if (CurrentToken() != Token::kIDENT) {
+ // Not a legal type identifier.
return false;
}
const intptr_t saved_pos = token_index_;
bool is_var_decl = false;
if (IsOptionalType()) {
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
ConsumeToken();
if ((CurrentToken() == Token::kSEMICOLON) ||
(CurrentToken() == Token::kCOMMA) ||
@@ -3998,9 +3999,8 @@
bool Parser::IsTopLevelFunction() {
// Top-level function declarations can omit the return type. Check for
// that case separately.
- return ((CurrentToken() == Token::kIDENT) &&
- (LookaheadToken(1) == Token::kLPAREN)) ||
- IsFunctionDeclaration();
+ return (IsIdentifier() &&
+ (LookaheadToken(1) == Token::kLPAREN)) || IsFunctionDeclaration();
}
@@ -4011,7 +4011,7 @@
const intptr_t saved_pos = token_index_;
if (IsReturnType()) {
if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
- if (LookaheadToken(1) == Token::kIDENT) { // Accessor name.
+ if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name.
SetPosition(saved_pos);
return true;
}
@@ -4028,11 +4028,10 @@
}
const intptr_t saved_pos = token_index_;
bool is_function_literal = false;
- if ((CurrentToken() == Token::kIDENT) &&
- (LookaheadToken(1) == Token::kLPAREN)) {
+ if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
ConsumeToken(); // Consume function identifier.
} else if (IsReturnType()) {
- if (CurrentToken() != Token::kIDENT) {
+ if (!IsIdentifier()) {
SetPosition(saved_pos);
return false;
}
@@ -4059,11 +4058,11 @@
if (CurrentToken() == Token::kVAR || CurrentToken() == Token::kFINAL) {
ConsumeToken();
}
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
if (LookaheadToken(1) == Token::kIN) {
result = true;
} else if (IsOptionalType()) {
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
ConsumeToken();
}
result = (CurrentToken() == Token::kIN);
@@ -4214,8 +4213,7 @@
// clause. If we see 'case' or 'default', optionally preceeded by
// a label, or closing brace, we stop parsing statements.
Token::Kind next_token;
- if (CurrentToken() == Token::kIDENT &&
- LookaheadToken(1) == Token::kCOLON) {
+ if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) {
next_token = LookaheadToken(2);
} else {
next_token = CurrentToken();
@@ -4288,8 +4286,7 @@
while (true) {
// Check for statement label
SourceLabel* case_label = NULL;
- if (CurrentToken() == Token::kIDENT &&
- LookaheadToken(1) == Token::kCOLON) {
+ if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) {
// Case statements start with a label.
String* label_name = CurrentLiteral();
const intptr_t label_pos = token_index_;
@@ -4648,12 +4645,8 @@
catch_param->is_final = (CurrentToken() == Token::kFINAL);
catch_param->type = &AbstractType::ZoneHandle(
ParseFinalVarOrType(kIsMandatory, kMustResolve));
- if (CurrentToken() != Token::kIDENT) {
- ErrorMsg("identifier expected");
- }
catch_param->token_index = token_index_;
- catch_param->var = CurrentLiteral();
- ConsumeToken();
+ catch_param->var = ExpectIdentifier("identifier expected");
}
@@ -4988,7 +4981,7 @@
const intptr_t jump_pos = token_index_;
SourceLabel* target = NULL;
ConsumeToken();
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
// Explicit label after break/continue.
const String& target_name = *CurrentLiteral();
ConsumeToken();
@@ -5044,12 +5037,22 @@
}
+bool Parser::IsDefinedInLexicalScope(const String& ident) {
+ if (ResolveIdentInLocalScope(token_index_, ident, NULL)) {
+ return true;
+ }
+ Object& obj = Object::Handle();
+ obj = library_.LookupObject(ident);
+ return !obj.IsNull();
+}
+
+
AstNode* Parser::ParseStatement() {
TRACE_PARSER("ParseStatement");
AstNode* statement = NULL;
intptr_t label_pos = 0;
String* label_name = NULL;
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
if (LookaheadToken(1) == Token::kCOLON) {
// Statement starts with a label.
label_name = CurrentLiteral();
@@ -5088,7 +5091,8 @@
ExpectSemicolon();
} else if (CurrentToken() == Token::kIF) {
statement = ParseIfStatement(label_name);
- } else if (CurrentToken() == Token::kASSERT) {
+ } else if ((CurrentToken() == Token::kASSERT) &&
+ !IsDefinedInLexicalScope(*CurrentLiteral())) {
statement = ParseAssertStatement();
ExpectSemicolon();
} else if (IsVariableDeclaration()) {
@@ -5314,7 +5318,7 @@
}
-String* Parser::ExpectIdentifier(const char* msg) {
+String* Parser::ExpectTypeIdentifier(const char* msg) {
if (CurrentToken() != Token::kIDENT) {
ErrorMsg(msg);
}
@@ -5323,12 +5327,21 @@
return ident;
}
+// Check whether current token is an identifier or a built-in identifier.
+String* Parser::ExpectIdentifier(const char* msg) {
+ if (!IsIdentifier()) {
+ ErrorMsg(msg);
+ }
+ String* ident = CurrentLiteral();
+ ConsumeToken();
+ return ident;
+}
+
bool Parser::IsLiteral(const char* literal) {
const uint8_t* characters = reinterpret_cast<const uint8_t*>(literal);
intptr_t len = strlen(literal);
- return (CurrentToken() == Token::kIDENT)
- && CurrentLiteral()->Equals(characters, len);
+ return IsIdentifier() && CurrentLiteral()->Equals(characters, len);
}
@@ -5704,8 +5717,7 @@
ASSERT((CurrentToken() == Token::kLPAREN) ||
(CurrentToken() == Token::kCOMMA));
ConsumeToken();
- if ((CurrentToken() == Token::kIDENT) &&
- (LookaheadToken(1) == Token::kCOLON)) {
+ if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) {
named_argument_seen = true;
// The canonicalization of the argument descriptor array built in the
// code generator requires that the names are symbols, i.e.
@@ -7089,7 +7101,7 @@
ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
bool is_const = (CurrentToken() == Token::kCONST);
ConsumeToken();
- if (CurrentToken() != Token::kIDENT) {
+ if (!IsIdentifier()) {
ErrorMsg("type name expected");
}
@@ -7350,7 +7362,7 @@
OpenBlock();
primary = ParseFunctionStatement(true);
CloseBlock();
- } else if (CurrentToken() == Token::kIDENT) {
+ } else if (IsIdentifier()) {
QualIdent qual_ident;
ParseQualIdent(&qual_ident);
if (qual_ident.is_local_scope_ident) {
@@ -7486,7 +7498,7 @@
void Parser::SkipFunctionLiteral() {
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
if (LookaheadToken(1) != Token::kLPAREN) {
SkipType(true);
}
@@ -7564,7 +7576,7 @@
void Parser::SkipNewOperator() {
ConsumeToken(); // Skip new or const keyword.
- if (CurrentToken() == Token::kIDENT) {
+ if (IsIdentifier()) {
SkipType(false);
if (CurrentToken() == Token::kLPAREN) {
SkipActualParameters();
@@ -7644,8 +7656,12 @@
SkipCompoundLiteral();
break;
default:
- UnexpectedToken();
- UNREACHABLE();
+ if (IsIdentifier()) {
+ ConsumeToken(); // Handle pseudo-keyword identifiers.
+ } else {
+ UnexpectedToken();
+ UNREACHABLE();
+ }
break;
}
}
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/token.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698