OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 | 725 |
726 void Parser::ParseClass(const Class& cls) { | 726 void Parser::ParseClass(const Class& cls) { |
727 if (!cls.is_synthesized_class()) { | 727 if (!cls.is_synthesized_class()) { |
728 Isolate* isolate = Isolate::Current(); | 728 Isolate* isolate = Isolate::Current(); |
729 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer); | 729 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer); |
730 ASSERT(isolate->long_jump_base()->IsSafeToJump()); | 730 ASSERT(isolate->long_jump_base()->IsSafeToJump()); |
731 const Script& script = Script::Handle(isolate, cls.script()); | 731 const Script& script = Script::Handle(isolate, cls.script()); |
732 const Library& lib = Library::Handle(isolate, cls.library()); | 732 const Library& lib = Library::Handle(isolate, cls.library()); |
733 Parser parser(script, lib, cls.token_pos()); | 733 Parser parser(script, lib, cls.token_pos()); |
734 parser.ParseClassDefinition(cls); | 734 parser.ParseClassDefinition(cls); |
735 } else if (cls.is_enum_class()) { | |
736 Isolate* isolate = Isolate::Current(); | |
737 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer); | |
738 ASSERT(isolate->long_jump_base()->IsSafeToJump()); | |
739 const Script& script = Script::Handle(isolate, cls.script()); | |
740 const Library& lib = Library::Handle(isolate, cls.library()); | |
741 Parser parser(script, lib, cls.token_pos()); | |
742 parser.ParseEnumDefinition(cls); | |
735 } | 743 } |
736 } | 744 } |
737 | 745 |
738 | 746 |
739 RawObject* Parser::ParseFunctionParameters(const Function& func) { | 747 RawObject* Parser::ParseFunctionParameters(const Function& func) { |
740 ASSERT(!func.IsNull()); | 748 ASSERT(!func.IsNull()); |
741 Isolate* isolate = Isolate::Current(); | 749 Isolate* isolate = Isolate::Current(); |
742 StackZone zone(isolate); | 750 StackZone zone(isolate); |
743 LongJumpScope jump; | 751 LongJumpScope jump; |
744 if (setjmp(*jump.Set()) == 0) { | 752 if (setjmp(*jump.Set()) == 0) { |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1118 ASSERT(!func.HasOptionalParameters()); | 1126 ASSERT(!func.HasOptionalParameters()); |
1119 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); | 1127 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); |
1120 | 1128 |
1121 // Build local scope for function and populate with the formal parameters. | 1129 // Build local scope for function and populate with the formal parameters. |
1122 OpenFunctionBlock(func); | 1130 OpenFunctionBlock(func); |
1123 AddFormalParamsToScope(¶ms, current_block_->scope); | 1131 AddFormalParamsToScope(¶ms, current_block_->scope); |
1124 | 1132 |
1125 // Receiver is local 0. | 1133 // Receiver is local 0. |
1126 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 1134 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
1127 LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver); | 1135 LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver); |
1128 ASSERT(IsIdentifier()); | 1136 String& field_name = String::Handle(I, func.name()); |
1129 const String& field_name = *CurrentLiteral(); | 1137 field_name = Field::NameFromGetter(field_name); |
1138 | |
1130 const Class& field_class = Class::Handle(I, func.Owner()); | 1139 const Class& field_class = Class::Handle(I, func.Owner()); |
1131 const Field& field = | 1140 const Field& field = |
1132 Field::ZoneHandle(I, field_class.LookupInstanceField(field_name)); | 1141 Field::ZoneHandle(I, field_class.LookupInstanceField(field_name)); |
1142 ASSERT(!field.IsNull()); | |
1133 | 1143 |
1134 LoadInstanceFieldNode* load_field = | 1144 LoadInstanceFieldNode* load_field = |
1135 new LoadInstanceFieldNode(ident_pos, load_receiver, field); | 1145 new LoadInstanceFieldNode(ident_pos, load_receiver, field); |
1136 | 1146 |
1137 ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, load_field); | 1147 ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, load_field); |
1138 current_block_->statements->Add(return_node); | 1148 current_block_->statements->Add(return_node); |
1139 return CloseBlock(); | 1149 return CloseBlock(); |
1140 } | 1150 } |
1141 | 1151 |
1142 | 1152 |
(...skipping 1901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3044 } else if (func.is_async_closure()) { | 3054 } else if (func.is_async_closure()) { |
3045 OpenAsyncClosure(); | 3055 OpenAsyncClosure(); |
3046 } | 3056 } |
3047 | 3057 |
3048 bool saved_await_is_keyword = await_is_keyword_; | 3058 bool saved_await_is_keyword = await_is_keyword_; |
3049 await_is_keyword_ = func.IsAsyncFunction() || func.is_async_closure(); | 3059 await_is_keyword_ = func.IsAsyncFunction() || func.is_async_closure(); |
3050 | 3060 |
3051 intptr_t end_token_pos = 0; | 3061 intptr_t end_token_pos = 0; |
3052 if (CurrentToken() == Token::kLBRACE) { | 3062 if (CurrentToken() == Token::kLBRACE) { |
3053 ConsumeToken(); | 3063 ConsumeToken(); |
3054 if (String::Handle(I, func.name()).Equals( | 3064 if (String::Handle(I, func.name()).Equals(Symbols::EqualOperator())) { |
3055 Symbols::EqualOperator())) { | |
3056 const Class& owner = Class::Handle(I, func.Owner()); | 3065 const Class& owner = Class::Handle(I, func.Owner()); |
3057 if (!owner.IsObjectClass()) { | 3066 if (!owner.IsObjectClass()) { |
3058 AddEqualityNullCheck(); | 3067 AddEqualityNullCheck(); |
3059 } | 3068 } |
3060 } | 3069 } |
3061 ParseStatementSequence(); | 3070 ParseStatementSequence(); |
3062 end_token_pos = TokenPos(); | 3071 end_token_pos = TokenPos(); |
3063 ExpectToken(Token::kRBRACE); | 3072 ExpectToken(Token::kRBRACE); |
3064 } else if (CurrentToken() == Token::kARROW) { | 3073 } else if (CurrentToken() == Token::kARROW) { |
3065 ConsumeToken(); | 3074 ConsumeToken(); |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3995 ParseFieldDefinition(members, &member); | 4004 ParseFieldDefinition(members, &member); |
3996 } else { | 4005 } else { |
3997 UnexpectedToken(); | 4006 UnexpectedToken(); |
3998 } | 4007 } |
3999 current_member_ = NULL; | 4008 current_member_ = NULL; |
4000 CheckMemberNameConflict(members, &member); | 4009 CheckMemberNameConflict(members, &member); |
4001 members->AddMember(member); | 4010 members->AddMember(member); |
4002 } | 4011 } |
4003 | 4012 |
4004 | 4013 |
4014 void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, | |
4015 const Class& toplevel_class, | |
4016 intptr_t metadata_pos) { | |
4017 TRACE_PARSER("ParseEnumDeclaration"); | |
4018 ConsumeToken(); | |
4019 const intptr_t enum_pos = TokenPos(); | |
4020 String* enum_name = | |
4021 ExpectUserDefinedTypeIdentifier("enum type name expected"); | |
4022 if (FLAG_trace_parser) { | |
4023 OS::Print("TopLevel parsing enum '%s'\n", enum_name->ToCString()); | |
4024 } | |
4025 ExpectToken(Token::kLBRACE); | |
4026 if (!IsIdentifier()) { | |
4027 ReportError("Enumeration must have at least one name"); | |
4028 } | |
4029 while (IsIdentifier()) { | |
4030 ConsumeToken(); | |
4031 if (CurrentToken() == Token::kCOMMA) { | |
4032 ConsumeToken(); | |
4033 if (CurrentToken() == Token::kRBRACE) { | |
4034 break; | |
4035 } | |
4036 } else if (CurrentToken() == Token::kRBRACE) { | |
4037 break; | |
4038 } else { | |
4039 ReportError(", or } expected"); | |
4040 } | |
4041 } | |
4042 ExpectToken(Token::kRBRACE); | |
4043 | |
4044 Object& obj = Object::Handle(I, library_.LookupLocalObject(*enum_name)); | |
4045 if (!obj.IsNull()) { | |
4046 ReportError(enum_pos, "'%s' is already defined", enum_name->ToCString()); | |
4047 } | |
4048 Class& cls = Class::Handle(I); | |
4049 cls = Class::New(*enum_name, script_, enum_pos); | |
4050 cls.set_library(library_); | |
4051 library_.AddClass(cls); | |
4052 cls.set_is_synthesized_class(); | |
4053 cls.set_is_enum_class(); | |
4054 if (metadata_pos >= 0) { | |
4055 library_.AddClassMetadata(cls, toplevel_class, metadata_pos); | |
4056 } | |
4057 cls.set_super_type(Type::Handle(I, Type::ObjectType())); | |
4058 pending_classes.Add(cls, Heap::kOld); | |
4059 } | |
4060 | |
4061 | |
4005 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, | 4062 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, |
4006 const Class& toplevel_class, | 4063 const Class& toplevel_class, |
4007 intptr_t metadata_pos) { | 4064 intptr_t metadata_pos) { |
4008 TRACE_PARSER("ParseClassDeclaration"); | 4065 TRACE_PARSER("ParseClassDeclaration"); |
4009 bool is_patch = false; | 4066 bool is_patch = false; |
4010 bool is_abstract = false; | 4067 bool is_abstract = false; |
4011 if (is_patch_source() && | 4068 if (is_patch_source() && |
4012 (CurrentToken() == Token::kIDENT) && | 4069 (CurrentToken() == Token::kIDENT) && |
4013 CurrentLiteral()->Equals("patch")) { | 4070 CurrentLiteral()->Equals("patch")) { |
4014 ConsumeToken(); | 4071 ConsumeToken(); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4237 const Class& orig_class = Class::Cast(obj); | 4294 const Class& orig_class = Class::Cast(obj); |
4238 ASSERT(!orig_class.is_finalized()); | 4295 ASSERT(!orig_class.is_finalized()); |
4239 Error& error = Error::Handle(I); | 4296 Error& error = Error::Handle(I); |
4240 if (!orig_class.ApplyPatch(cls, &error)) { | 4297 if (!orig_class.ApplyPatch(cls, &error)) { |
4241 Report::LongJumpF(error, script_, class_pos, "applying patch failed"); | 4298 Report::LongJumpF(error, script_, class_pos, "applying patch failed"); |
4242 } | 4299 } |
4243 } | 4300 } |
4244 } | 4301 } |
4245 | 4302 |
4246 | 4303 |
4304 void Parser::ParseEnumDefinition(const Class& cls) { | |
4305 TRACE_PARSER("ParseEnumDefinition"); | |
4306 CompilerStats::num_classes_compiled++; | |
4307 | |
4308 const String& enum_name = String::Handle(I, cls.Name()); | |
4309 ClassDesc enum_members(cls, enum_name, false, cls.token_pos()); | |
4310 | |
4311 // Add instance field 'final int index'. | |
4312 Field& index_field = Field::ZoneHandle(I); | |
4313 const Type& int_type = Type::Handle(I, Type::IntType()); | |
4314 const Type& dynamic_type = Type::Handle(Type::DynamicType()); | |
4315 index_field = Field::New(Symbols::Index(), | |
4316 false, // Not static. | |
4317 true, // Field is final. | |
4318 false, // Not const. | |
4319 false, // Not synthetic. | |
4320 cls, | |
4321 cls.token_pos()); | |
4322 index_field.set_type(int_type); | |
4323 enum_members.AddField(index_field); | |
4324 | |
4325 // Add implicit getter for index field. | |
4326 const String& getter_name = | |
4327 String::Handle(I, Field::GetterSymbol(Symbols::Index())); | |
4328 Function& getter = Function::Handle(I); | |
4329 getter = Function::New(getter_name, | |
4330 RawFunction::kImplicitGetter, | |
4331 /* is_static = */ false, | |
4332 /* is_const = */ true, | |
4333 /* is_abstract = */ false, | |
4334 /* is_external = */ false, | |
4335 /* is_native = */ false, | |
4336 cls, | |
4337 cls.token_pos()); | |
4338 getter.set_result_type(int_type); | |
4339 ParamList params; | |
4340 params.AddReceiver(&dynamic_type, cls.token_pos()); | |
4341 AddFormalParamsToFunction(¶ms, getter); | |
4342 enum_members.AddFunction(getter); | |
4343 | |
4344 GrowableObjectArray& enum_names = GrowableObjectArray::Handle(I, | |
4345 GrowableObjectArray::New(8, Heap::kOld)); | |
4346 const String& name_prefix = | |
4347 String::Handle(String::Concat(enum_name, Symbols::Dot())); | |
4348 | |
4349 ASSERT(IsIdentifier()); | |
4350 ASSERT(CurrentLiteral()->raw() == cls.Name()); | |
4351 | |
4352 ConsumeToken(); // Enum type name. | |
4353 ExpectToken(Token::kLBRACE); | |
4354 Field& enum_value = Field::Handle(I); | |
4355 String& enum_value_name = String::Handle(I); | |
4356 intptr_t i = 0; | |
4357 GrowableArray<String*> declared_names(8); | |
4358 | |
4359 while (IsIdentifier()) { | |
4360 String* enum_ident = CurrentLiteral(); | |
4361 | |
4362 // Check for name conflicts. | |
4363 if (enum_ident->raw() == cls.Name()) { | |
4364 ReportError("enum identifier '%s' cannot be equal to enum type name", | |
4365 CurrentLiteral()->ToCString()); | |
4366 } else if (enum_ident->raw() == Symbols::Index().raw()) { | |
4367 ReportError("enum identifier conflicts with " | |
4368 "implicit instance field 'index'"); | |
4369 } else if (enum_ident->raw() == Symbols::Values().raw()) { | |
4370 ReportError("enum identifier conflicts with " | |
4371 "implicit static field 'values'"); | |
4372 } else if (enum_ident->raw() == Symbols::toString().raw()) { | |
4373 ReportError("enum identifier conflicts with " | |
4374 "implicit instance method 'toString()'"); | |
4375 } | |
4376 for (intptr_t i = 0; i < declared_names.length(); i++) { | |
4377 if (enum_ident->Equals(*declared_names[i])) { | |
4378 ReportError("Duplicate name '%s' in enum definition '%s'", | |
4379 enum_ident->ToCString(), | |
4380 enum_name.ToCString()); | |
4381 } | |
4382 } | |
4383 declared_names.Add(enum_ident); | |
4384 | |
4385 // Create the static const field for the enumeration value. | |
4386 enum_value = Field::New(*enum_ident, | |
4387 /* is_static = */ true, | |
4388 /* is_final = */ true, | |
4389 /* is_const = */ true, | |
4390 /* is_synthetic = */ false, | |
4391 cls, | |
4392 cls.token_pos()); | |
4393 enum_value.set_type(dynamic_type); | |
4394 enum_value.set_has_initializer(false); | |
4395 enum_members.AddField(enum_value); | |
4396 // Initialize the field with the ordinal value. It will be patched | |
4397 // later with the enum constant instance. | |
4398 Smi& ordinal_value = Smi::Handle(I, Smi::New(i)); | |
srdjan
2014/11/18 21:19:18
const Smi&
hausner
2014/11/18 23:14:07
Done.
| |
4399 enum_value.set_value(ordinal_value); | |
4400 enum_value.RecordStore(ordinal_value); | |
4401 i++; | |
4402 | |
4403 // For the user-visible name of the enumeration value, we need to | |
4404 // unmangle private names. | |
4405 if (enum_ident->CharAt(0) == '_') { | |
4406 *enum_ident = String::IdentifierPrettyName(*enum_ident); | |
4407 } | |
4408 enum_value_name = Symbols::FromConcat(name_prefix, *enum_ident); | |
4409 enum_names.Add(enum_value_name, Heap::kOld); | |
4410 | |
4411 ConsumeToken(); // Enum value name. | |
4412 if (CurrentToken() == Token::kCOMMA) { | |
4413 ConsumeToken(); | |
4414 } | |
4415 } | |
4416 ExpectToken(Token::kRBRACE); | |
4417 | |
4418 const Class& helper_class = | |
4419 Class::Handle(I, Library::LookupCoreClass(Symbols::_EnumHelper())); | |
4420 ASSERT(!helper_class.IsNull()); | |
4421 | |
4422 // Add static field 'const List values'. | |
4423 Field& values_field = Field::ZoneHandle(I); | |
4424 values_field = Field::New(Symbols::Values(), | |
4425 /* is_static = */ true, | |
4426 /* is_final = */ true, | |
4427 /* is_const = */ true, | |
4428 /* is_synthetic = */ false, | |
4429 cls, | |
4430 cls.token_pos()); | |
4431 values_field.set_type(Type::Handle(I, Type::ArrayType())); | |
4432 enum_members.AddField(values_field); | |
4433 | |
4434 // Allocate the immutable array containing the enumeration values. | |
4435 // The actual enum instance values will be patched in later. | |
4436 const Array& values_array = Array::Handle(I, Array::New(i, Heap::kOld)); | |
4437 values_field.set_value(values_array); | |
4438 values_field.RecordStore(values_array); | |
4439 | |
4440 // Create a static field that contains the list of enumeration names. | |
4441 // Clone the _enum_names field from the helper class. | |
4442 Field& names_field = Field::Handle(I, | |
4443 helper_class.LookupStaticField(Symbols::_EnumNames())); | |
4444 ASSERT(!names_field.IsNull()); | |
4445 names_field = names_field.Clone(cls); | |
4446 enum_members.AddField(names_field); | |
4447 const Array& names_array = Array::Handle(Array::MakeArray(enum_names)); | |
4448 names_field.set_value(names_array); | |
4449 names_field.RecordStore(names_array); | |
4450 | |
4451 // Clone the toString() function from the helper class. | |
4452 Function& to_string_func = Function::Handle(I, | |
4453 helper_class.LookupDynamicFunctionAllowPrivate(Symbols::toString())); | |
4454 ASSERT(!to_string_func.IsNull()); | |
4455 to_string_func = to_string_func.Clone(cls); | |
4456 to_string_func.set_is_visible(false); | |
4457 enum_members.AddFunction(to_string_func); | |
4458 | |
4459 cls.AddFields(enum_members.fields()); | |
4460 const Array& functions = | |
4461 Array::Handle(I, Array::MakeArray(enum_members.functions())); | |
4462 cls.SetFunctions(functions); | |
4463 } | |
4464 | |
4465 | |
4247 // Add an implicit constructor to the given class. | 4466 // Add an implicit constructor to the given class. |
4248 void Parser::AddImplicitConstructor(const Class& cls) { | 4467 void Parser::AddImplicitConstructor(const Class& cls) { |
4249 // The implicit constructor is unnamed, has no explicit parameter. | 4468 // The implicit constructor is unnamed, has no explicit parameter. |
4250 String& ctor_name = String::ZoneHandle(I, cls.Name()); | 4469 String& ctor_name = String::ZoneHandle(I, cls.Name()); |
4251 ctor_name = String::Concat(ctor_name, Symbols::Dot()); | 4470 ctor_name = String::Concat(ctor_name, Symbols::Dot()); |
4252 ctor_name = Symbols::New(ctor_name); | 4471 ctor_name = Symbols::New(ctor_name); |
4253 // To indicate that this is an implicit constructor, we set the | 4472 // To indicate that this is an implicit constructor, we set the |
4254 // token position and end token position of the function | 4473 // token position and end token position of the function |
4255 // to the token position of the class. | 4474 // to the token position of the class. |
4256 Function& ctor = Function::Handle(I, | 4475 Function& ctor = Function::Handle(I, |
(...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5419 } else if (is_part_source()) { | 5638 } else if (is_part_source()) { |
5420 ParsePartHeader(); | 5639 ParsePartHeader(); |
5421 } | 5640 } |
5422 | 5641 |
5423 const Class& cls = Class::Handle(I); | 5642 const Class& cls = Class::Handle(I); |
5424 while (true) { | 5643 while (true) { |
5425 set_current_class(cls); // No current class. | 5644 set_current_class(cls); // No current class. |
5426 intptr_t metadata_pos = SkipMetadata(); | 5645 intptr_t metadata_pos = SkipMetadata(); |
5427 if (CurrentToken() == Token::kCLASS) { | 5646 if (CurrentToken() == Token::kCLASS) { |
5428 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); | 5647 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
5648 } else if (CurrentToken() == Token::kENUM) { | |
5649 ParseEnumDeclaration(pending_classes, toplevel_class, metadata_pos); | |
5429 } else if ((CurrentToken() == Token::kTYPEDEF) && | 5650 } else if ((CurrentToken() == Token::kTYPEDEF) && |
5430 (LookaheadToken(1) != Token::kLPAREN)) { | 5651 (LookaheadToken(1) != Token::kLPAREN)) { |
5431 set_current_class(toplevel_class); | 5652 set_current_class(toplevel_class); |
5432 ParseTypedef(pending_classes, toplevel_class, metadata_pos); | 5653 ParseTypedef(pending_classes, toplevel_class, metadata_pos); |
5433 } else if ((CurrentToken() == Token::kABSTRACT) && | 5654 } else if ((CurrentToken() == Token::kABSTRACT) && |
5434 (LookaheadToken(1) == Token::kCLASS)) { | 5655 (LookaheadToken(1) == Token::kCLASS)) { |
5435 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); | 5656 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
5436 } else if (is_patch_source() && IsLiteral("patch") && | 5657 } else if (is_patch_source() && IsLiteral("patch") && |
5437 (LookaheadToken(1) == Token::kCLASS)) { | 5658 (LookaheadToken(1) == Token::kCLASS)) { |
5438 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); | 5659 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
(...skipping 6453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11892 void Parser::SkipQualIdent() { | 12113 void Parser::SkipQualIdent() { |
11893 ASSERT(IsIdentifier()); | 12114 ASSERT(IsIdentifier()); |
11894 ConsumeToken(); | 12115 ConsumeToken(); |
11895 if (CurrentToken() == Token::kPERIOD) { | 12116 if (CurrentToken() == Token::kPERIOD) { |
11896 ConsumeToken(); // Consume the kPERIOD token. | 12117 ConsumeToken(); // Consume the kPERIOD token. |
11897 ExpectIdentifier("identifier expected after '.'"); | 12118 ExpectIdentifier("identifier expected after '.'"); |
11898 } | 12119 } |
11899 } | 12120 } |
11900 | 12121 |
11901 } // namespace dart | 12122 } // namespace dart |
OLD | NEW |