| 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 "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1806 // No function or field exists of the specified field_name. | 1806 // No function or field exists of the specified field_name. |
| 1807 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. | 1807 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. |
| 1808 } | 1808 } |
| 1809 } | 1809 } |
| 1810 return new StaticGetterNode( | 1810 return new StaticGetterNode( |
| 1811 field_pos, implicit_argument, true, super_class, field_name); | 1811 field_pos, implicit_argument, true, super_class, field_name); |
| 1812 } | 1812 } |
| 1813 | 1813 |
| 1814 | 1814 |
| 1815 void Parser::GenerateSuperConstructorCall(const Class& cls, | 1815 void Parser::GenerateSuperConstructorCall(const Class& cls, |
| 1816 LocalVariable* receiver) { | 1816 LocalVariable* receiver, |
| 1817 ArgumentListNode* forwarding_args) { |
| 1817 const intptr_t supercall_pos = TokenPos(); | 1818 const intptr_t supercall_pos = TokenPos(); |
| 1818 const Class& super_class = Class::Handle(cls.SuperClass()); | 1819 const Class& super_class = Class::Handle(cls.SuperClass()); |
| 1819 // Omit the implicit super() if there is no super class (i.e. | 1820 // Omit the implicit super() if there is no super class (i.e. |
| 1820 // we're not compiling class Object), or if the super class is an | 1821 // we're not compiling class Object), or if the super class is an |
| 1821 // artificially generated "wrapper class" that has no constructor. | 1822 // artificially generated "wrapper class" that has no constructor. |
| 1822 if (super_class.IsNull() || | 1823 if (super_class.IsNull() || |
| 1823 (super_class.num_native_fields() > 0 && | 1824 (super_class.num_native_fields() > 0 && |
| 1824 Class::Handle(super_class.SuperClass()).IsObjectClass())) { | 1825 Class::Handle(super_class.SuperClass()).IsObjectClass())) { |
| 1825 return; | 1826 return; |
| 1826 } | 1827 } |
| 1827 String& ctor_name = String::Handle(super_class.Name()); | 1828 String& super_ctor_name = String::Handle(super_class.Name()); |
| 1828 ctor_name = String::Concat(ctor_name, Symbols::Dot()); | 1829 super_ctor_name = String::Concat(super_ctor_name, Symbols::Dot()); |
| 1830 |
| 1829 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 1831 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 1830 // Implicit 'this' parameter is the first argument. | 1832 // Implicit 'this' parameter is the first argument. |
| 1831 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); | 1833 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 1832 arguments->Add(implicit_argument); | 1834 arguments->Add(implicit_argument); |
| 1833 // Implicit construction phase parameter is second argument. | 1835 // Implicit construction phase parameter is second argument. |
| 1834 AstNode* phase_parameter = | 1836 AstNode* phase_parameter = |
| 1835 new LiteralNode(supercall_pos, | 1837 new LiteralNode(supercall_pos, |
| 1836 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 1838 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 1837 arguments->Add(phase_parameter); | 1839 arguments->Add(phase_parameter); |
| 1840 |
| 1841 // If this is a super call in a forwarding constructor, add the user- |
| 1842 // defined arguments to the super call and adjust the the super |
| 1843 // constructor name to the respective named constructor if necessary. |
| 1844 if (forwarding_args != NULL) { |
| 1845 for (int i = 0; i < forwarding_args->length(); i++) { |
| 1846 arguments->Add(forwarding_args->NodeAt(i)); |
| 1847 } |
| 1848 String& ctor_name = String::Handle(current_function().name()); |
| 1849 String& class_name = String::Handle(cls.Name()); |
| 1850 if (ctor_name.Length() > class_name.Length() + 1) { |
| 1851 // Generating a forwarding call to a named constructor 'C.n'. |
| 1852 // Add the constructor name 'n' to the super constructor. |
| 1853 ctor_name = String::SubString(ctor_name, class_name.Length() + 1); |
| 1854 super_ctor_name = String::Concat(super_ctor_name, ctor_name); |
| 1855 } |
| 1856 } |
| 1857 |
| 1858 // Resolve super constructor function and check arguments. |
| 1838 const Function& super_ctor = Function::ZoneHandle( | 1859 const Function& super_ctor = Function::ZoneHandle( |
| 1839 super_class.LookupConstructor(ctor_name)); | 1860 super_class.LookupConstructor(super_ctor_name)); |
| 1840 if (super_ctor.IsNull()) { | 1861 if (super_ctor.IsNull()) { |
| 1841 ErrorMsg(supercall_pos, | 1862 ErrorMsg(supercall_pos, |
| 1842 "unresolved implicit call to super constructor '%s()'", | 1863 "unresolved implicit call to super constructor '%s()'", |
| 1843 String::Handle(super_class.Name()).ToCString()); | 1864 String::Handle(super_class.Name()).ToCString()); |
| 1844 } | 1865 } |
| 1845 if (current_function().is_const() && !super_ctor.is_const()) { | 1866 if (current_function().is_const() && !super_ctor.is_const()) { |
| 1846 ErrorMsg(supercall_pos, "implicit call to non-const super constructor"); | 1867 ErrorMsg(supercall_pos, "implicit call to non-const super constructor"); |
| 1847 } | 1868 } |
| 1848 | 1869 |
| 1849 String& error_message = String::Handle(); | 1870 String& error_message = String::Handle(); |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2122 super_init_seen = true; | 2143 super_init_seen = true; |
| 2123 } else { | 2144 } else { |
| 2124 init_statement = ParseInitializer(cls, receiver, initialized_fields); | 2145 init_statement = ParseInitializer(cls, receiver, initialized_fields); |
| 2125 } | 2146 } |
| 2126 current_block_->statements->Add(init_statement); | 2147 current_block_->statements->Add(init_statement); |
| 2127 } while (CurrentToken() == Token::kCOMMA); | 2148 } while (CurrentToken() == Token::kCOMMA); |
| 2128 } | 2149 } |
| 2129 if (!super_init_seen) { | 2150 if (!super_init_seen) { |
| 2130 // Generate implicit super() if we haven't seen an explicit super call | 2151 // Generate implicit super() if we haven't seen an explicit super call |
| 2131 // or constructor redirection. | 2152 // or constructor redirection. |
| 2132 GenerateSuperConstructorCall(cls, receiver); | 2153 GenerateSuperConstructorCall(cls, receiver, NULL); |
| 2133 } | 2154 } |
| 2134 CheckConstFieldsInitialized(cls); | 2155 CheckConstFieldsInitialized(cls); |
| 2135 } | 2156 } |
| 2136 | 2157 |
| 2137 | 2158 |
| 2138 void Parser::ParseConstructorRedirection(const Class& cls, | 2159 void Parser::ParseConstructorRedirection(const Class& cls, |
| 2139 LocalVariable* receiver) { | 2160 LocalVariable* receiver) { |
| 2140 TRACE_PARSER("ParseConstructorRedirection"); | 2161 TRACE_PARSER("ParseConstructorRedirection"); |
| 2141 ASSERT(CurrentToken() == Token::kTHIS); | 2162 ASSERT(CurrentToken() == Token::kTHIS); |
| 2142 const intptr_t call_pos = TokenPos(); | 2163 const intptr_t call_pos = TokenPos(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2183 current_block_->statements->Add( | 2204 current_block_->statements->Add( |
| 2184 new StaticCallNode(call_pos, redirect_ctor, arguments)); | 2205 new StaticCallNode(call_pos, redirect_ctor, arguments)); |
| 2185 } | 2206 } |
| 2186 | 2207 |
| 2187 | 2208 |
| 2188 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { | 2209 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { |
| 2189 ASSERT(func.IsConstructor()); | 2210 ASSERT(func.IsConstructor()); |
| 2190 const intptr_t ctor_pos = TokenPos(); | 2211 const intptr_t ctor_pos = TokenPos(); |
| 2191 OpenFunctionBlock(func); | 2212 OpenFunctionBlock(func); |
| 2192 const Class& cls = Class::Handle(func.Owner()); | 2213 const Class& cls = Class::Handle(func.Owner()); |
| 2214 |
| 2193 LocalVariable* receiver = new LocalVariable( | 2215 LocalVariable* receiver = new LocalVariable( |
| 2194 ctor_pos, | 2216 ctor_pos, |
| 2195 Symbols::This(), | 2217 Symbols::This(), |
| 2196 Type::ZoneHandle(Type::DynamicType())); | 2218 Type::ZoneHandle(Type::DynamicType())); |
| 2197 current_block_->scope->AddVariable(receiver); | 2219 current_block_->scope->AddVariable(receiver); |
| 2198 | 2220 |
| 2199 LocalVariable* phase_parameter = new LocalVariable( | 2221 LocalVariable* phase_parameter = new LocalVariable( |
| 2200 ctor_pos, | 2222 ctor_pos, |
| 2201 Symbols::PhaseParameter(), | 2223 Symbols::PhaseParameter(), |
| 2202 Type::ZoneHandle(Type::SmiType())); | 2224 Type::ZoneHandle(Type::SmiType())); |
| 2203 current_block_->scope->AddVariable(phase_parameter); | 2225 current_block_->scope->AddVariable(phase_parameter); |
| 2204 | 2226 |
| 2205 // Parse expressions of instance fields that have an explicit | 2227 // Parse expressions of instance fields that have an explicit |
| 2206 // initializer expression. | 2228 // initializer expression. |
| 2207 // The receiver must not be visible to field initializer expressions. | 2229 // The receiver must not be visible to field initializer expressions. |
| 2208 receiver->set_invisible(true); | 2230 receiver->set_invisible(true); |
| 2209 GrowableArray<Field*> initialized_fields; | 2231 GrowableArray<Field*> initialized_fields; |
| 2210 ParseInitializedInstanceFields(cls, receiver, &initialized_fields); | 2232 ParseInitializedInstanceFields(cls, receiver, &initialized_fields); |
| 2211 receiver->set_invisible(false); | 2233 receiver->set_invisible(false); |
| 2212 | 2234 |
| 2213 GenerateSuperConstructorCall(cls, receiver); | 2235 // If the class of this implicit constructor is a mixin application class, |
| 2236 // it is a forwarding constructor of the mixin. The forwarding |
| 2237 // constructor initializes the instance fields that have initializer |
| 2238 // expressions and then calls the respective super constructor with |
| 2239 // the same name and number of parameters. |
| 2240 ArgumentListNode* forwarding_args = NULL; |
| 2241 if (cls.mixin() != Type::null()) { |
| 2242 // At this point we don't support forwarding constructors |
| 2243 // that have optional parameters because we don't know the default |
| 2244 // values of the optional parameters. We would have to compile the super |
| 2245 // constructor to get the default values. Also, the spec is not clear |
| 2246 // whether optional parameters are even allowed in this situation. |
| 2247 // TODO(hausner): Remove this limitation if the language spec indeed |
| 2248 // allows optional parameters. |
| 2249 if (func.HasOptionalParameters()) { |
| 2250 ErrorMsg(ctor_pos, |
| 2251 "forwarding constructors must not have optional parameters"); |
| 2252 } |
| 2253 |
| 2254 // Prepare user-defined arguments to be forwarded to super call. |
| 2255 // The first user-defined argument is at position 2. |
| 2256 forwarding_args = new ArgumentListNode(ctor_pos); |
| 2257 for (int i = 2; i < func.NumParameters(); i++) { |
| 2258 LocalVariable* param = new LocalVariable( |
| 2259 ctor_pos, |
| 2260 String::ZoneHandle(func.ParameterNameAt(i)), |
| 2261 Type::ZoneHandle(Type::DynamicType())); |
| 2262 current_block_->scope->AddVariable(param); |
| 2263 forwarding_args->Add(new LoadLocalNode(ctor_pos, param)); |
| 2264 } |
| 2265 } |
| 2266 |
| 2267 GenerateSuperConstructorCall(cls, receiver, forwarding_args); |
| 2214 CheckConstFieldsInitialized(cls); | 2268 CheckConstFieldsInitialized(cls); |
| 2215 | 2269 |
| 2216 // Empty constructor body. | 2270 // Empty constructor body. |
| 2217 SequenceNode* statements = CloseBlock(); | 2271 SequenceNode* statements = CloseBlock(); |
| 2218 return statements; | 2272 return statements; |
| 2219 } | 2273 } |
| 2220 | 2274 |
| 2221 | 2275 |
| 2222 // Helper function to make the first num_variables variables in the | 2276 // Helper function to make the first num_variables variables in the |
| 2223 // given scope visible/invisible. | 2277 // given scope visible/invisible. |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2849 } | 2903 } |
| 2850 SkipToMatchingParenthesis(); | 2904 SkipToMatchingParenthesis(); |
| 2851 } else { | 2905 } else { |
| 2852 SkipInitializers(); | 2906 SkipInitializers(); |
| 2853 } | 2907 } |
| 2854 } | 2908 } |
| 2855 | 2909 |
| 2856 // Only constructors can redirect to another method. | 2910 // Only constructors can redirect to another method. |
| 2857 ASSERT((method->redirect_name == NULL) || method->IsConstructor()); | 2911 ASSERT((method->redirect_name == NULL) || method->IsConstructor()); |
| 2858 | 2912 |
| 2859 intptr_t method_end_pos = method_pos; | 2913 intptr_t method_end_pos = TokenPos(); |
| 2860 if ((CurrentToken() == Token::kLBRACE) || | 2914 if ((CurrentToken() == Token::kLBRACE) || |
| 2861 (CurrentToken() == Token::kARROW)) { | 2915 (CurrentToken() == Token::kARROW)) { |
| 2862 if (method->has_abstract) { | 2916 if (method->has_abstract) { |
| 2863 ErrorMsg(method->name_pos, | 2917 ErrorMsg(method->name_pos, |
| 2864 "abstract method '%s' may not have a function body", | 2918 "abstract method '%s' may not have a function body", |
| 2865 method->name->ToCString()); | 2919 method->name->ToCString()); |
| 2866 } else if (method->has_external) { | 2920 } else if (method->has_external) { |
| 2867 ErrorMsg(method->name_pos, | 2921 ErrorMsg(method->name_pos, |
| 2868 "external method '%s' may not have a function body", | 2922 "external method '%s' may not have a function body", |
| 2869 method->name->ToCString()); | 2923 method->name->ToCString()); |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3564 } | 3618 } |
| 3565 | 3619 |
| 3566 | 3620 |
| 3567 // Add an implicit constructor to the given class. | 3621 // Add an implicit constructor to the given class. |
| 3568 void Parser::AddImplicitConstructor(const Class& cls) { | 3622 void Parser::AddImplicitConstructor(const Class& cls) { |
| 3569 // The implicit constructor is unnamed, has no explicit parameter. | 3623 // The implicit constructor is unnamed, has no explicit parameter. |
| 3570 String& ctor_name = String::ZoneHandle(cls.Name()); | 3624 String& ctor_name = String::ZoneHandle(cls.Name()); |
| 3571 ctor_name = String::Concat(ctor_name, Symbols::Dot()); | 3625 ctor_name = String::Concat(ctor_name, Symbols::Dot()); |
| 3572 ctor_name = Symbols::New(ctor_name); | 3626 ctor_name = Symbols::New(ctor_name); |
| 3573 // To indicate that this is an implicit constructor, we set the | 3627 // To indicate that this is an implicit constructor, we set the |
| 3574 // token position is the same as the token position of the class. | 3628 // token position and end token position of the function |
| 3629 // to the token position of the class. |
| 3575 Function& ctor = Function::Handle( | 3630 Function& ctor = Function::Handle( |
| 3576 Function::New(ctor_name, | 3631 Function::New(ctor_name, |
| 3577 RawFunction::kConstructor, | 3632 RawFunction::kConstructor, |
| 3578 /* is_static = */ false, | 3633 /* is_static = */ false, |
| 3579 /* is_const = */ false, | 3634 /* is_const = */ false, |
| 3580 /* is_abstract = */ false, | 3635 /* is_abstract = */ false, |
| 3581 /* is_external = */ false, | 3636 /* is_external = */ false, |
| 3582 cls, | 3637 cls, |
| 3583 cls.token_pos())); | 3638 cls.token_pos())); |
| 3639 ctor.set_end_token_pos(ctor.token_pos()); |
| 3640 |
| 3584 ParamList params; | 3641 ParamList params; |
| 3585 // Add implicit 'this' parameter. We don't care about the specific type | 3642 // Add implicit 'this' parameter. We don't care about the specific type |
| 3586 // and just specify dynamic. | 3643 // and just specify dynamic. |
| 3587 const Type& receiver_type = Type::Handle(Type::DynamicType()); | 3644 const Type& receiver_type = Type::Handle(Type::DynamicType()); |
| 3588 params.AddReceiver(&receiver_type, cls.token_pos()); | 3645 params.AddReceiver(&receiver_type, cls.token_pos()); |
| 3589 // Add implicit parameter for construction phase. | 3646 // Add implicit parameter for construction phase. |
| 3590 params.AddFinalParameter(cls.token_pos(), | 3647 params.AddFinalParameter(cls.token_pos(), |
| 3591 &Symbols::PhaseParameter(), | 3648 &Symbols::PhaseParameter(), |
| 3592 &Type::ZoneHandle(Type::SmiType())); | 3649 &Type::ZoneHandle(Type::SmiType())); |
| 3593 | 3650 |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4087 mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand()); | 4144 mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand()); |
| 4088 mixin_app_name = String::Concat(mixin_app_name, | 4145 mixin_app_name = String::Concat(mixin_app_name, |
| 4089 String::Handle(mixin_type.ClassName())); | 4146 String::Handle(mixin_type.ClassName())); |
| 4090 mixin_app_name = Symbols::New(mixin_app_name); | 4147 mixin_app_name = Symbols::New(mixin_app_name); |
| 4091 | 4148 |
| 4092 mixin_application = Class::New(mixin_app_name, script_, mixin_pos); | 4149 mixin_application = Class::New(mixin_app_name, script_, mixin_pos); |
| 4093 mixin_application.set_super_type(mixin_super_type); | 4150 mixin_application.set_super_type(mixin_super_type); |
| 4094 mixin_application.set_mixin(Type::Cast(mixin_type)); | 4151 mixin_application.set_mixin(Type::Cast(mixin_type)); |
| 4095 mixin_application.set_library(library_); | 4152 mixin_application.set_library(library_); |
| 4096 mixin_application.set_is_synthesized_class(); | 4153 mixin_application.set_is_synthesized_class(); |
| 4097 AddImplicitConstructor(mixin_application); | 4154 |
| 4098 // Add the mixin type to the interfaces that the mixin application | 4155 // Add the mixin type to the interfaces that the mixin application |
| 4099 // class implements. This is necessary so that type tests work. | 4156 // class implements. This is necessary so that type tests work. |
| 4100 mixin_application_interfaces = Array::New(1); | 4157 mixin_application_interfaces = Array::New(1); |
| 4101 mixin_application_interfaces.SetAt(0, mixin_type); | 4158 mixin_application_interfaces.SetAt(0, mixin_type); |
| 4102 mixin_application.set_interfaces(mixin_application_interfaces); | 4159 mixin_application.set_interfaces(mixin_application_interfaces); |
| 4103 | 4160 |
| 4104 // For the type arguments of the mixin application type, we need | 4161 // For the type arguments of the mixin application type, we need |
| 4105 // a copy of the type arguments to the mixin type. The simplest way | 4162 // a copy of the type arguments to the mixin type. The simplest way |
| 4106 // to get the copy is to rewind the parser, parse the mixin type | 4163 // to get the copy is to rewind the parser, parse the mixin type |
| 4107 // again and steal its type arguments. | 4164 // again and steal its type arguments. |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4819 // Populate the parameter type array and parameter name array of the function | 4876 // Populate the parameter type array and parameter name array of the function |
| 4820 // with the formal parameter types and names. | 4877 // with the formal parameter types and names. |
| 4821 void Parser::AddFormalParamsToFunction(const ParamList* params, | 4878 void Parser::AddFormalParamsToFunction(const ParamList* params, |
| 4822 const Function& func) { | 4879 const Function& func) { |
| 4823 ASSERT((params != NULL) && (params->parameters != NULL)); | 4880 ASSERT((params != NULL) && (params->parameters != NULL)); |
| 4824 ASSERT((params->num_optional_parameters > 0) == | 4881 ASSERT((params->num_optional_parameters > 0) == |
| 4825 (params->has_optional_positional_parameters || | 4882 (params->has_optional_positional_parameters || |
| 4826 params->has_optional_named_parameters)); | 4883 params->has_optional_named_parameters)); |
| 4827 if (!Utils::IsInt(16, params->num_fixed_parameters) || | 4884 if (!Utils::IsInt(16, params->num_fixed_parameters) || |
| 4828 !Utils::IsInt(16, params->num_optional_parameters)) { | 4885 !Utils::IsInt(16, params->num_optional_parameters)) { |
| 4829 ErrorMsg("too many formal parameters"); | 4886 ErrorMsg(func.token_pos(), "too many formal parameters"); |
| 4830 } | 4887 } |
| 4831 func.set_num_fixed_parameters(params->num_fixed_parameters); | 4888 func.set_num_fixed_parameters(params->num_fixed_parameters); |
| 4832 func.SetNumOptionalParameters(params->num_optional_parameters, | 4889 func.SetNumOptionalParameters(params->num_optional_parameters, |
| 4833 params->has_optional_positional_parameters); | 4890 params->has_optional_positional_parameters); |
| 4834 const int num_parameters = params->parameters->length(); | 4891 const int num_parameters = params->parameters->length(); |
| 4835 ASSERT(num_parameters == func.NumParameters()); | 4892 ASSERT(num_parameters == func.NumParameters()); |
| 4836 func.set_parameter_types(Array::Handle(Array::New(num_parameters, | 4893 func.set_parameter_types(Array::Handle(Array::New(num_parameters, |
| 4837 Heap::kOld))); | 4894 Heap::kOld))); |
| 4838 func.set_parameter_names(Array::Handle(Array::New(num_parameters, | 4895 func.set_parameter_names(Array::Handle(Array::New(num_parameters, |
| 4839 Heap::kOld))); | 4896 Heap::kOld))); |
| (...skipping 5237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10077 void Parser::SkipQualIdent() { | 10134 void Parser::SkipQualIdent() { |
| 10078 ASSERT(IsIdentifier()); | 10135 ASSERT(IsIdentifier()); |
| 10079 ConsumeToken(); | 10136 ConsumeToken(); |
| 10080 if (CurrentToken() == Token::kPERIOD) { | 10137 if (CurrentToken() == Token::kPERIOD) { |
| 10081 ConsumeToken(); // Consume the kPERIOD token. | 10138 ConsumeToken(); // Consume the kPERIOD token. |
| 10082 ExpectIdentifier("identifier expected after '.'"); | 10139 ExpectIdentifier("identifier expected after '.'"); |
| 10083 } | 10140 } |
| 10084 } | 10141 } |
| 10085 | 10142 |
| 10086 } // namespace dart | 10143 } // namespace dart |
| OLD | NEW |