Chromium Code Reviews| 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 28 matching lines...) Expand all Loading... | |
| 39 namespace dart { | 39 namespace dart { |
| 40 | 40 |
| 41 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); | 41 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); |
| 42 DEFINE_FLAG(bool, enable_mirrors, true, | 42 DEFINE_FLAG(bool, enable_mirrors, true, |
| 43 "Disable to make importing dart:mirrors an error."); | 43 "Disable to make importing dart:mirrors an error."); |
| 44 DEFINE_FLAG(bool, load_deferred_eagerly, false, | 44 DEFINE_FLAG(bool, load_deferred_eagerly, false, |
| 45 "Load deferred libraries eagerly."); | 45 "Load deferred libraries eagerly."); |
| 46 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 46 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
| 47 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); | 47 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); |
| 48 DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily"); | 48 DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily"); |
| 49 DEFINE_FLAG(bool, move_super, false, "Move super initializer to end of list"); | |
| 49 | 50 |
| 50 DECLARE_FLAG(bool, lazy_dispatchers); | 51 DECLARE_FLAG(bool, lazy_dispatchers); |
| 51 DECLARE_FLAG(bool, load_deferred_eagerly); | 52 DECLARE_FLAG(bool, load_deferred_eagerly); |
| 52 DECLARE_FLAG(bool, profile_vm); | 53 DECLARE_FLAG(bool, profile_vm); |
| 53 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 54 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 54 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 55 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
| 55 | 56 |
| 56 // Quick access to the current thread, isolate and zone. | 57 // Quick access to the current thread, isolate and zone. |
| 57 #define T (thread()) | 58 #define T (thread()) |
| 58 #define I (isolate()) | 59 #define I (isolate()) |
| (...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2321 } | 2322 } |
| 2322 // No function or field exists of the specified field_name. | 2323 // No function or field exists of the specified field_name. |
| 2323 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. | 2324 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. |
| 2324 } | 2325 } |
| 2325 } | 2326 } |
| 2326 return new(Z) StaticGetterNode( | 2327 return new(Z) StaticGetterNode( |
| 2327 field_pos, implicit_argument, super_class, field_name); | 2328 field_pos, implicit_argument, super_class, field_name); |
| 2328 } | 2329 } |
| 2329 | 2330 |
| 2330 | 2331 |
| 2331 void Parser::GenerateSuperConstructorCall(const Class& cls, | 2332 StaticCallNode* Parser::GenerateSuperConstructorCall( |
| 2332 intptr_t supercall_pos, | 2333 const Class& cls, |
| 2333 LocalVariable* receiver, | 2334 intptr_t supercall_pos, |
| 2334 AstNode* phase_parameter, | 2335 LocalVariable* receiver, |
| 2335 ArgumentListNode* forwarding_args) { | 2336 AstNode* phase_parameter, |
| 2337 ArgumentListNode* forwarding_args) { | |
| 2336 const Class& super_class = Class::Handle(Z, cls.SuperClass()); | 2338 const Class& super_class = Class::Handle(Z, cls.SuperClass()); |
| 2337 // Omit the implicit super() if there is no super class (i.e. | 2339 // Omit the implicit super() if there is no super class (i.e. |
| 2338 // we're not compiling class Object), or if the super class is an | 2340 // we're not compiling class Object), or if the super class is an |
| 2339 // artificially generated "wrapper class" that has no constructor. | 2341 // artificially generated "wrapper class" that has no constructor. |
| 2340 if (super_class.IsNull() || | 2342 if (super_class.IsNull() || |
| 2341 (super_class.num_native_fields() > 0 && | 2343 (super_class.num_native_fields() > 0 && |
| 2342 Class::Handle(Z, super_class.SuperClass()).IsObjectClass())) { | 2344 Class::Handle(Z, super_class.SuperClass()).IsObjectClass())) { |
| 2343 return; | 2345 return NULL; |
| 2344 } | 2346 } |
| 2345 String& super_ctor_name = String::Handle(Z, super_class.Name()); | 2347 String& super_ctor_name = String::Handle(Z, super_class.Name()); |
| 2346 super_ctor_name = Symbols::FromConcat(super_ctor_name, Symbols::Dot()); | 2348 super_ctor_name = Symbols::FromConcat(super_ctor_name, Symbols::Dot()); |
| 2347 | 2349 |
| 2348 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 2350 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 2349 // Implicit 'this' parameter is the first argument. | 2351 // Implicit 'this' parameter is the first argument. |
| 2350 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); | 2352 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 2351 arguments->Add(implicit_argument); | 2353 arguments->Add(implicit_argument); |
| 2352 // Implicit construction phase parameter is second argument. | 2354 // Implicit construction phase parameter is second argument. |
| 2353 arguments->Add(phase_parameter); | 2355 arguments->Add(phase_parameter); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2384 | 2386 |
| 2385 String& error_message = String::Handle(Z); | 2387 String& error_message = String::Handle(Z); |
| 2386 if (!super_ctor.AreValidArguments(arguments->length(), | 2388 if (!super_ctor.AreValidArguments(arguments->length(), |
| 2387 arguments->names(), | 2389 arguments->names(), |
| 2388 &error_message)) { | 2390 &error_message)) { |
| 2389 ReportError(supercall_pos, | 2391 ReportError(supercall_pos, |
| 2390 "invalid arguments passed to super constructor '%s()': %s", | 2392 "invalid arguments passed to super constructor '%s()': %s", |
| 2391 String::Handle(Z, super_class.Name()).ToCString(), | 2393 String::Handle(Z, super_class.Name()).ToCString(), |
| 2392 error_message.ToCString()); | 2394 error_message.ToCString()); |
| 2393 } | 2395 } |
| 2394 current_block_->statements->Add( | 2396 return new StaticCallNode(supercall_pos, super_ctor, arguments); |
| 2395 new StaticCallNode(supercall_pos, super_ctor, arguments)); | |
| 2396 } | 2397 } |
| 2397 | 2398 |
| 2398 | 2399 |
| 2399 AstNode* Parser::ParseSuperInitializer(const Class& cls, | 2400 StaticCallNode* Parser::ParseSuperInitializer(const Class& cls, |
| 2400 LocalVariable* receiver) { | 2401 LocalVariable* receiver) { |
| 2401 TRACE_PARSER("ParseSuperInitializer"); | 2402 TRACE_PARSER("ParseSuperInitializer"); |
| 2402 ASSERT(CurrentToken() == Token::kSUPER); | 2403 ASSERT(CurrentToken() == Token::kSUPER); |
| 2403 const intptr_t supercall_pos = TokenPos(); | 2404 const intptr_t supercall_pos = TokenPos(); |
| 2404 ConsumeToken(); | 2405 ConsumeToken(); |
| 2405 const Class& super_class = Class::Handle(Z, cls.SuperClass()); | 2406 const Class& super_class = Class::Handle(Z, cls.SuperClass()); |
| 2406 ASSERT(!super_class.IsNull()); | 2407 ASSERT(!super_class.IsNull()); |
| 2407 String& ctor_name = String::Handle(Z, super_class.Name()); | 2408 String& ctor_name = String::Handle(Z, super_class.Name()); |
| 2408 ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot()); | 2409 ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot()); |
| 2409 if (CurrentToken() == Token::kPERIOD) { | 2410 if (CurrentToken() == Token::kPERIOD) { |
| 2410 ConsumeToken(); | 2411 ConsumeToken(); |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2721 } | 2722 } |
| 2722 initialized_fields->Add(field); | 2723 initialized_fields->Add(field); |
| 2723 return result; | 2724 return result; |
| 2724 } | 2725 } |
| 2725 | 2726 |
| 2726 | 2727 |
| 2727 void Parser::ParseInitializers(const Class& cls, | 2728 void Parser::ParseInitializers(const Class& cls, |
| 2728 LocalVariable* receiver, | 2729 LocalVariable* receiver, |
| 2729 GrowableArray<Field*>* initialized_fields) { | 2730 GrowableArray<Field*>* initialized_fields) { |
| 2730 TRACE_PARSER("ParseInitializers"); | 2731 TRACE_PARSER("ParseInitializers"); |
| 2731 bool super_init_seen = false; | 2732 bool super_init_is_last = false; |
| 2733 intptr_t super_init_index = -1; | |
| 2734 StaticCallNode* super_init_call = NULL; | |
| 2732 if (CurrentToken() == Token::kCOLON) { | 2735 if (CurrentToken() == Token::kCOLON) { |
| 2733 do { | 2736 do { |
| 2734 ConsumeToken(); // Colon or comma. | 2737 ConsumeToken(); // Colon or comma. |
| 2735 AstNode* init_statement; | |
| 2736 if (CurrentToken() == Token::kSUPER) { | 2738 if (CurrentToken() == Token::kSUPER) { |
| 2737 if (super_init_seen) { | 2739 if (super_init_call != NULL) { |
| 2738 ReportError("duplicate call to super constructor"); | 2740 ReportError("duplicate call to super constructor"); |
| 2739 } | 2741 } |
| 2740 init_statement = ParseSuperInitializer(cls, receiver); | 2742 super_init_call = ParseSuperInitializer(cls, receiver); |
| 2741 super_init_seen = true; | 2743 super_init_index = current_block_->statements->length(); |
| 2744 current_block_->statements->Add(super_init_call); | |
| 2745 super_init_is_last = true; | |
| 2742 } else { | 2746 } else { |
| 2743 init_statement = ParseInitializer(cls, receiver, initialized_fields); | 2747 AstNode* init_statement = |
| 2748 ParseInitializer(cls, receiver, initialized_fields); | |
| 2749 super_init_is_last = false; | |
| 2750 current_block_->statements->Add(init_statement); | |
| 2744 } | 2751 } |
| 2745 current_block_->statements->Add(init_statement); | |
| 2746 } while (CurrentToken() == Token::kCOMMA); | 2752 } while (CurrentToken() == Token::kCOMMA); |
| 2747 } | 2753 } |
| 2748 if (!super_init_seen) { | 2754 if (super_init_call == NULL) { |
| 2749 // Generate implicit super() if we haven't seen an explicit super call | 2755 // Generate implicit super() if we haven't seen an explicit super call |
| 2750 // or constructor redirection. | 2756 // or constructor redirection. |
| 2751 AstNode* phase_parameter = new LiteralNode( | 2757 AstNode* phase_parameter = new LiteralNode( |
| 2752 TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll))); | 2758 TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll))); |
| 2753 GenerateSuperConstructorCall( | 2759 super_init_call = GenerateSuperConstructorCall( |
| 2754 cls, TokenPos(), receiver, phase_parameter, NULL); | 2760 cls, TokenPos(), receiver, phase_parameter, NULL); |
| 2761 if (super_init_call != NULL) { | |
| 2762 super_init_index = current_block_->statements->length(); | |
| 2763 current_block_->statements->Add(super_init_call); | |
| 2764 super_init_is_last = true; | |
| 2765 } | |
| 2766 } | |
| 2767 if (FLAG_move_super && super_init_call != NULL && !super_init_is_last) { | |
|
regis
2015/10/07 16:54:43
parenthesis missing
hausner
2015/10/07 17:27:22
Done.
| |
| 2768 // If the super initializer call is not at the end of the initializer | |
| 2769 // list, implicitly move it to the end. The actual parameter values | |
| 2770 // are evaluated at the original position in the list and preserved | |
| 2771 // in temporary variables. (The following initializer expressions | |
| 2772 // could have side effects that alter the arguments to the super | |
| 2773 // initializer.) E.g: | |
| 2774 // A(x) : super(x), f = x++ { ... } | |
| 2775 // is transformed to: | |
| 2776 // A(x) : temp = x, f = x++, super(temp) { ... } | |
| 2777 ReportWarning("Super initizlizer not at end"); | |
| 2778 ASSERT(super_init_index >= 0); | |
| 2779 ArgumentListNode* ctor_args = super_init_call->arguments(); | |
| 2780 LetNode* saved_args = new(Z) LetNode(super_init_call->token_pos()); | |
| 2781 // The super initializer call has at least 2 arguments: the | |
| 2782 // implicit receiver, and the hidden construction phase. | |
| 2783 ASSERT(ctor_args->length() >= 2); | |
| 2784 for (int i = 2; i < ctor_args->length(); i++) { | |
| 2785 AstNode* arg = ctor_args->NodeAt(i); | |
| 2786 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca"); | |
| 2787 AstNode* save_temp = new(Z) StoreLocalNode(arg->token_pos(), temp, arg); | |
| 2788 saved_args->AddNode(save_temp); | |
| 2789 ctor_args->SetNodeAt(i, new(Z) LoadLocalNode(arg->token_pos(), temp)); | |
| 2790 } | |
| 2791 current_block_->statements->ReplaceNodeAt(super_init_index, saved_args); | |
| 2792 current_block_->statements->Add(super_init_call); | |
| 2755 } | 2793 } |
| 2756 CheckFieldsInitialized(cls); | 2794 CheckFieldsInitialized(cls); |
| 2757 } | 2795 } |
| 2758 | 2796 |
| 2759 | 2797 |
| 2760 void Parser::ParseConstructorRedirection(const Class& cls, | 2798 void Parser::ParseConstructorRedirection(const Class& cls, |
| 2761 LocalVariable* receiver) { | 2799 LocalVariable* receiver) { |
| 2762 TRACE_PARSER("ParseConstructorRedirection"); | 2800 TRACE_PARSER("ParseConstructorRedirection"); |
| 2763 ExpectToken(Token::kCOLON); | 2801 ExpectToken(Token::kCOLON); |
| 2764 ASSERT(CurrentToken() == Token::kTHIS); | 2802 ASSERT(CurrentToken() == Token::kTHIS); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2867 for (int i = 2; i < func.NumParameters(); i++) { | 2905 for (int i = 2; i < func.NumParameters(); i++) { |
| 2868 LocalVariable* param = new LocalVariable( | 2906 LocalVariable* param = new LocalVariable( |
| 2869 Scanner::kNoSourcePos, | 2907 Scanner::kNoSourcePos, |
| 2870 String::ZoneHandle(Z, func.ParameterNameAt(i)), | 2908 String::ZoneHandle(Z, func.ParameterNameAt(i)), |
| 2871 Type::ZoneHandle(Z, Type::DynamicType())); | 2909 Type::ZoneHandle(Z, Type::DynamicType())); |
| 2872 current_block_->scope->InsertParameterAt(i, param); | 2910 current_block_->scope->InsertParameterAt(i, param); |
| 2873 forwarding_args->Add(new LoadLocalNode(Scanner::kNoSourcePos, param)); | 2911 forwarding_args->Add(new LoadLocalNode(Scanner::kNoSourcePos, param)); |
| 2874 } | 2912 } |
| 2875 } | 2913 } |
| 2876 | 2914 |
| 2877 GenerateSuperConstructorCall( | 2915 AstNode* super_call = GenerateSuperConstructorCall( |
| 2878 current_class(), | 2916 current_class(), |
| 2879 Scanner::kNoSourcePos, | 2917 Scanner::kNoSourcePos, |
| 2880 receiver, | 2918 receiver, |
| 2881 new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter), | 2919 new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter), |
| 2882 forwarding_args); | 2920 forwarding_args); |
| 2921 if (super_call != NULL) { | |
| 2922 current_block_->statements->Add(super_call); | |
| 2923 } | |
| 2883 CheckFieldsInitialized(current_class()); | 2924 CheckFieldsInitialized(current_class()); |
| 2884 | 2925 |
| 2885 // Empty constructor body. | 2926 // Empty constructor body. |
| 2886 current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos)); | 2927 current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos)); |
| 2887 SequenceNode* statements = CloseBlock(); | 2928 SequenceNode* statements = CloseBlock(); |
| 2888 return statements; | 2929 return statements; |
| 2889 } | 2930 } |
| 2890 | 2931 |
| 2891 | 2932 |
| 2892 void Parser::CheckRecursiveInvocation() { | 2933 void Parser::CheckRecursiveInvocation() { |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3084 if (init_statements->NodeAt(i)->IsStaticCallNode()) { | 3125 if (init_statements->NodeAt(i)->IsStaticCallNode()) { |
| 3085 StaticCallNode* static_call = | 3126 StaticCallNode* static_call = |
| 3086 init_statements->NodeAt(i)->AsStaticCallNode(); | 3127 init_statements->NodeAt(i)->AsStaticCallNode(); |
| 3087 if (static_call->function().IsGenerativeConstructor()) { | 3128 if (static_call->function().IsGenerativeConstructor()) { |
| 3088 super_call = static_call; | 3129 super_call = static_call; |
| 3089 break; | 3130 break; |
| 3090 } | 3131 } |
| 3091 } | 3132 } |
| 3092 } | 3133 } |
| 3093 if (super_call != NULL) { | 3134 if (super_call != NULL) { |
| 3135 ASSERT(!FLAG_move_super); | |
| 3094 // Generate an implicit call to the super constructor's body. | 3136 // Generate an implicit call to the super constructor's body. |
| 3095 // We need to patch the super _initializer_ call so that it | 3137 // We need to patch the super _initializer_ call so that it |
| 3096 // saves the evaluated actual arguments in temporary variables. | 3138 // saves the evaluated actual arguments in temporary variables. |
| 3097 // The temporary variables are necessary so that the argument | 3139 // The temporary variables are necessary so that the argument |
| 3098 // expressions are not evaluated twice. | 3140 // expressions are not evaluated twice. |
| 3099 // Note: we should never get here in the case of a redirecting | 3141 // Note: we should never get here in the case of a redirecting |
| 3100 // constructor. In that case, the call to the target constructor | 3142 // constructor. In that case, the call to the target constructor |
| 3101 // is the "super call" and is implicitly at the end of the | 3143 // is the "super call" and is implicitly at the end of the |
| 3102 // initializer list. | 3144 // initializer list. |
| 3103 ASSERT(!is_redirecting_constructor); | 3145 ASSERT(!is_redirecting_constructor); |
| 3104 ArgumentListNode* ctor_args = super_call->arguments(); | 3146 ArgumentListNode* ctor_args = super_call->arguments(); |
| 3105 // The super initializer call has at least 2 arguments: the | 3147 // The super initializer call has at least 2 arguments: the |
| 3106 // implicit receiver, and the hidden construction phase. | 3148 // implicit receiver, and the hidden construction phase. |
| 3107 ASSERT(ctor_args->length() >= 2); | 3149 ASSERT(ctor_args->length() >= 2); |
| 3108 for (int i = 2; i < ctor_args->length(); i++) { | 3150 for (int i = 2; i < ctor_args->length(); i++) { |
| 3109 AstNode* arg = ctor_args->NodeAt(i); | 3151 AstNode* arg = ctor_args->NodeAt(i); |
| 3110 if (!IsSimpleLocalOrLiteralNode(arg)) { | 3152 if (!IsSimpleLocalOrLiteralNode(arg)) { |
| 3111 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca"); | 3153 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca"); |
| 3112 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); | 3154 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); |
| 3113 ctor_args->SetNodeAt(i, save_temp); | 3155 ctor_args->SetNodeAt(i, save_temp); |
| 3114 } | 3156 } |
| 3115 } | 3157 } |
| 3116 } | 3158 } |
| 3117 OpenBlock(); // Block to collect constructor body nodes. | 3159 OpenBlock(); // Block to collect constructor body nodes. |
| 3118 intptr_t body_pos = TokenPos(); | 3160 intptr_t body_pos = TokenPos(); |
| 3119 | 3161 |
| 3120 // Insert the implicit super call to the super constructor body. | 3162 // Insert the implicit super call to the super constructor body. |
| 3121 if (super_call != NULL) { | 3163 if (super_call != NULL) { |
| 3164 ASSERT(!FLAG_move_super); | |
| 3122 ArgumentListNode* initializer_args = super_call->arguments(); | 3165 ArgumentListNode* initializer_args = super_call->arguments(); |
| 3123 const Function& super_ctor = super_call->function(); | 3166 const Function& super_ctor = super_call->function(); |
| 3124 // Patch the initializer call so it only executes the super initializer. | 3167 // Patch the initializer call so it only executes the super initializer. |
| 3125 initializer_args->SetNodeAt(1, new LiteralNode( | 3168 initializer_args->SetNodeAt(1, new LiteralNode( |
| 3126 body_pos, Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseInit)))); | 3169 body_pos, Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseInit)))); |
| 3127 | 3170 |
| 3128 ArgumentListNode* super_call_args = new ArgumentListNode(body_pos); | 3171 ArgumentListNode* super_call_args = new ArgumentListNode(body_pos); |
| 3129 // First argument is the receiver. | 3172 // First argument is the receiver. |
| 3130 super_call_args->Add(new LoadLocalNode(body_pos, receiver)); | 3173 super_call_args->Add(new LoadLocalNode(body_pos, receiver)); |
| 3131 // Second argument is the construction phase argument. | 3174 // Second argument is the construction phase argument. |
| (...skipping 11129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14261 void Parser::SkipQualIdent() { | 14304 void Parser::SkipQualIdent() { |
| 14262 ASSERT(IsIdentifier()); | 14305 ASSERT(IsIdentifier()); |
| 14263 ConsumeToken(); | 14306 ConsumeToken(); |
| 14264 if (CurrentToken() == Token::kPERIOD) { | 14307 if (CurrentToken() == Token::kPERIOD) { |
| 14265 ConsumeToken(); // Consume the kPERIOD token. | 14308 ConsumeToken(); // Consume the kPERIOD token. |
| 14266 ExpectIdentifier("identifier expected after '.'"); | 14309 ExpectIdentifier("identifier expected after '.'"); |
| 14267 } | 14310 } |
| 14268 } | 14311 } |
| 14269 | 14312 |
| 14270 } // namespace dart | 14313 } // namespace dart |
| OLD | NEW |